Skip to content

Commit

Permalink
Don't let a blocked_rdev interfere with read request in raid5/6
Browse files Browse the repository at this point in the history
When we have externally managed metadata, we need to mark a failed
device as 'Blocked' and not allow any writes until that device
have been marked as faulty in the metadata and the Blocked flag has
been removed.

However it is perfectly OK to allow read requests when there is a
Blocked device, and with a readonly array, there may not be any
metadata-handler watching for blocked devices.

So in raid5/raid6 only allow a Blocked device to interfere with
Write request or resync.  Read requests go through untouched.

raid1 and raid10 already differentiate between read and write
properly.

Signed-off-by: NeilBrown <neilb@suse.de>
  • Loading branch information
NeilBrown committed Aug 5, 2008
1 parent dba034e commit ac4090d
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions drivers/md/raid5.c
Original file line number Diff line number Diff line change
Expand Up @@ -2568,10 +2568,10 @@ static bool handle_stripe5(struct stripe_head *sh)
if (dev->written)
s.written++;
rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
if (blocked_rdev == NULL &&
rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
break;
}
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */
Expand All @@ -2588,8 +2588,14 @@ static bool handle_stripe5(struct stripe_head *sh)
rcu_read_unlock();

if (unlikely(blocked_rdev)) {
set_bit(STRIPE_HANDLE, &sh->state);
goto unlock;
if (s.syncing || s.expanding || s.expanded ||
s.to_write || s.written) {
set_bit(STRIPE_HANDLE, &sh->state);
goto unlock;
}
/* There is nothing for the blocked_rdev to block */
rdev_dec_pending(blocked_rdev, conf->mddev);
blocked_rdev = NULL;
}

if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {
Expand Down Expand Up @@ -2832,10 +2838,10 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
if (dev->written)
s.written++;
rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
if (blocked_rdev == NULL &&
rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
break;
}
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */
Expand All @@ -2853,9 +2859,16 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
rcu_read_unlock();

if (unlikely(blocked_rdev)) {
set_bit(STRIPE_HANDLE, &sh->state);
goto unlock;
if (s.syncing || s.expanding || s.expanded ||
s.to_write || s.written) {
set_bit(STRIPE_HANDLE, &sh->state);
goto unlock;
}
/* There is nothing for the blocked_rdev to block */
rdev_dec_pending(blocked_rdev, conf->mddev);
blocked_rdev = NULL;
}

pr_debug("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d,%d\n",
s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
Expand Down

0 comments on commit ac4090d

Please sign in to comment.