aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/bsg.c198
1 files changed, 121 insertions, 77 deletions
diff --git a/block/bsg.c b/block/bsg.c
index 53a09a52d154..6d139d20ec99 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -103,8 +103,8 @@ struct bsg_command {
103 struct request *rq; 103 struct request *rq;
104 struct bio *bio; 104 struct bio *bio;
105 int err; 105 int err;
106 struct sg_io_hdr hdr; 106 struct sg_io_v4 hdr;
107 struct sg_io_hdr __user *uhdr; 107 struct sg_io_v4 __user *uhdr;
108 char sense[SCSI_SENSE_BUFFERSIZE]; 108 char sense[SCSI_SENSE_BUFFERSIZE];
109}; 109};
110 110
@@ -235,57 +235,82 @@ static struct bsg_command *bsg_get_command(struct bsg_device *bd)
235 return bc; 235 return bc;
236} 236}
237 237
238static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq,
239 struct sg_io_v4 *hdr, int has_write_perm)
240{
241 memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
242
243 if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
244 hdr->request_len))
245 return -EFAULT;
246 if (blk_verify_command(rq->cmd, has_write_perm))
247 return -EPERM;
248
249 /*
250 * fill in request structure
251 */
252 rq->cmd_len = hdr->request_len;
253 rq->cmd_type = REQ_TYPE_BLOCK_PC;
254
255 rq->timeout = (hdr->timeout * HZ) / 1000;
256 if (!rq->timeout)
257 rq->timeout = q->sg_timeout;
258 if (!rq->timeout)
259 rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
260
261 return 0;
262}
263
238/* 264/*
239 * Check if sg_io_hdr from user is allowed and valid 265 * Check if sg_io_v4 from user is allowed and valid
240 */ 266 */
241static int 267static int
242bsg_validate_sghdr(request_queue_t *q, struct sg_io_hdr *hdr, int *rw) 268bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw)
243{ 269{
244 if (hdr->interface_id != 'S') 270 if (hdr->guard != 'Q')
245 return -EINVAL; 271 return -EINVAL;
246 if (hdr->cmd_len > BLK_MAX_CDB) 272 if (hdr->request_len > BLK_MAX_CDB)
247 return -EINVAL; 273 return -EINVAL;
248 if (hdr->dxfer_len > (q->max_sectors << 9)) 274 if (hdr->dout_xfer_len > (q->max_sectors << 9) ||
275 hdr->din_xfer_len > (q->max_sectors << 9))
249 return -EIO; 276 return -EIO;
250 277
278 /* not supported currently */
279 if (hdr->protocol || hdr->subprotocol)
280 return -EINVAL;
281
251 /* 282 /*
252 * looks sane, if no data then it should be fine from our POV 283 * looks sane, if no data then it should be fine from our POV
253 */ 284 */
254 if (!hdr->dxfer_len) 285 if (!hdr->dout_xfer_len && !hdr->din_xfer_len)
255 return 0; 286 return 0;
256 287
257 switch (hdr->dxfer_direction) { 288 /* not supported currently */
258 case SG_DXFER_TO_FROM_DEV: 289 if (hdr->dout_xfer_len && hdr->din_xfer_len)
259 case SG_DXFER_FROM_DEV: 290 return -EINVAL;
260 *rw = READ; 291
261 break; 292 *rw = hdr->dout_xfer_len ? WRITE : READ;
262 case SG_DXFER_TO_DEV:
263 *rw = WRITE;
264 break;
265 default:
266 return -EINVAL;
267 }
268 293
269 return 0; 294 return 0;
270} 295}
271 296
272/* 297/*
273 * map sg_io_hdr to a request. for scatter-gather sg_io_hdr, we map 298 * map sg_io_v4 to a request.
274 * each segment to a bio and string multiple bio's to the request
275 */ 299 */
276static struct request * 300static struct request *
277bsg_map_hdr(struct bsg_device *bd, int rw, struct sg_io_hdr *hdr) 301bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
278{ 302{
279 request_queue_t *q = bd->queue; 303 request_queue_t *q = bd->queue;
280 struct sg_iovec iov;
281 struct sg_iovec __user *u_iov;
282 struct request *rq; 304 struct request *rq;
283 int ret, i = 0; 305 int ret, rw;
306 unsigned int dxfer_len;
307 void *dxferp = NULL;
284 308
285 dprintk("map hdr %p/%d/%d\n", hdr->dxferp, hdr->dxfer_len, 309 dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
286 hdr->iovec_count); 310 hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
311 hdr->din_xfer_len);
287 312
288 ret = bsg_validate_sghdr(q, hdr, &rw); 313 ret = bsg_validate_sgv4_hdr(q, hdr, &rw);
289 if (ret) 314 if (ret)
290 return ERR_PTR(ret); 315 return ERR_PTR(ret);
291 316
@@ -293,44 +318,29 @@ bsg_map_hdr(struct bsg_device *bd, int rw, struct sg_io_hdr *hdr)
293 * map scatter-gather elements seperately and string them to request 318 * map scatter-gather elements seperately and string them to request
294 */ 319 */
295 rq = blk_get_request(q, rw, GFP_KERNEL); 320 rq = blk_get_request(q, rw, GFP_KERNEL);
296 ret = blk_fill_sghdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM, 321 ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM,
297 &bd->flags)); 322 &bd->flags));
298 if (ret) { 323 if (ret) {
299 blk_put_request(rq); 324 blk_put_request(rq);
300 return ERR_PTR(ret); 325 return ERR_PTR(ret);
301 } 326 }
302 327
303 if (!hdr->iovec_count) { 328 if (hdr->dout_xfer_len) {
304 ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); 329 dxfer_len = hdr->dout_xfer_len;
305 if (ret) 330 dxferp = (void*)(unsigned long)hdr->dout_xferp;
306 goto out; 331 } else if (hdr->din_xfer_len) {
307 } 332 dxfer_len = hdr->din_xfer_len;
308 333 dxferp = (void*)(unsigned long)hdr->din_xferp;
309 u_iov = hdr->dxferp; 334 } else
310 for (ret = 0, i = 0; i < hdr->iovec_count; i++, u_iov++) { 335 dxfer_len = 0;
311 if (copy_from_user(&iov, u_iov, sizeof(iov))) { 336
312 ret = -EFAULT; 337 if (dxfer_len) {
313 break; 338 ret = blk_rq_map_user(q, rq, dxferp, dxfer_len);
314 } 339 if (ret) {
315 340 dprintk("failed map at %d\n", ret);
316 if (!iov.iov_len || !iov.iov_base) { 341 blk_put_request(rq);
317 ret = -EINVAL; 342 rq = ERR_PTR(ret);
318 break;
319 } 343 }
320
321 ret = blk_rq_map_user(q, rq, iov.iov_base, iov.iov_len);
322 if (ret)
323 break;
324 }
325
326 /*
327 * bugger, cleanup
328 */
329 if (ret) {
330out:
331 dprintk("failed map at %d: %d\n", i, ret);
332 blk_unmap_sghdr_rq(rq, hdr);
333 rq = ERR_PTR(ret);
334 } 344 }
335 345
336 return rq; 346 return rq;
@@ -346,7 +356,7 @@ static void bsg_rq_end_io(struct request *rq, int uptodate)
346 struct bsg_device *bd = bc->bd; 356 struct bsg_device *bd = bc->bd;
347 unsigned long flags; 357 unsigned long flags;
348 358
349 dprintk("%s: finished rq %p bc %p, bio %p offset %d stat %d\n", 359 dprintk("%s: finished rq %p bc %p, bio %p offset %Zd stat %d\n",
350 bd->name, rq, bc, bc->bio, bc - bd->cmd_map, uptodate); 360 bd->name, rq, bc, bc->bio, bc - bd->cmd_map, uptodate);
351 361
352 bc->hdr.duration = jiffies_to_msecs(jiffies - bc->hdr.duration); 362 bc->hdr.duration = jiffies_to_msecs(jiffies - bc->hdr.duration);
@@ -434,6 +444,42 @@ bsg_get_done_cmd_nosignals(struct bsg_device *bd)
434 return __bsg_get_done_cmd(bd, TASK_UNINTERRUPTIBLE); 444 return __bsg_get_done_cmd(bd, TASK_UNINTERRUPTIBLE);
435} 445}
436 446
447static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
448 struct bio *bio)
449{
450 int ret = 0;
451
452 dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
453 /*
454 * fill in all the output members
455 */
456 hdr->device_status = status_byte(rq->errors);
457 hdr->transport_status = host_byte(rq->errors);
458 hdr->driver_status = driver_byte(rq->errors);
459 hdr->info = 0;
460 if (hdr->device_status || hdr->transport_status || hdr->driver_status)
461 hdr->info |= SG_INFO_CHECK;
462 hdr->din_resid = rq->data_len;
463 hdr->response_len = 0;
464
465 if (rq->sense_len && hdr->response) {
466 int len = min((unsigned int) hdr->max_response_len,
467 rq->sense_len);
468
469 ret = copy_to_user((void*)(unsigned long)hdr->response,
470 rq->sense, len);
471 if (!ret)
472 hdr->response_len = len;
473 else
474 ret = -EFAULT;
475 }
476
477 blk_rq_unmap_user(bio);
478 blk_put_request(rq);
479
480 return ret;
481}
482
437static int bsg_complete_all_commands(struct bsg_device *bd) 483static int bsg_complete_all_commands(struct bsg_device *bd)
438{ 484{
439 struct bsg_command *bc; 485 struct bsg_command *bc;
@@ -476,7 +522,7 @@ static int bsg_complete_all_commands(struct bsg_device *bd)
476 break; 522 break;
477 } 523 }
478 524
479 tret = blk_complete_sghdr_rq(bc->rq, &bc->hdr, bc->bio); 525 tret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio);
480 if (!ret) 526 if (!ret)
481 ret = tret; 527 ret = tret;
482 528
@@ -495,11 +541,11 @@ __bsg_read(char __user *buf, size_t count, bsg_command_callback get_bc,
495 struct bsg_command *bc; 541 struct bsg_command *bc;
496 int nr_commands, ret; 542 int nr_commands, ret;
497 543
498 if (count % sizeof(struct sg_io_hdr)) 544 if (count % sizeof(struct sg_io_v4))
499 return -EINVAL; 545 return -EINVAL;
500 546
501 ret = 0; 547 ret = 0;
502 nr_commands = count / sizeof(struct sg_io_hdr); 548 nr_commands = count / sizeof(struct sg_io_v4);
503 while (nr_commands) { 549 while (nr_commands) {
504 bc = get_bc(bd, iov); 550 bc = get_bc(bd, iov);
505 if (IS_ERR(bc)) { 551 if (IS_ERR(bc)) {
@@ -512,7 +558,7 @@ __bsg_read(char __user *buf, size_t count, bsg_command_callback get_bc,
512 * after completing the request. so do that here, 558 * after completing the request. so do that here,
513 * bsg_complete_work() cannot do that for us 559 * bsg_complete_work() cannot do that for us
514 */ 560 */
515 ret = blk_complete_sghdr_rq(bc->rq, &bc->hdr, bc->bio); 561 ret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio);
516 562
517 if (copy_to_user(buf, (char *) &bc->hdr, sizeof(bc->hdr))) 563 if (copy_to_user(buf, (char *) &bc->hdr, sizeof(bc->hdr)))
518 ret = -EFAULT; 564 ret = -EFAULT;
@@ -522,8 +568,8 @@ __bsg_read(char __user *buf, size_t count, bsg_command_callback get_bc,
522 if (ret) 568 if (ret)
523 break; 569 break;
524 570
525 buf += sizeof(struct sg_io_hdr); 571 buf += sizeof(struct sg_io_v4);
526 *bytes_read += sizeof(struct sg_io_hdr); 572 *bytes_read += sizeof(struct sg_io_v4);
527 nr_commands--; 573 nr_commands--;
528 } 574 }
529 575
@@ -582,16 +628,15 @@ static ssize_t __bsg_write(struct bsg_device *bd, const char __user *buf,
582 struct request *rq; 628 struct request *rq;
583 int ret, nr_commands; 629 int ret, nr_commands;
584 630
585 if (count % sizeof(struct sg_io_hdr)) 631 if (count % sizeof(struct sg_io_v4))
586 return -EINVAL; 632 return -EINVAL;
587 633
588 nr_commands = count / sizeof(struct sg_io_hdr); 634 nr_commands = count / sizeof(struct sg_io_v4);
589 rq = NULL; 635 rq = NULL;
590 bc = NULL; 636 bc = NULL;
591 ret = 0; 637 ret = 0;
592 while (nr_commands) { 638 while (nr_commands) {
593 request_queue_t *q = bd->queue; 639 request_queue_t *q = bd->queue;
594 int rw = READ;
595 640
596 bc = bsg_get_command(bd); 641 bc = bsg_get_command(bd);
597 if (!bc) 642 if (!bc)
@@ -602,7 +647,7 @@ static ssize_t __bsg_write(struct bsg_device *bd, const char __user *buf,
602 break; 647 break;
603 } 648 }
604 649
605 bc->uhdr = (struct sg_io_hdr __user *) buf; 650 bc->uhdr = (struct sg_io_v4 __user *) buf;
606 if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) { 651 if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) {
607 ret = -EFAULT; 652 ret = -EFAULT;
608 break; 653 break;
@@ -611,7 +656,7 @@ static ssize_t __bsg_write(struct bsg_device *bd, const char __user *buf,
611 /* 656 /*
612 * get a request, fill in the blanks, and add to request queue 657 * get a request, fill in the blanks, and add to request queue
613 */ 658 */
614 rq = bsg_map_hdr(bd, rw, &bc->hdr); 659 rq = bsg_map_hdr(bd, &bc->hdr);
615 if (IS_ERR(rq)) { 660 if (IS_ERR(rq)) {
616 ret = PTR_ERR(rq); 661 ret = PTR_ERR(rq);
617 rq = NULL; 662 rq = NULL;
@@ -622,12 +667,10 @@ static ssize_t __bsg_write(struct bsg_device *bd, const char __user *buf,
622 bc = NULL; 667 bc = NULL;
623 rq = NULL; 668 rq = NULL;
624 nr_commands--; 669 nr_commands--;
625 buf += sizeof(struct sg_io_hdr); 670 buf += sizeof(struct sg_io_v4);
626 *bytes_read += sizeof(struct sg_io_hdr); 671 *bytes_read += sizeof(struct sg_io_v4);
627 } 672 }
628 673
629 if (rq)
630 blk_unmap_sghdr_rq(rq, &bc->hdr);
631 if (bc) 674 if (bc)
632 bsg_free_command(bc); 675 bsg_free_command(bc);
633 676
@@ -898,11 +941,12 @@ bsg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
898 case SG_GET_RESERVED_SIZE: 941 case SG_GET_RESERVED_SIZE:
899 case SG_SET_RESERVED_SIZE: 942 case SG_SET_RESERVED_SIZE:
900 case SG_EMULATED_HOST: 943 case SG_EMULATED_HOST:
901 case SG_IO:
902 case SCSI_IOCTL_SEND_COMMAND: { 944 case SCSI_IOCTL_SEND_COMMAND: {
903 void __user *uarg = (void __user *) arg; 945 void __user *uarg = (void __user *) arg;
904 return scsi_cmd_ioctl(file, bd->disk, cmd, uarg); 946 return scsi_cmd_ioctl(file, bd->disk, cmd, uarg);
905 } 947 }
948 case SG_IO:
949 return -EINVAL;
906 /* 950 /*
907 * block device ioctls 951 * block device ioctls
908 */ 952 */