md: remove need for mddev_lock() in md_seq_show()
authorNeilBrown <neilb@suse.de>
Mon, 15 Dec 2014 01:56:59 +0000 (12:56 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 5 Feb 2015 22:32:55 +0000 (09:32 +1100)
The only access in md_seq_show that could suffer from races
not protected by ->lock is walking the rdev list.
This can receive sufficient protection from 'rcu'.

So use rdev_for_each_rcu() and get rid of mddev_lock().

Now reading /proc/mdstat will never block in md_seq_show.

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/md.c

index 4db4e4146a35837f54dbd6f6c63e51e85f1ec85d..eb0c3b576d7dd52f1607003559be6e7709fd0892 100644 (file)
@@ -6950,9 +6950,6 @@ static int md_seq_show(struct seq_file *seq, void *v)
                return 0;
        }
 
-       if (mddev_lock(mddev) < 0)
-               return -EINTR;
-
        spin_lock(&mddev->lock);
        if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
                seq_printf(seq, "%s : %sactive", mdname(mddev),
@@ -6966,7 +6963,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
                }
 
                sectors = 0;
-               rdev_for_each(rdev, mddev) {
+               rcu_read_lock();
+               rdev_for_each_rcu(rdev, mddev) {
                        char b[BDEVNAME_SIZE];
                        seq_printf(seq, " %s[%d]",
                                bdevname(rdev->bdev,b), rdev->desc_nr);
@@ -6982,6 +6980,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
                                seq_printf(seq, "(R)");
                        sectors += rdev->sectors;
                }
+               rcu_read_unlock();
 
                if (!list_empty(&mddev->disks)) {
                        if (mddev->pers)
@@ -7025,7 +7024,6 @@ static int md_seq_show(struct seq_file *seq, void *v)
                seq_printf(seq, "\n");
        }
        spin_unlock(&mddev->lock);
-       mddev_unlock(mddev);
 
        return 0;
 }