Commit cf1b6d44 authored by Yu Kuai's avatar Yu Kuai Committed by Song Liu
Browse files

md: simplify md_seq_ops



Before this patch, the implementation is hacky and hard to understand:

1) md_seq_start set pos to 1;
2) md_seq_show found pos is 1, then print Personalities;
3) md_seq_next found pos is 1, then it update pos to the first mddev;
4) md_seq_show found pos is not 1 or 2, show mddev;
5) md_seq_next found pos is not 1 or 2, update pos to next mddev;
6) loop 4-5 until the last mddev, then md_seq_next update pos to 2;
7) md_seq_show found pos is 2, then print unused devices;
8) md_seq_next found pos is 2, stop;

This patch remove the magic value and use seq_list_start/next/stop()
directly, and move printing "Personalities" to md_seq_start(),
"unsed devices" to md_seq_stop():

1) md_seq_start print Personalities, and then set pos to first mddev;
2) md_seq_show show mddev;
3) md_seq_next update pos to next mddev;
4) loop 2-3 until the last mddev;
5) md_seq_stop print unsed devices;

Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20230927061241.1552837-3-yukuai1@huaweicloud.com
parent 3d8d3287
Loading
Loading
Loading
Loading
+22 −78
Original line number Diff line number Diff line
@@ -8213,105 +8213,46 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
}

static void *md_seq_start(struct seq_file *seq, loff_t *pos)
	__acquires(&all_mddevs_lock)
{
	struct list_head *tmp;
	loff_t l = *pos;
	struct mddev *mddev;

	if (l == 0x10000) {
		++*pos;
		return (void *)2;
	}
	if (l > 0x10000)
		return NULL;
	if (!l--)
		/* header */
		return (void*)1;

	spin_lock(&all_mddevs_lock);
	list_for_each(tmp,&all_mddevs)
		if (!l--) {
			mddev = list_entry(tmp, struct mddev, all_mddevs);
			if (!mddev_get(mddev))
				continue;
			spin_unlock(&all_mddevs_lock);
			return mddev;
		}
	spin_unlock(&all_mddevs_lock);
	if (!l--)
		return (void*)2;/* tail */
	return NULL;
}
	struct md_personality *pers;

static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct list_head *tmp;
	struct mddev *next_mddev, *mddev = v;
	struct mddev *to_put = NULL;
	seq_puts(seq, "Personalities : ");
	spin_lock(&pers_lock);
	list_for_each_entry(pers, &pers_list, list)
		seq_printf(seq, "[%s] ", pers->name);

	++*pos;
	if (v == (void*)2)
		return NULL;
	spin_unlock(&pers_lock);
	seq_puts(seq, "\n");
	seq->poll_event = atomic_read(&md_event_count);

	spin_lock(&all_mddevs_lock);
	if (v == (void*)1) {
		tmp = all_mddevs.next;
	} else {
		to_put = mddev;
		tmp = mddev->all_mddevs.next;
	}

	for (;;) {
		if (tmp == &all_mddevs) {
			next_mddev = (void*)2;
			*pos = 0x10000;
			break;
	return seq_list_start(&all_mddevs, *pos);
}
		next_mddev = list_entry(tmp, struct mddev, all_mddevs);
		if (mddev_get(next_mddev))
			break;
		mddev = next_mddev;
		tmp = mddev->all_mddevs.next;
	}
	spin_unlock(&all_mddevs_lock);

	if (to_put)
		mddev_put(to_put);
	return next_mddev;

static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	return seq_list_next(v, &all_mddevs, pos);
}

static void md_seq_stop(struct seq_file *seq, void *v)
	__releases(&all_mddevs_lock)
{
	struct mddev *mddev = v;

	if (mddev && v != (void*)1 && v != (void*)2)
		mddev_put(mddev);
	status_unused(seq);
	spin_unlock(&all_mddevs_lock);
}

static int md_seq_show(struct seq_file *seq, void *v)
{
	struct mddev *mddev = v;
	struct mddev *mddev = list_entry(v, struct mddev, all_mddevs);
	sector_t sectors;
	struct md_rdev *rdev;

	if (v == (void*)1) {
		struct md_personality *pers;
		seq_printf(seq, "Personalities : ");
		spin_lock(&pers_lock);
		list_for_each_entry(pers, &pers_list, list)
			seq_printf(seq, "[%s] ", pers->name);

		spin_unlock(&pers_lock);
		seq_printf(seq, "\n");
		seq->poll_event = atomic_read(&md_event_count);
		return 0;
	}
	if (v == (void*)2) {
		status_unused(seq);
	if (!mddev_get(mddev))
		return 0;
	}

	spin_unlock(&all_mddevs_lock);
	spin_lock(&mddev->lock);
	if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
		seq_printf(seq, "%s : %sactive", mdname(mddev),
@@ -8382,6 +8323,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
		seq_printf(seq, "\n");
	}
	spin_unlock(&mddev->lock);
	spin_lock(&all_mddevs_lock);
	if (atomic_dec_and_test(&mddev->active))
		__mddev_put(mddev);

	return 0;
}