diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2010-08-11 23:14:00 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2010-08-11 23:14:00 -0400 |
commit | 708e929513502fb050c0a3c3ee267cab5b056ded (patch) | |
tree | e7b6845a3d53c5b92350f1755b4e89418f0c351c /drivers/md | |
parent | 87c961cb747fa55b664b76abfcb9d44c14ae851f (diff) |
dm: skip second flush on bio unsupported error
When processing barriers, skip the second flush if processing the bio
failed with -EOPNOTSUPP. This can happen with discard+barrier requests.
If the device doesn't support discard, there would be two useless
SYNCHRONIZE CACHE commands. The first dm_flush cannot be so easily
optimized out, so we leave it there.
Previously, -EOPNOTSUPP could be received in dec_pending only with empty
barriers and we ignored that error, assuming the device not supporting
cache flushes has cache always consistent. With the addition of discard
barriers, this -EOPNOTSUPP can also be generated by discards and we
must record it in md->barrier_error for process_barrier.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a503b95ecbfb..f3cc5d99fe8d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -639,8 +639,14 @@ static void dec_pending(struct dm_io *io, int error) | |||
639 | * There can be just one barrier request so we use | 639 | * There can be just one barrier request so we use |
640 | * a per-device variable for error reporting. | 640 | * a per-device variable for error reporting. |
641 | * Note that you can't touch the bio after end_io_acct | 641 | * Note that you can't touch the bio after end_io_acct |
642 | * | ||
643 | * We ignore -EOPNOTSUPP for empty flush reported by | ||
644 | * underlying devices. We assume that if the device | ||
645 | * doesn't support empty barriers, it doesn't need | ||
646 | * cache flushing commands. | ||
642 | */ | 647 | */ |
643 | if (!md->barrier_error && io_error != -EOPNOTSUPP) | 648 | if (!md->barrier_error && |
649 | !(bio_empty_barrier(bio) && io_error == -EOPNOTSUPP)) | ||
644 | md->barrier_error = io_error; | 650 | md->barrier_error = io_error; |
645 | end_io_acct(io); | 651 | end_io_acct(io); |
646 | free_io(md, io); | 652 | free_io(md, io); |
@@ -2284,7 +2290,12 @@ static void process_barrier(struct mapped_device *md, struct bio *bio) | |||
2284 | 2290 | ||
2285 | if (!bio_empty_barrier(bio)) { | 2291 | if (!bio_empty_barrier(bio)) { |
2286 | __split_and_process_bio(md, bio); | 2292 | __split_and_process_bio(md, bio); |
2287 | dm_flush(md); | 2293 | /* |
2294 | * If the request isn't supported, don't waste time with | ||
2295 | * the second flush. | ||
2296 | */ | ||
2297 | if (md->barrier_error != -EOPNOTSUPP) | ||
2298 | dm_flush(md); | ||
2288 | } | 2299 | } |
2289 | 2300 | ||
2290 | if (md->barrier_error != DM_ENDIO_REQUEUE) | 2301 | if (md->barrier_error != DM_ENDIO_REQUEUE) |