diff options
author | Christoph Hellwig <hch@lst.de> | 2016-10-20 09:12:15 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-10-28 10:48:54 -0400 |
commit | 87374179c535a98337569904727aa02f960fe79e (patch) | |
tree | 6c71566fb8bda79fbf683e60e207739cbae50bad | |
parent | ef295ecf090d3e86e5b742fc6ab34f1122a43773 (diff) |
block: add a proper block layer data direction encoding
Currently the block layer op_is_write, bio_data_dir and rq_data_dir
helper treat every operation that is not a READ as a data out operation.
This worked surprisingly long, but the new REQ_OP_ZONE_REPORT operation
actually adds a second operation that reads data from the device.
Surprisingly nothing critical relied on this direction, but this might
be a good opportunity to properly fix this issue up.
We take a little inspiration and use the least significant bit of the
operation number to encode the data direction, which just requires us
to renumber the operations to fix this scheme.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Shaun Tancheff <shaun.tancheff@seagate.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | include/linux/blk_types.h | 38 | ||||
-rw-r--r-- | include/linux/fs.h | 5 |
2 files changed, 30 insertions, 13 deletions
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index dca972d67548..3fa62cabe8d2 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
@@ -131,20 +131,37 @@ struct bio { | |||
131 | /* | 131 | /* |
132 | * Operations and flags common to the bio and request structures. | 132 | * Operations and flags common to the bio and request structures. |
133 | * We use 8 bits for encoding the operation, and the remaining 24 for flags. | 133 | * We use 8 bits for encoding the operation, and the remaining 24 for flags. |
134 | * | ||
135 | * The least significant bit of the operation number indicates the data | ||
136 | * transfer direction: | ||
137 | * | ||
138 | * - if the least significant bit is set transfers are TO the device | ||
139 | * - if the least significant bit is not set transfers are FROM the device | ||
140 | * | ||
141 | * If a operation does not transfer data the least significant bit has no | ||
142 | * meaning. | ||
134 | */ | 143 | */ |
135 | #define REQ_OP_BITS 8 | 144 | #define REQ_OP_BITS 8 |
136 | #define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1) | 145 | #define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1) |
137 | #define REQ_FLAG_BITS 24 | 146 | #define REQ_FLAG_BITS 24 |
138 | 147 | ||
139 | enum req_opf { | 148 | enum req_opf { |
140 | REQ_OP_READ, | 149 | /* read sectors from the device */ |
141 | REQ_OP_WRITE, | 150 | REQ_OP_READ = 0, |
142 | REQ_OP_DISCARD, /* request to discard sectors */ | 151 | /* write sectors to the device */ |
143 | REQ_OP_SECURE_ERASE, /* request to securely erase sectors */ | 152 | REQ_OP_WRITE = 1, |
144 | REQ_OP_WRITE_SAME, /* write same block many times */ | 153 | /* flush the volatile write cache */ |
145 | REQ_OP_FLUSH, /* request for cache flush */ | 154 | REQ_OP_FLUSH = 2, |
146 | REQ_OP_ZONE_REPORT, /* Get zone information */ | 155 | /* discard sectors */ |
147 | REQ_OP_ZONE_RESET, /* Reset a zone write pointer */ | 156 | REQ_OP_DISCARD = 3, |
157 | /* get zone information */ | ||
158 | REQ_OP_ZONE_REPORT = 4, | ||
159 | /* securely erase sectors */ | ||
160 | REQ_OP_SECURE_ERASE = 5, | ||
161 | /* seset a zone write pointer */ | ||
162 | REQ_OP_ZONE_RESET = 6, | ||
163 | /* write the same sector many times */ | ||
164 | REQ_OP_WRITE_SAME = 7, | ||
148 | 165 | ||
149 | REQ_OP_LAST, | 166 | REQ_OP_LAST, |
150 | }; | 167 | }; |
@@ -194,6 +211,11 @@ enum req_flag_bits { | |||
194 | #define bio_set_op_attrs(bio, op, op_flags) \ | 211 | #define bio_set_op_attrs(bio, op, op_flags) \ |
195 | ((bio)->bi_opf |= (op | op_flags)) | 212 | ((bio)->bi_opf |= (op | op_flags)) |
196 | 213 | ||
214 | static inline bool op_is_write(unsigned int op) | ||
215 | { | ||
216 | return (op & 1); | ||
217 | } | ||
218 | |||
197 | static inline bool op_is_sync(unsigned int op) | 219 | static inline bool op_is_sync(unsigned int op) |
198 | { | 220 | { |
199 | return (op & REQ_OP_MASK) == REQ_OP_READ || (op & REQ_SYNC); | 221 | return (op & REQ_OP_MASK) == REQ_OP_READ || (op & REQ_SYNC); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 16d2b6e874d6..e3e878f12b25 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2499,11 +2499,6 @@ extern void make_bad_inode(struct inode *); | |||
2499 | extern bool is_bad_inode(struct inode *); | 2499 | extern bool is_bad_inode(struct inode *); |
2500 | 2500 | ||
2501 | #ifdef CONFIG_BLOCK | 2501 | #ifdef CONFIG_BLOCK |
2502 | static inline bool op_is_write(unsigned int op) | ||
2503 | { | ||
2504 | return op == REQ_OP_READ ? false : true; | ||
2505 | } | ||
2506 | |||
2507 | /* | 2502 | /* |
2508 | * return data direction, READ or WRITE | 2503 | * return data direction, READ or WRITE |
2509 | */ | 2504 | */ |