md: move GET_BITMAP_FILE ioctl out from mddev_lock.
authorNeilBrown <neilb@suse.de>
Mon, 15 Dec 2014 01:57:00 +0000 (12:57 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 5 Feb 2015 22:32:56 +0000 (09:32 +1100)
It makes more sense to report bitmap_info->file, rather than
bitmap->file (the later is only available once the array is
active).

With that change, use mddev->lock to protect bitmap_info being
set to NULL, and we can call get_bitmap_file() without taking
the mutex.

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/md.c
drivers/md/md.h

index 72c44d337ee20dda3c3a41351ecbf23a8804e7dd..5a949166dac0a5facf38225543ecdcc02312ca58 100644 (file)
@@ -5292,8 +5292,11 @@ static int do_md_stop(struct mddev *mddev, int mode,
 
                bitmap_destroy(mddev);
                if (mddev->bitmap_info.file) {
-                       fput(mddev->bitmap_info.file);
+                       struct file *f = mddev->bitmap_info.file;
+                       spin_lock(&mddev->lock);
                        mddev->bitmap_info.file = NULL;
+                       spin_unlock(&mddev->lock);
+                       fput(f);
                }
                mddev->bitmap_info.offset = 0;
 
@@ -5503,32 +5506,30 @@ static int get_bitmap_file(struct mddev *mddev, void __user * arg)
 {
        mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
        char *ptr;
-       int err = -ENOMEM;
+       int err;
 
        file = kmalloc(sizeof(*file), GFP_NOIO);
-
        if (!file)
-               goto out;
+               return -ENOMEM;
 
+       err = 0;
+       spin_lock(&mddev->lock);
        /* bitmap disabled, zero the first byte and copy out */
-       if (!mddev->bitmap || !mddev->bitmap->storage.file) {
+       if (!mddev->bitmap_info.file)
                file->pathname[0] = '\0';
-               goto copy_out;
-       }
-
-       ptr = d_path(&mddev->bitmap->storage.file->f_path,
-                    file->pathname, sizeof(file->pathname));
-       if (IS_ERR(ptr))
-               goto out;
-
-       memmove(file->pathname, ptr,
-               sizeof(file->pathname)-(ptr-file->pathname));
+       else if ((ptr = d_path(&mddev->bitmap_info.file->f_path,
+                              file->pathname, sizeof(file->pathname))),
+                IS_ERR(ptr))
+               err = PTR_ERR(ptr);
+       else
+               memmove(file->pathname, ptr,
+                       sizeof(file->pathname)-(ptr-file->pathname));
+       spin_unlock(&mddev->lock);
 
-copy_out:
-       err = 0;
-       if (copy_to_user(arg, file, sizeof(*file)))
+       if (err == 0 &&
+           copy_to_user(arg, file, sizeof(*file)))
                err = -EFAULT;
-out:
+
        kfree(file);
        return err;
 }
@@ -5900,9 +5901,13 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
                mddev->pers->quiesce(mddev, 0);
        }
        if (fd < 0) {
-               if (mddev->bitmap_info.file)
-                       fput(mddev->bitmap_info.file);
-               mddev->bitmap_info.file = NULL;
+               struct file *f = mddev->bitmap_info.file;
+               if (f) {
+                       spin_lock(&mddev->lock);
+                       mddev->bitmap_info.file = NULL;
+                       spin_unlock(&mddev->lock);
+                       fput(f);
+               }
        }
 
        return err;
@@ -6315,6 +6320,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
        case SET_DISK_FAULTY:
                err = set_disk_faulty(mddev, new_decode_dev(arg));
                goto out;
+
+       case GET_BITMAP_FILE:
+               err = get_bitmap_file(mddev, argp);
+               goto out;
+
        }
 
        if (cmd == ADD_NEW_DISK)
@@ -6406,10 +6416,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
         * Commands even a read-only array can execute:
         */
        switch (cmd) {
-       case GET_BITMAP_FILE:
-               err = get_bitmap_file(mddev, argp);
-               goto unlock;
-
        case RESTART_ARRAY_RW:
                err = restart_array(mddev);
                goto unlock;
index 8770308a8052c4bcbae08adb89954372a4409864..b4fbd6a63fcf0e7de7658d784afe436a428a91c6 100644 (file)
@@ -393,6 +393,7 @@ struct mddev {
         *   in_sync - and related safemode and MD_CHANGE changes
         *   pers (also protected by reconfig_mutex and pending IO).
         *   clearing ->bitmap
+        *   clearing ->bitmap_info.file
         */
        spinlock_t                      lock;
        wait_queue_head_t               sb_wait;        /* for waiting on superblock updates */