summaryrefslogtreecommitdiff
path: root/include/linux/bvec.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/bvec.h')
-rw-r--r--include/linux/bvec.h112
1 files changed, 78 insertions, 34 deletions
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index d36dd476feda..92837e2743f1 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -74,6 +74,21 @@ static inline void bvec_set_virt(struct bio_vec *bv, void *vaddr,
bvec_set_page(bv, virt_to_page(vaddr), len, offset_in_page(vaddr));
}
+/**
+ * bvec_folio - Return the first folio referenced by this bvec
+ * @bv: bvec to access
+ *
+ * A bvec can contain non-folio memory, so this should only be called by
+ * the creator of the bvec; drivers have no business looking at the owner
+ * of the memory. It may not even be the right interface for the caller
+ * to use as a bvec can span multiple folios. You may be better off using
+ * something like bio_for_each_folio_all() which iterates over all folios.
+ */
+static inline struct folio *bvec_folio(const struct bio_vec *bv)
+{
+ return page_folio(bv->bv_page);
+}
+
struct bvec_iter {
/*
* Current device address in 512 byte sectors. Only updated by the bio
@@ -104,51 +119,78 @@ struct bvec_iter_all {
unsigned done;
};
-/*
- * various member access, note that bio_data should of course not be used
- * on highmem page vectors
- */
-#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx])
+static __always_inline const struct bio_vec *
+__bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return bvecs + iter.bi_idx;
+}
/* multi-page (mp_bvec) helpers */
-#define mp_bvec_iter_page(bvec, iter) \
- (__bvec_iter_bvec((bvec), (iter))->bv_page)
+static __always_inline struct page *
+mp_bvec_iter_page(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return __bvec_iter_bvec(bvecs, iter)->bv_page;
+}
-#define mp_bvec_iter_len(bvec, iter) \
- min((iter).bi_size, \
- __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
+static __always_inline unsigned int
+mp_bvec_iter_len(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return min(__bvec_iter_bvec(bvecs, iter)->bv_len - iter.bi_bvec_done,
+ iter.bi_size);
+}
-#define mp_bvec_iter_offset(bvec, iter) \
- (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
+static __always_inline unsigned int
+mp_bvec_iter_offset(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return __bvec_iter_bvec(bvecs, iter)->bv_offset + iter.bi_bvec_done;
+}
-#define mp_bvec_iter_page_idx(bvec, iter) \
- (mp_bvec_iter_offset((bvec), (iter)) / PAGE_SIZE)
+static __always_inline unsigned int
+mp_bvec_iter_page_idx(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return mp_bvec_iter_offset(bvecs, iter) / PAGE_SIZE;
+}
-#define mp_bvec_iter_bvec(bvec, iter) \
-((struct bio_vec) { \
- .bv_page = mp_bvec_iter_page((bvec), (iter)), \
- .bv_len = mp_bvec_iter_len((bvec), (iter)), \
- .bv_offset = mp_bvec_iter_offset((bvec), (iter)), \
-})
+static __always_inline struct bio_vec
+mp_bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return (struct bio_vec) {
+ .bv_page = mp_bvec_iter_page(bvecs, iter),
+ .bv_len = mp_bvec_iter_len(bvecs, iter),
+ .bv_offset = mp_bvec_iter_offset(bvecs, iter),
+ };
+}
/* For building single-page bvec in flight */
- #define bvec_iter_offset(bvec, iter) \
- (mp_bvec_iter_offset((bvec), (iter)) % PAGE_SIZE)
+static __always_inline unsigned int
+bvec_iter_offset(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return mp_bvec_iter_offset(bvecs, iter) % PAGE_SIZE;
+}
-#define bvec_iter_len(bvec, iter) \
- min_t(unsigned, mp_bvec_iter_len((bvec), (iter)), \
- PAGE_SIZE - bvec_iter_offset((bvec), (iter)))
+static __always_inline unsigned int
+bvec_iter_len(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return min(mp_bvec_iter_len(bvecs, iter),
+ PAGE_SIZE - bvec_iter_offset(bvecs, iter));
+}
-#define bvec_iter_page(bvec, iter) \
- (mp_bvec_iter_page((bvec), (iter)) + \
- mp_bvec_iter_page_idx((bvec), (iter)))
+static __always_inline struct page *
+bvec_iter_page(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return mp_bvec_iter_page(bvecs, iter) +
+ mp_bvec_iter_page_idx(bvecs, iter);
+}
-#define bvec_iter_bvec(bvec, iter) \
-((struct bio_vec) { \
- .bv_page = bvec_iter_page((bvec), (iter)), \
- .bv_len = bvec_iter_len((bvec), (iter)), \
- .bv_offset = bvec_iter_offset((bvec), (iter)), \
-})
+static __always_inline struct bio_vec
+bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return (struct bio_vec) {
+ .bv_page = bvec_iter_page(bvecs, iter),
+ .bv_len = bvec_iter_len(bvecs, iter),
+ .bv_offset = bvec_iter_offset(bvecs, iter),
+ };
+}
static inline bool bvec_iter_advance(const struct bio_vec *bv,
struct bvec_iter *iter, unsigned bytes)
@@ -247,6 +289,7 @@ static inline void *bvec_kmap_local(struct bio_vec *bvec)
/**
* memcpy_from_bvec - copy data from a bvec
+ * @to: Kernel virtual address to copy to.
* @bvec: bvec to copy from
*
* Must be called on single-page bvecs only.
@@ -259,6 +302,7 @@ static inline void memcpy_from_bvec(char *to, struct bio_vec *bvec)
/**
* memcpy_to_bvec - copy data to a bvec
* @bvec: bvec to copy to
+ * @from: Kernel virtual address to copy from.
*
* Must be called on single-page bvecs only.
*/