usb: gadget: file_storage: fix race on unloading
There is a race, reproduced rarely if you unload the module when host finishes mass storage device initialization (reading partition table and so on): fsg_unbind() code first closes lun files then waits for worker thread to finish its work, as the result the thread may operate on already closed device with an oops and backtrace: [ 484.937225] [<b00e403c>] (touch_atime+0x4/0x140) from [<b00a1498>] (generic_file_aio_read+0x678/0x6f0) [ 484.946563] [<b00a1498>] (generic_file_aio_read+0x678/0x6f0) from [<b00d08c4>] (do_sync_read+0xb0/0xf4) [ 484.955963] [<b00d08c4>] (do_sync_read+0xb0/0xf4) from [<b00d1478>] (vfs_read+0xac/0x144) [ 484.964172] [<b00d1478>] (vfs_read+0xac/0x144) from [<af24c6a8>] (fsg_setup+0x7f4/0x900 [g_file_storage]) [ 484.973785] [<af24c6a8>] (fsg_setup+0x7f4/0x900 [g_file_storage]) from [<af24da14>] (fsg_main_thread+0x85c/0x175c [g_file_storage]) [ 484.985626] [<af24da14>] (fsg_main_thread+0x85c/0x175c [g_file_storage]) from [<b0077c48>] (kthread+0x7c/0x84) [ 484.995666] [<b0077c48>] (kthread+0x7c/0x84) from [<b002f950>] (kernel_thread_exit+0x0/0x8) [ 485.004028] Code: eaffffd0 e28dd008 e8bd8df0 e92d40f7 (e591400c) Change the order in unbind: wait for the thread first, then close the files. Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
1d749f9afa
commit
91960c2ef0
|
@ -3153,6 +3153,15 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
|
|||
DBG(fsg, "unbind\n");
|
||||
clear_bit(REGISTERED, &fsg->atomic_bitflags);
|
||||
|
||||
/* If the thread isn't already dead, tell it to exit now */
|
||||
if (fsg->state != FSG_STATE_TERMINATED) {
|
||||
raise_exception(fsg, FSG_STATE_EXIT);
|
||||
wait_for_completion(&fsg->thread_notifier);
|
||||
|
||||
/* The cleanup routine waits for this completion also */
|
||||
complete(&fsg->thread_notifier);
|
||||
}
|
||||
|
||||
/* Unregister the sysfs attribute files and the LUNs */
|
||||
for (i = 0; i < fsg->nluns; ++i) {
|
||||
curlun = &fsg->luns[i];
|
||||
|
@ -3166,15 +3175,6 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
|
|||
}
|
||||
}
|
||||
|
||||
/* If the thread isn't already dead, tell it to exit now */
|
||||
if (fsg->state != FSG_STATE_TERMINATED) {
|
||||
raise_exception(fsg, FSG_STATE_EXIT);
|
||||
wait_for_completion(&fsg->thread_notifier);
|
||||
|
||||
/* The cleanup routine waits for this completion also */
|
||||
complete(&fsg->thread_notifier);
|
||||
}
|
||||
|
||||
/* Free the data buffers */
|
||||
for (i = 0; i < fsg_num_buffers; ++i)
|
||||
kfree(fsg->buffhds[i].buf);
|
||||
|
|
Loading…
Reference in New Issue