Re: [PATCH v5 06/16] usb: defer suspension of superspeed port while peer is powered

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2014-02-25 at 13:19 -0500, Alan Stern wrote:
> On Mon, 24 Feb 2014, Dan Williams wrote:
> 
> > On Mon, 2014-02-24 at 19:01 -0800, Dan Williams wrote:
> > > As mentioned in the comments on patch 2, while ->peer is being modified
> > > we don't want usb_port_runtime_{suspend|resume} to run.  Introduce
> > > pre_modify_peers() and post_modify_peers() to close that hole.
> > 
> > ...thinking about it further, when we unlink the peers it might be the
> > final put on the device, so {pre|post}_modify_peers() need to take and
> > drop a device reference.
> 
> This is getting ridiculous.
> 
> Look, we guarantee that the peer relation is dropped when either of the 
> devices is unregistered.  Therefore there's no need to take a reference 
> to the peer device.

Ugh, yes.  Reference counts alone don't save us from this scenario:

CPU1                            CPU2
mutex_lock(peer_lock)
unlink_peers(portA, portC)
mutex_unlock(peer_lock)
                                mutex_lock(peer_lock)
device_unregister(portA)
                                link_peers(portB, portA)
                                mutex_unlock(peer_lock)

> This will cause a problem only if something else goes wrong.  That's
> why I suggested, in patch 2, that when a peering error is detected, you
> print out the erroneous pointer rather than assuming it points to a
> valid port structure.

...but even with the invalid port flag portA can theoretically still be
a stale pointer.

> This is also why I suggested that you close the race in 
> usb_hub_remove_port_device: to make sure that the guarantee really is 
> enforced.

You proposed a flag on the port_dev once it goes invalid.  It seems to
me the flag to check if a port is valid is parent_hub->disconnected.
However, in the case above, I believe find_port_by_location() and
find_default_peer() need to prevent the "link_peers(portB, portA)"
event.  When these routines walk down the tree they should be taking
usb_lock_device() to make sure they are not racing with disconnect
operations.

Locking while traversing the list and otherwise checking for
hub->disconnected closes the race.  We can't solve the race at the
port_dev level alone.  Agreed?


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux