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