From: Deepak Colluru <deepakrc@xxxxxxxxx> Add support for io vectors in bsg. Signed-off-by: Deepak Colluru <deepakrc@xxxxxxxxx> --- bsg.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/block/bsg.c b/block/bsg.c index 8e181ab..78f47ed 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -245,7 +245,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr) struct request_queue *q = bd->queue; struct request *rq, *next_rq = NULL; int ret, rw; - unsigned int dxfer_len; + unsigned int dxfer_len, iovec_count = 0; void *dxferp = NULL; dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp, @@ -281,7 +281,31 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr) rq->next_rq = next_rq; dxferp = (void*)(unsigned long)hdr->din_xferp; - ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len); + iovec_count = hdr->din_iovec_count; + dxfer_len = hdr->din_xfer_len; + + if (iovec_count) { + const int size = sizeof(struct sg_iovec) * iovec_count; + struct sg_iovec *iov; + + iov = kmalloc(size, GFP_KERNEL); + if (!iov) { + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(iov, dxferp, size)) { + kfree(iov); + ret = -EFAULT; + goto out; + } + ret = blk_rq_map_user_iov(q, rq, iov, iovec_count, + dxfer_len); + kfree(iov); + } else { + ret = blk_rq_map_user(q, rq, dxferp, dxfer_len); + } + if (ret) goto out; } @@ -289,14 +313,36 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr) if (hdr->dout_xfer_len) { dxfer_len = hdr->dout_xfer_len; dxferp = (void*)(unsigned long)hdr->dout_xferp; + iovec_count = hdr->dout_iovec_count; } else if (hdr->din_xfer_len) { dxfer_len = hdr->din_xfer_len; dxferp = (void*)(unsigned long)hdr->din_xferp; + iovec_count = hdr->din_iovec_count; } else dxfer_len = 0; if (dxfer_len) { - ret = blk_rq_map_user(q, rq, dxferp, dxfer_len); + if (iovec_count) { + const int size = sizeof(struct sg_iovec) * iovec_count; + struct sg_iovec *iov; + + iov = kmalloc(size, GFP_KERNEL); + if (!iov) { + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(iov, dxferp, size)) { + kfree(iov); + ret = -EFAULT; + goto out; + } + ret = blk_rq_map_user_iov(q, rq, iov, iovec_count, + dxfer_len); + kfree(iov); + } else { + ret = blk_rq_map_user(q, rq, dxferp, dxfer_len); + } if (ret) goto out; } - To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html