Re: [RFC/PATCH] usb-storage: wait for device scanning before mounting root

Previous thread: Regression: starting X locks box with git master by James Cloos on Thursday, April 24, 2008 - 12:59 pm. (12 messages)

Next thread: no help text for DVB_TUNER_ITD1000 by Adrian Bunk on Thursday, April 24, 2008 - 1:22 pm. (7 messages)
From: Pekka J Enberg
Date: Thursday, April 24, 2008 - 1:21 pm

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 ...
From: Alan Stern
Date: Thursday, April 24, 2008 - 2:08 pm

This doesn't take into account what happens when CONFIG_SCSI_SCAN_ASYNC
is set.

Alan Stern


--

From: Pekka J Enberg
Date: Thursday, April 24, 2008 - 2:25 pm

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;
 ...
From: Greg KH
Date: Thursday, April 24, 2008 - 3:56 pm

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
--

From: Matthew Dharm
Date: Thursday, April 24, 2008 - 4:30 pm

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
From: Pekka J Enberg
Date: Thursday, April 24, 2008 - 11:30 pm

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
--

From: Matthew Dharm
Date: Friday, April 25, 2008 - 12:04 am

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
From: Pekka J Enberg
Date: Friday, April 25, 2008 - 1:19 am

Hi Matthew,




How can we add such a guarantee? Don't we have this problem with any other 
storage devices?

			Pekka
--

From: Matthew Dharm
Date: Friday, April 25, 2008 - 8:35 am

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
From: Greg KH
Date: Friday, April 25, 2008 - 9:05 am

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
--

From: Pekka J Enberg
Date: Thursday, April 24, 2008 - 11:09 pm

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
--

From: Stefan Richter
Date: Friday, April 25, 2008 - 12:53 am

(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/
--

From: Pekka J Enberg
Date: Friday, April 25, 2008 - 1:15 am

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
--

From: Matthew Wilcox
Date: Friday, April 25, 2008 - 2:11 am

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) {
+               ...
From: Matthew Wilcox
Date: Thursday, June 19, 2008 - 11:23 am

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."
--

From: Stefan Richter
Date: Thursday, June 19, 2008 - 11:39 am

[...]

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/
--

From: Stefan Richter
Date: Thursday, June 19, 2008 - 11:43 am

-- 
Stefan Richter
-=====-==--- -==- =--==
http://arcgraph.de/sr/
--

From: Matthew Wilcox
Date: Thursday, June 19, 2008 - 11:54 am

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."
--

From: Stefan Richter
Date: Thursday, June 19, 2008 - 12:54 pm

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/
--

From: Matthew Wilcox
Date: Thursday, June 19, 2008 - 1:22 pm

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."
--

From: Stefan Richter
Date: Thursday, June 19, 2008 - 1:34 pm

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/
--

From: Matthew Dharm
Date: Thursday, June 19, 2008 - 12:52 pm

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
From: Matthew Wilcox
Date: Thursday, June 19, 2008 - 1:49 pm

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."
--

From: Stefan Richter
Date: Thursday, June 19, 2008 - 2:19 pm

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/
--

From: Alan Stern
Date: Thursday, June 19, 2008 - 2:39 pm

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

--

From: David Brownell
Date: Thursday, June 19, 2008 - 4:13 pm

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

--

From: Gabor Gombas
Date: Friday, June 20, 2008 - 2:53 am

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
     ---------------------------------------------------------
--

From: Matthew Dharm
Date: Friday, June 20, 2008 - 7:14 am

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
From: Vegard Nossum
Date: Friday, June 20, 2008 - 8:15 am

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
--

From: Matthew Wilcox
Date: Friday, June 20, 2008 - 8:31 am

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."
--

From: Alan Stern
Date: Friday, June 20, 2008 - 8:42 am

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

--

From: Stefan Richter
Date: Friday, June 20, 2008 - 9:37 am

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/
--

Previous thread: Regression: starting X locks box with git master by James Cloos on Thursday, April 24, 2008 - 12:59 pm. (12 messages)

Next thread: no help text for DVB_TUNER_ITD1000 by Adrian Bunk on Thursday, April 24, 2008 - 1:22 pm. (7 messages)