Skip to content

Commit f9df1cd

Browse files
Dmitry Monakhovaxboe
authored andcommitted
bio: add bvec_iter rewind API
Some ->bi_end_io handlers (for example: pi_verify or decrypt handlers) need to know original data vector, but after bio traverse io-stack it may be advanced, splited and relocated many times so it is hard to guess original iterator. Let's add 'bi_done' conter which accounts number of bytes iterator was advanced during it's evolution. Later end_io handler may easily restore original iterator by rewinding iterator to iter->bi_done. Note: this change makes sizeof (struct bvec_iter) multiple to 8 Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Dmitry Monakhov <[email protected]> [hch: switched to true/false return] Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent b1fb2c5 commit f9df1cd

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

include/linux/bio.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,29 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
165165
{
166166
iter->bi_sector += bytes >> 9;
167167

168-
if (bio_no_advance_iter(bio))
168+
if (bio_no_advance_iter(bio)) {
169169
iter->bi_size -= bytes;
170-
else {
170+
iter->bi_done += bytes;
171+
} else {
171172
bvec_iter_advance(bio->bi_io_vec, iter, bytes);
172173
/* TODO: It is reasonable to complete bio with error here. */
173174
}
174175
}
175176

177+
static inline bool bio_rewind_iter(struct bio *bio, struct bvec_iter *iter,
178+
unsigned int bytes)
179+
{
180+
iter->bi_sector -= bytes >> 9;
181+
182+
if (bio_no_advance_iter(bio)) {
183+
iter->bi_size += bytes;
184+
iter->bi_done -= bytes;
185+
return true;
186+
}
187+
188+
return bvec_iter_rewind(bio->bi_io_vec, iter, bytes);
189+
}
190+
176191
#define __bio_for_each_segment(bvl, bio, iter, start) \
177192
for (iter = (start); \
178193
(iter).bi_size && \

include/linux/bvec.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ struct bvec_iter {
4040

4141
unsigned int bi_idx; /* current index into bvl_vec */
4242

43+
unsigned int bi_done; /* number of bytes completed */
44+
4345
unsigned int bi_bvec_done; /* number of bytes completed in
4446
current bvec */
4547
};
@@ -83,6 +85,7 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv,
8385
bytes -= len;
8486
iter->bi_size -= len;
8587
iter->bi_bvec_done += len;
88+
iter->bi_done += len;
8689

8790
if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) {
8891
iter->bi_bvec_done = 0;
@@ -92,6 +95,30 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv,
9295
return true;
9396
}
9497

98+
static inline bool bvec_iter_rewind(const struct bio_vec *bv,
99+
struct bvec_iter *iter,
100+
unsigned int bytes)
101+
{
102+
while (bytes) {
103+
unsigned len = min(bytes, iter->bi_bvec_done);
104+
105+
if (iter->bi_bvec_done == 0) {
106+
if (WARN_ONCE(iter->bi_idx == 0,
107+
"Attempted to rewind iter beyond "
108+
"bvec's boundaries\n")) {
109+
return false;
110+
}
111+
iter->bi_idx--;
112+
iter->bi_bvec_done = __bvec_iter_bvec(bv, *iter)->bv_len;
113+
continue;
114+
}
115+
bytes -= len;
116+
iter->bi_size += len;
117+
iter->bi_bvec_done -= len;
118+
}
119+
return true;
120+
}
121+
95122
#define for_each_bvec(bvl, bio_vec, iter, start) \
96123
for (iter = (start); \
97124
(iter).bi_size && \

0 commit comments

Comments
 (0)