From: Pekka Enberg <penberg@cs.helsinki.fi>
Add a new kernel config option CONFIG_LATE_ROOT_MOUNT that makes the kernel
wait until background scanning of USB mass storage devices is complete before
attempting to mount the root filesystem.
The config option is an alternative to the root_delay= kernel parameter
solution people currently use to boot from USB mass storage devices.
Cc: Daniel Drake <dsd@gentoo.org>
Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Cc: <linux-usb@vger.kernel.org>
Tested-by: Vegard Nossum <vegardno@ifi.uio.no>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
---
drivers/usb/storage/usb.c | 3 +++
include/linux/init.h | 12 ++++++++++++
init/Kconfig | 5 +++++
init/do_mounts.c | 32 ++++++++++++++++++++++++++++++++
4 files changed, 52 insertions(+)
Index: linux-2.6/drivers/usb/storage/usb.c
===================================================================
--- linux-2.6.orig/drivers/usb/storage/usb.c
+++ linux-2.6/drivers/usb/storage/usb.c
@@ -928,6 +928,7 @@ static int usb_stor_scan_thread(void * _
/* Should we unbind if no devices were detected? */
}
+ complete_root_scan();
complete_and_exit(&us->scanning_done, 0);
}
@@ -1007,12 +1008,14 @@ static int storage_probe(struct usb_inte
goto BadDevice;
}
+ begin_root_scan();
/* Start up the thread for delayed SCSI-device scanning */
th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
quiesce_and_remove_host(us);
+ complete_root_scan();
result = PTR_ERR(th);
goto BadDevice;
}
Index: linux-2.6/include/linux/init.h
===================================================================
--- linux-2.6.orig/include/linux/init.h
+++ linux-2.6/include/linux/init.h
@@ -147,6 +147,18 @@ extern unsigned int reset_devices;
void setup_arch(char **);
void prepare_namespace(void);
+#ifdef ...This doesn't take into account what happens when CONFIG_SCSI_SCAN_ASYNC is set. Alan Stern --
Oh, right. Thanks! So something like the following should take care of it.
Pekka
Subject: [RFC/PATCH] usb-storage: wait for device scanning before mounting root V2
From: Pekka Enberg <penberg@cs.helsinki.fi>
Add a new kernel config option CONFIG_LATE_ROOT_MOUNT that makes the kernel
wait until background scanning of USB mass storage devices is complete before
attempting to mount the root filesystem.
The config option is an alternative to the root_delay= kernel parameter
solution people currently use to boot from USB mass storage devices.
Cc: Daniel Drake <dsd@gentoo.org>
Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Cc: <linux-usb@vger.kernel.org>
Cc: James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
Cc: <linux-scsi@vger.kernel.org>
Tested-by: Vegard Nossum <vegardno@ifi.uio.no>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
---
drivers/scsi/scsi_scan.c | 2 ++
drivers/usb/storage/usb.c | 3 +++
include/linux/init.h | 12 ++++++++++++
init/Kconfig | 5 +++++
init/do_mounts.c | 32 ++++++++++++++++++++++++++++++++
5 files changed, 54 insertions(+)
Index: linux-2.6/drivers/usb/storage/usb.c
===================================================================
--- linux-2.6.orig/drivers/usb/storage/usb.c
+++ linux-2.6/drivers/usb/storage/usb.c
@@ -928,6 +928,7 @@ static int usb_stor_scan_thread(void * _
/* Should we unbind if no devices were detected? */
}
+ complete_root_scan();
complete_and_exit(&us->scanning_done, 0);
}
@@ -1007,12 +1008,14 @@ static int storage_probe(struct usb_inte
goto BadDevice;
}
+ begin_root_scan();
/* Start up the thread for delayed SCSI-device scanning */
th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
quiesce_and_remove_host(us);
+ complete_root_scan();
result = PTR_ERR(th);
goto BadDevice;
...What happens if there is no USB device present in the system? Because of that, there is no way that this option could ever be enabled by any distro or anyone wanting their kernel to run on more than one machine :( I don't like it. thanks, greg k-h --
This also has all sorts of races between do_mounts 'waiting' and the actual USB device enumeration. It's entirely possible that the kernel loads via BIOS, the USB drivers are loaded, that forces devices to disconnect/reset, and they take a while to re-enumerate. During that delay, the kernel gets to do_mount; now, no devices show in this "waiting for scan" count. The right way to do this is via initrd and something like devlabel to wait for a specific device to appear. On some systems, you may want to wait for several devices to appear. I don't like this either. Matt --=20 Matthew Dharm Home: mdharm-usb@one-eyed-alien.= net=20 Maintainer, Linux USB Mass Storage Driver What, are you one of those Microsoft-bashing Linux freaks? -- Customer to Greg User Friendly, 2/10/1999
So how does that happen? ->storage_probe fails and driver core calls it later at some point? You should be able to boot from an external USB disk without initrd. That's why we have the current root_delay= hack. Pekka --
There's no guarantee that storage_probe is going to get called in a timely manner. Matt --=20 Matthew Dharm Home: mdharm-usb@one-eyed-alien.= net=20 Maintainer, Linux USB Mass Storage Driver It was a new hope. -- Dust Puppy User Friendly, 12/25/1998
Hi Matthew, How can we add such a guarantee? Don't we have this problem with any other storage devices? Pekka --
I doubt it. It all depends on exactly when the USB controller initializes, all relevant hubs get initialized, and the device finally discovered. Matt --=20 Matthew Dharm Home: mdharm-usb@one-eyed-alien.= net=20 Maintainer, Linux USB Mass Storage Driver I don't have a left mouse button. I only have one mouse and it's on my rig= ht. -- Customer User Friendly, 2/13/1999
No we don't. The problem with USB is that you _never_ know if you are done discovering all of the devices that are currently plugged into the bus. For PCI SCSI and ATA devices, that is not an issue. So no matter how many times you think you can mark things "done" you never really know for sure. So this means that we can't do this in the kernel, use an initramfs if you want such functionality, you can sit and spin there and wait until the device that you think you "know" is there to show up before continuing on with the boot process. thanks, greg k-h --
Not sure what you mean. If there are no USB devices present on the system, the boot proceeds as usual. The config option will make the kernel wait only if you have a USB mass storage device (or some other device that cause async SCSI scanning) _plugged in_. Pekka --
(Adding Cc: Matthew Wilcox) Looks like you want complete_root_scan() after IS_ERR(p). Are there any other thread exit paths which don't call complete_root_scan() yet? Besides, can't you use the generic async scan facility of the SCSI stack for your purpose? If not, can it be extended to make it usable? -- Stefan Richter -=====-==--- -=-- ==--= http://arcgraph.de/sr/ --
Hi Stefan, No, we call complete_root_scan() in do_scan_sync() which is either called asynchronously from the kernel thread or synchronously on IS_ERR(p). So you mean drivers/scsi/scsi_scan.c, right? We probably can and should so I'll take a look. Pekka --
The problem is that USB has one scsi_host per device (rather than, say,
having one scsi_host and adding new devices to it as they're found on
the USB bus).
I'm certainly open to ideas of hooking into the mechanism -- it's just a
list of completions after all. Something like this:
void *scsi_insert_into_scan_list(void)
{
return scsi_prep_async_scan(NULL);
}
void scsi_scan_completed(void *cookie)
{
struct async_scan_data *data = cookie;
wait_for_completion(&data->prev_finished);
spin_lock(&async_scan_lock);
list_del(&data->list);
if (!list_empty(&scanning_hosts)) {
struct async_scan_data *next = list_entry(scanning_hosts.next,
struct async_scan_data, list);
complete(&next->prev_finished);
}
spin_unlock(&async_scan_lock);
kfree(data);
}
Perhaps refactor a little -- everything inside the async_scan_lock would
be common to scsi_scan_completed() and scsi_finish_async_scan().
with appropriate checks for shost being NULL in scsi_prep_async_scan:
+++ b/drivers/scsi/scsi_scan.c
@@ -1698,7 +1698,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct
if (strncmp(scsi_scan_type, "sync", 4) == 0)
return NULL;
- if (shost->async_scan) {
+ if (shost && shost->async_scan) {
printk("%s called twice for host %d", __FUNCTION__,
shost->host_no);
dump_stack();
@@ -1708,16 +1708,19 @@ static struct async_scan_data *scsi_prep_async_scan(stru
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
goto err;
- data->shost = scsi_host_get(shost);
- if (!data->shost)
- goto err;
init_completion(&data->prev_finished);
- mutex_lock(&shost->scan_mutex);
- spin_lock_irqsave(shost->host_lock, flags);
- shost->async_scan = 1;
- spin_unlock_irqrestore(shost->host_lock, flags);
- mutex_unlock(&shost->scan_mutex);
+ if (shost) {
+ ...This discussion seemed to die off ... did anything ever come of it? -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." --
[...] The problem is AFAIU not exactly how many Scsi_Host instances (initiator port representations, or something remotely related to that) are instantiated, but rather _when_ they are instantiated. On multi protocol buses or networks like USB and FireWire, it makes sense to create the SCSI initiator port representation when we discovered that there are actually SCSI targets on the bus or network. scsi_scan's API is geared towards drivers which create one or more initiator port representations right up front before going on target discovery, right? -- Stefan Richter -=====-==--- -==- =--== http://arcgraph.de/sr/ --
-- Stefan Richter -=====-==--- -==- =--== http://arcgraph.de/sr/ --
I'm not convinced of that. Why shouldn't we create one scsi host for all USB scsi devices? I know that today there's a certain amount of Today, yes. The mail that I just pinged described a way to enhance the API -- letting you tell scsi "I've started scanning, save me a place in the queue" and "I've finished scanning, hook me up". The advantage to this is that you can spend a lot more time waiting for devices without increasing boot time significantly, since you wait while the rest of the system initialises. -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." --
Drivers like usb-storage and sbp2 are high-level drivers (protocol drivers) on top of driver stacks. They a priori talk to struct device instances which represent subunits on "external" devices; they don't have much business with the local host controller device. For them, "SCSI initiator port" is a rather hazy and, in the implementation, uninteresting concept. (That's how it is with sbp2; I'm only guessing how it is with usb-storage.) However, there are several ways to accomplish the same thing in the implementation. I heard there were more constraints under Linux 2.4; Or one for each USB HCD. I thought about that for FireWire but never started to actually try it out. Parent-child relationships of struct devices would be different from what we have today. When would be the right time to say "I've started scanning"? SCSI transport driver initialization? Or end of USB/FireWire/... HCD registration? When to say "I've finished scanning"? --- I think the answer is: When (a) probing of a configurable number of SCSI targets or logical units was finished or (b) a configurable timeout occurs, whatever of the two happens first. (Explanation, if one is necessary: SCSI targets may pop out of the woods any time; it is impossible to say "from this moment on there won't show up any new ones anymore". This is just as true for cold boot and warm boot as it is for subsequent operation.) -- Stefan Richter -=====-==--- -==- =--== http://arcgraph.de/sr/ --
You would need to call it before you could attempt to register any Yes, I do see the problem. There's no way the SCSI core can know when a driver has finished scanning, so I've punted to the driver to set its own timeout here. I know that new devices really can show up at any time, but I think it's reasonable to say that if a machine is booted with the same configuration as last time, the drives should show up with the same names. -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." --
This can of course (and frequently is) implemented in userspace, but requires an initrd. I'm not up to speed how scsi_wait_scan is put to I know that is not what you meant here, but...: They do show up with the same target identifiers and logical unit identifiers. The SCSI core doesn't pass the identifiers through to userland though. (Couldn't resist to go off-subject. Sorry.) -- Stefan Richter -=====-==--- -==- =--== http://arcgraph.de/sr/ --
First, there are usb-storage devices which are USB<->SCSI bridges and therefore support multiple target devices. Second, you would still need multiple hosts when you have more than 15 target USB devices, anyway. Matt --=20 Matthew Dharm Home: mdharm-usb@one-eyed-alien.= net=20 Maintainer, Linux USB Mass Storage Driver E: You run this ship with Windows?! YOU IDIOT! L: Give me a break, it came bundled with the computer! -- ESR and Lan Solaris User Friendly, 12/8/1998
This isn't true. Look at topologies like fibre channel which can have thousands of targets on a single host. I would suggest that you want one 'channel' per usb endpoint. -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." --
Let's face it, from the POV of several if not all transport layer drivers, the core API element Scsi_Host is just a superfluous appendage to the only interesting elements -- target and logical unit, or even logical unit alone. No, "channel" is meaningless. Friends don't let friends invent new meanings for "channel". -- Stefan Richter -=====-==--- -==- =--== http://arcgraph.de/sr/ --
As I recall, it died because the whole notion was very poorly defined to begin with. The idea was to stop waiting when all the SCSI buses had been scanned -- but there's no way to know when that occurs because new buses can be added at any time. Maybe a better approach would be to poll at reasonable intervals (HZ/10, for example) for the existence of the root device. If it hasn't appeared after some reasonable time (30 seconds?) then give up. Alan Stern --
Why give up, ever? If someone has to walk across the room to grab the device with the root filesystem, then has to answer the phone, then deal with the next interruption ... for an hour before getting back to the machine they rebooted, why shouldn't it just work to plug in the USB flash drive (CF card, MMC card, or whatever) *THEN* instead of having had to rush and meet some arbitrarily early deadline? When there's no root, I don't see how waiting for it to arrive could be a lose... - Dave --
It would be quite useful to time out and reboot using the previous
kernel ("lilo -R") when one wants to figure out remotely why the new
kernel does not boot.
Gabor
--
---------------------------------------------------------
MTA SZTAKI Computer and Automation Research Institute
Hungarian Academy of Sciences
---------------------------------------------------------
--
And thus we arrive at only one conclusion: You should do this with an initrd so that any policy that is desired can be implemented. No matter what the kernel does by default, it will be incorrect for some scenarios. Matt --=20 Matthew Dharm Home: mdharm-usb@one-eyed-alien.= net=20 Maintainer, Linux USB Mass Storage Driver It was a new hope. -- Dust Puppy User Friendly, 12/25/1998
Hi, Can you please explain why this is? We only want to scan buses that are present when the system is started. If we reach the point where all USB ports/devices/whatever have been enumerated, all SCSI buses scanned, and all partition tables loaded, what more is there to wait for? I can't understand that this is fundamentally a hardware problem. I understand that there might be a problem with the patch that was proposed a the beginning of the thread, but is this really a truly unsolvable problem? Please correct me if I am wrong -- the problem here is that Pekka's newly introduced nr_root_scans can drop to 0 before everything has been enumerated at least once. This is because scsi_scan_host() forks a new thread which is what's actually doing the scanning. Can't we just stick a begin_root_scan() before forking, and drop it inside the thread, just like we do with the usb_stor_scan_thread? If the thread is actually a loop, the first iteration should be enough, right? I'm grateful for any explanations that will help my poor head understand... :-) Vegard -- "The animistic metaphor of the bug that maliciously sneaked in while the programmer was not looking is intellectually dishonest as it disguises that the error is the programmer's own creation." -- E. W. Dijkstra, EWD1036 --
The USB spec doesn't mandate a minimum time before devices come available. There's no way for the device to say "I'm here, I will be providing USB Storage, but I'm not ready yet". So we can't know when we've enumerated all the USB devices on the system. -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." --
New USB devices can appear at any time. None are present when the system is started; they are all detected dynamically by the khubd thread. While I'm not familiar with the details of any other hotpluggable Suppose there are two USB disk drives attached, and the one containing the root fs is probed second. The count could easily drop to 0 when the first drive has been scanned, especially if scanning is done synchronously. What happens when the root fs is on a hotpluggable bus that doesn't use the SCSI infrastructure? You'd have to extend your hooks into that other subsystem as well. Besides, why do you want to go to all this trouble to find out _exactly_ when the device containing the root fs becomes available? What's wrong with just checking at 1/10-second intervals? For example, what happens if the USB device containing the root fs isn't plugged in when the system boots? The user will quickly realize that nothing is happening and will then plug it in. But your code will already have decided that the device doesn't exist and given up. Wouldn't it be better simply to keep on trying, so that then the device does get plugged in the system can use it? Alan Stern --
It's very similar with FireWire. FireWire devices announce SBP-2 target capability (if they have it) after they became ready. The ieee1394 or firewire core then scans or re-scans them in a process context. Then upper layer drivers like the SBP-2 driver are matched, bound, probed. If SBP-2 targets went through a power state change, they typically first power everything up (spin up media etc.) before they announce their protocol capabilities, and this may of course take a while. Before that they just are inaccessible, and it is unknown whether they could become candidates for access by upper layer drivers. -- Stefan Richter -=====-==--- -==- =-=-- http://arcgraph.de/sr/ --
