[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-kernel
Subject:    [PATCH] 2.5.44-ac3, cciss, more scatter gather elements
From:       Stephen Cameron <steve.cameron () hp ! com>
Date:       2002-10-25 19:59:14
[Download RAW message or body]


Add blk_rq_map_sg_one_by_one function to ll_rw_blk.c in order to allow a low 
level driver to map scatter gather elements from the block subsystem one 
at a time into device specific data structures instead of having to take 
a copy of all of them all at once and then afterwards copy them into a device 
specific format. 

To follow, a patch to the cciss driver using this interface which
allows up to 256 scatter gather elements (current limit is 31). 

-- steve

 drivers/block/ll_rw_blk.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/blkdev.h    |    4 +++
 2 files changed, 63 insertions

--- lx2544ac3/drivers/block/ll_rw_blk.c~blkdev_sg	Fri Oct 25 13:46:08 2002
+++ lx2544ac3-scameron/drivers/block/ll_rw_blk.c	Fri Oct 25 13:46:08 2002
@@ -766,6 +766,64 @@ inline int blk_hw_contig_segment(request
 }
 
 /*
+ * Map a request to a single scatterlist, one by one.  As each scatterlist is
+ * constructed consume_sg is called so the scattlerlist may be used.  The idea
+ * is the caller won't have to allocate all the space needed for a potentially
+ * large number of sg elements, instead the consume_sg callback function
+ * consumes each element as it's made.  sg_state is a pointer meant to be
+ * used by consume_sg to remember its state between calls.
+ */
+int blk_rq_map_sg_one_by_one(request_queue_t *q, struct request *rq,
+		consume_sg_callback consume_sg, void *sg_state)
+{
+	struct scatterlist sg;
+	struct bio_vec *bvec, *bvprv;
+	struct bio *bio;
+	int nsegs, i, cluster;
+
+	nsegs = 0;
+	cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
+
+	/*
+	 * for each bio in rq
+	 */
+	bvprv = NULL;
+	rq_for_each_bio(bio, rq) {
+		/*
+		 * for each segment in bio
+		 */
+		bio_for_each_segment(bvec, bio, i) {
+			int nbytes = bvec->bv_len;
+
+			if (bvprv && cluster) {
+				if (sg.length + nbytes > q->max_segment_size)
+					goto new_segment;
+
+				if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
+					goto new_segment;
+				if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
+					goto new_segment;
+
+				sg.length += nbytes;
+			} else {
+new_segment:
+				if (bvprv) consume_sg(&sg, sg_state);
+				memset(&sg,0,sizeof(struct scatterlist));
+				sg.page = bvec->bv_page;
+				sg.length = nbytes;
+				sg.offset = bvec->bv_offset;
+				nsegs++;
+			}
+			bvprv = bvec;
+		} /* segments in bio */
+	} /* bios in rq */
+
+	if (bvprv) consume_sg(&sg, sg_state);
+
+	return nsegs;
+}
+
+/*
  * map a request to scatterlist, return number of sg entries setup. Caller
  * must make sure sg can hold rq->nr_phys_segments entries
  */
@@ -2112,6 +2170,7 @@ EXPORT_SYMBOL(blk_queue_max_hw_segments)
 EXPORT_SYMBOL(blk_queue_max_segment_size);
 EXPORT_SYMBOL(blk_queue_hardsect_size);
 EXPORT_SYMBOL(blk_queue_segment_boundary);
+EXPORT_SYMBOL(blk_rq_map_sg_one_by_one);
 EXPORT_SYMBOL(blk_rq_map_sg);
 EXPORT_SYMBOL(blk_nohighio);
 EXPORT_SYMBOL(blk_dump_rq_flags);
--- lx2544ac3/include/linux/blkdev.h~blkdev_sg	Fri Oct 25 13:46:08 2002
+++ lx2544ac3-scameron/include/linux/blkdev.h	Fri Oct 25 13:46:08 2002
@@ -341,6 +341,10 @@ extern void blk_queue_prep_rq(request_qu
 extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
 
+typedef void (*consume_sg_callback)(struct scatterlist *, void *);
+extern int blk_rq_map_sg_one_by_one(request_queue_t *, struct request *,
+	consume_sg_callback consume_sg, void * sg_state);
+
 extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
 extern void generic_unplug_device(void *);

.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic