[PATCH 252/260] usb: gadget: file_storage: fix race on unloading

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Yauheni Kaliuta <yauheni.kaliuta@xxxxxxxxx>

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@xxxxxxxxx>
Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/gadget/file_storage.c |   18 +++++++++---------
 1 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 5779549..3ac4f51 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -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);
-- 
1.7.7

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux