aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/scsi_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/scsi_ioctl.c')
-rw-r--r--drivers/block/scsi_ioctl.c60
1 files changed, 36 insertions, 24 deletions
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 681871ca5d60..abb2df249fd3 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 writing = 0, ret = 0;
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];
@@ -231,38 +231,48 @@ 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 if (hdr->dxfer_len)
244 if (hdr->dxfer_len) {
245 switch (hdr->dxfer_direction) { 238 switch (hdr->dxfer_direction) {
246 default: 239 default:
247 return -EINVAL; 240 return -EINVAL;
248 case SG_DXFER_TO_FROM_DEV: 241 case SG_DXFER_TO_FROM_DEV:
249 reading = 1;
250 /* fall through */
251 case SG_DXFER_TO_DEV: 242 case SG_DXFER_TO_DEV:
252 writing = 1; 243 writing = 1;
253 break; 244 break;
254 case SG_DXFER_FROM_DEV: 245 case SG_DXFER_FROM_DEV:
255 reading = 1;
256 break; 246 break;
257 } 247 }
258 248
259 rq = blk_rq_map_user(q, writing ? WRITE : READ, hdr->dxferp, 249 rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
260 hdr->dxfer_len); 250 if (!rq)
251 return -ENOMEM;
252
253 if (hdr->iovec_count) {
254 const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
255 struct sg_iovec *iov;
256
257 iov = kmalloc(size, GFP_KERNEL);
258 if (!iov) {
259 ret = -ENOMEM;
260 goto out;
261 }
262
263 if (copy_from_user(iov, hdr->dxferp, size)) {
264 kfree(iov);
265 ret = -EFAULT;
266 goto out;
267 }
268
269 ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
270 kfree(iov);
271 } else if (hdr->dxfer_len)
272 ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
261 273
262 if (IS_ERR(rq)) 274 if (ret)
263 return PTR_ERR(rq); 275 goto out;
264 } else
265 rq = blk_get_request(q, READ, __GFP_WAIT);
266 276
267 /* 277 /*
268 * fill in request structure 278 * fill in request structure
@@ -298,7 +308,7 @@ static int sg_io(struct file *file, request_queue_t *q,
298 * (if he doesn't check that is his problem). 308 * (if he doesn't check that is his problem).
299 * N.B. a non-zero SCSI status is _not_ necessarily an error. 309 * N.B. a non-zero SCSI status is _not_ necessarily an error.
300 */ 310 */
301 blk_execute_rq(q, bd_disk, rq); 311 blk_execute_rq(q, bd_disk, rq, 0);
302 312
303 /* write to all output members */ 313 /* write to all output members */
304 hdr->status = 0xff & rq->errors; 314 hdr->status = 0xff & rq->errors;
@@ -320,12 +330,14 @@ static int sg_io(struct file *file, request_queue_t *q,
320 hdr->sb_len_wr = len; 330 hdr->sb_len_wr = len;
321 } 331 }
322 332
323 if (blk_rq_unmap_user(rq, bio, hdr->dxfer_len)) 333 if (blk_rq_unmap_user(bio, hdr->dxfer_len))
324 return -EFAULT; 334 ret = -EFAULT;
325 335
326 /* may not have succeeded, but output values written to control 336 /* may not have succeeded, but output values written to control
327 * structure (struct sg_io_hdr). */ 337 * structure (struct sg_io_hdr). */
328 return 0; 338out:
339 blk_put_request(rq);
340 return ret;
329} 341}
330 342
331#define OMAX_SB_LEN 16 /* For backward compatibility */ 343#define OMAX_SB_LEN 16 /* For backward compatibility */
@@ -408,7 +420,7 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
408 rq->data_len = bytes; 420 rq->data_len = bytes;
409 rq->flags |= REQ_BLOCK_PC; 421 rq->flags |= REQ_BLOCK_PC;
410 422
411 blk_execute_rq(q, bd_disk, rq); 423 blk_execute_rq(q, bd_disk, rq, 0);
412 err = rq->errors & 0xff; /* only 8 bit SCSI status */ 424 err = rq->errors & 0xff; /* only 8 bit SCSI status */
413 if (err) { 425 if (err) {
414 if (rq->sense_len && rq->sense) { 426 if (rq->sense_len && rq->sense) {
@@ -561,7 +573,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd,
561 rq->cmd[0] = GPCMD_START_STOP_UNIT; 573 rq->cmd[0] = GPCMD_START_STOP_UNIT;
562 rq->cmd[4] = 0x02 + (close != 0); 574 rq->cmd[4] = 0x02 + (close != 0);
563 rq->cmd_len = 6; 575 rq->cmd_len = 6;
564 err = blk_execute_rq(q, bd_disk, rq); 576 err = blk_execute_rq(q, bd_disk, rq, 0);
565 blk_put_request(rq); 577 blk_put_request(rq);
566 break; 578 break;
567 default: 579 default: