Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5705f702 authored by NeilBrown's avatar NeilBrown Committed by Jens Axboe
Browse files

Introduce rq_for_each_segment replacing rq_for_each_bio



Every usage of rq_for_each_bio wraps a usage of
bio_for_each_segment, so these can be combined into
rq_for_each_segment.

We define "struct req_iterator" to hold the 'bio' and 'index' that
are needed for the double iteration.

Signed-off-by: default avatarNeil Brown <neilb@suse.de>

Various compile fixes by me...

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 9dfa5283
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -477,9 +477,9 @@ With this multipage bio design:
  the same bi_io_vec array, but with the index and size accordingly modified)
- A linked list of bios is used as before for unrelated merges (*) - this
  avoids reallocs and makes independent completions easier to handle.
- Code that traverses the req list needs to make a distinction between
  segments of a request (bio_for_each_segment) and the distinct completion
  units/bios (rq_for_each_bio).
- Code that traverses the req list can find all the segments of a bio
  by using rq_for_each_segment.  This handles the fact that a request
  has multiple bios, each of which can have multiple segments.
- Drivers which can't process a large bio in one shot can use the bi_idx
  field to keep track of the next bio_vec entry to process.
  (e.g a 1MB bio_vec needs to be handled in max 128kB chunks for IDE)
@@ -664,13 +664,13 @@ in lvm or md.

3.2.1 Traversing segments and completion units in a request

The macros bio_for_each_segment() and rq_for_each_bio() should be used for
traversing the bios in the request list (drivers should avoid directly
trying to do it themselves). Using these helpers should also make it easier
to cope with block changes in the future.
The macro rq_for_each_segment() should be used for traversing the bios
in the request list (drivers should avoid directly trying to do it
themselves). Using these helpers should also make it easier to cope
with block changes in the future.

	rq_for_each_bio(bio, rq)
		bio_for_each_segment(bio_vec, bio, i)
	struct req_iterator iter;
	rq_for_each_segment(bio_vec, rq, iter)
		/* bio_vec is now current segment */

I/O completion callbacks are per-bio rather than per-segment, so drivers
+6 −13
Original line number Diff line number Diff line
@@ -1244,8 +1244,7 @@ static void blk_recalc_rq_segments(struct request *rq)
	int seg_size;
	int hw_seg_size;
	int cluster;
	struct bio *bio;
	int i;
	struct req_iterator iter;
	int high, highprv = 1;
	struct request_queue *q = rq->q;

@@ -1255,8 +1254,7 @@ static void blk_recalc_rq_segments(struct request *rq)
	cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
	hw_seg_size = seg_size = 0;
	phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0;
	rq_for_each_bio(bio, rq)
	    bio_for_each_segment(bv, bio, i) {
	rq_for_each_segment(bv, rq, iter) {
		/*
		 * the trick here is making sure that a high page is never
		 * considered part of another segment, since that might
@@ -1353,8 +1351,8 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
		  struct scatterlist *sg)
{
	struct bio_vec *bvec, *bvprv;
	struct bio *bio;
	int nsegs, i, cluster;
	struct req_iterator iter;
	int nsegs, cluster;

	nsegs = 0;
	cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
@@ -1363,11 +1361,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
	 * 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) {
	rq_for_each_segment(bvec, rq, iter) {
			int nbytes = bvec->bv_len;

			if (bvprv && cluster) {
@@ -1390,8 +1384,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
				nsegs++;
			}
			bvprv = bvec;
		} /* segments in bio */
	} /* bios in rq */
	} /* segments in rq */

	return nsegs;
}
+38 −43
Original line number Diff line number Diff line
@@ -2437,23 +2437,20 @@ static void rw_interrupt(void)
/* Compute maximal contiguous buffer size. */
static int buffer_chain_size(void)
{
	struct bio *bio;
	struct bio_vec *bv;
	int size, i;
	int size;
	struct req_iterator iter;
	char *base;

	base = bio_data(current_req->bio);
	size = 0;

	rq_for_each_bio(bio, current_req) {
		bio_for_each_segment(bv, bio, i) {
			if (page_address(bv->bv_page) + bv->bv_offset !=
			    base + size)
	rq_for_each_segment(bv, current_req, iter) {
		if (page_address(bv->bv_page) + bv->bv_offset != base + size)
			break;

		size += bv->bv_len;
	}
	}

	return size >> 9;
}
@@ -2479,9 +2476,9 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
{
	int remaining;		/* number of transferred 512-byte sectors */
	struct bio_vec *bv;
	struct bio *bio;
	char *buffer, *dma_buffer;
	int size, i;
	int size;
	struct req_iterator iter;

	max_sector = transfer_size(ssize,
				   min(max_sector, max_sector_2),
@@ -2514,8 +2511,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)

	size = current_req->current_nr_sectors << 9;

	rq_for_each_bio(bio, current_req) {
		bio_for_each_segment(bv, bio, i) {
	rq_for_each_segment(bv, current_req, iter) {
		if (!remaining)
			break;

@@ -2551,7 +2547,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
		remaining -= size;
		dma_buffer += size;
	}
	}
#ifdef FLOPPY_SANITY_CHECK
	if (remaining) {
		if (remaining > 0)
+4 −6
Original line number Diff line number Diff line
@@ -142,12 +142,11 @@ static irqreturn_t lgb_irq(int irq, void *_bd)
 * return the total length. */
static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma)
{
	unsigned int i = 0, idx, len = 0;
	struct bio *bio;

	rq_for_each_bio(bio, req) {
	unsigned int i = 0, len = 0;
	struct req_iterator iter;
	struct bio_vec *bvec;
		bio_for_each_segment(bvec, bio, idx) {

	rq_for_each_segment(bvec, req, iter) {
			/* We told the block layer not to give us too many. */
			BUG_ON(i == LGUEST_MAX_DMA_SECTIONS);
			/* If we had a zero-length segment, it would look like
@@ -161,7 +160,6 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma)
			len += bvec->bv_len;
			i++;
	}
	}
	/* If the array isn't full, we mark the end with a 0 length */
	if (i < LGUEST_MAX_DMA_SECTIONS)
		dma->len[i] = 0;
+9 −13
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,

static int nbd_send_req(struct nbd_device *lo, struct request *req)
{
	int result, i, flags;
	int result, flags;
	struct nbd_request request;
	unsigned long size = req->nr_sectors << 9;
	struct socket *sock = lo->sock;
@@ -205,16 +205,15 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
	}

	if (nbd_cmd(req) == NBD_CMD_WRITE) {
		struct bio *bio;
		struct req_iterator iter;
		struct bio_vec *bvec;
		/*
		 * we are really probing at internals to determine
		 * whether to set MSG_MORE or not...
		 */
		rq_for_each_bio(bio, req) {
			struct bio_vec *bvec;
			bio_for_each_segment(bvec, bio, i) {
		rq_for_each_segment(bvec, req, iter) {
				flags = 0;
				if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
				if (!rq_iter_last(req, iter))
					flags = MSG_MORE;
				dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
						lo->disk->disk_name, req,
@@ -228,7 +227,6 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
				}
		}
	}
	}
	return 0;

error_out:
@@ -321,11 +319,10 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
	dprintk(DBG_RX, "%s: request %p: got reply\n",
			lo->disk->disk_name, req);
	if (nbd_cmd(req) == NBD_CMD_READ) {
		int i;
		struct bio *bio;
		rq_for_each_bio(bio, req) {
		struct req_iterator iter;
		struct bio_vec *bvec;
			bio_for_each_segment(bvec, bio, i) {

		rq_for_each_segment(bvec, req, iter) {
				result = sock_recv_bvec(sock, bvec);
				if (result <= 0) {
					printk(KERN_ERR "%s: Receive data failed (result %d)\n",
@@ -338,7 +335,6 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
					lo->disk->disk_name, req, bvec->bv_len);
		}
	}
	}
	return req;
harderror:
	lo->harderror = result;
Loading