Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "scsi: target: Add WRITE_ATOMIC_16 support"

John Garry <john.g.garry@oracle.com> says:

This is a reposting of Mike's atomic writes support for the SCSI
target.

Again, we are now only supporting target_core_iblock. It's implemented
similar to UNMAP where we do not do any emulation and instead pass the
operation to the block layer.

Link: https://patch.msgid.link/20251020103820.2917593-1-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+148 -15
+15
drivers/target/target_core_configfs.c
··· 578 578 DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); 579 579 DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); 580 580 DEF_CONFIGFS_ATTRIB_SHOW(submit_type); 581 + DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len); 582 + DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment); 583 + DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity); 584 + DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary); 585 + DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary); 581 586 582 587 #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ 583 588 static ssize_t _name##_store(struct config_item *item, const char *page,\ ··· 1305 1300 CONFIGFS_ATTR(, alua_support); 1306 1301 CONFIGFS_ATTR(, pgr_support); 1307 1302 CONFIGFS_ATTR(, submit_type); 1303 + CONFIGFS_ATTR_RO(, atomic_max_len); 1304 + CONFIGFS_ATTR_RO(, atomic_alignment); 1305 + CONFIGFS_ATTR_RO(, atomic_granularity); 1306 + CONFIGFS_ATTR_RO(, atomic_max_with_boundary); 1307 + CONFIGFS_ATTR_RO(, atomic_max_boundary); 1308 1308 1309 1309 /* 1310 1310 * dev_attrib attributes for devices using the target core SBC/SPC ··· 1353 1343 &attr_pgr_support, 1354 1344 &attr_emulate_rsoc, 1355 1345 &attr_submit_type, 1346 + &attr_atomic_alignment, 1347 + &attr_atomic_max_len, 1348 + &attr_atomic_granularity, 1349 + &attr_atomic_max_with_boundary, 1350 + &attr_atomic_max_boundary, 1356 1351 NULL, 1357 1352 }; 1358 1353 EXPORT_SYMBOL(sbc_attrib_attrs);
+20 -3
drivers/target/target_core_device.c
··· 840 840 return NULL; 841 841 } 842 842 843 + void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib, 844 + struct block_device *bdev) 845 + { 846 + struct request_queue *q = bdev_get_queue(bdev); 847 + int block_size = bdev_logical_block_size(bdev); 848 + 849 + if (!bdev_can_atomic_write(bdev)) 850 + return; 851 + 852 + attrib->atomic_max_len = queue_atomic_write_max_bytes(q) / block_size; 853 + attrib->atomic_granularity = attrib->atomic_alignment = 854 + queue_atomic_write_unit_min_bytes(q) / block_size; 855 + attrib->atomic_max_with_boundary = 0; 856 + attrib->atomic_max_boundary = 0; 857 + } 858 + EXPORT_SYMBOL_GPL(target_configure_write_atomic_from_bdev); 859 + 843 860 /* 844 861 * Check if the underlying struct block_device supports discard and if yes 845 862 * configure the UNMAP parameters. 846 863 */ 847 - bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, 848 - struct block_device *bdev) 864 + bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib, 865 + struct block_device *bdev) 849 866 { 850 867 int block_size = bdev_logical_block_size(bdev); 851 868 ··· 880 863 bdev_discard_alignment(bdev) / block_size; 881 864 return true; 882 865 } 883 - EXPORT_SYMBOL(target_configure_unmap_from_queue); 866 + EXPORT_SYMBOL(target_configure_unmap_from_bdev); 884 867 885 868 /* 886 869 * Convert from blocksize advertised to the initiator to the 512 byte
+2 -2
drivers/target/target_core_file.c
··· 92 92 struct inode *inode = file->f_mapping->host; 93 93 94 94 if (S_ISBLK(inode->i_mode)) 95 - return target_configure_unmap_from_queue(&dev->dev_attrib, 96 - I_BDEV(inode)); 95 + return target_configure_unmap_from_bdev(&dev->dev_attrib, 96 + I_BDEV(inode)); 97 97 98 98 /* Limit UNMAP emulation to 8k Number of LBAs (NoLB) */ 99 99 dev->dev_attrib.max_unmap_lba_count = 0x2000;
+7 -2
drivers/target/target_core_iblock.c
··· 84 84 { 85 85 struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 86 86 87 - return target_configure_unmap_from_queue(&dev->dev_attrib, 88 - ib_dev->ibd_bd); 87 + return target_configure_unmap_from_bdev(&dev->dev_attrib, 88 + ib_dev->ibd_bd); 89 89 } 90 90 91 91 static int iblock_configure_device(struct se_device *dev) ··· 151 151 152 152 if (bdev_nonrot(bd)) 153 153 dev->dev_attrib.is_nonrot = 1; 154 + 155 + target_configure_write_atomic_from_bdev(&dev->dev_attrib, bd); 154 156 155 157 bi = bdev_get_integrity(bd); 156 158 if (!bi) ··· 775 773 else if (!bdev_write_cache(ib_dev->ibd_bd)) 776 774 opf |= REQ_FUA; 777 775 } 776 + 777 + if (cmd->se_cmd_flags & SCF_ATOMIC) 778 + opf |= REQ_ATOMIC; 778 779 } else { 779 780 opf = REQ_OP_READ; 780 781 miter_dir = SG_MITER_FROM_SG;
+51
drivers/target/target_core_sbc.c
··· 764 764 return 0; 765 765 } 766 766 767 + static sense_reason_t 768 + sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) 769 + { 770 + struct se_dev_attrib *attrib = &dev->dev_attrib; 771 + u16 boundary, transfer_len; 772 + u64 lba; 773 + 774 + lba = transport_lba_64(cdb); 775 + boundary = get_unaligned_be16(&cdb[10]); 776 + transfer_len = get_unaligned_be16(&cdb[12]); 777 + 778 + if (!attrib->atomic_max_len) 779 + return TCM_UNSUPPORTED_SCSI_OPCODE; 780 + 781 + if (boundary) { 782 + if (transfer_len > attrib->atomic_max_with_boundary) 783 + return TCM_INVALID_CDB_FIELD; 784 + 785 + if (boundary > attrib->atomic_max_boundary) 786 + return TCM_INVALID_CDB_FIELD; 787 + } else { 788 + if (transfer_len > attrib->atomic_max_len) 789 + return TCM_INVALID_CDB_FIELD; 790 + } 791 + 792 + if (attrib->atomic_granularity) { 793 + if (transfer_len % attrib->atomic_granularity) 794 + return TCM_INVALID_CDB_FIELD; 795 + 796 + if (boundary && boundary % attrib->atomic_granularity) 797 + return TCM_INVALID_CDB_FIELD; 798 + } 799 + 800 + if (dev->dev_attrib.atomic_alignment) { 801 + u64 _lba = lba; 802 + 803 + if (do_div(_lba, dev->dev_attrib.atomic_alignment)) 804 + return TCM_INVALID_CDB_FIELD; 805 + } 806 + 807 + return 0; 808 + } 809 + 767 810 sense_reason_t 768 811 sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) 769 812 { ··· 904 861 break; 905 862 case WRITE_16: 906 863 case WRITE_VERIFY_16: 864 + case WRITE_ATOMIC_16: 907 865 sectors = transport_get_sectors_16(cdb); 908 866 cmd->t_task_lba = transport_lba_64(cdb); 909 867 ··· 916 872 return ret; 917 873 918 874 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 875 + if (cdb[0] == WRITE_ATOMIC_16) { 876 + cmd->se_cmd_flags |= SCF_ATOMIC; 877 + 878 + ret = sbc_check_atomic(dev, cmd, cdb); 879 + if (ret) 880 + return ret; 881 + } 919 882 cmd->execute_cmd = sbc_execute_rw; 920 883 break; 921 884 case VARIABLE_LENGTH_CMD:
+43 -6
drivers/target/target_core_spc.c
··· 521 521 have_tp = 1; 522 522 523 523 buf[0] = dev->transport->get_device_type(dev); 524 - buf[3] = have_tp ? 0x3c : 0x10; 525 524 526 525 /* Set WSNZ to 1 */ 527 526 buf[4] = 0x01; ··· 561 562 else 562 563 put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); 563 564 564 - /* 565 - * Exit now if we don't support TP. 566 - */ 565 + put_unaligned_be16(12, &buf[2]); 566 + 567 567 if (!have_tp) 568 - goto max_write_same; 568 + goto try_atomic; 569 569 570 570 /* 571 571 * Set MAXIMUM UNMAP LBA COUNT ··· 593 595 /* 594 596 * MAXIMUM WRITE SAME LENGTH 595 597 */ 596 - max_write_same: 597 598 put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); 598 599 600 + put_unaligned_be16(40, &buf[2]); 601 + 602 + try_atomic: 603 + /* 604 + * ATOMIC 605 + */ 606 + if (!dev->dev_attrib.atomic_max_len) 607 + goto done; 608 + 609 + if (dev->dev_attrib.atomic_max_len < io_max_blocks) 610 + put_unaligned_be32(dev->dev_attrib.atomic_max_len, &buf[44]); 611 + else 612 + put_unaligned_be32(io_max_blocks, &buf[44]); 613 + 614 + put_unaligned_be32(dev->dev_attrib.atomic_alignment, &buf[48]); 615 + put_unaligned_be32(dev->dev_attrib.atomic_granularity, &buf[52]); 616 + put_unaligned_be32(dev->dev_attrib.atomic_max_with_boundary, &buf[56]); 617 + put_unaligned_be32(dev->dev_attrib.atomic_max_boundary, &buf[60]); 618 + 619 + put_unaligned_be16(60, &buf[2]); 620 + done: 599 621 return 0; 600 622 } 601 623 ··· 1470 1452 .update_usage_bits = set_dpofua_usage_bits32, 1471 1453 }; 1472 1454 1455 + static bool tcm_is_atomic_enabled(const struct target_opcode_descriptor *descr, 1456 + struct se_cmd *cmd) 1457 + { 1458 + return cmd->se_dev->dev_attrib.atomic_max_len; 1459 + } 1460 + 1461 + static struct target_opcode_descriptor tcm_opcode_write_atomic16 = { 1462 + .support = SCSI_SUPPORT_FULL, 1463 + .opcode = WRITE_ATOMIC_16, 1464 + .cdb_size = 16, 1465 + .usage_bits = {WRITE_ATOMIC_16, 0xf8, 0xff, 0xff, 1466 + 0xff, 0xff, 0xff, 0xff, 1467 + 0xff, 0xff, 0xff, 0xff, 1468 + 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, 1469 + .enabled = tcm_is_atomic_enabled, 1470 + .update_usage_bits = set_dpofua_usage_bits, 1471 + }; 1472 + 1473 1473 static bool tcm_is_caw_enabled(const struct target_opcode_descriptor *descr, 1474 1474 struct se_cmd *cmd) 1475 1475 { ··· 2044 2008 &tcm_opcode_write16, 2045 2009 &tcm_opcode_write_verify16, 2046 2010 &tcm_opcode_write_same32, 2011 + &tcm_opcode_write_atomic16, 2047 2012 &tcm_opcode_compare_write, 2048 2013 &tcm_opcode_read_capacity, 2049 2014 &tcm_opcode_read_capacity16,
+4 -2
include/target/target_core_backend.h
··· 121 121 122 122 bool target_sense_desc_format(struct se_device *dev); 123 123 sector_t target_to_linux_sector(struct se_device *dev, sector_t lb); 124 - bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, 125 - struct block_device *bdev); 124 + bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib, 125 + struct block_device *bdev); 126 + void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib, 127 + struct block_device *bdev); 126 128 127 129 static inline bool target_dev_configured(struct se_device *se_dev) 128 130 {
+6
include/target/target_core_base.h
··· 158 158 SCF_TASK_ATTR_SET = (1 << 17), 159 159 SCF_TREAT_READ_AS_NORMAL = (1 << 18), 160 160 SCF_TASK_ORDERED_SYNC = (1 << 19), 161 + SCF_ATOMIC = (1 << 20), 161 162 }; 162 163 163 164 /* ··· 732 731 u32 unmap_granularity; 733 732 u32 unmap_granularity_alignment; 734 733 u32 max_write_same_len; 734 + u32 atomic_max_len; 735 + u32 atomic_alignment; 736 + u32 atomic_granularity; 737 + u32 atomic_max_with_boundary; 738 + u32 atomic_max_boundary; 735 739 u8 submit_type; 736 740 struct se_device *da_dev; 737 741 struct config_group da_group;