diff options
author | Tejun Heo <tj@kernel.org> | 2010-09-03 05:56:17 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-09-10 06:35:37 -0400 |
commit | 4fed947cb311e5aa51781d316cefca836352f6ce (patch) | |
tree | eada83d5bf503244628e3c190e97e8c7af847e35 /include | |
parent | dd4c133f387c48f526022860ad70354637a80f4c (diff) |
block: implement REQ_FLUSH/FUA based interface for FLUSH/FUA requests
Now that the backend conversion is complete, export sequenced
FLUSH/FUA capability through REQ_FLUSH/FUA flags. REQ_FLUSH means the
device cache should be flushed before executing the request. REQ_FUA
means that the data in the request should be on non-volatile media on
completion.
Block layer will choose the correct way of implementing the semantics
and execute it. The request may be passed to the device directly if
the device can handle it; otherwise, it will be sequenced using one or
more proxy requests. Devices will never see REQ_FLUSH and/or FUA
which it doesn't support.
Also, unlike the original REQ_HARDBARRIER, REQ_FLUSH/FUA requests are
never failed with -EOPNOTSUPP. If the underlying device doesn't
support FLUSH/FUA, the block layer simply make those noop. IOW, it no
longer distinguishes between writeback cache which doesn't support
cache flush and writethrough/no cache. Devices which have WB cache
w/o flush are very difficult to come by these days and there's nothing
much we can do anyway, so it doesn't make sense to require everyone to
implement -EOPNOTSUPP handling. This will simplify filesystems and
block drivers as they can drop -EOPNOTSUPP retry logic for barriers.
* QUEUE_ORDERED_* are removed and QUEUE_FSEQ_* are moved into
blk-flush.c.
* REQ_FLUSH w/o data can also be directly passed to drivers without
sequencing but some drivers assume that zero length requests don't
have rq->bio which isn't true for these requests requiring the use
of proxy requests.
* REQ_COMMON_MASK now includes REQ_FLUSH | REQ_FUA so that they are
copied from bio to request.
* WRITE_BARRIER is marked deprecated and WRITE_FLUSH, WRITE_FUA and
WRITE_FLUSH_FUA are added.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/blk_types.h | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 38 | ||||
-rw-r--r-- | include/linux/buffer_head.h | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 19 |
4 files changed, 17 insertions, 44 deletions
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 9192282b4259..179799479e6f 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
@@ -167,7 +167,7 @@ enum rq_flag_bits { | |||
167 | (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) | 167 | (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) |
168 | #define REQ_COMMON_MASK \ | 168 | #define REQ_COMMON_MASK \ |
169 | (REQ_WRITE | REQ_FAILFAST_MASK | REQ_HARDBARRIER | REQ_SYNC | \ | 169 | (REQ_WRITE | REQ_FAILFAST_MASK | REQ_HARDBARRIER | REQ_SYNC | \ |
170 | REQ_META| REQ_DISCARD | REQ_NOIDLE) | 170 | REQ_META | REQ_DISCARD | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) |
171 | 171 | ||
172 | #define REQ_UNPLUG (1 << __REQ_UNPLUG) | 172 | #define REQ_UNPLUG (1 << __REQ_UNPLUG) |
173 | #define REQ_RAHEAD (1 << __REQ_RAHEAD) | 173 | #define REQ_RAHEAD (1 << __REQ_RAHEAD) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1cd83ec077db..8ef705f800ab 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -357,7 +357,6 @@ struct request_queue | |||
357 | /* | 357 | /* |
358 | * for flush operations | 358 | * for flush operations |
359 | */ | 359 | */ |
360 | unsigned int ordered, next_ordered; | ||
361 | unsigned int flush_flags; | 360 | unsigned int flush_flags; |
362 | unsigned int flush_seq; | 361 | unsigned int flush_seq; |
363 | int flush_err; | 362 | int flush_err; |
@@ -465,40 +464,6 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) | |||
465 | __clear_bit(flag, &q->queue_flags); | 464 | __clear_bit(flag, &q->queue_flags); |
466 | } | 465 | } |
467 | 466 | ||
468 | enum { | ||
469 | /* | ||
470 | * Hardbarrier is supported with one of the following methods. | ||
471 | * | ||
472 | * NONE : hardbarrier unsupported | ||
473 | * DRAIN : ordering by draining is enough | ||
474 | * DRAIN_FLUSH : ordering by draining w/ pre and post flushes | ||
475 | * DRAIN_FUA : ordering by draining w/ pre flush and FUA write | ||
476 | */ | ||
477 | QUEUE_ORDERED_DO_PREFLUSH = 0x10, | ||
478 | QUEUE_ORDERED_DO_BAR = 0x20, | ||
479 | QUEUE_ORDERED_DO_POSTFLUSH = 0x40, | ||
480 | QUEUE_ORDERED_DO_FUA = 0x80, | ||
481 | |||
482 | QUEUE_ORDERED_NONE = 0x00, | ||
483 | |||
484 | QUEUE_ORDERED_DRAIN = QUEUE_ORDERED_DO_BAR, | ||
485 | QUEUE_ORDERED_DRAIN_FLUSH = QUEUE_ORDERED_DRAIN | | ||
486 | QUEUE_ORDERED_DO_PREFLUSH | | ||
487 | QUEUE_ORDERED_DO_POSTFLUSH, | ||
488 | QUEUE_ORDERED_DRAIN_FUA = QUEUE_ORDERED_DRAIN | | ||
489 | QUEUE_ORDERED_DO_PREFLUSH | | ||
490 | QUEUE_ORDERED_DO_FUA, | ||
491 | |||
492 | /* | ||
493 | * FLUSH/FUA sequences. | ||
494 | */ | ||
495 | QUEUE_FSEQ_STARTED = (1 << 0), /* flushing in progress */ | ||
496 | QUEUE_FSEQ_PREFLUSH = (1 << 1), /* pre-flushing in progress */ | ||
497 | QUEUE_FSEQ_DATA = (1 << 2), /* data write in progress */ | ||
498 | QUEUE_FSEQ_POSTFLUSH = (1 << 3), /* post-flushing in progress */ | ||
499 | QUEUE_FSEQ_DONE = (1 << 4), | ||
500 | }; | ||
501 | |||
502 | #define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) | 467 | #define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) |
503 | #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) | 468 | #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) |
504 | #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) | 469 | #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) |
@@ -578,7 +543,8 @@ static inline void blk_clear_queue_full(struct request_queue *q, int sync) | |||
578 | * it already be started by driver. | 543 | * it already be started by driver. |
579 | */ | 544 | */ |
580 | #define RQ_NOMERGE_FLAGS \ | 545 | #define RQ_NOMERGE_FLAGS \ |
581 | (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER) | 546 | (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER | \ |
547 | REQ_FLUSH | REQ_FUA) | ||
582 | #define rq_mergeable(rq) \ | 548 | #define rq_mergeable(rq) \ |
583 | (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \ | 549 | (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \ |
584 | (((rq)->cmd_flags & REQ_DISCARD) || \ | 550 | (((rq)->cmd_flags & REQ_DISCARD) || \ |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index ec94c12f21da..fc999f583fda 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
@@ -32,7 +32,7 @@ enum bh_state_bits { | |||
32 | BH_Delay, /* Buffer is not yet allocated on disk */ | 32 | BH_Delay, /* Buffer is not yet allocated on disk */ |
33 | BH_Boundary, /* Block is followed by a discontiguity */ | 33 | BH_Boundary, /* Block is followed by a discontiguity */ |
34 | BH_Write_EIO, /* I/O error on write */ | 34 | BH_Write_EIO, /* I/O error on write */ |
35 | BH_Eopnotsupp, /* operation not supported (barrier) */ | 35 | BH_Eopnotsupp, /* DEPRECATED: operation not supported (barrier) */ |
36 | BH_Unwritten, /* Buffer is allocated on disk but not written */ | 36 | BH_Unwritten, /* Buffer is allocated on disk but not written */ |
37 | BH_Quiet, /* Buffer Error Prinks to be quiet */ | 37 | BH_Quiet, /* Buffer Error Prinks to be quiet */ |
38 | 38 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 76041b614758..352c48627381 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -135,12 +135,13 @@ struct inodes_stat_t { | |||
135 | * immediately after submission. The write equivalent | 135 | * immediately after submission. The write equivalent |
136 | * of READ_SYNC. | 136 | * of READ_SYNC. |
137 | * WRITE_ODIRECT_PLUG Special case write for O_DIRECT only. | 137 | * WRITE_ODIRECT_PLUG Special case write for O_DIRECT only. |
138 | * WRITE_BARRIER Like WRITE_SYNC, but tells the block layer that all | 138 | * WRITE_BARRIER DEPRECATED. Always fails. Use FLUSH/FUA instead. |
139 | * previously submitted writes must be safely on storage | 139 | * WRITE_FLUSH Like WRITE_SYNC but with preceding cache flush. |
140 | * before this one is started. Also guarantees that when | 140 | * WRITE_FUA Like WRITE_SYNC but data is guaranteed to be on |
141 | * this write is complete, it itself is also safely on | 141 | * non-volatile media on completion. |
142 | * storage. Prevents reordering of writes on both sides | 142 | * WRITE_FLUSH_FUA Combination of WRITE_FLUSH and FUA. The IO is preceded |
143 | * of this IO. | 143 | * by a cache flush and data is guaranteed to be on |
144 | * non-volatile media on completion. | ||
144 | * | 145 | * |
145 | */ | 146 | */ |
146 | #define RW_MASK REQ_WRITE | 147 | #define RW_MASK REQ_WRITE |
@@ -158,6 +159,12 @@ struct inodes_stat_t { | |||
158 | #define WRITE_META (WRITE | REQ_META) | 159 | #define WRITE_META (WRITE | REQ_META) |
159 | #define WRITE_BARRIER (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ | 160 | #define WRITE_BARRIER (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ |
160 | REQ_HARDBARRIER) | 161 | REQ_HARDBARRIER) |
162 | #define WRITE_FLUSH (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ | ||
163 | REQ_FLUSH) | ||
164 | #define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ | ||
165 | REQ_FUA) | ||
166 | #define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ | ||
167 | REQ_FLUSH | REQ_FUA) | ||
161 | 168 | ||
162 | /* | 169 | /* |
163 | * These aren't really reads or writes, they pass down information about | 170 | * These aren't really reads or writes, they pass down information about |