md: only count actual openers as access which prevent a 'stop'
authorNeilBrown <neilb@suse.de>
Mon, 21 Jul 2008 07:05:25 +0000 (17:05 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 21 Jul 2008 07:05:25 +0000 (17:05 +1000)
Open isn't the only thing that increments ->active.  e.g. reading
/proc/mdstat will increment it briefly.  So to avoid false positives
in testing for concurrent access, introduce a new counter that counts
just the number of times the md device it open.

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

index 4bfbc1982cda977ff28ee312fe0a84372b0a833d..450f30b6edf94db4de30ec19d2d8ba59dcf977be 100644 (file)
@@ -273,6 +273,7 @@ static mddev_t * mddev_find(dev_t unit)
        INIT_LIST_HEAD(&new->all_mddevs);
        init_timer(&new->safemode_timer);
        atomic_set(&new->active, 1);
+       atomic_set(&new->openers, 0);
        spin_lock_init(&new->write_lock);
        init_waitqueue_head(&new->sb_wait);
        init_waitqueue_head(&new->recovery_wait);
@@ -2695,14 +2696,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                break;
        case clear:
                /* stopping an active array */
-               if (atomic_read(&mddev->active) > 1)
+               if (atomic_read(&mddev->openers) > 0)
                        return -EBUSY;
                err = do_md_stop(mddev, 0, 0);
                break;
        case inactive:
                /* stopping an active array */
                if (mddev->pers) {
-                       if (atomic_read(&mddev->active) > 1)
+                       if (atomic_read(&mddev->openers) > 0)
                                return -EBUSY;
                        err = do_md_stop(mddev, 2, 0);
                } else
@@ -3816,7 +3817,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
        int err = 0;
        struct gendisk *disk = mddev->gendisk;
 
-       if (atomic_read(&mddev->active) > 1 + is_open) {
+       if (atomic_read(&mddev->openers) > is_open) {
                printk("md: %s still in use.\n",mdname(mddev));
                return -EBUSY;
        }
@@ -5014,6 +5015,7 @@ static int md_open(struct inode *inode, struct file *file)
 
        err = 0;
        mddev_get(mddev);
+       atomic_inc(&mddev->openers);
        mddev_unlock(mddev);
 
        check_disk_change(inode->i_bdev);
@@ -5026,6 +5028,7 @@ static int md_release(struct inode *inode, struct file * file)
        mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
 
        BUG_ON(!mddev);
+       atomic_dec(&mddev->openers);
        mddev_put(mddev);
 
        return 0;
index 6f72b47ae41c0aa29c163647f2bbc54b1ba85120..4bef4791d80df3db59053b2ba5a3aa21ca8d130e 100644 (file)
@@ -215,7 +215,8 @@ struct mddev_s
 
        int                             in_sync;        /* know to not need resync */
        struct mutex                    reconfig_mutex;
-       atomic_t                        active;
+       atomic_t                        active;         /* general refcount */
+       atomic_t                        openers;        /* number of active opens */
 
        int                             changed;        /* true if we might need to reread partition info */
        int                             degraded;       /* whether md should consider