Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net
[cascardo/linux.git] / drivers / md / md.c
index 4ad5cc4..8fda38d 100644 (file)
@@ -5181,32 +5181,6 @@ static int restart_array(struct mddev *mddev)
        return 0;
 }
 
-/* similar to deny_write_access, but accounts for our holding a reference
- * to the file ourselves */
-static int deny_bitmap_write_access(struct file * file)
-{
-       struct inode *inode = file->f_mapping->host;
-
-       spin_lock(&inode->i_lock);
-       if (atomic_read(&inode->i_writecount) > 1) {
-               spin_unlock(&inode->i_lock);
-               return -ETXTBSY;
-       }
-       atomic_set(&inode->i_writecount, -1);
-       spin_unlock(&inode->i_lock);
-
-       return 0;
-}
-
-void restore_bitmap_write_access(struct file *file)
-{
-       struct inode *inode = file->f_mapping->host;
-
-       spin_lock(&inode->i_lock);
-       atomic_set(&inode->i_writecount, 1);
-       spin_unlock(&inode->i_lock);
-}
-
 static void md_clean(struct mddev *mddev)
 {
        mddev->array_sectors = 0;
@@ -5427,7 +5401,6 @@ static int do_md_stop(struct mddev * mddev, int mode,
 
                bitmap_destroy(mddev);
                if (mddev->bitmap_info.file) {
-                       restore_bitmap_write_access(mddev->bitmap_info.file);
                        fput(mddev->bitmap_info.file);
                        mddev->bitmap_info.file = NULL;
                }
@@ -5979,7 +5952,7 @@ abort_export:
 
 static int set_bitmap_file(struct mddev *mddev, int fd)
 {
-       int err;
+       int err = 0;
 
        if (mddev->pers) {
                if (!mddev->pers->quiesce)
@@ -5991,6 +5964,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
 
 
        if (fd >= 0) {
+               struct inode *inode;
                if (mddev->bitmap)
                        return -EEXIST; /* cannot add when bitmap is present */
                mddev->bitmap_info.file = fget(fd);
@@ -6001,10 +5975,21 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
                        return -EBADF;
                }
 
-               err = deny_bitmap_write_access(mddev->bitmap_info.file);
-               if (err) {
+               inode = mddev->bitmap_info.file->f_mapping->host;
+               if (!S_ISREG(inode->i_mode)) {
+                       printk(KERN_ERR "%s: error: bitmap file must be a regular file\n",
+                              mdname(mddev));
+                       err = -EBADF;
+               } else if (!(mddev->bitmap_info.file->f_mode & FMODE_WRITE)) {
+                       printk(KERN_ERR "%s: error: bitmap file must open for write\n",
+                              mdname(mddev));
+                       err = -EBADF;
+               } else if (atomic_read(&inode->i_writecount) != 1) {
                        printk(KERN_ERR "%s: error: bitmap file is already in use\n",
                               mdname(mddev));
+                       err = -EBUSY;
+               }
+               if (err) {
                        fput(mddev->bitmap_info.file);
                        mddev->bitmap_info.file = NULL;
                        return err;
@@ -6027,10 +6012,8 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
                mddev->pers->quiesce(mddev, 0);
        }
        if (fd < 0) {
-               if (mddev->bitmap_info.file) {
-                       restore_bitmap_write_access(mddev->bitmap_info.file);
+               if (mddev->bitmap_info.file)
                        fput(mddev->bitmap_info.file);
-               }
                mddev->bitmap_info.file = NULL;
        }
 
@@ -7182,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 */
@@ -8672,6 +8658,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);
@@ -8680,7 +8667,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;