Commit f97a5528 authored by Ye Bin's avatar Ye Bin Committed by Song Liu
Browse files

md: introduce md_ro_state



Introduce md_ro_state for mddev->ro, so it is easy to understand.

Signed-off-by: default avatarYe Bin <yebin10@huawei.com>
Signed-off-by: default avatarSong Liu <song@kernel.org>
parent 2f6d261e
Loading
Loading
Loading
Loading
+82 −70
Original line number Diff line number Diff line
@@ -93,6 +93,18 @@ static int remove_and_add_spares(struct mddev *mddev,
				 struct md_rdev *this);
static void mddev_detach(struct mddev *mddev);

enum md_ro_state {
	MD_RDWR,
	MD_RDONLY,
	MD_AUTO_READ,
	MD_MAX_STATE
};

static bool md_is_rdwr(struct mddev *mddev)
{
	return (mddev->ro == MD_RDWR);
}

/*
 * Default number of read corrections we'll attempt on an rdev
 * before ejecting it from the array. We divide the read error
@@ -444,7 +456,7 @@ static void md_submit_bio(struct bio *bio)

	bio = bio_split_to_limits(bio);

	if (mddev->ro == 1 && unlikely(rw == WRITE)) {
	if (mddev->ro == MD_RDONLY && unlikely(rw == WRITE)) {
		if (bio_sectors(bio) != 0)
			bio->bi_status = BLK_STS_IOERR;
		bio_endio(bio);
@@ -2639,7 +2651,7 @@ void md_update_sb(struct mddev *mddev, int force_change)
	int any_badblocks_changed = 0;
	int ret = -1;

	if (mddev->ro) {
	if (!md_is_rdwr(mddev)) {
		if (force_change)
			set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
		return;
@@ -3901,7 +3913,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
		goto out_unlock;
	}
	rv = -EROFS;
	if (mddev->ro)
	if (!md_is_rdwr(mddev))
		goto out_unlock;

	/* request to change the personality.  Need to ensure:
@@ -4107,7 +4119,7 @@ layout_store(struct mddev *mddev, const char *buf, size_t len)
	if (mddev->pers) {
		if (mddev->pers->check_reshape == NULL)
			err = -EBUSY;
		else if (mddev->ro)
		else if (!md_is_rdwr(mddev))
			err = -EROFS;
		else {
			mddev->new_layout = n;
@@ -4216,7 +4228,7 @@ chunk_size_store(struct mddev *mddev, const char *buf, size_t len)
	if (mddev->pers) {
		if (mddev->pers->check_reshape == NULL)
			err = -EBUSY;
		else if (mddev->ro)
		else if (!md_is_rdwr(mddev))
			err = -EROFS;
		else {
			mddev->new_chunk_sectors = n >> 9;
@@ -4339,13 +4351,13 @@ array_state_show(struct mddev *mddev, char *page)

	if (mddev->pers && !test_bit(MD_NOT_READY, &mddev->flags)) {
		switch(mddev->ro) {
		case 1:
		case MD_RDONLY:
			st = readonly;
			break;
		case 2:
		case MD_AUTO_READ:
			st = read_auto;
			break;
		case 0:
		case MD_RDWR:
			spin_lock(&mddev->lock);
			if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
				st = write_pending;
@@ -4381,7 +4393,8 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
	int err = 0;
	enum array_state st = match_word(buf, array_states);

	if (mddev->pers && (st == active || st == clean) && mddev->ro != 1) {
	if (mddev->pers && (st == active || st == clean) &&
	    mddev->ro != MD_RDONLY) {
		/* don't take reconfig_mutex when toggling between
		 * clean and active
		 */
@@ -4425,23 +4438,23 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
		if (mddev->pers)
			err = md_set_readonly(mddev, NULL);
		else {
			mddev->ro = 1;
			mddev->ro = MD_RDONLY;
			set_disk_ro(mddev->gendisk, 1);
			err = do_md_run(mddev);
		}
		break;
	case read_auto:
		if (mddev->pers) {
			if (mddev->ro == 0)
			if (md_is_rdwr(mddev))
				err = md_set_readonly(mddev, NULL);
			else if (mddev->ro == 1)
			else if (mddev->ro == MD_RDONLY)
				err = restart_array(mddev);
			if (err == 0) {
				mddev->ro = 2;
				mddev->ro = MD_AUTO_READ;
				set_disk_ro(mddev->gendisk, 0);
			}
		} else {
			mddev->ro = 2;
			mddev->ro = MD_AUTO_READ;
			err = do_md_run(mddev);
		}
		break;
@@ -4466,7 +4479,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
			wake_up(&mddev->sb_wait);
			err = 0;
		} else {
			mddev->ro = 0;
			mddev->ro = MD_RDWR;
			set_disk_ro(mddev->gendisk, 0);
			err = do_md_run(mddev);
		}
@@ -4765,7 +4778,7 @@ action_show(struct mddev *mddev, char *page)
	if (test_bit(MD_RECOVERY_FROZEN, &recovery))
		type = "frozen";
	else if (test_bit(MD_RECOVERY_RUNNING, &recovery) ||
	    (!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &recovery))) {
	    (md_is_rdwr(mddev) && test_bit(MD_RECOVERY_NEEDED, &recovery))) {
		if (test_bit(MD_RECOVERY_RESHAPE, &recovery))
			type = "reshape";
		else if (test_bit(MD_RECOVERY_SYNC, &recovery)) {
@@ -4851,11 +4864,11 @@ action_store(struct mddev *mddev, const char *page, size_t len)
		set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
		set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
	}
	if (mddev->ro == 2) {
	if (mddev->ro == MD_AUTO_READ) {
		/* A write to sync_action is enough to justify
		 * canceling read-auto mode
		 */
		mddev->ro = 0;
		mddev->ro = MD_RDWR;
		md_wakeup_thread(mddev->sync_thread);
	}
	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -5083,8 +5096,7 @@ max_sync_store(struct mddev *mddev, const char *buf, size_t len)
			goto out_unlock;

		err = -EBUSY;
		if (max < mddev->resync_max &&
		    mddev->ro == 0 &&
		if (max < mddev->resync_max && md_is_rdwr(mddev) &&
		    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
			goto out_unlock;

@@ -5813,8 +5825,8 @@ int md_run(struct mddev *mddev)
			continue;
		sync_blockdev(rdev->bdev);
		invalidate_bdev(rdev->bdev);
		if (mddev->ro != 1 && rdev_read_only(rdev)) {
			mddev->ro = 1;
		if (mddev->ro != MD_RDONLY && rdev_read_only(rdev)) {
			mddev->ro = MD_RDONLY;
			if (mddev->gendisk)
				set_disk_ro(mddev->gendisk, 1);
		}
@@ -5917,8 +5929,8 @@ int md_run(struct mddev *mddev)

	mddev->ok_start_degraded = start_dirty_degraded;

	if (start_readonly && mddev->ro == 0)
		mddev->ro = 2; /* read-only, but switch on first write */
	if (start_readonly && md_is_rdwr(mddev))
		mddev->ro = MD_AUTO_READ; /* read-only, but switch on first write */

	err = pers->run(mddev);
	if (err)
@@ -5996,8 +6008,8 @@ int md_run(struct mddev *mddev)
		mddev->sysfs_action = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_action");
		mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed");
		mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded");
	} else if (mddev->ro == 2) /* auto-readonly not meaningful */
		mddev->ro = 0;
	} else if (mddev->ro == MD_AUTO_READ)
		mddev->ro = MD_RDWR;

	atomic_set(&mddev->max_corr_read_errors,
		   MD_DEFAULT_MAX_CORRECTED_READ_ERRORS);
@@ -6015,7 +6027,7 @@ int md_run(struct mddev *mddev)
		if (rdev->raid_disk >= 0)
			sysfs_link_rdev(mddev, rdev); /* failure here is OK */

	if (mddev->degraded && !mddev->ro)
	if (mddev->degraded && md_is_rdwr(mddev))
		/* This ensures that recovering status is reported immediately
		 * via sysfs - until a lack of spares is confirmed.
		 */
@@ -6105,7 +6117,7 @@ static int restart_array(struct mddev *mddev)
		return -ENXIO;
	if (!mddev->pers)
		return -EINVAL;
	if (!mddev->ro)
	if (md_is_rdwr(mddev))
		return -EBUSY;

	rcu_read_lock();
@@ -6124,7 +6136,7 @@ static int restart_array(struct mddev *mddev)
		return -EROFS;

	mddev->safemode = 0;
	mddev->ro = 0;
	mddev->ro = MD_RDWR;
	set_disk_ro(disk, 0);
	pr_debug("md: %s switched to read-write mode.\n", mdname(mddev));
	/* Kick recovery or resync if necessary */
@@ -6151,7 +6163,7 @@ static void md_clean(struct mddev *mddev)
	mddev->clevel[0] = 0;
	mddev->flags = 0;
	mddev->sb_flags = 0;
	mddev->ro = 0;
	mddev->ro = MD_RDWR;
	mddev->metadata_type[0] = 0;
	mddev->chunk_sectors = 0;
	mddev->ctime = mddev->utime = 0;
@@ -6203,7 +6215,7 @@ static void __md_stop_writes(struct mddev *mddev)
	}
	md_bitmap_flush(mddev);

	if (mddev->ro == 0 &&
	if (md_is_rdwr(mddev) &&
	    ((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
	     mddev->sb_flags)) {
		/* mark array as shutdown cleanly */
@@ -6312,9 +6324,9 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
		__md_stop_writes(mddev);

		err  = -ENXIO;
		if (mddev->ro==1)
		if (mddev->ro == MD_RDONLY)
			goto out;
		mddev->ro = 1;
		mddev->ro = MD_RDONLY;
		set_disk_ro(mddev->gendisk, 1);
		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -6371,7 +6383,7 @@ static int do_md_stop(struct mddev *mddev, int mode,
		return -EBUSY;
	}
	if (mddev->pers) {
		if (mddev->ro)
		if (!md_is_rdwr(mddev))
			set_disk_ro(disk, 0);

		__md_stop_writes(mddev);
@@ -6388,8 +6400,8 @@ static int do_md_stop(struct mddev *mddev, int mode,
		mutex_unlock(&mddev->open_mutex);
		mddev->changed = 1;

		if (mddev->ro)
			mddev->ro = 0;
		if (!md_is_rdwr(mddev))
			mddev->ro = MD_RDWR;
	} else
		mutex_unlock(&mddev->open_mutex);
	/*
@@ -7204,7 +7216,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
	    mddev->sync_thread)
		return -EBUSY;
	if (mddev->ro)
	if (!md_is_rdwr(mddev))
		return -EROFS;

	rdev_for_each(rdev, mddev) {
@@ -7234,7 +7246,7 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
	/* change the number of raid disks */
	if (mddev->pers->check_reshape == NULL)
		return -EINVAL;
	if (mddev->ro)
	if (!md_is_rdwr(mddev))
		return -EROFS;
	if (raid_disks <= 0 ||
	    (mddev->max_disks && raid_disks >= mddev->max_disks))
@@ -7663,9 +7675,12 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
	 * The remaining ioctls are changing the state of the
	 * superblock, so we do not allow them on read-only arrays.
	 */
	if (mddev->ro && mddev->pers) {
		if (mddev->ro == 2) {
			mddev->ro = 0;
	if (!md_is_rdwr(mddev) && mddev->pers) {
		if (mddev->ro != MD_AUTO_READ) {
			err = -EROFS;
			goto unlock;
		}
		mddev->ro = MD_RDWR;
		sysfs_notify_dirent_safe(mddev->sysfs_state);
		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
		/* mddev_unlock will wake thread */
@@ -7679,10 +7694,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
				   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
			mddev_lock_nointr(mddev);
		}
		} else {
			err = -EROFS;
			goto unlock;
		}
	}

	switch (cmd) {
@@ -7768,11 +7779,11 @@ static int md_set_read_only(struct block_device *bdev, bool ro)
	 * Transitioning to read-auto need only happen for arrays that call
	 * md_write_start and which are not ready for writes yet.
	 */
	if (!ro && mddev->ro == 1 && mddev->pers) {
	if (!ro && mddev->ro == MD_RDONLY && mddev->pers) {
		err = restart_array(mddev);
		if (err)
			goto out_unlock;
		mddev->ro = 2;
		mddev->ro = MD_AUTO_READ;
	}

out_unlock:
@@ -8246,9 +8257,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
		seq_printf(seq, "%s : %sactive", mdname(mddev),
						mddev->pers ? "" : "in");
		if (mddev->pers) {
			if (mddev->ro==1)
			if (mddev->ro == MD_RDONLY)
				seq_printf(seq, " (read-only)");
			if (mddev->ro==2)
			if (mddev->ro == MD_AUTO_READ)
				seq_printf(seq, " (auto-read-only)");
			seq_printf(seq, " %s", mddev->pers->name);
		}
@@ -8507,10 +8518,10 @@ bool md_write_start(struct mddev *mddev, struct bio *bi)
	if (bio_data_dir(bi) != WRITE)
		return true;

	BUG_ON(mddev->ro == 1);
	if (mddev->ro == 2) {
	BUG_ON(mddev->ro == MD_RDONLY);
	if (mddev->ro == MD_AUTO_READ) {
		/* need to switch to read/write */
		mddev->ro = 0;
		mddev->ro = MD_RDWR;
		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
		md_wakeup_thread(mddev->thread);
		md_wakeup_thread(mddev->sync_thread);
@@ -8561,7 +8572,7 @@ void md_write_inc(struct mddev *mddev, struct bio *bi)
{
	if (bio_data_dir(bi) != WRITE)
		return;
	WARN_ON_ONCE(mddev->in_sync || mddev->ro);
	WARN_ON_ONCE(mddev->in_sync || !md_is_rdwr(mddev));
	percpu_ref_get(&mddev->writes_pending);
}
EXPORT_SYMBOL(md_write_inc);
@@ -8666,7 +8677,7 @@ void md_allow_write(struct mddev *mddev)
{
	if (!mddev->pers)
		return;
	if (mddev->ro)
	if (!md_is_rdwr(mddev))
		return;
	if (!mddev->pers->sync_request)
		return;
@@ -8714,7 +8725,7 @@ void md_do_sync(struct md_thread *thread)
	if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
	    test_bit(MD_RECOVERY_WAIT, &mddev->recovery))
		return;
	if (mddev->ro) {/* never try to sync a read-only array */
	if (!md_is_rdwr(mddev)) {/* never try to sync a read-only array */
		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
		return;
	}
@@ -9183,7 +9194,7 @@ static int remove_and_add_spares(struct mddev *mddev,
		if (test_bit(Faulty, &rdev->flags))
			continue;
		if (!test_bit(Journal, &rdev->flags)) {
			if (mddev->ro &&
			if (!md_is_rdwr(mddev) &&
			    !(rdev->saved_raid_disk >= 0 &&
			      !test_bit(Bitmap_sync, &rdev->flags)))
				continue;
@@ -9283,7 +9294,8 @@ void md_check_recovery(struct mddev *mddev)
		flush_signals(current);
	}

	if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
	if (!md_is_rdwr(mddev) &&
	    !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
		return;
	if ( ! (
		(mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) ||
@@ -9302,7 +9314,7 @@ void md_check_recovery(struct mddev *mddev)
		if (!mddev->external && mddev->safemode == 1)
			mddev->safemode = 0;

		if (mddev->ro) {
		if (!md_is_rdwr(mddev)) {
			struct md_rdev *rdev;
			if (!mddev->external && mddev->in_sync)
				/* 'Blocked' flag not needed as failed devices