From: NeilBrown <neilb@suse.com>
To: Shaohua Li <shli@kernel.org>
Cc: linux-raid@vger.kernel.org
Subject: [md PATCH 17/18] md: be extra careful not to take a reference to a Faulty device.
Date: Thu, 02 Jun 2016 16:19:53 +1000 [thread overview]
Message-ID: <20160602061952.2939.5666.stgit@noble> (raw)
In-Reply-To: <20160602061319.2939.72280.stgit@noble>
It is important that we never increment rdev->nr_pending on a Faulty
device as ->hot_remove_disk() assumes that once the Faulty flag is visible
no code will take a new reference.
Some places take a new reference after only check In_sync. This should
be safe as the two are changed together. However to make the code more
obviously safe, add checks for 'Faulty' as well.
Note: the actual rule is:
Never increment nr_pending if Faulty is set and Blocked is clear,
never clear Faulty, and never set Blocked without holding a reference
through nr_pending.
Signed-off-by: NeilBrown <neilb@suse.com>
---
drivers/md/multipath.c | 3 ++-
drivers/md/raid10.c | 6 ++++++
drivers/md/raid5.c | 3 ++-
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 69244de2036b..7eb9972a37e6 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -43,7 +43,8 @@ static int multipath_map (struct mpconf *conf)
rcu_read_lock();
for (i = 0; i < disks; i++) {
struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
- if (rdev && test_bit(In_sync, &rdev->flags)) {
+ if (rdev && test_bit(In_sync, &rdev->flags) &&
+ !test_bit(Faulty, &rdev->flags)) {
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
return i;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 5d40612d6219..78016667ec00 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -2289,6 +2289,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags) &&
+ !test_bit(Faulty, &rdev->flags) &&
is_badblock(rdev, r10_bio->devs[sl].addr + sect, s,
&first_bad, &bad_sectors) == 0) {
atomic_inc(&rdev->nr_pending);
@@ -2341,6 +2342,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (!rdev ||
+ test_bit(Faulty, &rdev->flags) ||
!test_bit(In_sync, &rdev->flags))
continue;
@@ -2380,6 +2382,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (!rdev ||
+ test_bit(Faulty, &rdev->flags))
!test_bit(In_sync, &rdev->flags))
continue;
@@ -2948,6 +2951,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
mreplace = rcu_dereference(mirror->replacement);
if ((mrdev == NULL ||
+ test_bit(Faulty, &mrdev->flags) ||
test_bit(In_sync, &mrdev->flags))) {
rcu_read_unlock();
continue;
@@ -2964,6 +2968,8 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
rcu_read_unlock();
continue;
}
+ if (mreplace && test_bit(Faulty, &mreplace->flags))
+ mreplace = NULL;
/* Unless we are doing a full sync, or a replacement
* we only need to recover the block if it is set in
* the bitmap
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e9beba258f4f..94c180f16294 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3080,7 +3080,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
struct md_rdev *rdev;
rcu_read_lock();
rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && test_bit(In_sync, &rdev->flags))
+ if (rdev && test_bit(In_sync, &rdev->flags) &&
+ !test_bit(Faulty, &rdev->flags))
atomic_inc(&rdev->nr_pending);
else
rdev = NULL;
next prev parent reply other threads:[~2016-06-02 6:19 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-02 6:19 [md PATCH 00/18] Assorted minor fixes, particularly RCU protection NeilBrown
2016-06-02 6:19 ` [md PATCH 06/18] md/raid10: add rcu protection to rdev access during reshape NeilBrown
2016-06-02 6:19 ` [md PATCH 14/18] md/raid5: add rcu protection to rdev accesses in want_replace NeilBrown
2016-06-02 6:19 ` [md PATCH 12/18] md/raid1: add rcu protection to rdev in fix_read_error NeilBrown
2016-06-02 6:19 ` [md PATCH 04/18] md/raid10: add rcu protection in raid10_status NeilBrown
2016-06-02 6:19 ` [md PATCH 16/18] md/multipath: add rcu protection to rdev access in multipath_status NeilBrown
2016-06-02 6:19 ` [md PATCH 02/18] md/raid1, raid10: don't recheck "Faulty" flag in read-balance NeilBrown
2016-06-02 6:19 ` [md PATCH 10/18] md/raid1: small cleanup in raid1_end_read/write_request NeilBrown
2016-06-02 6:19 ` [md PATCH 01/18] md: disconnect device from personality before trying to remove it NeilBrown
2016-06-03 22:31 ` Shaohua Li
2016-06-10 6:40 ` NeilBrown
2016-06-02 6:19 ` [md PATCH 05/18] md/raid10: add rcu protection to rdev access in raid10_sync_request NeilBrown
2016-06-03 22:33 ` Shaohua Li
2016-06-10 6:46 ` NeilBrown
2016-06-10 16:22 ` Shaohua Li
2016-06-02 6:19 ` [md PATCH 09/18] md/raid10: stop print_conf from being too verbose NeilBrown
2016-06-02 18:47 ` John Stoffel
2016-06-02 22:48 ` NeilBrown
2016-06-03 22:39 ` Shaohua Li
2016-06-10 6:47 ` NeilBrown
2016-06-02 6:19 ` [md PATCH 03/18] md/raid10: fix refounct imbalance when resyncing an array with a replacement device NeilBrown
2016-06-02 6:19 ` [md PATCH 15/18] md/raid5: add rcu protection to rdev accesses in raid5_status NeilBrown
2016-06-02 6:19 ` [md PATCH 13/18] md/raid5: add rcu protection to rdev accesses in handle_failed_sync NeilBrown
2016-06-02 6:19 ` [md PATCH 11/18] md/raid1: small code cleanup in end_sync_write NeilBrown
2016-06-02 6:19 ` [md PATCH 07/18] md/raid10: minor code improvement in fix_read_error() NeilBrown
2016-06-02 6:19 ` [md PATCH 08/18] md/raid10: simplify print_conf a little NeilBrown
2016-06-02 6:19 ` NeilBrown [this message]
2016-06-02 6:19 ` [md PATCH 18/18] md: reduce the number of synchronize_rcu() calls when multiple devices fail NeilBrown
2016-06-03 22:28 ` [md PATCH 00/18] Assorted minor fixes, particularly RCU protection Shaohua Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160602061952.2939.5666.stgit@noble \
--to=neilb@suse.com \
--cc=linux-raid@vger.kernel.org \
--cc=shli@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.