[RFC C 1/5] blk_rq_map_pages() new API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Define a new API for mapping array of pages into a request.

Internally the bio is created using the
rq_map_data + null_mapped + NULL_buffer mode of
bio_copy_user(). The bio is only referenced once
and there is no unmap function to call.

TODO:
   out of the 7 users of blk_rq_map_user + rq_map_data, 6 of them
   are null_mapped + NULL_buffer and could be converted to this
   API.

Signed-off-by: Boaz Harrosh <bharrosh@xxxxxxxxxxx>
---
 block/blk-map.c        |   54 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/blkdev.h |    3 ++
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/block/blk-map.c b/block/blk-map.c
index ada399e..60a7a0b 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -325,3 +325,57 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
 	return 0;
 }
 EXPORT_SYMBOL(blk_rq_map_kern);
+
+/**
+ * blk_rq_map_pages - map pages array to a request, for REQ_TYPE_BLOCK_PC usage
+ * @q:		request queue where request should be inserted
+ * @rq:		request to fill
+ * @pages:	an array of struct page pointers to map
+ * @nr_pages:	count of valid pages at @pages
+ * @offset:	Offset into first page to start from (Must be blk_rq_aligned())
+ * @len:	length of user data to map
+ * @gfp_mask:	memory allocation flags
+ *
+ * Description:
+ *    Data will be mapped directly if possible. Otherwise a bounce
+ *    buffer is used. Can be called multiple times to append multiple
+ *    page arrays. No need to call an unmap function, and bio is only
+ *    referenced once. (Pages are of zero order)
+ */
+int blk_rq_map_pages(struct request_queue *q, struct request *rq,
+		    struct page **pages, unsigned nr_pages,
+		    unsigned long offset, unsigned len, gfp_t gfp_mask)
+{
+	struct bio *bio;
+	int reading, ret;
+	struct rq_map_data map_data = {
+		.pages = pages,
+		.nr_entries = nr_pages,
+		.offset = offset,
+		.null_mapped = 1,
+		.page_order = 0,
+	};
+
+	reading = rq_data_dir(rq) == READ;
+
+	/* The name is confusing, but bio_copy_user+map_data+NULL_buffer
+         * Actually just adds the pages to the bio, no copy is performed.
+	 */
+	bio = bio_copy_user(q, &map_data, 0, len, reading, gfp_mask);
+
+	if (IS_ERR(bio))
+		return PTR_ERR(bio);
+
+	bio->bi_flags |= (1 << BIO_NULL_MAPPED);
+
+	/* We might still need to bounce if memory mask does not match */
+	blk_queue_bounce(q, &bio);
+
+	ret = blk_rq_append_bio(q, rq, bio);
+	if (likely(!ret))
+		return 0;
+
+	bio_put(bio);
+	return ret;
+}
+EXPORT_SYMBOL(blk_rq_map_pages);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 22dcdde..81b681c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -784,6 +784,9 @@ extern int blk_rq_map_user(struct request_queue *, struct request *,
 extern int blk_rq_unmap_user(struct bio *);
 extern int blk_rq_map_kern(struct request_queue *, struct request *, void *,
 			   unsigned int, gfp_t);
+extern int blk_rq_map_pages(struct request_queue *, struct request *,
+			    struct page **, unsigned, unsigned long offset,
+			    unsigned , gfp_t);
 extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
 			       struct rq_map_data *, struct sg_iovec *, int,
 			       unsigned int, gfp_t);
-- 
1.6.2.1


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux