diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-12-18 00:49:38 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-01-02 12:10:35 -0500 |
commit | 97ae77a1cd332c7b011d71315c8faabce6840c72 (patch) | |
tree | fc243ca28ea474eaf81729079eeb3b259cd1b81b | |
parent | 56c451f4b583ccdf80c9e676179c9cb49de86745 (diff) |
[SCSI] block: make blk_rq_map_user take a NULL user-space buffer for WRITE
The commit 818827669d85b84241696ffef2de485db46b0b5e (block: make
blk_rq_map_user take a NULL user-space buffer) extended
blk_rq_map_user to accept a NULL user-space buffer with a READ
command. It was necessary to convert sg to use the block layer mapping
API.
This patch extends blk_rq_map_user again for a WRITE command. It is
necessary to convert st and osst drivers to use the block layer
apping API.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | block/blk-map.c | 16 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 1 | ||||
-rw-r--r-- | fs/bio.c | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 1 |
4 files changed, 10 insertions, 10 deletions
diff --git a/block/blk-map.c b/block/blk-map.c index c7e55b23a2bc..f103729b462f 100644 --- a/block/blk-map.c +++ b/block/blk-map.c | |||
@@ -42,7 +42,7 @@ static int __blk_rq_unmap_user(struct bio *bio) | |||
42 | 42 | ||
43 | static int __blk_rq_map_user(struct request_queue *q, struct request *rq, | 43 | static int __blk_rq_map_user(struct request_queue *q, struct request *rq, |
44 | struct rq_map_data *map_data, void __user *ubuf, | 44 | struct rq_map_data *map_data, void __user *ubuf, |
45 | unsigned int len, int null_mapped, gfp_t gfp_mask) | 45 | unsigned int len, gfp_t gfp_mask) |
46 | { | 46 | { |
47 | unsigned long uaddr; | 47 | unsigned long uaddr; |
48 | struct bio *bio, *orig_bio; | 48 | struct bio *bio, *orig_bio; |
@@ -63,7 +63,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
63 | if (IS_ERR(bio)) | 63 | if (IS_ERR(bio)) |
64 | return PTR_ERR(bio); | 64 | return PTR_ERR(bio); |
65 | 65 | ||
66 | if (null_mapped) | 66 | if (map_data && map_data->null_mapped) |
67 | bio->bi_flags |= (1 << BIO_NULL_MAPPED); | 67 | bio->bi_flags |= (1 << BIO_NULL_MAPPED); |
68 | 68 | ||
69 | orig_bio = bio; | 69 | orig_bio = bio; |
@@ -114,17 +114,15 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
114 | { | 114 | { |
115 | unsigned long bytes_read = 0; | 115 | unsigned long bytes_read = 0; |
116 | struct bio *bio = NULL; | 116 | struct bio *bio = NULL; |
117 | int ret, null_mapped = 0; | 117 | int ret; |
118 | 118 | ||
119 | if (len > (q->max_hw_sectors << 9)) | 119 | if (len > (q->max_hw_sectors << 9)) |
120 | return -EINVAL; | 120 | return -EINVAL; |
121 | if (!len) | 121 | if (!len) |
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | if (!ubuf) { | 123 | |
124 | if (!map_data || rq_data_dir(rq) != READ) | 124 | if (!ubuf && (!map_data || !map_data->null_mapped)) |
125 | return -EINVAL; | 125 | return -EINVAL; |
126 | null_mapped = 1; | ||
127 | } | ||
128 | 126 | ||
129 | while (bytes_read != len) { | 127 | while (bytes_read != len) { |
130 | unsigned long map_len, end, start; | 128 | unsigned long map_len, end, start; |
@@ -143,7 +141,7 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
143 | map_len -= PAGE_SIZE; | 141 | map_len -= PAGE_SIZE; |
144 | 142 | ||
145 | ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len, | 143 | ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len, |
146 | null_mapped, gfp_mask); | 144 | gfp_mask); |
147 | if (ret < 0) | 145 | if (ret < 0) |
148 | goto unmap_rq; | 146 | goto unmap_rq; |
149 | if (!bio) | 147 | if (!bio) |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7d0b3d9ee43b..8f0bd3f7a59f 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1670,6 +1670,7 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) | |||
1670 | md->page_order = req_schp->page_order; | 1670 | md->page_order = req_schp->page_order; |
1671 | md->nr_entries = req_schp->k_use_sg; | 1671 | md->nr_entries = req_schp->k_use_sg; |
1672 | md->offset = 0; | 1672 | md->offset = 0; |
1673 | md->null_mapped = hp->dxferp ? 0 : 1; | ||
1673 | } | 1674 | } |
1674 | 1675 | ||
1675 | if (iov_count) | 1676 | if (iov_count) |
@@ -859,7 +859,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
859 | /* | 859 | /* |
860 | * success | 860 | * success |
861 | */ | 861 | */ |
862 | if (!write_to_vm) { | 862 | if (!write_to_vm && (!map_data || !map_data->null_mapped)) { |
863 | ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); | 863 | ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); |
864 | if (ret) | 864 | if (ret) |
865 | goto cleanup; | 865 | goto cleanup; |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 811e5342c452..044467ef7b11 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -691,6 +691,7 @@ struct rq_map_data { | |||
691 | int page_order; | 691 | int page_order; |
692 | int nr_entries; | 692 | int nr_entries; |
693 | unsigned long offset; | 693 | unsigned long offset; |
694 | int null_mapped; | ||
694 | }; | 695 | }; |
695 | 696 | ||
696 | struct req_iterator { | 697 | struct req_iterator { |