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 <hare@suse.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> [hch: switched to true/false return] Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:

committed by
Jens Axboe

parent
b1fb2c52b2
commit
f9df1cd99e
@@ -40,6 +40,8 @@ struct bvec_iter {
|
||||
|
||||
unsigned int bi_idx; /* current index into bvl_vec */
|
||||
|
||||
unsigned int bi_done; /* number of bytes completed */
|
||||
|
||||
unsigned int bi_bvec_done; /* number of bytes completed in
|
||||
current bvec */
|
||||
};
|
||||
@@ -83,6 +85,7 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv,
|
||||
bytes -= len;
|
||||
iter->bi_size -= len;
|
||||
iter->bi_bvec_done += len;
|
||||
iter->bi_done += len;
|
||||
|
||||
if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) {
|
||||
iter->bi_bvec_done = 0;
|
||||
@@ -92,6 +95,30 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool bvec_iter_rewind(const struct bio_vec *bv,
|
||||
struct bvec_iter *iter,
|
||||
unsigned int bytes)
|
||||
{
|
||||
while (bytes) {
|
||||
unsigned len = min(bytes, iter->bi_bvec_done);
|
||||
|
||||
if (iter->bi_bvec_done == 0) {
|
||||
if (WARN_ONCE(iter->bi_idx == 0,
|
||||
"Attempted to rewind iter beyond "
|
||||
"bvec's boundaries\n")) {
|
||||
return false;
|
||||
}
|
||||
iter->bi_idx--;
|
||||
iter->bi_bvec_done = __bvec_iter_bvec(bv, *iter)->bv_len;
|
||||
continue;
|
||||
}
|
||||
bytes -= len;
|
||||
iter->bi_size += len;
|
||||
iter->bi_bvec_done -= len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define for_each_bvec(bvl, bio_vec, iter, start) \
|
||||
for (iter = (start); \
|
||||
(iter).bi_size && \
|
||||
|
Reference in New Issue
Block a user