OSDN Git Service

md: avoid possible spinning md thread at shutdown.
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / md / md.c
index 3fa2fc0..237b7e0 100644 (file)
@@ -7165,11 +7165,14 @@ static int md_seq_open(struct inode *inode, struct file *file)
        return error;
 }
 
+static int md_unloading;
 static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
 {
        struct seq_file *seq = filp->private_data;
        int mask;
 
+       if (md_unloading)
+               return POLLIN|POLLRDNORM|POLLERR|POLLPRI;;
        poll_wait(filp, &md_event_waiters, wait);
 
        /* always allow read */
@@ -8513,7 +8516,8 @@ static int md_notify_reboot(struct notifier_block *this,
                if (mddev_trylock(mddev)) {
                        if (mddev->pers)
                                __md_stop_writes(mddev);
-                       mddev->safemode = 2;
+                       if (mddev->persistent)
+                               mddev->safemode = 2;
                        mddev_unlock(mddev);
                }
                need_delay = 1;
@@ -8655,6 +8659,7 @@ static __exit void md_exit(void)
 {
        struct mddev *mddev;
        struct list_head *tmp;
+       int delay = 1;
 
        blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
        blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS);
@@ -8663,7 +8668,19 @@ static __exit void md_exit(void)
        unregister_blkdev(mdp_major, "mdp");
        unregister_reboot_notifier(&md_notifier);
        unregister_sysctl_table(raid_table_header);
+
+       /* We cannot unload the modules while some process is
+        * waiting for us in select() or poll() - wake them up
+        */
+       md_unloading = 1;
+       while (waitqueue_active(&md_event_waiters)) {
+               /* not safe to leave yet */
+               wake_up(&md_event_waiters);
+               msleep(delay);
+               delay += delay;
+       }
        remove_proc_entry("mdstat", NULL);
+
        for_each_mddev(mddev, tmp) {
                export_array(mddev);
                mddev->hold_active = 0;