aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/target/target_core_file.c82
-rw-r--r--drivers/target/target_core_iblock.c81
-rw-r--r--drivers/target/target_core_sbc.c85
-rw-r--r--include/target/target_core_backend.h4
4 files changed, 97 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
482static sense_reason_t 482static sense_reason_t
483fd_do_unmap(struct se_cmd *cmd, struct file *file, sector_t lba, sector_t nolb) 483fd_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)
542static sense_reason_t 543static sense_reason_t
543fd_execute_unmap(struct se_cmd *cmd) 544fd_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
618err:
619 transport_kunmap_data_sg(cmd);
620 if (!ret)
621 target_complete_cmd(cmd, GOOD);
622 return ret;
623} 549}
624 550
625static sense_reason_t 551static 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
382static sense_reason_t 382static sense_reason_t
383iblock_do_unmap(struct se_cmd *cmd, struct block_device *bdev, 383iblock_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,
397static sense_reason_t 398static sense_reason_t
398iblock_execute_unmap(struct se_cmd *cmd) 399iblock_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
472err: 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
479static sense_reason_t 406static 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}
598EXPORT_SYMBOL(sbc_get_device_type); 598EXPORT_SYMBOL(sbc_get_device_type);
599
600sense_reason_t
601sbc_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
677err:
678 transport_kunmap_data_sg(cmd);
679 if (!ret)
680 target_complete_cmd(cmd, GOOD);
681 return ret;
682}
683EXPORT_SYMBOL(sbc_execute_unmap);
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index b128c20770bc..ffa2696d64dc 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -60,6 +60,10 @@ sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops);
60u32 sbc_get_device_rev(struct se_device *dev); 60u32 sbc_get_device_rev(struct se_device *dev);
61u32 sbc_get_device_type(struct se_device *dev); 61u32 sbc_get_device_type(struct se_device *dev);
62sector_t sbc_get_write_same_sectors(struct se_cmd *cmd); 62sector_t sbc_get_write_same_sectors(struct se_cmd *cmd);
63sense_reason_t sbc_execute_unmap(struct se_cmd *cmd,
64 sense_reason_t (*do_unmap_fn)(struct se_cmd *cmd, void *priv,
65 sector_t lba, sector_t nolb),
66 void *priv);
63 67
64void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); 68void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
65int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); 69int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);