aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2005-06-20 08:06:01 -0400
committerJens Axboe <axboe@suse.de>2005-06-20 08:06:01 -0400
commitdd1cab95f356f1395278633565f198463cf6bd24 (patch)
treeddf12e2fad7c0df0656a10ee6aac3f12a04dbed8
parentb823825e8e09aac6dc1ca362cd5639a87329d636 (diff)
[PATCH] Cleanup blk_rq_map_* interfaces
Change the blk_rq_map_user() and blk_rq_map_kern() interface to require a previously allocated request to be passed in. This is both more efficient for multiple iterations of mapping data to the same request, and it is also a much nicer API. Signed-off-by: Jens Axboe <axboe@suse.de>
-rw-r--r--drivers/block/ll_rw_blk.c68
-rw-r--r--drivers/block/scsi_ioctl.c23
-rw-r--r--drivers/cdrom/cdrom.c13
-rw-r--r--include/linux/blkdev.h7
4 files changed, 53 insertions, 58 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 1471aca6fa18..42c4f3651cf8 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -2107,21 +2107,19 @@ EXPORT_SYMBOL(blk_insert_request);
2107 * original bio must be passed back in to blk_rq_unmap_user() for proper 2107 * original bio must be passed back in to blk_rq_unmap_user() for proper
2108 * unmapping. 2108 * unmapping.
2109 */ 2109 */
2110struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf, 2110int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
2111 unsigned int len) 2111 unsigned int len)
2112{ 2112{
2113 unsigned long uaddr; 2113 unsigned long uaddr;
2114 struct request *rq;
2115 struct bio *bio; 2114 struct bio *bio;
2115 int reading;
2116 2116
2117 if (len > (q->max_sectors << 9)) 2117 if (len > (q->max_sectors << 9))
2118 return ERR_PTR(-EINVAL); 2118 return -EINVAL;
2119 if ((!len && ubuf) || (len && !ubuf)) 2119 if (!len || !ubuf)
2120 return ERR_PTR(-EINVAL); 2120 return -EINVAL;
2121 2121
2122 rq = blk_get_request(q, rw, __GFP_WAIT); 2122 reading = rq_data_dir(rq) == READ;
2123 if (!rq)
2124 return ERR_PTR(-ENOMEM);
2125 2123
2126 /* 2124 /*
2127 * if alignment requirement is satisfied, map in user pages for 2125 * if alignment requirement is satisfied, map in user pages for
@@ -2129,9 +2127,9 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
2129 */ 2127 */
2130 uaddr = (unsigned long) ubuf; 2128 uaddr = (unsigned long) ubuf;
2131 if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q))) 2129 if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q)))
2132 bio = bio_map_user(q, NULL, uaddr, len, rw == READ); 2130 bio = bio_map_user(q, NULL, uaddr, len, reading);
2133 else 2131 else
2134 bio = bio_copy_user(q, uaddr, len, rw == READ); 2132 bio = bio_copy_user(q, uaddr, len, reading);
2135 2133
2136 if (!IS_ERR(bio)) { 2134 if (!IS_ERR(bio)) {
2137 rq->bio = rq->biotail = bio; 2135 rq->bio = rq->biotail = bio;
@@ -2139,14 +2137,13 @@ struct request *blk_rq_map_user(request_queue_t *q, int rw, void __user *ubuf,
2139 2137
2140 rq->buffer = rq->data = NULL; 2138 rq->buffer = rq->data = NULL;
2141 rq->data_len = len; 2139 rq->data_len = len;
2142 return rq; 2140 return 0;
2143 } 2141 }
2144 2142
2145 /* 2143 /*
2146 * bio is the err-ptr 2144 * bio is the err-ptr
2147 */ 2145 */
2148 blk_put_request(rq); 2146 return PTR_ERR(bio);
2149 return (struct request *) bio;
2150} 2147}
2151 2148
2152EXPORT_SYMBOL(blk_rq_map_user); 2149EXPORT_SYMBOL(blk_rq_map_user);
@@ -2160,7 +2157,7 @@ EXPORT_SYMBOL(blk_rq_map_user);
2160 * Description: 2157 * Description:
2161 * Unmap a request previously mapped by blk_rq_map_user(). 2158 * Unmap a request previously mapped by blk_rq_map_user().
2162 */ 2159 */
2163int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen) 2160int blk_rq_unmap_user(struct bio *bio, unsigned int ulen)
2164{ 2161{
2165 int ret = 0; 2162 int ret = 0;
2166 2163
@@ -2171,8 +2168,7 @@ int blk_rq_unmap_user(struct request *rq, struct bio *bio, unsigned int ulen)
2171 ret = bio_uncopy_user(bio); 2168 ret = bio_uncopy_user(bio);
2172 } 2169 }
2173 2170
2174 blk_put_request(rq); 2171 return 0;
2175 return ret;
2176} 2172}
2177 2173
2178EXPORT_SYMBOL(blk_rq_unmap_user); 2174EXPORT_SYMBOL(blk_rq_unmap_user);
@@ -2184,39 +2180,29 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
2184 * @kbuf: the kernel buffer 2180 * @kbuf: the kernel buffer
2185 * @len: length of user data 2181 * @len: length of user data
2186 */ 2182 */
2187struct request *blk_rq_map_kern(request_queue_t *q, int rw, void *kbuf, 2183int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
2188 unsigned int len, unsigned int gfp_mask) 2184 unsigned int len, unsigned int gfp_mask)
2189{ 2185{
2190 struct request *rq;
2191 struct bio *bio; 2186 struct bio *bio;
2192 2187
2193 if (len > (q->max_sectors << 9)) 2188 if (len > (q->max_sectors << 9))
2194 return ERR_PTR(-EINVAL); 2189 return -EINVAL;
2195 if ((!len && kbuf) || (len && !kbuf)) 2190 if (!len || !kbuf)
2196 return ERR_PTR(-EINVAL); 2191 return -EINVAL;
2197
2198 rq = blk_get_request(q, rw, gfp_mask);
2199 if (!rq)
2200 return ERR_PTR(-ENOMEM);
2201 2192
2202 bio = bio_map_kern(q, kbuf, len, gfp_mask); 2193 bio = bio_map_kern(q, kbuf, len, gfp_mask);
2203 if (!IS_ERR(bio)) { 2194 if (IS_ERR(bio))
2204 if (rw) 2195 return PTR_ERR(bio);
2205 bio->bi_rw |= (1 << BIO_RW);
2206 2196
2207 rq->bio = rq->biotail = bio; 2197 if (rq_data_dir(rq) == WRITE)
2208 blk_rq_bio_prep(q, rq, bio); 2198 bio->bi_rw |= (1 << BIO_RW);
2209 2199
2210 rq->buffer = rq->data = NULL; 2200 rq->bio = rq->biotail = bio;
2211 rq->data_len = len; 2201 blk_rq_bio_prep(q, rq, bio);
2212 return rq;
2213 }
2214 2202
2215 /* 2203 rq->buffer = rq->data = NULL;
2216 * bio is the err-ptr 2204 rq->data_len = len;
2217 */ 2205 return 0;
2218 blk_put_request(rq);
2219 return (struct request *) bio;
2220} 2206}
2221 2207
2222EXPORT_SYMBOL(blk_rq_map_kern); 2208EXPORT_SYMBOL(blk_rq_map_kern);
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 681871ca5d60..93c4ca874be3 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -216,7 +216,7 @@ static int sg_io(struct file *file, request_queue_t *q,
216 struct gendisk *bd_disk, struct sg_io_hdr *hdr) 216 struct gendisk *bd_disk, struct sg_io_hdr *hdr)
217{ 217{
218 unsigned long start_time; 218 unsigned long start_time;
219 int reading, writing; 219 int reading, writing, ret;
220 struct request *rq; 220 struct request *rq;
221 struct bio *bio; 221 struct bio *bio;
222 char sense[SCSI_SENSE_BUFFERSIZE]; 222 char sense[SCSI_SENSE_BUFFERSIZE];
@@ -255,14 +255,17 @@ static int sg_io(struct file *file, request_queue_t *q,
255 reading = 1; 255 reading = 1;
256 break; 256 break;
257 } 257 }
258 }
258 259
259 rq = blk_rq_map_user(q, writing ? WRITE : READ, hdr->dxferp, 260 rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
260 hdr->dxfer_len); 261 if (!rq)
262 return -ENOMEM;
261 263
262 if (IS_ERR(rq)) 264 if (reading || writing) {
263 return PTR_ERR(rq); 265 ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
264 } else 266 if (ret)
265 rq = blk_get_request(q, READ, __GFP_WAIT); 267 goto out;
268 }
266 269
267 /* 270 /*
268 * fill in request structure 271 * fill in request structure
@@ -321,11 +324,13 @@ static int sg_io(struct file *file, request_queue_t *q,
321 } 324 }
322 325
323 if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len)) 326 if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len))
324 return -EFAULT; 327 ret = -EFAULT;
325 328
326 /* may not have succeeded, but output values written to control 329 /* may not have succeeded, but output values written to control
327 * structure (struct sg_io_hdr). */ 330 * structure (struct sg_io_hdr). */
328 return 0; 331out:
332 blk_put_request(rq);
333 return ret;
329} 334}
330 335
331#define OMAX_SB_LEN 16 /* For backward compatibility */ 336#define OMAX_SB_LEN 16 /* For backward compatibility */
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index beaa561f2ed8..6a7d926774a1 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2097,6 +2097,10 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2097 if (!q) 2097 if (!q)
2098 return -ENXIO; 2098 return -ENXIO;
2099 2099
2100 rq = blk_get_request(q, READ, GFP_KERNEL);
2101 if (!rq)
2102 return -ENOMEM;
2103
2100 cdi->last_sense = 0; 2104 cdi->last_sense = 0;
2101 2105
2102 while (nframes) { 2106 while (nframes) {
@@ -2108,9 +2112,9 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2108 2112
2109 len = nr * CD_FRAMESIZE_RAW; 2113 len = nr * CD_FRAMESIZE_RAW;
2110 2114
2111 rq = blk_rq_map_user(q, READ, ubuf, len); 2115 ret = blk_rq_map_user(q, rq, ubuf, len);
2112 if (IS_ERR(rq)) 2116 if (ret)
2113 return PTR_ERR(rq); 2117 break;
2114 2118
2115 memset(rq->cmd, 0, sizeof(rq->cmd)); 2119 memset(rq->cmd, 0, sizeof(rq->cmd));
2116 rq->cmd[0] = GPCMD_READ_CD; 2120 rq->cmd[0] = GPCMD_READ_CD;
@@ -2138,7 +2142,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2138 cdi->last_sense = s->sense_key; 2142 cdi->last_sense = s->sense_key;
2139 } 2143 }
2140 2144
2141 if (blk_rq_unmap_user(rq, bio, len)) 2145 if (blk_rq_unmap_user(bio, len))
2142 ret = -EFAULT; 2146 ret = -EFAULT;
2143 2147
2144 if (ret) 2148 if (ret)
@@ -2149,6 +2153,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2149 ubuf += len; 2153 ubuf += len;
2150 } 2154 }
2151 2155
2156 blk_put_request(rq);
2152 return ret; 2157 return ret;
2153} 2158}
2154 2159
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 67339bc5f6bc..fc0dce078616 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -558,10 +558,9 @@ extern void blk_sync_queue(struct request_queue *q);
558extern void __blk_stop_queue(request_queue_t *q); 558extern void __blk_stop_queue(request_queue_t *q);
559extern void blk_run_queue(request_queue_t *); 559extern void blk_run_queue(request_queue_t *);
560extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *); 560extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
561extern struct request *blk_rq_map_user(request_queue_t *, int, void __user *, unsigned int); 561extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
562extern int blk_rq_unmap_user(struct request *, struct bio *, unsigned int); 562extern int blk_rq_unmap_user(struct bio *, unsigned int);
563extern struct request *blk_rq_map_kern(request_queue_t *, int, void *, 563extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, unsigned int);
564 unsigned int, unsigned int);
565extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *); 564extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *);
566 565
567static inline request_queue_t *bdev_get_queue(struct block_device *bdev) 566static inline request_queue_t *bdev_get_queue(struct block_device *bdev)