aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/scsi_ioctl.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@SteelEye.com>2005-06-20 08:06:52 -0400
committerJens Axboe <axboe@suse.de>2005-06-20 08:06:52 -0400
commitf1970baf6d74e03bd32072ab453f2fc01bc1b8d3 (patch)
tree559898cdf83bd0f93b8a72248c6423a6548fb604 /drivers/block/scsi_ioctl.c
parentdd1cab95f356f1395278633565f198463cf6bd24 (diff)
[PATCH] Add scatter-gather support for the block layer SG_IO
Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'drivers/block/scsi_ioctl.c')
-rw-r--r--drivers/block/scsi_ioctl.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 93c4ca874be3..09a7e73a0812 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -231,17 +231,11 @@ static int sg_io(struct file *file, request_queue_t *q,
231 if (verify_command(file, cmd)) 231 if (verify_command(file, cmd))
232 return -EPERM; 232 return -EPERM;
233 233
234 /*
235 * we'll do that later
236 */
237 if (hdr->iovec_count)
238 return -EOPNOTSUPP;
239
240 if (hdr->dxfer_len > (q->max_sectors << 9)) 234 if (hdr->dxfer_len > (q->max_sectors << 9))
241 return -EIO; 235 return -EIO;
242 236
243 reading = writing = 0; 237 reading = writing = 0;
244 if (hdr->dxfer_len) { 238 if (hdr->dxfer_len)
245 switch (hdr->dxfer_direction) { 239 switch (hdr->dxfer_direction) {
246 default: 240 default:
247 return -EINVAL; 241 return -EINVAL;
@@ -261,11 +255,29 @@ static int sg_io(struct file *file, request_queue_t *q,
261 if (!rq) 255 if (!rq)
262 return -ENOMEM; 256 return -ENOMEM;
263 257
264 if (reading || writing) { 258 if (hdr->iovec_count) {
265 ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); 259 const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
266 if (ret) 260 struct sg_iovec *iov;
261
262 iov = kmalloc(size, GFP_KERNEL);
263 if (!iov) {
264 ret = -ENOMEM;
267 goto out; 265 goto out;
268 } 266 }
267
268 if (copy_from_user(iov, hdr->dxferp, size)) {
269 kfree(iov);
270 ret = -EFAULT;
271 goto out;
272 }
273
274 ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
275 kfree(iov);
276 } else if (hdr->dxfer_len)
277 ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
278
279 if (ret)
280 goto out;
269 281
270 /* 282 /*
271 * fill in request structure 283 * fill in request structure