This is a note to let you know that I've just added the patch titled

     Subject: USB: file-storage gadget: Add reference count for children

to my gregkh-2.6 tree.  Its filename is

     usb-file-storage-gadget-add-reference-count-for-children.patch

This tree can be found at 
    http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/

Patches currently in gregkh-2.6 which might be from [EMAIL PROTECTED] are

usb/ehci-fix-conflation-of-buf-0-with-len-0.patch
usb/usb-libusual.patch
usb/usb-remove-usb_audio-and-usb_midi-drivers.patch
usb/usb-file-storage-gadget-add-reference-count-for-children.patch
usb/usb-makefile-change-for-libusual.patch


>From [EMAIL PROTECTED] Wed Nov  9 14:03:45 2005
Date: Wed, 9 Nov 2005 16:59:56 -0500 (EST)
From: Alan Stern <[EMAIL PROTECTED]>
To: Greg KH <[EMAIL PROTECTED]>
cc: USB development list <[email protected]>
Subject: USB: file-storage gadget: Add reference count for children
Message-ID: <[EMAIL PROTECTED]>

This patch (as601) adds a proper reference count to the file-storage
gadget's main data structure, to keep track of references held by child
devices (LUNs in this case).  Before this, the driver would wait for
each child to be released before unbinding.

While there's nothing really wrong with that (you can't create a hang by
doing "rmmod g_file_storage </sys/.../lun0/ro" since the open file will
prevent rmmod from running), the code might as well follow the standard
procedures.  Besides, this shrinks the size of the structure by a few
words...  :-)

Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
 drivers/usb/gadget/file_storage.c |   30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

--- gregkh-2.6.orig/drivers/usb/gadget/file_storage.c
+++ gregkh-2.6/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kref.h>
 #include <linux/kthread.h>
 #include <linux/limits.h>
 #include <linux/list.h>
@@ -631,6 +632,9 @@ struct fsg_dev {
        /* filesem protects: backing files in use */
        struct rw_semaphore     filesem;
 
+       /* reference counting: wait until all LUNs are released */
+       struct kref             ref;
+
        struct usb_ep           *ep0;           // Handy copy of gadget->ep0
        struct usb_request      *ep0req;        // For control responses
        volatile unsigned int   ep0_req_tag;
@@ -694,7 +698,6 @@ struct fsg_dev {
        unsigned int            nluns;
        struct lun              *luns;
        struct lun              *curlun;
-       struct completion       lun_released;
 };
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -3642,11 +3645,19 @@ static DEVICE_ATTR(file, 0444, show_file
 
 /*-------------------------------------------------------------------------*/
 
+static void fsg_release(struct kref *ref)
+{
+       struct fsg_dev  *fsg = container_of(ref, struct fsg_dev, ref);
+
+       kfree(fsg->luns);
+       kfree(fsg);
+}
+
 static void lun_release(struct device *dev)
 {
        struct fsg_dev  *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
 
-       complete(&fsg->lun_released);
+       kref_put(&fsg->ref, fsg_release);
 }
 
 static void fsg_unbind(struct usb_gadget *gadget)
@@ -3660,14 +3671,12 @@ static void fsg_unbind(struct usb_gadget
        clear_bit(REGISTERED, &fsg->atomic_bitflags);
 
        /* Unregister the sysfs attribute files and the LUNs */
-       init_completion(&fsg->lun_released);
        for (i = 0; i < fsg->nluns; ++i) {
                curlun = &fsg->luns[i];
                if (curlun->registered) {
                        device_remove_file(&curlun->dev, &dev_attr_ro);
                        device_remove_file(&curlun->dev, &dev_attr_file);
                        device_unregister(&curlun->dev);
-                       wait_for_completion(&fsg->lun_released);
                        curlun->registered = 0;
                }
        }
@@ -3846,6 +3855,7 @@ static int __init fsg_bind(struct usb_ga
                        curlun->dev.release = lun_release;
                        device_create_file(&curlun->dev, &dev_attr_ro);
                        device_create_file(&curlun->dev, &dev_attr_file);
+                       kref_get(&fsg->ref);
                }
 
                if (file[i] && *file[i]) {
@@ -4061,6 +4071,7 @@ static int __init fsg_alloc(void)
                return -ENOMEM;
        spin_lock_init(&fsg->lock);
        init_rwsem(&fsg->filesem);
+       kref_init(&fsg->ref);
        init_waitqueue_head(&fsg->thread_wqh);
        init_completion(&fsg->thread_notifier);
 
@@ -4069,13 +4080,6 @@ static int __init fsg_alloc(void)
 }
 
 
-static void fsg_free(struct fsg_dev *fsg)
-{
-       kfree(fsg->luns);
-       kfree(fsg);
-}
-
-
 static int __init fsg_init(void)
 {
        int             rc;
@@ -4085,7 +4089,7 @@ static int __init fsg_init(void)
                return rc;
        fsg = the_fsg;
        if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
-               fsg_free(fsg);
+               kref_put(&fsg->ref, fsg_release);
        return rc;
 }
 module_init(fsg_init);
@@ -4103,6 +4107,6 @@ static void __exit fsg_cleanup(void)
        wait_for_completion(&fsg->thread_notifier);
 
        close_all_backing_files(fsg);
-       fsg_free(fsg);
+       kref_put(&fsg->ref, fsg_release);
 }
 module_exit(fsg_cleanup);


-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to