This patch depends on patch 01. An inconsistency occurs between config state in takeover and percpu_ref state. Differentiate percpu_ref state setting for takeover and other to avoid the inconsistency. Therefore, add percpu_ref state setting to match config state in takeover. Signed-off-by: Keisuke TADA <keisuke1.tada@xxxxxxxxxx> Signed-off-by: Toshifumi OHTAKE <toshifumi.ootake@xxxxxxxxxx> --- drivers/md/raid5.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 25da83eaa2ef..b7056854375d 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -7396,7 +7396,8 @@ static unsigned long raid5_cache_count(struct shrinker *shrink, return max_stripes - min_stripes; } -static struct r5conf *setup_conf(struct mddev *mddev) + +static struct r5conf *setup_conf(struct mddev *mddev, bool quiesce) { struct r5conf *conf; int raid_disk, memory, max_disks; @@ -7407,6 +7408,7 @@ static struct r5conf *setup_conf(struct mddev *mddev) int group_cnt; struct r5worker_group *new_group; int ret = -ENOMEM; + unsigned int percpu_ref_init_flags; if (mddev->new_level != 5 && mddev->new_level != 4 @@ -7477,6 +7479,10 @@ static struct r5conf *setup_conf(struct mddev *mddev) init_llist_head(&conf->released_stripes); atomic_set(&conf->active_stripes, 0); atomic_set(&conf->preread_active_stripes, 0); + if (quiesce) + percpu_ref_init_flags = PERCPU_REF_ALLOW_REINIT | PERCPU_REF_INIT_DEAD; + else + percpu_ref_init_flags = PERCPU_REF_ALLOW_REINIT; atomic_set(&conf->active_aligned_reads, 0); spin_lock_init(&conf->pending_bios_lock); conf->batch_bio_dispatch = true; @@ -7657,6 +7663,23 @@ static struct r5conf *setup_conf(struct mddev *mddev) return ERR_PTR(ret); } +static struct r5conf *setup_conf_for_run(struct mddev *mddev) +{ + return setup_conf(mddev, false); +} + +static struct r5conf *setup_conf_for_takeover(struct mddev *mddev) +{ + struct r5conf *conf; + bool quiesce = false; + + if (mddev->level == 4 || mddev->level == 5 || mddev->level == 6) { + conf = mddev->private; + quiesce = false; + } + return setup_conf(mddev, quiesce); +} + static int only_parity(int raid_disk, int algo, int raid_disks, int max_degraded) { switch (algo) { @@ -7884,7 +7907,7 @@ static int raid5_run(struct mddev *mddev) } if (mddev->private == NULL) - conf = setup_conf(mddev); + conf = setup_conf_for_run(mddev); else conf = mddev->private; @@ -8627,7 +8650,7 @@ static void *raid45_takeover_raid0(struct mddev *mddev, int level) /* make sure it will be not marked as dirty */ mddev->recovery_cp = MaxSector; - return setup_conf(mddev); + return setup_conf_for_takeover(mddev); } static void *raid5_takeover_raid1(struct mddev *mddev) @@ -8655,7 +8678,7 @@ static void *raid5_takeover_raid1(struct mddev *mddev) mddev->new_layout = ALGORITHM_LEFT_SYMMETRIC; mddev->new_chunk_sectors = chunksect; - ret = setup_conf(mddev); + ret = setup_conf_for_takeover(mddev); if (!IS_ERR(ret)) mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS); @@ -8692,7 +8715,7 @@ static void *raid5_takeover_raid6(struct mddev *mddev) mddev->new_layout = new_layout; mddev->delta_disks = -1; mddev->raid_disks -= 1; - return setup_conf(mddev); + return setup_conf_for_takeover(mddev); } static int raid5_check_reshape(struct mddev *mddev) @@ -8770,7 +8793,7 @@ static void *raid5_takeover(struct mddev *mddev) if (mddev->level == 4) { mddev->new_layout = ALGORITHM_PARITY_N; mddev->new_level = 5; - return setup_conf(mddev); + return setup_conf_for_takeover(mddev); } if (mddev->level == 6) return raid5_takeover_raid6(mddev); @@ -8790,7 +8813,7 @@ static void *raid4_takeover(struct mddev *mddev) mddev->layout == ALGORITHM_PARITY_N) { mddev->new_layout = 0; mddev->new_level = 4; - return setup_conf(mddev); + return setup_conf_for_takeover(mddev); } return ERR_PTR(-EINVAL); } @@ -8840,7 +8863,7 @@ static void *raid6_takeover(struct mddev *mddev) mddev->new_layout = new_layout; mddev->delta_disks = 1; mddev->raid_disks += 1; - return setup_conf(mddev); + return setup_conf_for_takeover(mddev); } static int raid5_change_consistency_policy(struct mddev *mddev, const char *buf) -- 2.34.1