lkml.org 
[lkml]   [2009]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 32/32] USB: usbfs: keep async URBs until the device file is closed
    2.6.27-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Alan Stern <stern@rowland.harvard.edu>

    commit 6ff10464096540e14d7575a72c50d0316d003714 upstream.

    The usbfs driver manages a list of completed asynchronous URBs. But
    it is too eager to free the entries on this list: destroy_async() gets
    called whenever an interface is unbound or a device is removed, and it
    deallocates the outstanding struct async entries for all URBs on that
    interface or device. This is wrong; the user program should be able
    to reap an URB any time after it has completed, regardless of whether
    or not the interface is still bound or the device is still present.

    This patch (as1222) moves the code for deallocating the completed list
    entries from destroy_async() to usbdev_release(). The outstanding
    entries won't be freed until the user program has closed the device
    file, thereby eliminating any possibility that the remaining URBs
    might still be reaped.

    This fixes a bug in which a program can hang in the USBDEVFS_REAPURB
    ioctl when the device is unplugged.

    Reported-and-tested-by: Martin Poupe <martin.poupe@upek.com>
    Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/usb/core/devio.c | 12 +++++++-----
    1 file changed, 7 insertions(+), 5 deletions(-)

    --- a/drivers/usb/core/devio.c
    +++ b/drivers/usb/core/devio.c
    @@ -359,11 +359,6 @@ static void destroy_async(struct dev_sta
    spin_lock_irqsave(&ps->lock, flags);
    }
    spin_unlock_irqrestore(&ps->lock, flags);
    - as = async_getcompleted(ps);
    - while (as) {
    - free_async(as);
    - as = async_getcompleted(ps);
    - }
    }

    static void destroy_async_on_interface(struct dev_state *ps,
    @@ -639,6 +634,7 @@ static int usbdev_release(struct inode *
    struct dev_state *ps = file->private_data;
    struct usb_device *dev = ps->dev;
    unsigned int ifnum;
    + struct async *as;

    usb_lock_device(dev);

    @@ -657,6 +653,12 @@ static int usbdev_release(struct inode *
    usb_unlock_device(dev);
    usb_put_dev(dev);
    put_pid(ps->disc_pid);
    +
    + as = async_getcompleted(ps);
    + while (as) {
    + free_async(as);
    + as = async_getcompleted(ps);
    + }
    kfree(ps);
    return 0;
    }



    \
     
     \ /
      Last update: 2009-03-21 00:27    [W:0.021 / U:2.968 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site