Commit f2ea68cf authored by NeilBrown's avatar NeilBrown

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: default avatarNeilBrown <neilb@suse.de>
parent d6e22150
...@@ -273,6 +273,7 @@ static mddev_t * mddev_find(dev_t unit) ...@@ -273,6 +273,7 @@ static mddev_t * mddev_find(dev_t unit)
INIT_LIST_HEAD(&new->all_mddevs); INIT_LIST_HEAD(&new->all_mddevs);
init_timer(&new->safemode_timer); init_timer(&new->safemode_timer);
atomic_set(&new->active, 1); atomic_set(&new->active, 1);
atomic_set(&new->openers, 0);
spin_lock_init(&new->write_lock); spin_lock_init(&new->write_lock);
init_waitqueue_head(&new->sb_wait); init_waitqueue_head(&new->sb_wait);
init_waitqueue_head(&new->recovery_wait); init_waitqueue_head(&new->recovery_wait);
...@@ -2695,14 +2696,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -2695,14 +2696,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
break; break;
case clear: case clear:
/* stopping an active array */ /* stopping an active array */
if (atomic_read(&mddev->active) > 1) if (atomic_read(&mddev->openers) > 0)
return -EBUSY; return -EBUSY;
err = do_md_stop(mddev, 0, 0); err = do_md_stop(mddev, 0, 0);
break; break;
case inactive: case inactive:
/* stopping an active array */ /* stopping an active array */
if (mddev->pers) { if (mddev->pers) {
if (atomic_read(&mddev->active) > 1) if (atomic_read(&mddev->openers) > 0)
return -EBUSY; return -EBUSY;
err = do_md_stop(mddev, 2, 0); err = do_md_stop(mddev, 2, 0);
} else } else
...@@ -3816,7 +3817,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) ...@@ -3816,7 +3817,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
int err = 0; int err = 0;
struct gendisk *disk = mddev->gendisk; 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)); printk("md: %s still in use.\n",mdname(mddev));
return -EBUSY; return -EBUSY;
} }
...@@ -5014,6 +5015,7 @@ static int md_open(struct inode *inode, struct file *file) ...@@ -5014,6 +5015,7 @@ static int md_open(struct inode *inode, struct file *file)
err = 0; err = 0;
mddev_get(mddev); mddev_get(mddev);
atomic_inc(&mddev->openers);
mddev_unlock(mddev); mddev_unlock(mddev);
check_disk_change(inode->i_bdev); check_disk_change(inode->i_bdev);
...@@ -5026,6 +5028,7 @@ static int md_release(struct inode *inode, struct file * file) ...@@ -5026,6 +5028,7 @@ static int md_release(struct inode *inode, struct file * file)
mddev_t *mddev = inode->i_bdev->bd_disk->private_data; mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
BUG_ON(!mddev); BUG_ON(!mddev);
atomic_dec(&mddev->openers);
mddev_put(mddev); mddev_put(mddev);
return 0; return 0;
......
...@@ -215,7 +215,8 @@ struct mddev_s ...@@ -215,7 +215,8 @@ struct mddev_s
int in_sync; /* know to not need resync */ int in_sync; /* know to not need resync */
struct mutex reconfig_mutex; 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 changed; /* true if we might need to reread partition info */
int degraded; /* whether md should consider int degraded; /* whether md should consider
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment