[PATCH] USB: mass_storage: eject LUNs on thread exit

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

 



Adds a fallback which forces all LUNs ejection (including
non-removable and with prevent_medium_removal flag) when mass storage
function (MSF) worker thread exits and gadget fails to handle the
situation.

Previously, if thread_exits was not specified mass storage function
(MSF) did nothing when exiting thread as it's unclear for *function*
what to do when it's thread terminates so responsibility of handling
this situation was left to the *gadget* using the function.

The g_mass_storage handled the situation by unregistering itself (the
same thing that file storage gadget does).  However, g_multi did
nothing and so MSF did not eject LUNs which prevented file system
unmounting.

Signed-off-by: Michal Nazarewicz <m.nazarewicz@xxxxxxxxxxx>
Reviewed-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
 drivers/usb/gadget/f_mass_storage.c |   26 +++++++++++++++++++++-----
 drivers/usb/gadget/mass_storage.c   |    8 +++++++-
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 84f6491..1a845f1 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -368,7 +368,7 @@ struct fsg_common {
 	struct task_struct	*thread_task;
 
 	/* Callback function to call when thread exits. */
-	void			(*thread_exits)(struct fsg_common *common);
+	int			(*thread_exits)(struct fsg_common *common);
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -392,8 +392,12 @@ struct fsg_config {
 	const char		*lun_name_format;
 	const char		*thread_name;
 
-	/* Callback function to call when thread exits. */
-	void			(*thread_exits)(struct fsg_common *common);
+	/* Callback function to call when thread exits.  If no
+	 * callback is set or it returns value lower then zero MSF
+	 * will force eject all LUNs it operates on (including those
+	 * marked as non-removable or with prevent_medium_removal flag
+	 * set). */
+	int			(*thread_exits)(struct fsg_common *common);
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -2613,8 +2617,20 @@ static int fsg_main_thread(void *common_)
 	common->thread_task = NULL;
 	spin_unlock_irq(&common->lock);
 
-	if (common->thread_exits)
-		common->thread_exits(common);
+	if (!common->thread_exits || common->thread_exits(common) < 0) {
+		struct fsg_lun *curlun = common->luns;
+		unsigned i = common->nluns;
+
+		down_write(&common->filesem);
+		for (; i--; ++curlun) {
+			if (!fsg_lun_is_open(curlun))
+				continue;
+
+			fsg_lun_close(curlun);
+			curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
+		}
+		up_write(&common->filesem);
+	}
 
 	/* Let the unbind and cleanup routines know the thread has exited */
 	complete_and_exit(&common->thread_notifier, 0);
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 19619fb..705cc1f 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -135,6 +135,12 @@ FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
 static unsigned long msg_registered = 0;
 static void msg_cleanup(void);
 
+static int msg_thread_exits(struct fsg_common *common)
+{
+	msg_cleanup();
+	return 0;
+}
+
 static int __init msg_do_config(struct usb_configuration *c)
 {
 	struct fsg_common *common;
@@ -147,7 +153,7 @@ static int __init msg_do_config(struct usb_configuration *c)
 	}
 
 	fsg_config_from_params(&config, &mod_data);
-	config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup;
+	config.thread_exits = msg_thread_exits;
 	common = fsg_common_init(0, c->cdev, &config);
 	if (IS_ERR(common))
 		return PTR_ERR(common);
-- 
1.6.5

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

[Index of Archives]     [Linux Kernel]     [Linux USB Development]     [Yosemite News]     [Linux SCSI]

  Powered by Linux