aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-07-21 03:05:25 -0400
committerNeilBrown <neilb@suse.de>2008-07-21 03:05:25 -0400
commitf2ea68cf42aafdd93393b6b8b20fc3c2b5f4390c (patch)
tree00b025b91898ff32dba742b5075dd290fec4dc91
parentd6e2215052810678bc9782fd980b52706fc71f50 (diff)
md: only count actual openers as access which prevent a 'stop'
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>
-rw-r--r--drivers/md/md.c9
-rw-r--r--include/linux/raid/md_k.h3
2 files changed, 8 insertions, 4 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 4bfbc1982cda..450f30b6edf9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -273,6 +273,7 @@ static mddev_t * mddev_find(dev_t unit)
273 INIT_LIST_HEAD(&new->all_mddevs); 273 INIT_LIST_HEAD(&new->all_mddevs);
274 init_timer(&new->safemode_timer); 274 init_timer(&new->safemode_timer);
275 atomic_set(&new->active, 1); 275 atomic_set(&new->active, 1);
276 atomic_set(&new->openers, 0);
276 spin_lock_init(&new->write_lock); 277 spin_lock_init(&new->write_lock);
277 init_waitqueue_head(&new->sb_wait); 278 init_waitqueue_head(&new->sb_wait);
278 init_waitqueue_head(&new->recovery_wait); 279 init_waitqueue_head(&new->recovery_wait);
@@ -2695,14 +2696,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
2695 break; 2696 break;
2696 case clear: 2697 case clear:
2697 /* stopping an active array */ 2698 /* stopping an active array */
2698 if (atomic_read(&mddev->active) > 1) 2699 if (atomic_read(&mddev->openers) > 0)
2699 return -EBUSY; 2700 return -EBUSY;
2700 err = do_md_stop(mddev, 0, 0); 2701 err = do_md_stop(mddev, 0, 0);
2701 break; 2702 break;
2702 case inactive: 2703 case inactive:
2703 /* stopping an active array */ 2704 /* stopping an active array */
2704 if (mddev->pers) { 2705 if (mddev->pers) {
2705 if (atomic_read(&mddev->active) > 1) 2706 if (atomic_read(&mddev->openers) > 0)
2706 return -EBUSY; 2707 return -EBUSY;
2707 err = do_md_stop(mddev, 2, 0); 2708 err = do_md_stop(mddev, 2, 0);
2708 } else 2709 } else
@@ -3816,7 +3817,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
3816 int err = 0; 3817 int err = 0;
3817 struct gendisk *disk = mddev->gendisk; 3818 struct gendisk *disk = mddev->gendisk;
3818 3819
3819 if (atomic_read(&mddev->active) > 1 + is_open) { 3820 if (atomic_read(&mddev->openers) > is_open) {
3820 printk("md: %s still in use.\n",mdname(mddev)); 3821 printk("md: %s still in use.\n",mdname(mddev));
3821 return -EBUSY; 3822 return -EBUSY;
3822 } 3823 }
@@ -5014,6 +5015,7 @@ static int md_open(struct inode *inode, struct file *file)
5014 5015
5015 err = 0; 5016 err = 0;
5016 mddev_get(mddev); 5017 mddev_get(mddev);
5018 atomic_inc(&mddev->openers);
5017 mddev_unlock(mddev); 5019 mddev_unlock(mddev);
5018 5020
5019 check_disk_change(inode->i_bdev); 5021 check_disk_change(inode->i_bdev);
@@ -5026,6 +5028,7 @@ static int md_release(struct inode *inode, struct file * file)
5026 mddev_t *mddev = inode->i_bdev->bd_disk->private_data; 5028 mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
5027 5029
5028 BUG_ON(!mddev); 5030 BUG_ON(!mddev);
5031 atomic_dec(&mddev->openers);
5029 mddev_put(mddev); 5032 mddev_put(mddev);
5030 5033
5031 return 0; 5034 return 0;
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 6f72b47ae41c..4bef4791d80d 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -215,7 +215,8 @@ struct mddev_s
215 215
216 int in_sync; /* know to not need resync */ 216 int in_sync; /* know to not need resync */
217 struct mutex reconfig_mutex; 217 struct mutex reconfig_mutex;
218 atomic_t active; 218 atomic_t active; /* general refcount */
219 atomic_t openers; /* number of active opens */
219 220
220 int changed; /* true if we might need to reread partition info */ 221 int changed; /* true if we might need to reread partition info */
221 int degraded; /* whether md should consider 222 int degraded; /* whether md should consider