diff options
author | NeilBrown <neilb@suse.de> | 2009-12-13 20:49:49 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-12-13 20:49:49 -0500 |
commit | a2826aa92e2e14db372eda01d333267258944033 (patch) | |
tree | 9cdd3329205bf480a4782705a3db1738e3faae44 /drivers/md/raid5.c | |
parent | efa593390e70b0e3c39f6b2dca8876b6b1461e41 (diff) |
md: support barrier requests on all personalities.
Previously barriers were only supported on RAID1. This is because
other levels requires synchronisation across all devices and so needed
a different approach.
Here is that approach.
When a barrier arrives, we send a zero-length barrier to every active
device. When that completes - and if the original request was not
empty - we submit the barrier request itself (with the barrier flag
cleared) and then submit a fresh load of zero length barriers.
The barrier request itself is asynchronous, but any subsequent
request will block until the barrier completes.
The reason for clearing the barrier flag is that a barrier request is
allowed to fail. If we pass a non-empty barrier through a striping
raid level it is conceivable that part of it could succeed and part
could fail. That would be way too hard to deal with.
So if the first run of zero length barriers succeed, we assume all is
sufficiently well that we send the request and ignore errors in the
second run of barriers.
RAID5 needs extra care as write requests may not have been submitted
to the underlying devices yet. So we flush the stripe cache before
proceeding with the barrier.
Note that the second set of zero-length barriers are submitted
immediately after the original request is submitted. Thus when
a personality finds mddev->barrier to be set during make_request,
it should not return from make_request until the corresponding
per-device request(s) have been queued.
That will be done in later patches.
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Andre Noll <maan@systemlinux.org>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 34cb065f6d66..8c9395f2028f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3865,7 +3865,13 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
3865 | int cpu, remaining; | 3865 | int cpu, remaining; |
3866 | 3866 | ||
3867 | if (unlikely(bio_rw_flagged(bi, BIO_RW_BARRIER))) { | 3867 | if (unlikely(bio_rw_flagged(bi, BIO_RW_BARRIER))) { |
3868 | bio_endio(bi, -EOPNOTSUPP); | 3868 | /* Drain all pending writes. We only really need |
3869 | * to ensure they have been submitted, but this is | ||
3870 | * easier. | ||
3871 | */ | ||
3872 | mddev->pers->quiesce(mddev, 1); | ||
3873 | mddev->pers->quiesce(mddev, 0); | ||
3874 | md_barrier_request(mddev, bi); | ||
3869 | return 0; | 3875 | return 0; |
3870 | } | 3876 | } |
3871 | 3877 | ||