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:
parent
b1fb2c52b2
commit
f9df1cd99e
|
@ -165,14 +165,29 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
|
|||
{
|
||||
iter->bi_sector += bytes >> 9;
|
||||
|
||||
if (bio_no_advance_iter(bio))
|
||||
if (bio_no_advance_iter(bio)) {
|
||||
iter->bi_size -= bytes;
|
||||
else {
|
||||
iter->bi_done += bytes;
|
||||
} else {
|
||||
bvec_iter_advance(bio->bi_io_vec, iter, bytes);
|
||||
/* TODO: It is reasonable to complete bio with error here. */
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool bio_rewind_iter(struct bio *bio, struct bvec_iter *iter,
|
||||
unsigned int bytes)
|
||||
{
|
||||
iter->bi_sector -= bytes >> 9;
|
||||
|
||||
if (bio_no_advance_iter(bio)) {
|
||||
iter->bi_size += bytes;
|
||||
iter->bi_done -= bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
return bvec_iter_rewind(bio->bi_io_vec, iter, bytes);
|
||||
}
|
||||
|
||||
#define __bio_for_each_segment(bvl, bio, iter, start) \
|
||||
for (iter = (start); \
|
||||
(iter).bi_size && \
|
||||
|
|
|
@ -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 && \
|
||||
|
|
Loading…
Reference in New Issue