Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2ea68cf authored by NeilBrown's avatar NeilBrown
Browse files

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
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -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)
		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)
	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)


	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)
 	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;
+2 −1
Original line number Original line Diff line number Diff line
@@ -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