aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-12-18 00:49:38 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-01-02 12:10:35 -0500
commit97ae77a1cd332c7b011d71315c8faabce6840c72 (patch)
treefc243ca28ea474eaf81729079eeb3b259cd1b81b
parent56c451f4b583ccdf80c9e676179c9cb49de86745 (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.c16
-rw-r--r--drivers/scsi/sg.c1
-rw-r--r--fs/bio.c2
-rw-r--r--include/linux/blkdev.h1
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
43static int __blk_rq_map_user(struct request_queue *q, struct request *rq, 43static 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)
diff --git a/fs/bio.c b/fs/bio.c
index 13be075806b6..062299acbccd 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -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
696struct req_iterator { 697struct req_iterator {