diff options
author | Michal Nazarewicz <mina86@mina86.com> | 2010-10-28 17:31:18 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-11 05:58:48 -0800 |
commit | d9385b6352da7fed50981f375c2ccb60354039a6 (patch) | |
tree | 2b9c8dc9fcb6b6452634c853712bba71993ac797 /drivers/usb/gadget/file_storage.c | |
parent | 78bff3c65df33da47e93736bd8847b694084e5a9 (diff) | |
download | op-kernel-dev-d9385b6352da7fed50981f375c2ccb60354039a6.zip op-kernel-dev-d9385b6352da7fed50981f375c2ccb60354039a6.tar.gz |
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 d4fdf65..a6eacb5 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) 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); |