Commit c20413b7 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'md-6.17-20250722' of...

Merge tag 'md-6.17-20250722' of https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux into for-6.17/block

Pull MD updates from Yu:

"- call del_gendisk synchronously, from Xiao
 - cleanup unused variable, from John
 - cleanup workqueue flags, from Ryo
 - fix faulty rdev can't be removed during resync, from Qixing"

* tag 'md-6.17-20250722' of https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux:
  md/raid10: fix set but not used variable in sync_request_write()
  md: allow removing faulty rdev during resync
  md/raid5: unset WQ_CPU_INTENSIVE for raid5 unbound workqueue
  md: remove/add redundancy group only in level change
  md: Don't clear MD_CLOSING until mddev is freed
  md: call del_gendisk in control path
parents b8da7400 bc1c2f0a
Loading
Loading
Loading
Loading
+43 −30
Original line number Diff line number Diff line
@@ -636,9 +636,6 @@ static void __mddev_put(struct mddev *mddev)
	    mddev->ctime || mddev->hold_active)
		return;

	/* Array is not configured at all, and not held active, so destroy it */
	set_bit(MD_DELETED, &mddev->flags);

	/*
	 * Call queue_work inside the spinlock so that flush_workqueue() after
	 * mddev_find will succeed in waiting for the work to be done.
@@ -873,6 +870,16 @@ void mddev_unlock(struct mddev *mddev)
		kobject_del(&rdev->kobj);
		export_rdev(rdev, mddev);
	}

	/* Call del_gendisk after release reconfig_mutex to avoid
	 * deadlock (e.g. call del_gendisk under the lock and an
	 * access to sysfs files waits the lock)
	 * And MD_DELETED is only used for md raid which is set in
	 * do_md_stop. dm raid only uses md_stop to stop. So dm raid
	 * doesn't need to check MD_DELETED when getting reconfig lock
	 */
	if (test_bit(MD_DELETED, &mddev->flags))
		del_gendisk(mddev->gendisk);
}
EXPORT_SYMBOL_GPL(mddev_unlock);

@@ -5774,19 +5781,30 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
	struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
	struct mddev *mddev = container_of(kobj, struct mddev, kobj);
	ssize_t rv;
	struct kernfs_node *kn = NULL;

	if (!entry->store)
		return -EIO;
	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

	if (entry->store == array_state_store && cmd_match(page, "clear"))
		kn = sysfs_break_active_protection(kobj, attr);

	spin_lock(&all_mddevs_lock);
	if (!mddev_get(mddev)) {
		spin_unlock(&all_mddevs_lock);
		if (kn)
			sysfs_unbreak_active_protection(kn);
		return -EBUSY;
	}
	spin_unlock(&all_mddevs_lock);
	rv = entry->store(mddev, page, length);
	mddev_put(mddev);

	if (kn)
		sysfs_unbreak_active_protection(kn);

	return rv;
}

@@ -5794,12 +5812,6 @@ static void md_kobj_release(struct kobject *ko)
{
	struct mddev *mddev = container_of(ko, struct mddev, kobj);

	if (mddev->sysfs_state)
		sysfs_put(mddev->sysfs_state);
	if (mddev->sysfs_level)
		sysfs_put(mddev->sysfs_level);

	del_gendisk(mddev->gendisk);
	put_disk(mddev->gendisk);
}

@@ -6413,14 +6425,9 @@ static void md_clean(struct mddev *mddev)
	mddev->persistent = 0;
	mddev->level = LEVEL_NONE;
	mddev->clevel[0] = 0;
	/*
	 * Don't clear MD_CLOSING, or mddev can be opened again.
	 * 'hold_active != 0' means mddev is still in the creation
	 * process and will be used later.
	 */
	if (mddev->hold_active)
		mddev->flags = 0;
	else
	/* if UNTIL_STOP is set, it's cleared here */
	mddev->hold_active = 0;
	/* Don't clear MD_CLOSING, or mddev can be opened again. */
	mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
	mddev->sb_flags = 0;
	mddev->ro = MD_RDWR;
@@ -6516,8 +6523,6 @@ static void __md_stop(struct mddev *mddev)
	if (mddev->private)
		pers->free(mddev, mddev->private);
	mddev->private = NULL;
	if (pers->sync_request && mddev->to_remove == NULL)
		mddev->to_remove = &md_redundancy_group;
	put_pers(pers);
	clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);

@@ -6646,10 +6651,8 @@ static int do_md_stop(struct mddev *mddev, int mode)
		mddev->bitmap_info.offset = 0;

		export_array(mddev);

		md_clean(mddev);
		if (mddev->hold_active == UNTIL_STOP)
			mddev->hold_active = 0;
		set_bit(MD_DELETED, &mddev->flags);
	}
	md_new_event();
	sysfs_notify_dirent_safe(mddev->sysfs_state);
@@ -9456,17 +9459,11 @@ static bool md_spares_need_change(struct mddev *mddev)
	return false;
}

static int remove_and_add_spares(struct mddev *mddev,
				 struct md_rdev *this)
static int remove_spares(struct mddev *mddev, struct md_rdev *this)
{
	struct md_rdev *rdev;
	int spares = 0;
	int removed = 0;

	if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
		/* Mustn't remove devices when resync thread is running */
		return 0;

	rdev_for_each(rdev, mddev) {
		if ((this == NULL || rdev == this) && rdev_removeable(rdev) &&
		    !mddev->pers->hot_remove_disk(mddev, rdev)) {
@@ -9480,6 +9477,21 @@ static int remove_and_add_spares(struct mddev *mddev,
	if (removed && mddev->kobj.sd)
		sysfs_notify_dirent_safe(mddev->sysfs_degraded);

	return removed;
}

static int remove_and_add_spares(struct mddev *mddev,
				 struct md_rdev *this)
{
	struct md_rdev *rdev;
	int spares = 0;
	int removed = 0;

	if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
		/* Mustn't remove devices when resync thread is running */
		return 0;

	removed = remove_spares(mddev, this);
	if (this && removed)
		goto no_add;

@@ -9522,6 +9534,7 @@ static bool md_choose_sync_action(struct mddev *mddev, int *spares)

	/* Check if resync is in progress. */
	if (mddev->recovery_cp < MaxSector) {
		remove_spares(mddev, NULL);
		set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
		clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
		return true;
+24 −2
Original line number Diff line number Diff line
@@ -700,11 +700,26 @@ static inline bool reshape_interrupted(struct mddev *mddev)

static inline int __must_check mddev_lock(struct mddev *mddev)
{
	return mutex_lock_interruptible(&mddev->reconfig_mutex);
	int ret;

	ret = mutex_lock_interruptible(&mddev->reconfig_mutex);

	/* MD_DELETED is set in do_md_stop with reconfig_mutex.
	 * So check it here.
	 */
	if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
		ret = -ENODEV;
		mutex_unlock(&mddev->reconfig_mutex);
	}

	return ret;
}

/* Sometimes we need to take the lock in a situation where
 * failure due to interrupts is not acceptable.
 * It doesn't need to check MD_DELETED here, the owner which
 * holds the lock here can't be stopped. And all paths can't
 * call this function after do_md_stop.
 */
static inline void mddev_lock_nointr(struct mddev *mddev)
{
@@ -713,7 +728,14 @@ static inline void mddev_lock_nointr(struct mddev *mddev)

static inline int mddev_trylock(struct mddev *mddev)
{
	return mutex_trylock(&mddev->reconfig_mutex);
	int ret;

	ret = mutex_trylock(&mddev->reconfig_mutex);
	if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
		ret = -ENODEV;
		mutex_unlock(&mddev->reconfig_mutex);
	}
	return ret;
}
extern void mddev_unlock(struct mddev *mddev);

+0 −3
Original line number Diff line number Diff line
@@ -2438,15 +2438,12 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
	 * that are active
	 */
	for (i = 0; i < conf->copies; i++) {
		int d;

		tbio = r10_bio->devs[i].repl_bio;
		if (!tbio || !tbio->bi_end_io)
			continue;
		if (r10_bio->devs[i].bio->bi_end_io != end_sync_write
		    && r10_bio->devs[i].bio != fbio)
			bio_copy_data(tbio, fbio);
		d = r10_bio->devs[i].devnum;
		atomic_inc(&r10_bio->remaining);
		submit_bio_noacct(tbio);
	}
+1 −1
Original line number Diff line number Diff line
@@ -9040,7 +9040,7 @@ static int __init raid5_init(void)
	int ret;

	raid5_wq = alloc_workqueue("raid5wq",
		WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE|WQ_SYSFS, 0);
		WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_SYSFS, 0);
	if (!raid5_wq)
		return -ENOMEM;