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

Commit 27a353c0 authored by Shaohua Li's avatar Shaohua Li
Browse files

RAID5: check_reshape() shouldn't call mddev_suspend



check_reshape() is called from raid5d thread. raid5d thread shouldn't
call mddev_suspend(), because mddev_suspend() waits for all IO finish
but IO is handled in raid5d thread, we could easily deadlock here.

This issue is introduced by
738a2738 ("md/raid5: fix allocation of 'scribble' array.")

Cc: stable@vger.kernel.org (v4.1+)
Reported-and-tested-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent e7597e69
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -2089,6 +2089,14 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
	unsigned long cpu;
	int err = 0;

	/*
	 * Never shrink. And mddev_suspend() could deadlock if this is called
	 * from raid5d. In that case, scribble_disks and scribble_sectors
	 * should equal to new_disks and new_sectors
	 */
	if (conf->scribble_disks >= new_disks &&
	    conf->scribble_sectors >= new_sectors)
		return 0;
	mddev_suspend(conf->mddev);
	get_online_cpus();
	for_each_present_cpu(cpu) {
@@ -2110,6 +2118,10 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
	}
	put_online_cpus();
	mddev_resume(conf->mddev);
	if (!err) {
		conf->scribble_disks = new_disks;
		conf->scribble_sectors = new_sectors;
	}
	return err;
}

@@ -6413,6 +6425,12 @@ static int raid5_alloc_percpu(struct r5conf *conf)
	}
	put_online_cpus();

	if (!err) {
		conf->scribble_disks = max(conf->raid_disks,
			conf->previous_raid_disks);
		conf->scribble_sectors = max(conf->chunk_sectors,
			conf->prev_chunk_sectors);
	}
	return err;
}

+2 −0
Original line number Diff line number Diff line
@@ -510,6 +510,8 @@ struct r5conf {
					      * conversions
					      */
	} __percpu *percpu;
	int scribble_disks;
	int scribble_sectors;
#ifdef CONFIG_HOTPLUG_CPU
	struct notifier_block	cpu_notify;
#endif