summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/bio.c16
-rw-r--r--include/linux/bio.h1
2 files changed, 16 insertions, 1 deletions
diff --git a/block/bio.c b/block/bio.c
index 586e11dbf507..69654714d629 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -855,7 +855,20 @@ static void bio_get_pages(struct bio *bio)
get_page(bvec->bv_page);
}
-static void bio_release_pages(struct bio *bio, bool from_gup)
+/**
+ * bio_release_pages() - release all pages in a bio
+ * @bio: the bio struct containing the pages to release
+ * @from_gup: did the pages in the bio came from GUP (get_user_pages*())
+ *
+ * This will release page reference for all the pages in the bio.
+ *
+ * We also need to know if the pages in the bio are coming from GUP or not as
+ * GUPed page need to be release through specific put_user_page(). Please see
+ * Documentation/vm/get_user_pages.rst for details on that. Rules of dumb is
+ * that if the bio has been populated with the help of iov_iter_get_pages*()
+ * then it might have GUPed pages (see iov_iter_get_pages_use_gup())
+ */
+void bio_release_pages(struct bio *bio, bool from_gup)
{
struct bio_vec *bvec;
struct bvec_iter_all iter_all;
@@ -868,6 +881,7 @@ static void bio_release_pages(struct bio *bio, bool from_gup)
put_page(bvec->bv_page);
}
}
+EXPORT_SYMBOL_GPL(bio_release_pages);
static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
{
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 06d334fe38f9..ed861951db45 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -436,6 +436,7 @@ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int,
gfp_t, int);
extern void bio_set_pages_dirty(struct bio *bio);
+extern void bio_release_pages(struct bio *bio, bool from_gup);
extern void bio_check_pages_dirty(struct bio *bio, bool from_gup);
void generic_start_io_acct(struct request_queue *q, int op,