|
|
@@ -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 && \
|