USB: gadget: file_storage: put_device() in error recovery
authorMichal Nazarewicz <mina86@mina86.com>
Thu, 28 Oct 2010 15:31:18 +0000 (17:31 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 11 Nov 2010 13:58:48 +0000 (05:58 -0800)
This commit fixes some issues with File-backed Storage Gadget
error recovery when registering LUN's devices.

First of all, when device_register() fails the device still
needs to be put.  However, because lun_release() decreases
fsg->ref reference counter the counter must be incremented
beforehand.

Second of all, after any of the device_create_file()s fails,
device_unregister() is called which in turn (indirectly) calls
lun_release() which decrements fsg->ref.  So, again, the
reference counter must be incremented beforehand.

Lastly, if the first or the second device_create_file()
succeeds, the files are never removed.  To fix it,
device_remove_file() needs to be called.  This is done by
simply marking LUN as registered prior to creating files so
that fsg_unbind() can handle removing files.

Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
Reported-by: Rahul Ruikar <rahul.ruikar@gmail.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/file_storage.c

index d4fdf65fb9253fc1c9375d7c7a5885ee27915fe2..a6eacb59571b6075bddbb6388b132135334d0206 100644 (file)
@@ -3392,25 +3392,28 @@ static int __init fsg_bind(struct usb_gadget *gadget)
                dev_set_name(&curlun->dev,"%s-lun%d",
                             dev_name(&gadget->dev), i);
 
-               if ((rc = device_register(&curlun->dev)) != 0) {
+               kref_get(&fsg->ref);
+               rc = device_register(&curlun->dev);
+               if (rc) {
                        INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-                       goto out;
-               }
-               if ((rc = device_create_file(&curlun->dev,
-                                       &dev_attr_ro)) != 0 ||
-                               (rc = device_create_file(&curlun->dev,
-                                       &dev_attr_nofua)) != 0 ||
-                               (rc = device_create_file(&curlun->dev,
-                                       &dev_attr_file)) != 0) {
-                       device_unregister(&curlun->dev);
+                       put_device(&curlun->dev);
                        goto out;
                }
                curlun->registered = 1;
-               kref_get(&fsg->ref);
+
+               rc = device_create_file(&curlun->dev, &dev_attr_ro);
+               if (rc)
+                       goto out;
+               rc = device_create_file(&curlun->dev, &dev_attr_nofua);
+               if (rc)
+                       goto out;
+               rc = device_create_file(&curlun->dev, &dev_attr_file);
+               if (rc)
+                       goto out;
 
                if (mod_data.file[i] && *mod_data.file[i]) {
-                       if ((rc = fsg_lun_open(curlun,
-                                       mod_data.file[i])) != 0)
+                       rc = fsg_lun_open(curlun, mod_data.file[i]);
+                       if (rc)
                                goto out;
                } else if (!mod_data.removable) {
                        ERROR(fsg, "no file given for LUN%d\n", i);