diff options
author | Michal Nazarewicz <mina86@mina86.com> | 2010-10-28 11:31:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-11 08:58:48 -0500 |
commit | d9385b6352da7fed50981f375c2ccb60354039a6 (patch) | |
tree | 2b9c8dc9fcb6b6452634c853712bba71993ac797 /drivers/usb/gadget/file_storage.c | |
parent | 78bff3c65df33da47e93736bd8847b694084e5a9 (diff) |
USB: gadget: file_storage: put_device() in error recovery
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>
Diffstat (limited to 'drivers/usb/gadget/file_storage.c')
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index d4fdf65fb925..a6eacb59571b 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -3392,25 +3392,28 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3392 | dev_set_name(&curlun->dev,"%s-lun%d", | 3392 | dev_set_name(&curlun->dev,"%s-lun%d", |
3393 | dev_name(&gadget->dev), i); | 3393 | dev_name(&gadget->dev), i); |
3394 | 3394 | ||
3395 | if ((rc = device_register(&curlun->dev)) != 0) { | 3395 | kref_get(&fsg->ref); |
3396 | rc = device_register(&curlun->dev); | ||
3397 | if (rc) { | ||
3396 | INFO(fsg, "failed to register LUN%d: %d\n", i, rc); | 3398 | INFO(fsg, "failed to register LUN%d: %d\n", i, rc); |
3397 | goto out; | 3399 | put_device(&curlun->dev); |
3398 | } | ||
3399 | if ((rc = device_create_file(&curlun->dev, | ||
3400 | &dev_attr_ro)) != 0 || | ||
3401 | (rc = device_create_file(&curlun->dev, | ||
3402 | &dev_attr_nofua)) != 0 || | ||
3403 | (rc = device_create_file(&curlun->dev, | ||
3404 | &dev_attr_file)) != 0) { | ||
3405 | device_unregister(&curlun->dev); | ||
3406 | goto out; | 3400 | goto out; |
3407 | } | 3401 | } |
3408 | curlun->registered = 1; | 3402 | curlun->registered = 1; |
3409 | kref_get(&fsg->ref); | 3403 | |
3404 | rc = device_create_file(&curlun->dev, &dev_attr_ro); | ||
3405 | if (rc) | ||
3406 | goto out; | ||
3407 | rc = device_create_file(&curlun->dev, &dev_attr_nofua); | ||
3408 | if (rc) | ||
3409 | goto out; | ||
3410 | rc = device_create_file(&curlun->dev, &dev_attr_file); | ||
3411 | if (rc) | ||
3412 | goto out; | ||
3410 | 3413 | ||
3411 | if (mod_data.file[i] && *mod_data.file[i]) { | 3414 | if (mod_data.file[i] && *mod_data.file[i]) { |
3412 | if ((rc = fsg_lun_open(curlun, | 3415 | rc = fsg_lun_open(curlun, mod_data.file[i]); |
3413 | mod_data.file[i])) != 0) | 3416 | if (rc) |
3414 | goto out; | 3417 | goto out; |
3415 | } else if (!mod_data.removable) { | 3418 | } else if (!mod_data.removable) { |
3416 | ERROR(fsg, "no file given for LUN%d\n", i); | 3419 | ERROR(fsg, "no file given for LUN%d\n", i); |