|
@@ -752,6 +752,47 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
|
|
|
}
|
|
|
EXPORT_SYMBOL(bio_add_page);
|
|
|
|
|
|
+/**
|
|
|
+ * bio_advance - increment/complete a bio by some number of bytes
|
|
|
+ * @bio: bio to advance
|
|
|
+ * @bytes: number of bytes to complete
|
|
|
+ *
|
|
|
+ * This updates bi_sector, bi_size and bi_idx; if the number of bytes to
|
|
|
+ * complete doesn't align with a bvec boundary, then bv_len and bv_offset will
|
|
|
+ * be updated on the last bvec as well.
|
|
|
+ *
|
|
|
+ * @bio will then represent the remaining, uncompleted portion of the io.
|
|
|
+ */
|
|
|
+void bio_advance(struct bio *bio, unsigned bytes)
|
|
|
+{
|
|
|
+ if (bio_integrity(bio))
|
|
|
+ bio_integrity_advance(bio, bytes);
|
|
|
+
|
|
|
+ bio->bi_sector += bytes >> 9;
|
|
|
+ bio->bi_size -= bytes;
|
|
|
+
|
|
|
+ if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK)
|
|
|
+ return;
|
|
|
+
|
|
|
+ while (bytes) {
|
|
|
+ if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
|
|
|
+ WARN_ONCE(1, "bio idx %d >= vcnt %d\n",
|
|
|
+ bio->bi_idx, bio->bi_vcnt);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bytes >= bio_iovec(bio)->bv_len) {
|
|
|
+ bytes -= bio_iovec(bio)->bv_len;
|
|
|
+ bio->bi_idx++;
|
|
|
+ } else {
|
|
|
+ bio_iovec(bio)->bv_len -= bytes;
|
|
|
+ bio_iovec(bio)->bv_offset += bytes;
|
|
|
+ bytes = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(bio_advance);
|
|
|
+
|
|
|
struct bio_map_data {
|
|
|
struct bio_vec *iovecs;
|
|
|
struct sg_iovec *sgvecs;
|