summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-03-31 15:52:24 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-03-31 18:02:57 -0400
commit7f102ee83d83fd918783ca542fac1574f9b2c623 (patch)
treeda560f908d970d3dbad5749c1407ed30b6965c4c /include/linux
parentd22c79d2fff10dd782caf5668fd019387914a5bb (diff)
Update bcachefs sources to 8fd009dd76 bcachefs: Rip out code for storing backpointers in alloc keysv0.28
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bio.h35
-rw-r--r--include/linux/bvec.h52
2 files changed, 77 insertions, 10 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 0ad5a87d..206e5baa 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -113,17 +113,40 @@ static inline void *bio_data(struct bio *bio)
#define __bio_kunmap_atomic(addr) kunmap_atomic(addr)
-static inline struct bio_vec *bio_next_segment(const struct bio *bio,
+static inline struct bio_vec bio_iter_all_peek(const struct bio *bio,
struct bvec_iter_all *iter)
{
- if (iter->idx >= bio->bi_vcnt)
- return NULL;
+ if (WARN_ON(iter->idx >= bio->bi_vcnt))
+ return (struct bio_vec) { NULL };
- return &bio->bi_io_vec[iter->idx];
+ return bvec_iter_all_peek(bio->bi_io_vec, iter);
}
-#define bio_for_each_segment_all(bvl, bio, iter) \
- for ((iter).idx = 0; (bvl = bio_next_segment((bio), &(iter))); (iter).idx++)
+static inline void bio_iter_all_advance(const struct bio *bio,
+ struct bvec_iter_all *iter,
+ unsigned bytes)
+{
+ bvec_iter_all_advance(bio->bi_io_vec, iter, bytes);
+
+ WARN_ON(iter->idx > bio->bi_vcnt ||
+ (iter->idx == bio->bi_vcnt && iter->done));
+}
+
+#define bio_for_each_segment_all_continue(bvl, bio, iter) \
+ for (; \
+ iter.idx < bio->bi_vcnt && \
+ ((bvl = bio_iter_all_peek(bio, &iter)), true); \
+ bio_iter_all_advance((bio), &iter, bvl.bv_len))
+
+/*
+ * drivers should _never_ use the all version - the bio may have been split
+ * before it got to the driver and the driver won't own all of it
+ */
+#define bio_for_each_segment_all(bvl, bio, iter) \
+ for (bvec_iter_all_init(&iter); \
+ iter.idx < (bio)->bi_vcnt && \
+ ((bvl = bio_iter_all_peek((bio), &iter)), true); \
+ bio_iter_all_advance((bio), &iter, bvl.bv_len))
static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
unsigned bytes)
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index 5bc68b42..a11373db 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -43,10 +43,6 @@ struct bvec_iter {
current bvec */
};
-struct bvec_iter_all {
- int idx;
-};
-
/*
* various member access, note that bio_data should of course not be used
* on highmem page vectors
@@ -98,4 +94,52 @@ static inline void bvec_iter_advance(const struct bio_vec *bv,
((bvl = bvec_iter_bvec((bio_vec), (iter))), 1); \
bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))
+/*
+ * bvec_iter_all: for advancing over individual pages in a bio, as it was when
+ * it was first created:
+ */
+struct bvec_iter_all {
+ int idx;
+ unsigned done;
+};
+
+static inline void bvec_iter_all_init(struct bvec_iter_all *iter_all)
+{
+ iter_all->done = 0;
+ iter_all->idx = 0;
+}
+
+static inline struct bio_vec __bvec_iter_all_peek(const struct bio_vec *bvec,
+ const struct bvec_iter_all *iter)
+{
+ struct bio_vec bv = bvec[iter->idx];
+
+ BUG_ON(iter->done >= bv.bv_len);
+
+ bv.bv_offset += iter->done;
+ bv.bv_len -= iter->done;
+ return bv;
+}
+
+static inline struct bio_vec bvec_iter_all_peek(const struct bio_vec *bvec,
+ const struct bvec_iter_all *iter)
+{
+ struct bio_vec bv = __bvec_iter_all_peek(bvec, iter);
+
+ bv.bv_len = min_t(unsigned, PAGE_SIZE - bv.bv_offset, bv.bv_len);
+ return bv;
+}
+
+static inline void bvec_iter_all_advance(const struct bio_vec *bvec,
+ struct bvec_iter_all *iter,
+ unsigned bytes)
+{
+ iter->done += bytes;
+
+ while (iter->done && iter->done >= bvec[iter->idx].bv_len) {
+ iter->done -= bvec[iter->idx].bv_len;
+ iter->idx++;
+ }
+}
+
#endif /* __LINUX_BVEC_ITER_H */