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

Commit 56c451f4 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by James Bottomley
Browse files

[SCSI] block: fix the partial mappings with struct rq_map_data



This fixes bio_copy_user_iov to properly handle the partial mappings
with struct rq_map_data (which only sg uses for now but st and osst
will shortly). It adds the offset member to struct rq_map_data and
changes blk_rq_map_user to update it so that bio_copy_user_iov can add
an appropriate page frame via bio_add_pc_page().

Signed-off-by: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: default avatarJens Axboe <jens.axboe@oracle.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent e623ddb4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -150,6 +150,9 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
			bio = rq->bio;
		bytes_read += ret;
		ubuf += ret;

		if (map_data)
			map_data->offset += ret;
	}

	if (!bio_flagged(bio, BIO_USER_MAPPED))
+1 −0
Original line number Diff line number Diff line
@@ -1669,6 +1669,7 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
		md->pages = req_schp->pages;
		md->page_order = req_schp->page_order;
		md->nr_entries = req_schp->k_use_sg;
		md->offset = 0;
	}

	if (iov_count)
+9 −3
Original line number Diff line number Diff line
@@ -788,6 +788,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
	int i, ret;
	int nr_pages = 0;
	unsigned int len = 0;
	unsigned int offset = map_data ? map_data->offset & ~PAGE_MASK : 0;

	for (i = 0; i < iov_count; i++) {
		unsigned long uaddr;
@@ -814,12 +815,16 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
	bio->bi_rw |= (!write_to_vm << BIO_RW);

	ret = 0;
	i = 0;
	if (map_data)

	if (map_data) {
		nr_pages = 1 << map_data->page_order;
		i = map_data->offset / PAGE_SIZE;
	}
	while (len) {
		unsigned int bytes = PAGE_SIZE;

		bytes -= offset;

		if (bytes > len)
			bytes = len;

@@ -841,10 +846,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
			}
		}

		if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
		if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes)
			break;

		len -= bytes;
		offset = 0;
	}

	if (ret)
+1 −0
Original line number Diff line number Diff line
@@ -690,6 +690,7 @@ struct rq_map_data {
	struct page **pages;
	int page_order;
	int nr_entries;
	unsigned long offset;
};

struct req_iterator {