diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-05-04 16:05:23 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-05-04 16:05:23 +0200 |
commit | 8560b9321f9050968f393ce1ec67e47c1a0bd5cf (patch) | |
tree | 658ebb20e4fd5dee840f27103b59da367ff473b1 /block/scsi_ioctl.c | |
parent | 72e31981a4e91f84c5b5e8994f5d25b1cf22b6cf (diff) | |
parent | 6574612fbb34c63117581e68f2231ddce027e41e (diff) |
Merge branch 'fix/asoc' into topic/asoc
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r-- | block/scsi_ioctl.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 626ee274c5c..82a0ca2f672 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -217,7 +217,7 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { - int ret = 0; + int r, ret = 0; /* * fill in all the output members @@ -242,7 +242,9 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, ret = -EFAULT; } - blk_rq_unmap_user(bio); + r = blk_rq_unmap_user(bio); + if (!ret) + ret = r; blk_put_request(rq); return ret; @@ -288,6 +290,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, if (hdr->iovec_count) { const int size = sizeof(struct sg_iovec) * hdr->iovec_count; + size_t iov_data_len; struct sg_iovec *iov; iov = kmalloc(size, GFP_KERNEL); @@ -302,8 +305,18 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, goto out; } + /* SG_IO howto says that the shorter of the two wins */ + iov_data_len = iov_length((struct iovec *)iov, + hdr->iovec_count); + if (hdr->dxfer_len < iov_data_len) { + hdr->iovec_count = iov_shorten((struct iovec *)iov, + hdr->iovec_count, + hdr->dxfer_len); + iov_data_len = hdr->dxfer_len; + } + ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, - hdr->dxfer_len, GFP_KERNEL); + iov_data_len, GFP_KERNEL); kfree(iov); } else if (hdr->dxfer_len) ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, |