summaryrefslogtreecommitdiffstats
path: root/fs/bio.c
diff options
context:
space:
mode:
authorKent Overstreet <koverstreet@google.com>2012-09-10 14:03:28 -0700
committerKent Overstreet <koverstreet@google.com>2013-03-23 14:26:31 -0700
commita07876064a0b73ab5ef1ebcf14b1cf0231c07858 (patch)
tree74a0567401bcdb60f5a8e65c76d5a3a21aeb548f /fs/bio.c
parentcb34e057ad22a1c2c6f2cb6cd1cbd05cc2f28f28 (diff)
block: Add bio_alloc_pages()
More utility code to replace stuff that's getting open coded. Signed-off-by: Kent Overstreet <koverstreet@google.com> CC: Jens Axboe <axboe@kernel.dk> CC: NeilBrown <neilb@suse.de>
Diffstat (limited to 'fs/bio.c')
-rw-r--r--fs/bio.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/fs/bio.c b/fs/bio.c
index fe3aee90c98..e545a440d37 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -830,6 +830,34 @@ void bio_advance(struct bio *bio, unsigned bytes)
EXPORT_SYMBOL(bio_advance);
/**
+ * bio_alloc_pages - allocates a single page for each bvec in a bio
+ * @bio: bio to allocate pages for
+ * @gfp_mask: flags for allocation
+ *
+ * Allocates pages up to @bio->bi_vcnt.
+ *
+ * Returns 0 on success, -ENOMEM on failure. On failure, any allocated pages are
+ * freed.
+ */
+int bio_alloc_pages(struct bio *bio, gfp_t gfp_mask)
+{
+ int i;
+ struct bio_vec *bv;
+
+ bio_for_each_segment_all(bv, bio, i) {
+ bv->bv_page = alloc_page(gfp_mask);
+ if (!bv->bv_page) {
+ while (--bv >= bio->bi_io_vec)
+ __free_page(bv->bv_page);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(bio_alloc_pages);
+
+/**
* bio_copy_data - copy contents of data buffers from one chain of bios to
* another
* @src: source bio list