diff options
author | NeilBrown <neilb@suse.de> | 2008-07-21 03:05:25 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2008-07-21 03:05:25 -0400 |
commit | f2ea68cf42aafdd93393b6b8b20fc3c2b5f4390c (patch) | |
tree | 00b025b91898ff32dba742b5075dd290fec4dc91 /drivers/md | |
parent | d6e2215052810678bc9782fd980b52706fc71f50 (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>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/md.c | 9 |
1 files changed, 6 insertions, 3 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; |