Skip to content

Commit f9cfe7e

Browse files
YuKuai-huaweiliu-song-6
authored andcommitted
md: Fix md_seq_ops() regressions
Commit cf1b6d4 ("md: simplify md_seq_ops") introduce following regressions: 1) If list all_mddevs is emptly, personalities and unused devices won't be showed to user anymore. 2) If seq_file buffer overflowed from md_seq_show(), then md_seq_start() will be called again, hence personalities will be showed to user again. 3) If seq_file buffer overflowed from md_seq_stop(), seq_read_iter() doesn't handle this, hence unused devices won't be showed to user. Fix above problems by printing personalities and unused devices in md_seq_show(). Fixes: cf1b6d4 ("md: simplify md_seq_ops") Cc: [email protected] # v6.7+ Signed-off-by: Yu Kuai <[email protected]> Signed-off-by: Song Liu <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 53889bc commit f9cfe7e

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

drivers/md/md.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8135,6 +8135,19 @@ static void status_unused(struct seq_file *seq)
81358135
seq_printf(seq, "\n");
81368136
}
81378137

8138+
static void status_personalities(struct seq_file *seq)
8139+
{
8140+
struct md_personality *pers;
8141+
8142+
seq_puts(seq, "Personalities : ");
8143+
spin_lock(&pers_lock);
8144+
list_for_each_entry(pers, &pers_list, list)
8145+
seq_printf(seq, "[%s] ", pers->name);
8146+
8147+
spin_unlock(&pers_lock);
8148+
seq_puts(seq, "\n");
8149+
}
8150+
81388151
static int status_resync(struct seq_file *seq, struct mddev *mddev)
81398152
{
81408153
sector_t max_sectors, resync, res;
@@ -8276,20 +8289,10 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
82768289
static void *md_seq_start(struct seq_file *seq, loff_t *pos)
82778290
__acquires(&all_mddevs_lock)
82788291
{
8279-
struct md_personality *pers;
8280-
8281-
seq_puts(seq, "Personalities : ");
8282-
spin_lock(&pers_lock);
8283-
list_for_each_entry(pers, &pers_list, list)
8284-
seq_printf(seq, "[%s] ", pers->name);
8285-
8286-
spin_unlock(&pers_lock);
8287-
seq_puts(seq, "\n");
82888292
seq->poll_event = atomic_read(&md_event_count);
8289-
82908293
spin_lock(&all_mddevs_lock);
82918294

8292-
return seq_list_start(&all_mddevs, *pos);
8295+
return seq_list_start_head(&all_mddevs, *pos);
82938296
}
82948297

82958298
static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
@@ -8300,16 +8303,23 @@ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
83008303
static void md_seq_stop(struct seq_file *seq, void *v)
83018304
__releases(&all_mddevs_lock)
83028305
{
8303-
status_unused(seq);
83048306
spin_unlock(&all_mddevs_lock);
83058307
}
83068308

83078309
static int md_seq_show(struct seq_file *seq, void *v)
83088310
{
8309-
struct mddev *mddev = list_entry(v, struct mddev, all_mddevs);
8311+
struct mddev *mddev;
83108312
sector_t sectors;
83118313
struct md_rdev *rdev;
83128314

8315+
if (v == &all_mddevs) {
8316+
status_personalities(seq);
8317+
if (list_empty(&all_mddevs))
8318+
status_unused(seq);
8319+
return 0;
8320+
}
8321+
8322+
mddev = list_entry(v, struct mddev, all_mddevs);
83138323
if (!mddev_get(mddev))
83148324
return 0;
83158325

@@ -8385,6 +8395,10 @@ static int md_seq_show(struct seq_file *seq, void *v)
83858395
}
83868396
spin_unlock(&mddev->lock);
83878397
spin_lock(&all_mddevs_lock);
8398+
8399+
if (mddev == list_last_entry(&all_mddevs, struct mddev, all_mddevs))
8400+
status_unused(seq);
8401+
83888402
if (atomic_dec_and_test(&mddev->active))
83898403
__mddev_put(mddev);
83908404

0 commit comments

Comments
 (0)