diff options
author | James Bottomley <James.Bottomley@SteelEye.com> | 2005-06-20 08:06:52 -0400 |
---|---|---|
committer | Jens Axboe <axboe@suse.de> | 2005-06-20 08:06:52 -0400 |
commit | f1970baf6d74e03bd32072ab453f2fc01bc1b8d3 (patch) | |
tree | 559898cdf83bd0f93b8a72248c6423a6548fb604 /drivers/block/scsi_ioctl.c | |
parent | dd1cab95f356f1395278633565f198463cf6bd24 (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.c | 34 |
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 |