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>
This commit is contained in:
Michal Nazarewicz 2010-10-28 17:31:18 +02:00 committed by Greg Kroah-Hartman
parent 78bff3c65d
commit d9385b6352

View 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);