On Mon, 12 Apr 2004, David Brownell wrote:
> >>Hmm, could you elaborate? The bus rwsem is only to protect
>
> Capsule summary: you're assuming a "topology change lock".
Isn't that one of the major functions of the bus rwsem?
> OK, you're strictly correct from the driver model perspective,
> but that doesn't contradict what I said either.
Sure it does -- you said the rwsem protects _only_ against changes in
binding. :-)
> The bus rwsem
> is grabbed when devices or drivers are created, which is also
> the time driver bindings are changed (which is why we care),
> but there are several kinds of entity:
>
> - USB Interfaces. Created only by holders of dev->serialize.
> - USB Devices. Created by khubd.
> - USB Hubs. Special devices, managed by usbcore/khubd.
> - USB Drivers. Created by module's init code.
>
> So what I said is true: dev->serialize protects against add/remove
> of the devices that drivers care about ("interfaces"), and anyone
> caring about a stable set of interface-to-driver bindings must hold
> the bus readlock instead. That's the lock hierarchy of today.
>
> The current code is logically "for each device, dump its descriptors
> and their bindings" ... so I described per-device locking.
That's the natural approach. I question whether it provides adequate
protection of the "for each device" part.
> It's a question of lock scope. Grabbing the bus rwsem locks every
> USB device in the whole system. I described a less global scheme.
>
> One example of where a global scheme would have issues: when fetching
> the string descriptors takes a long time. Then "cat devices" could
> block most of the USB subsystem, not just the one device which was
> actually misbehaving.
Certainly we want to avoid doing that.
> > It's not entirely clear (to me anyway) that holding ->serialize will
> > provide sufficient protection against disconnection. That is, when a
> > device is disconnected, the core doesn't acquire the parent hub's
>
> At any given instant, the usbcore data records for a given device
> will be consistent if dev->serialize is used to lock it. Plus of
> course it must have been consistent when "dev" was located -- yes?
> Doesn't matter if it was disconnected later; it was OK to start.
> (And next time, it won't be there.)
I agree with that.
> > ->serialize. So when traversing the device tree below that hub we run the
> > risk of trying to access a nonexistent device structure. It seems that
> > the _only_ way to protect against these changes in the bus topology is by
> > using the bus rwsem.
>
> I'm not sure why you'd want to protect against topology changes.
> That's global state, so of course my "synchronize locally" reflex
> kicks right in ... creating central synch points, to be held
> during I/O and state changes, can cause trouble. Why care if a
> device you already printed (or haven't yet printed) is unplugged?
>
> If you didn't have such a "global synch" model, what problems would
> arise? I don't think the current code is guaranteed to provide
> a globally consistent snapshot of the device tree.
Here's a problem that can arise. The usb_device_dump() function in
devices.c contains this code:
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
if (usbdev->children[chix]) {
ret = usb_device_dump(buffer, nbytes, skip_bytes,
file_offset, usbdev->children[chix],
bus, level + 1, chix, ++cnt);
What happens if the child on port chix is disconnected between the time of
the test and the time of the recursive function call? I don't care if we
don't give a globally consistent snapshot, but causing an oops isn't
acceptable.
> > Then of course we end up running into problems about trying to acquire the
> > two locks in the correct order...
>
> Given that the physical hierarchy is (root) hub down, the logical
> one for such a case should do the same thing ... I'd say, going
> just by rules of thumb! One could hold hub->dev->serialize while
> scanning its children.
In addition the code that removes children (usb_disconnect) must be
changed to hold the parent hub's ->serialize. It wouldn't hurt to do that
while adding children as well, although it's not necessary.
Like I said originally, the locking here needs to be fixed. I wasn't sure
what was the best way to do it; looks like you've identified the necessary
changes.
Alan Stern
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel