diff options
author | Asias He <asias@redhat.com> | 2013-02-25 01:03:46 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-04-25 04:05:24 -0400 |
commit | 86d7182985d25900929adce14fffd729cc8c6fb8 (patch) | |
tree | 8e5e755c5badf3a09b5b0c4e6c2f76c72c080dcf /drivers/target | |
parent | dbc21c5abbeb4419da5a54157c4b7a0ec0dee185 (diff) |
target: Add sbc_execute_unmap() helper
iblock_execute_unmap() and fd_execute_unmap share a lot of code.
Add sbc_execute_unmap() helper to remove duplicated code for
iblock_execute_unmap() and fd_execute_unmap().
Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Asias He <asias@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_file.c | 82 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 81 | ||||
-rw-r--r-- | drivers/target/target_core_sbc.c | 85 |
3 files changed, 93 insertions, 155 deletions
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index d5b84fac31c7..9063c31df9e1 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -480,8 +480,9 @@ fd_execute_write_same(struct se_cmd *cmd) | |||
480 | } | 480 | } |
481 | 481 | ||
482 | static sense_reason_t | 482 | static sense_reason_t |
483 | fd_do_unmap(struct se_cmd *cmd, struct file *file, sector_t lba, sector_t nolb) | 483 | fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) |
484 | { | 484 | { |
485 | struct file *file = priv; | ||
485 | struct inode *inode = file->f_mapping->host; | 486 | struct inode *inode = file->f_mapping->host; |
486 | int ret; | 487 | int ret; |
487 | 488 | ||
@@ -542,84 +543,9 @@ fd_execute_write_same_unmap(struct se_cmd *cmd) | |||
542 | static sense_reason_t | 543 | static sense_reason_t |
543 | fd_execute_unmap(struct se_cmd *cmd) | 544 | fd_execute_unmap(struct se_cmd *cmd) |
544 | { | 545 | { |
545 | struct se_device *dev = cmd->se_dev; | 546 | struct file *file = FD_DEV(cmd->se_dev)->fd_file; |
546 | struct fd_dev *fd_dev = FD_DEV(dev); | ||
547 | struct file *file = fd_dev->fd_file; | ||
548 | unsigned char *buf, *ptr = NULL; | ||
549 | sector_t lba; | ||
550 | int size; | ||
551 | u32 range; | ||
552 | sense_reason_t ret = 0; | ||
553 | int dl, bd_dl; | ||
554 | |||
555 | /* We never set ANC_SUP */ | ||
556 | if (cmd->t_task_cdb[1]) | ||
557 | return TCM_INVALID_CDB_FIELD; | ||
558 | |||
559 | if (cmd->data_length == 0) { | ||
560 | target_complete_cmd(cmd, SAM_STAT_GOOD); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | if (cmd->data_length < 8) { | ||
565 | pr_warn("UNMAP parameter list length %u too small\n", | ||
566 | cmd->data_length); | ||
567 | return TCM_PARAMETER_LIST_LENGTH_ERROR; | ||
568 | } | ||
569 | |||
570 | buf = transport_kmap_data_sg(cmd); | ||
571 | if (!buf) | ||
572 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
573 | |||
574 | dl = get_unaligned_be16(&buf[0]); | ||
575 | bd_dl = get_unaligned_be16(&buf[2]); | ||
576 | 547 | ||
577 | size = cmd->data_length - 8; | 548 | return sbc_execute_unmap(cmd, fd_do_unmap, file); |
578 | if (bd_dl > size) | ||
579 | pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", | ||
580 | cmd->data_length, bd_dl); | ||
581 | else | ||
582 | size = bd_dl; | ||
583 | |||
584 | if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { | ||
585 | ret = TCM_INVALID_PARAMETER_LIST; | ||
586 | goto err; | ||
587 | } | ||
588 | |||
589 | /* First UNMAP block descriptor starts at 8 byte offset */ | ||
590 | ptr = &buf[8]; | ||
591 | pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" | ||
592 | " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); | ||
593 | |||
594 | while (size >= 16) { | ||
595 | lba = get_unaligned_be64(&ptr[0]); | ||
596 | range = get_unaligned_be32(&ptr[8]); | ||
597 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", | ||
598 | (unsigned long long)lba, range); | ||
599 | |||
600 | if (range > dev->dev_attrib.max_unmap_lba_count) { | ||
601 | ret = TCM_INVALID_PARAMETER_LIST; | ||
602 | goto err; | ||
603 | } | ||
604 | |||
605 | if (lba + range > dev->transport->get_blocks(dev) + 1) { | ||
606 | ret = TCM_ADDRESS_OUT_OF_RANGE; | ||
607 | goto err; | ||
608 | } | ||
609 | |||
610 | ret = fd_do_unmap(cmd, file, lba, range); | ||
611 | if (ret) | ||
612 | goto err; | ||
613 | |||
614 | ptr += 16; | ||
615 | size -= 16; | ||
616 | } | ||
617 | |||
618 | err: | ||
619 | transport_kunmap_data_sg(cmd); | ||
620 | if (!ret) | ||
621 | target_complete_cmd(cmd, GOOD); | ||
622 | return ret; | ||
623 | } | 549 | } |
624 | 550 | ||
625 | static sense_reason_t | 551 | static sense_reason_t |
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 96a9b620e89a..07f5f94634bb 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -380,9 +380,10 @@ iblock_execute_sync_cache(struct se_cmd *cmd) | |||
380 | } | 380 | } |
381 | 381 | ||
382 | static sense_reason_t | 382 | static sense_reason_t |
383 | iblock_do_unmap(struct se_cmd *cmd, struct block_device *bdev, | 383 | iblock_do_unmap(struct se_cmd *cmd, void *priv, |
384 | sector_t lba, sector_t nolb) | 384 | sector_t lba, sector_t nolb) |
385 | { | 385 | { |
386 | struct block_device *bdev = priv; | ||
386 | int ret; | 387 | int ret; |
387 | 388 | ||
388 | ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0); | 389 | ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0); |
@@ -397,83 +398,9 @@ iblock_do_unmap(struct se_cmd *cmd, struct block_device *bdev, | |||
397 | static sense_reason_t | 398 | static sense_reason_t |
398 | iblock_execute_unmap(struct se_cmd *cmd) | 399 | iblock_execute_unmap(struct se_cmd *cmd) |
399 | { | 400 | { |
400 | struct se_device *dev = cmd->se_dev; | 401 | struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd; |
401 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | ||
402 | unsigned char *buf, *ptr = NULL; | ||
403 | sector_t lba; | ||
404 | int size; | ||
405 | u32 range; | ||
406 | sense_reason_t ret = 0; | ||
407 | int dl, bd_dl; | ||
408 | |||
409 | /* We never set ANC_SUP */ | ||
410 | if (cmd->t_task_cdb[1]) | ||
411 | return TCM_INVALID_CDB_FIELD; | ||
412 | |||
413 | if (cmd->data_length == 0) { | ||
414 | target_complete_cmd(cmd, SAM_STAT_GOOD); | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | if (cmd->data_length < 8) { | ||
419 | pr_warn("UNMAP parameter list length %u too small\n", | ||
420 | cmd->data_length); | ||
421 | return TCM_PARAMETER_LIST_LENGTH_ERROR; | ||
422 | } | ||
423 | |||
424 | buf = transport_kmap_data_sg(cmd); | ||
425 | if (!buf) | ||
426 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
427 | |||
428 | dl = get_unaligned_be16(&buf[0]); | ||
429 | bd_dl = get_unaligned_be16(&buf[2]); | ||
430 | |||
431 | size = cmd->data_length - 8; | ||
432 | if (bd_dl > size) | ||
433 | pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", | ||
434 | cmd->data_length, bd_dl); | ||
435 | else | ||
436 | size = bd_dl; | ||
437 | |||
438 | if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { | ||
439 | ret = TCM_INVALID_PARAMETER_LIST; | ||
440 | goto err; | ||
441 | } | ||
442 | |||
443 | /* First UNMAP block descriptor starts at 8 byte offset */ | ||
444 | ptr = &buf[8]; | ||
445 | pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" | ||
446 | " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); | ||
447 | |||
448 | while (size >= 16) { | ||
449 | lba = get_unaligned_be64(&ptr[0]); | ||
450 | range = get_unaligned_be32(&ptr[8]); | ||
451 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", | ||
452 | (unsigned long long)lba, range); | ||
453 | |||
454 | if (range > dev->dev_attrib.max_unmap_lba_count) { | ||
455 | ret = TCM_INVALID_PARAMETER_LIST; | ||
456 | goto err; | ||
457 | } | ||
458 | |||
459 | if (lba + range > dev->transport->get_blocks(dev) + 1) { | ||
460 | ret = TCM_ADDRESS_OUT_OF_RANGE; | ||
461 | goto err; | ||
462 | } | ||
463 | |||
464 | ret = iblock_do_unmap(cmd, ib_dev->ibd_bd, lba, range); | ||
465 | if (ret) | ||
466 | goto err; | ||
467 | |||
468 | ptr += 16; | ||
469 | size -= 16; | ||
470 | } | ||
471 | 402 | ||
472 | err: | 403 | return sbc_execute_unmap(cmd, iblock_do_unmap, bdev); |
473 | transport_kunmap_data_sg(cmd); | ||
474 | if (!ret) | ||
475 | target_complete_cmd(cmd, GOOD); | ||
476 | return ret; | ||
477 | } | 404 | } |
478 | 405 | ||
479 | static sense_reason_t | 406 | static sense_reason_t |
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 60d4b5185f32..bbc5b0ee2bdc 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -596,3 +596,88 @@ u32 sbc_get_device_type(struct se_device *dev) | |||
596 | return TYPE_DISK; | 596 | return TYPE_DISK; |
597 | } | 597 | } |
598 | EXPORT_SYMBOL(sbc_get_device_type); | 598 | EXPORT_SYMBOL(sbc_get_device_type); |
599 | |||
600 | sense_reason_t | ||
601 | sbc_execute_unmap(struct se_cmd *cmd, | ||
602 | sense_reason_t (*do_unmap_fn)(struct se_cmd *, void *, | ||
603 | sector_t, sector_t), | ||
604 | void *priv) | ||
605 | { | ||
606 | struct se_device *dev = cmd->se_dev; | ||
607 | unsigned char *buf, *ptr = NULL; | ||
608 | sector_t lba; | ||
609 | int size; | ||
610 | u32 range; | ||
611 | sense_reason_t ret = 0; | ||
612 | int dl, bd_dl; | ||
613 | |||
614 | /* We never set ANC_SUP */ | ||
615 | if (cmd->t_task_cdb[1]) | ||
616 | return TCM_INVALID_CDB_FIELD; | ||
617 | |||
618 | if (cmd->data_length == 0) { | ||
619 | target_complete_cmd(cmd, SAM_STAT_GOOD); | ||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | if (cmd->data_length < 8) { | ||
624 | pr_warn("UNMAP parameter list length %u too small\n", | ||
625 | cmd->data_length); | ||
626 | return TCM_PARAMETER_LIST_LENGTH_ERROR; | ||
627 | } | ||
628 | |||
629 | buf = transport_kmap_data_sg(cmd); | ||
630 | if (!buf) | ||
631 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
632 | |||
633 | dl = get_unaligned_be16(&buf[0]); | ||
634 | bd_dl = get_unaligned_be16(&buf[2]); | ||
635 | |||
636 | size = cmd->data_length - 8; | ||
637 | if (bd_dl > size) | ||
638 | pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", | ||
639 | cmd->data_length, bd_dl); | ||
640 | else | ||
641 | size = bd_dl; | ||
642 | |||
643 | if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { | ||
644 | ret = TCM_INVALID_PARAMETER_LIST; | ||
645 | goto err; | ||
646 | } | ||
647 | |||
648 | /* First UNMAP block descriptor starts at 8 byte offset */ | ||
649 | ptr = &buf[8]; | ||
650 | pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" | ||
651 | " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); | ||
652 | |||
653 | while (size >= 16) { | ||
654 | lba = get_unaligned_be64(&ptr[0]); | ||
655 | range = get_unaligned_be32(&ptr[8]); | ||
656 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", | ||
657 | (unsigned long long)lba, range); | ||
658 | |||
659 | if (range > dev->dev_attrib.max_unmap_lba_count) { | ||
660 | ret = TCM_INVALID_PARAMETER_LIST; | ||
661 | goto err; | ||
662 | } | ||
663 | |||
664 | if (lba + range > dev->transport->get_blocks(dev) + 1) { | ||
665 | ret = TCM_ADDRESS_OUT_OF_RANGE; | ||
666 | goto err; | ||
667 | } | ||
668 | |||
669 | ret = do_unmap_fn(cmd, priv, lba, range); | ||
670 | if (ret) | ||
671 | goto err; | ||
672 | |||
673 | ptr += 16; | ||
674 | size -= 16; | ||
675 | } | ||
676 | |||
677 | err: | ||
678 | transport_kunmap_data_sg(cmd); | ||
679 | if (!ret) | ||
680 | target_complete_cmd(cmd, GOOD); | ||
681 | return ret; | ||
682 | } | ||
683 | EXPORT_SYMBOL(sbc_execute_unmap); | ||