From e31468d6643a1f24dd6f736f12b226f05794fc27 Mon Sep 17 00:00:00 2001 From: Ryan Ronnander Date: Fri, 10 Apr 2026 18:41:00 -0400 Subject: [PATCH 1/5] iSCSILogicalUnit: add block_size parameter for lio-t and scst Add optional block_size parameter to override the logical block size (512, 1024, 2048, or 4096) presented to initiators. - lio-t: writes to configfs block_size attribute after backstore creation, before LUN mapping (must be set before LUN assignment) - scst: passes blocksize in the -open_dev attributes string at device creation time (read-only after creation) No-op when unset; kernel default (typically 512) is preserved. --- heartbeat/iSCSILogicalUnit.in | 40 ++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/heartbeat/iSCSILogicalUnit.in b/heartbeat/iSCSILogicalUnit.in index efcb3a66d..aa4d1bc64 100644 --- a/heartbeat/iSCSILogicalUnit.in +++ b/heartbeat/iSCSILogicalUnit.in @@ -69,6 +69,8 @@ OCF_RESKEY_lio_iblock=${OCF_RESKEY_lio_iblock:-$OCF_RESKEY_lio_iblock_default} # Set LIO-T backend default as 'block' OCF_RESKEY_liot_bstype_default="block" : ${OCF_RESKEY_liot_bstype=${OCF_RESKEY_liot_bstype_default}} +OCF_RESKEY_block_size_default="" +: ${OCF_RESKEY_block_size=${OCF_RESKEY_block_size_default}} ## tgt specifics # tgt has "backing store type" and "backing store open flags", @@ -294,6 +296,19 @@ Do not use PSCSI unless you know exactly how it will be used. + + +Override the block size presented to initiators for this +Logical Unit. Accepted values are 512, 1024, 2048, or 4096. +This sets the block_size attribute in the LIO kernel target +(configfs) or the blocksize attribute in SCST. +Requires the lio-t or scst implementation. +If unset, the kernel default (typically 512) is used. + +Block size (512, 1024, 2048, or 4096) + + + @@ -452,6 +467,9 @@ iSCSILogicalUnit_start() { if [ -n "${OCF_RESKEY_product_id}" ]; then echo "${OCF_RESKEY_product_id}" > /sys/kernel/config/target/core/iblock_*/${OCF_RESOURCE_INSTANCE}/wwn/product_id fi + if [ -n "${OCF_RESKEY_block_size}" ]; then + echo ${OCF_RESKEY_block_size} > ${iblock_attrib_path}/block_size || exit $OCF_ERR_GENERIC + fi ocf_run targetcli /iscsi/${OCF_RESKEY_target_iqn}/tpg1/luns create /backstores/${OCF_RESKEY_liot_bstype}/${OCF_RESOURCE_INSTANCE} ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC @@ -486,7 +504,11 @@ iSCSILogicalUnit_start() { fi ;; scst) - ocf_run scstadmin -open_dev "${OCF_RESOURCE_INSTANCE}" -handler vdisk_blockio -attributes "filename=${OCF_RESKEY_path},nv_cache=0,write_through=1" + local scst_attrs="filename=${OCF_RESKEY_path},nv_cache=0,write_through=1" + if [ -n "${OCF_RESKEY_block_size}" ]; then + scst_attrs="${scst_attrs},blocksize=${OCF_RESKEY_block_size}" + fi + ocf_run scstadmin -open_dev "${OCF_RESOURCE_INSTANCE}" -handler vdisk_blockio -attributes "${scst_attrs}" if [ -n "${OCF_RESKEY_scsi_sn}" ]; then ocf_run scstadmin -set_dev_attr "${OCF_RESOURCE_INSTANCE}" -attributes "usn=${OCF_RESKEY_scsi_sn}" -force -noprompt fi @@ -657,6 +679,22 @@ iSCSILogicalUnit_validate() { fi done + # Validate block_size if set + if [ -n "${OCF_RESKEY_block_size}" ]; then + case "${OCF_RESKEY_block_size}" in + 512|1024|2048|4096) + ;; + *) + ocf_exit_reason "Invalid block_size ${OCF_RESKEY_block_size} (must be 512, 1024, 2048, or 4096)" + exit $OCF_ERR_CONFIGURED + ;; + esac + if [ "${OCF_RESKEY_implementation}" != "lio-t" ] && [ "${OCF_RESKEY_implementation}" != "scst" ]; then + ocf_exit_reason "block_size is only supported with the lio-t or scst implementation" + exit $OCF_ERR_CONFIGURED + fi + fi + # Is the configured implementation supported? case "$OCF_RESKEY_implementation" in "iet"|"tgt"|"lio"|"lio-t"|"scst") From fcab65364a831253f00307994588b7c7dda0b02d Mon Sep 17 00:00:00 2001 From: Ryan Ronnander Date: Sat, 11 Apr 2026 09:50:23 -0400 Subject: [PATCH 2/5] iSCSILogicalUnit: add scst_bstype parameter for SCST handler selection The SCST handler was hardcoded to vdisk_blockio, which uses direct I/O. Add scst_bstype parameter (default: vdisk_blockio) to allow selecting vdisk_fileio, which routes I/O through the kernel page cache. The fileio handler is needed when presenting smaller block sizes on 4K-native backing devices (for example, block_size=512 on a 4K NVMe drive). --- heartbeat/iSCSILogicalUnit.in | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/heartbeat/iSCSILogicalUnit.in b/heartbeat/iSCSILogicalUnit.in index aa4d1bc64..8066a7223 100644 --- a/heartbeat/iSCSILogicalUnit.in +++ b/heartbeat/iSCSILogicalUnit.in @@ -71,6 +71,9 @@ OCF_RESKEY_liot_bstype_default="block" : ${OCF_RESKEY_liot_bstype=${OCF_RESKEY_liot_bstype_default}} OCF_RESKEY_block_size_default="" : ${OCF_RESKEY_block_size=${OCF_RESKEY_block_size_default}} +# Set SCST backing store type default as 'vdisk_blockio' +OCF_RESKEY_scst_bstype_default="vdisk_blockio" +: ${OCF_RESKEY_scst_bstype=${OCF_RESKEY_scst_bstype_default}} ## tgt specifics # tgt has "backing store type" and "backing store open flags", @@ -309,6 +312,18 @@ If unset, the kernel default (typically 512) is used. + + +SCST device handler to use when creating the backstore. +Use "vdisk_blockio" for direct I/O (the default) or +"vdisk_fileio" for page cache backed I/O. The fileio handler +is required when presenting smaller block sizes on 4K-native +backing devices. Requires the scst implementation. + +SCST device handler (vdisk_blockio or vdisk_fileio) + + + @@ -508,7 +523,7 @@ iSCSILogicalUnit_start() { if [ -n "${OCF_RESKEY_block_size}" ]; then scst_attrs="${scst_attrs},blocksize=${OCF_RESKEY_block_size}" fi - ocf_run scstadmin -open_dev "${OCF_RESOURCE_INSTANCE}" -handler vdisk_blockio -attributes "${scst_attrs}" + ocf_run scstadmin -open_dev "${OCF_RESOURCE_INSTANCE}" -handler ${OCF_RESKEY_scst_bstype} -attributes "${scst_attrs}" if [ -n "${OCF_RESKEY_scsi_sn}" ]; then ocf_run scstadmin -set_dev_attr "${OCF_RESOURCE_INSTANCE}" -attributes "usn=${OCF_RESKEY_scsi_sn}" -force -noprompt fi @@ -599,7 +614,7 @@ iSCSILogicalUnit_stop() { ;; scst) ocf_run -warn scstadmin -rem_lun ${OCF_RESKEY_lun} -driver iscsi -target "${OCF_RESKEY_target_iqn}" -force -noprompt - ocf_run scstadmin -close_dev "${OCF_RESOURCE_INSTANCE}" -handler vdisk_blockio -force -noprompt + ocf_run scstadmin -close_dev "${OCF_RESOURCE_INSTANCE}" -handler ${OCF_RESKEY_scst_bstype} -force -noprompt ;; esac @@ -679,6 +694,20 @@ iSCSILogicalUnit_validate() { fi done + # Validate scst_bstype + case "${OCF_RESKEY_scst_bstype}" in + vdisk_blockio|vdisk_fileio) + ;; + *) + ocf_exit_reason "Invalid scst_bstype ${OCF_RESKEY_scst_bstype} (must be vdisk_blockio or vdisk_fileio)" + exit $OCF_ERR_CONFIGURED + ;; + esac + if [ "${OCF_RESKEY_scst_bstype}" != "${OCF_RESKEY_scst_bstype_default}" ] && [ "${OCF_RESKEY_implementation}" != "scst" ]; then + ocf_exit_reason "scst_bstype is only supported with the scst implementation" + exit $OCF_ERR_CONFIGURED + fi + # Validate block_size if set if [ -n "${OCF_RESKEY_block_size}" ]; then case "${OCF_RESKEY_block_size}" in From 2cbca1f4268b61087ac70eeee71e3029600e7063 Mon Sep 17 00:00:00 2001 From: Ryan Ronnander Date: Sat, 11 Apr 2026 09:57:41 -0400 Subject: [PATCH 3/5] iSCSILogicalUnit: add scst_bstype and liot_bstype to unsupported param lists Add scst_bstype to the unsupported parameter lists for iet, tgt, lio, and lio-t implementations so users get a warning when setting it on a non-scst target. Add liot_bstype to the scst list for the same reason. --- heartbeat/iSCSILogicalUnit.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/heartbeat/iSCSILogicalUnit.in b/heartbeat/iSCSILogicalUnit.in index 8066a7223..77784227c 100644 --- a/heartbeat/iSCSILogicalUnit.in +++ b/heartbeat/iSCSILogicalUnit.in @@ -789,19 +789,19 @@ iSCSILogicalUnit_validate() { iet) # IET does not support setting the vendor and product ID # (it always uses "IET" and "VIRTUAL-DISK") - unsupported_params="vendor_id product_id allowed_initiators lio_iblock tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw liot_bstype" + unsupported_params="vendor_id product_id allowed_initiators lio_iblock tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw liot_bstype scst_bstype" ;; tgt) - unsupported_params="allowed_initiators lio_iblock emulate_tpu emulate_3pc emulate_caw liot_bstype" + unsupported_params="allowed_initiators lio_iblock emulate_tpu emulate_3pc emulate_caw liot_bstype scst_bstype" ;; lio) - unsupported_params="scsi_id vendor_id product_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw liot_bstype" + unsupported_params="scsi_id vendor_id product_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw liot_bstype scst_bstype" ;; lio-t) - unsupported_params="scsi_id vendor_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type lio_iblock" + unsupported_params="scsi_id vendor_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type lio_iblock scst_bstype" ;; scst) - unsupported_params="scsi_id emulate_tpu emulate_3pc emulate_caw" + unsupported_params="scsi_id emulate_tpu emulate_3pc emulate_caw liot_bstype" ;; esac From 146da1e0b29933a14d6f3ba35796b235477d3801 Mon Sep 17 00:00:00 2001 From: Ryan Ronnander Date: Sat, 11 Apr 2026 10:53:56 -0400 Subject: [PATCH 4/5] iSCSILogicalUnit: fix lio-t configfs paths for fileio and pscsi backstores The lio-t code path hardcoded iblock_* in configfs paths for scsi_sn, product_id, block_size, and emulate_* attribute writes. This only works for the default block backstore. When liot_bstype is set to fileio or pscsi, the configfs directory is fileio_* or pscsi_* respectively. Map liot_bstype to the correct configfs core directory name in both the start and monitor functions. --- heartbeat/iSCSILogicalUnit.in | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/heartbeat/iSCSILogicalUnit.in b/heartbeat/iSCSILogicalUnit.in index 77784227c..b37dc0864 100644 --- a/heartbeat/iSCSILogicalUnit.in +++ b/heartbeat/iSCSILogicalUnit.in @@ -460,7 +460,13 @@ iSCSILogicalUnit_start() { lio-t) ocf_take_lock $TARGETLOCKFILE ocf_release_lock_on_exit $TARGETLOCKFILE - iblock_attrib_path="/sys/kernel/config/target/core/iblock_*/${OCF_RESOURCE_INSTANCE}/attrib" + # Map liot_bstype to the configfs core directory name + case "${OCF_RESKEY_liot_bstype}" in + block) liot_configfs_core="iblock_*" ;; + fileio) liot_configfs_core="fileio_*" ;; + pscsi) liot_configfs_core="pscsi_*" ;; + esac + liot_core_path="/sys/kernel/config/target/core/${liot_configfs_core}/${OCF_RESOURCE_INSTANCE}" # For lio, we first have to create a target device, then # add it to the Target Portal Group as an LU. # Handle differently 'block', 'fileio' and 'pscsi' @@ -477,13 +483,13 @@ iSCSILogicalUnit_start() { ocf_run targetcli /backstores/${OCF_RESKEY_liot_bstype} create ${OCF_RESOURCE_INSTANCE} ${OCF_RESKEY_path} || exit $OCF_ERR_GENERIC fi if [ -n "${OCF_RESKEY_scsi_sn}" ]; then - echo ${OCF_RESKEY_scsi_sn} > /sys/kernel/config/target/core/iblock_*/${OCF_RESOURCE_INSTANCE}/wwn/vpd_unit_serial + echo ${OCF_RESKEY_scsi_sn} > ${liot_core_path}/wwn/vpd_unit_serial fi if [ -n "${OCF_RESKEY_product_id}" ]; then - echo "${OCF_RESKEY_product_id}" > /sys/kernel/config/target/core/iblock_*/${OCF_RESOURCE_INSTANCE}/wwn/product_id + echo "${OCF_RESKEY_product_id}" > ${liot_core_path}/wwn/product_id fi if [ -n "${OCF_RESKEY_block_size}" ]; then - echo ${OCF_RESKEY_block_size} > ${iblock_attrib_path}/block_size || exit $OCF_ERR_GENERIC + echo ${OCF_RESKEY_block_size} > ${liot_core_path}/attrib/block_size || exit $OCF_ERR_GENERIC fi ocf_run targetcli /iscsi/${OCF_RESKEY_target_iqn}/tpg1/luns create /backstores/${OCF_RESKEY_liot_bstype}/${OCF_RESOURCE_INSTANCE} ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC @@ -509,13 +515,13 @@ iSCSILogicalUnit_start() { fi if [ -n "${OCF_RESKEY_emulate_tpu}" ]; then - echo ${OCF_RESKEY_emulate_tpu} > ${iblock_attrib_path}/emulate_tpu || exit $OCF_ERR_GENERIC + echo ${OCF_RESKEY_emulate_tpu} > ${liot_core_path}/attrib/emulate_tpu || exit $OCF_ERR_GENERIC fi if [ -n "${OCF_RESKEY_emulate_3pc}" ]; then - echo ${OCF_RESKEY_emulate_3pc} > ${iblock_attrib_path}/emulate_3pc || exit $OCF_ERR_GENERIC + echo ${OCF_RESKEY_emulate_3pc} > ${liot_core_path}/attrib/emulate_3pc || exit $OCF_ERR_GENERIC fi if [ -n "${OCF_RESKEY_emulate_caw}" ]; then - echo ${OCF_RESKEY_emulate_caw} > ${iblock_attrib_path}/emulate_caw || exit $OCF_ERR_GENERIC + echo ${OCF_RESKEY_emulate_caw} > ${liot_core_path}/attrib/emulate_caw || exit $OCF_ERR_GENERIC fi ;; scst) @@ -668,9 +674,14 @@ iSCSILogicalUnit_monitor() { configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_target_iqn}/tpgt_1/lun/lun_${OCF_RESKEY_lun}/*/udev_path" [ -e ${configfs_path} ] && [ `cat ${configfs_path}` = "${OCF_RESKEY_path}" ] && return $OCF_SUCCESS - # if we aren't activated, is a block device still left over? - block_configfs_path="/sys/kernel/config/target/core/iblock_*/${OCF_RESOURCE_INSTANCE}/udev_path" - [ -e ${block_configfs_path} ] && ocf_log warn "existing block without an active lun: ${block_configfs_path}" + # if we aren't activated, is a backstore still left over? + case "${OCF_RESKEY_liot_bstype}" in + block) liot_configfs_core="iblock_*" ;; + fileio) liot_configfs_core="fileio_*" ;; + pscsi) liot_configfs_core="pscsi_*" ;; + esac + block_configfs_path="/sys/kernel/config/target/core/${liot_configfs_core}/${OCF_RESOURCE_INSTANCE}/udev_path" + [ -e ${block_configfs_path} ] && ocf_log warn "existing backstore without an active lun: ${block_configfs_path}" [ -e ${block_configfs_path} ] && return $OCF_ERR_GENERIC ;; scst) From 8f9f820cf03c011bfdc858e1c8f13f204f2e4d4e Mon Sep 17 00:00:00 2001 From: Ryan Ronnander Date: Sat, 11 Apr 2026 15:32:35 -0400 Subject: [PATCH 5/5] iSCSILogicalUnit: add emulate_write_cache parameter for lio-t Expose the LIO configfs emulate_write_cache attribute as an RA parameter. Fileio backstores default to write-back caching which is unsafe for HA configurations. Setting emulate_write_cache=0 enables write-through mode. Follows the existing emulate_tpu, emulate_3pc, emulate_caw pattern. --- heartbeat/iSCSILogicalUnit.in | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/heartbeat/iSCSILogicalUnit.in b/heartbeat/iSCSILogicalUnit.in index b37dc0864..74d732710 100644 --- a/heartbeat/iSCSILogicalUnit.in +++ b/heartbeat/iSCSILogicalUnit.in @@ -193,6 +193,20 @@ Setting this integer to 1 will enable CAW IOCTL emulation. + + +Enable or disable write-back caching for this Logical Unit. +Setting to 1 enables write-back caching (the default for fileio +backstores). Setting to 0 disables it, enabling write-through mode. +Write-through mode is recommended for HA configurations to ensure +data is flushed to disk before the iSCSI write is acknowledged. +Requires the lio-t implementation. For SCST, use the +"scst_write_cache" parameter instead. + +Write-back cache (0 or 1) + + + The SCSI vendor ID to be configured for this Logical Unit. @@ -523,6 +537,9 @@ iSCSILogicalUnit_start() { if [ -n "${OCF_RESKEY_emulate_caw}" ]; then echo ${OCF_RESKEY_emulate_caw} > ${liot_core_path}/attrib/emulate_caw || exit $OCF_ERR_GENERIC fi + if [ -n "${OCF_RESKEY_emulate_write_cache}" ]; then + echo ${OCF_RESKEY_emulate_write_cache} > ${liot_core_path}/attrib/emulate_write_cache || exit $OCF_ERR_GENERIC + fi ;; scst) local scst_attrs="filename=${OCF_RESKEY_path},nv_cache=0,write_through=1" @@ -800,19 +817,19 @@ iSCSILogicalUnit_validate() { iet) # IET does not support setting the vendor and product ID # (it always uses "IET" and "VIRTUAL-DISK") - unsupported_params="vendor_id product_id allowed_initiators lio_iblock tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw liot_bstype scst_bstype" + unsupported_params="vendor_id product_id allowed_initiators lio_iblock tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw emulate_write_cache liot_bstype scst_bstype" ;; tgt) - unsupported_params="allowed_initiators lio_iblock emulate_tpu emulate_3pc emulate_caw liot_bstype scst_bstype" + unsupported_params="allowed_initiators lio_iblock emulate_tpu emulate_3pc emulate_caw emulate_write_cache liot_bstype scst_bstype" ;; lio) - unsupported_params="scsi_id vendor_id product_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw liot_bstype scst_bstype" + unsupported_params="scsi_id vendor_id product_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type emulate_tpu emulate_3pc emulate_caw emulate_write_cache liot_bstype scst_bstype" ;; lio-t) unsupported_params="scsi_id vendor_id tgt_bstype tgt_bsoflags tgt_bsopts tgt_device_type lio_iblock scst_bstype" ;; scst) - unsupported_params="scsi_id emulate_tpu emulate_3pc emulate_caw liot_bstype" + unsupported_params="scsi_id emulate_tpu emulate_3pc emulate_caw emulate_write_cache liot_bstype" ;; esac