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

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
...@@ -8213,105 +8213,46 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev) ...@@ -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) static void *md_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(&all_mddevs_lock)
{ {
struct list_head *tmp; struct md_personality *pers;
loff_t l = *pos;
struct mddev *mddev;
if (l == 0x10000) { seq_puts(seq, "Personalities : ");
++*pos; spin_lock(&pers_lock);
return (void *)2; list_for_each_entry(pers, &pers_list, list)
} seq_printf(seq, "[%s] ", pers->name);
if (l > 0x10000)
return NULL; spin_unlock(&pers_lock);
if (!l--) seq_puts(seq, "\n");
/* header */ seq->poll_event = atomic_read(&md_event_count);
return (void*)1;
spin_lock(&all_mddevs_lock); spin_lock(&all_mddevs_lock);
list_for_each(tmp,&all_mddevs)
if (!l--) { return seq_list_start(&all_mddevs, *pos);
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;
} }
static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
struct list_head *tmp; return seq_list_next(v, &all_mddevs, pos);
struct mddev *next_mddev, *mddev = v;
struct mddev *to_put = NULL;
++*pos;
if (v == (void*)2)
return NULL;
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;
}
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_stop(struct seq_file *seq, void *v) static void md_seq_stop(struct seq_file *seq, void *v)
__releases(&all_mddevs_lock)
{ {
struct mddev *mddev = v; status_unused(seq);
spin_unlock(&all_mddevs_lock);
if (mddev && v != (void*)1 && v != (void*)2)
mddev_put(mddev);
} }
static int md_seq_show(struct seq_file *seq, void *v) 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; sector_t sectors;
struct md_rdev *rdev; struct md_rdev *rdev;
if (v == (void*)1) { if (!mddev_get(mddev))
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; return 0;
}
if (v == (void*)2) {
status_unused(seq);
return 0;
}
spin_unlock(&all_mddevs_lock);
spin_lock(&mddev->lock); spin_lock(&mddev->lock);
if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) { if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
seq_printf(seq, "%s : %sactive", mdname(mddev), seq_printf(seq, "%s : %sactive", mdname(mddev),
...@@ -8382,6 +8323,9 @@ static int md_seq_show(struct seq_file *seq, void *v) ...@@ -8382,6 +8323,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "\n"); seq_printf(seq, "\n");
} }
spin_unlock(&mddev->lock); spin_unlock(&mddev->lock);
spin_lock(&all_mddevs_lock);
if (atomic_dec_and_test(&mddev->active))
__mddev_put(mddev);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment