Message ID | 20241008020437.78788-3-michael.christie@oracle.com |
---|---|
State | New |
Headers | show |
Series | scsi: target: Add WRITE_ATOMIC_16 support | expand |
On 08/10/2024 03:03, Mike Christie wrote: > This adds atomic fields to the se_device and exports them in configfs. > > Initially only target_core_iblock will be supported and we will inherit > all the settings from the block layer except the alignment which userspace > will set. > > Signed-off-by: Mike Christie <michael.christie@oracle.com> > --- > drivers/target/target_core_configfs.c | 42 +++++++++++++++++++++++++++ > include/target/target_core_base.h | 6 ++++ > 2 files changed, 48 insertions(+) > > diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c > index c40217f44b1b..f3c7da650f65 100644 > --- a/drivers/target/target_core_configfs.c > +++ b/drivers/target/target_core_configfs.c > @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data); > DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); > DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); > DEF_CONFIGFS_ATTRIB_SHOW(submit_type); > +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported); > +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment); > +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len); > +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity); > +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary); > +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary); > > #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ > static ssize_t _name##_store(struct config_item *item, const char *page,\ > @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct config_item *item, const char *page, > return count; > } > > +static ssize_t atomic_alignment_store(struct config_item *item, > + const char *page, size_t count) What is special about alignment that we need to be able to configure this? Won't that be derived from the block device queue_limits (like granularity)? > +{ > + struct se_dev_attrib *da = to_attrib(item); > + u32 val; > + int ret; > + > + ret = kstrtou32(page, 0, &val); > + if (ret < 0) > + return ret; > + > + if (da->da_dev->export_count) { > + pr_err("dev[%p]: Unable to change SE Device atomic_alignment while export_count is %d\n", > + da->da_dev, da->da_dev->export_count); > + return -EINVAL; > + } > + > + da->atomic_alignment = val; > + > + pr_debug("dev[%p]: SE Device atomic_alignment changed to %u\n", > + da->da_dev, val); > + return count; > +} > + > CONFIGFS_ATTR(, emulate_model_alias); > CONFIGFS_ATTR(, emulate_dpo); > CONFIGFS_ATTR(, emulate_fua_write); > @@ -1302,6 +1332,12 @@ CONFIGFS_ATTR(, max_write_same_len); > CONFIGFS_ATTR(, alua_support); > CONFIGFS_ATTR(, pgr_support); > CONFIGFS_ATTR(, submit_type); > +CONFIGFS_ATTR(, atomic_alignment); > +CONFIGFS_ATTR_RO(, atomic_supported); isn't a non-zero atomic_max_len the same thing as this? > +CONFIGFS_ATTR_RO(, atomic_max_len); > +CONFIGFS_ATTR_RO(, atomic_granularity); > +CONFIGFS_ATTR_RO(, atomic_max_with_boundary); > +CONFIGFS_ATTR_RO(, atomic_max_boundary); > > /* > * dev_attrib attributes for devices using the target core SBC/SPC > @@ -1345,6 +1381,12 @@ struct configfs_attribute *sbc_attrib_attrs[] = { > &attr_pgr_support, > &attr_emulate_rsoc, > &attr_submit_type, > + &attr_atomic_supported, > + &attr_atomic_alignment, > + &attr_atomic_max_len, > + &attr_atomic_granularity, > + &attr_atomic_max_with_boundary, > + &attr_atomic_max_boundary, > NULL, > }; > EXPORT_SYMBOL(sbc_attrib_attrs); > diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h > index 97099a5e3f6c..6c87bd018983 100644 > --- a/include/target/target_core_base.h > +++ b/include/target/target_core_base.h > @@ -715,6 +715,7 @@ struct se_dev_attrib { > bool is_nonrot; > bool emulate_rest_reord; > bool unmap_zeroes_data; > + bool atomic_supported; > u32 hw_block_size; > u32 block_size; > u32 hw_max_sectors; > @@ -726,6 +727,11 @@ struct se_dev_attrib { > u32 unmap_granularity; > u32 unmap_granularity_alignment; > u32 max_write_same_len; > + u32 atomic_max_len; > + u32 atomic_alignment; > + u32 atomic_granularity; > + u32 atomic_max_with_boundary; > + u32 atomic_max_boundary; these will always be zero, right? I don't see much point in even storing them. > u8 submit_type; > struct se_device *da_dev; > struct config_group da_group;
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index c40217f44b1b..f3c7da650f65 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -578,6 +578,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data); DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); DEF_CONFIGFS_ATTRIB_SHOW(submit_type); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_supported); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary); #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ static ssize_t _name##_store(struct config_item *item, const char *page,\ @@ -1266,6 +1272,30 @@ static ssize_t submit_type_store(struct config_item *item, const char *page, return count; } +static ssize_t atomic_alignment_store(struct config_item *item, + const char *page, size_t count) +{ + struct se_dev_attrib *da = to_attrib(item); + u32 val; + int ret; + + ret = kstrtou32(page, 0, &val); + if (ret < 0) + return ret; + + if (da->da_dev->export_count) { + pr_err("dev[%p]: Unable to change SE Device atomic_alignment while export_count is %d\n", + da->da_dev, da->da_dev->export_count); + return -EINVAL; + } + + da->atomic_alignment = val; + + pr_debug("dev[%p]: SE Device atomic_alignment changed to %u\n", + da->da_dev, val); + return count; +} + CONFIGFS_ATTR(, emulate_model_alias); CONFIGFS_ATTR(, emulate_dpo); CONFIGFS_ATTR(, emulate_fua_write); @@ -1302,6 +1332,12 @@ CONFIGFS_ATTR(, max_write_same_len); CONFIGFS_ATTR(, alua_support); CONFIGFS_ATTR(, pgr_support); CONFIGFS_ATTR(, submit_type); +CONFIGFS_ATTR(, atomic_alignment); +CONFIGFS_ATTR_RO(, atomic_supported); +CONFIGFS_ATTR_RO(, atomic_max_len); +CONFIGFS_ATTR_RO(, atomic_granularity); +CONFIGFS_ATTR_RO(, atomic_max_with_boundary); +CONFIGFS_ATTR_RO(, atomic_max_boundary); /* * dev_attrib attributes for devices using the target core SBC/SPC @@ -1345,6 +1381,12 @@ struct configfs_attribute *sbc_attrib_attrs[] = { &attr_pgr_support, &attr_emulate_rsoc, &attr_submit_type, + &attr_atomic_supported, + &attr_atomic_alignment, + &attr_atomic_max_len, + &attr_atomic_granularity, + &attr_atomic_max_with_boundary, + &attr_atomic_max_boundary, NULL, }; EXPORT_SYMBOL(sbc_attrib_attrs); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 97099a5e3f6c..6c87bd018983 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -715,6 +715,7 @@ struct se_dev_attrib { bool is_nonrot; bool emulate_rest_reord; bool unmap_zeroes_data; + bool atomic_supported; u32 hw_block_size; u32 block_size; u32 hw_max_sectors; @@ -726,6 +727,11 @@ struct se_dev_attrib { u32 unmap_granularity; u32 unmap_granularity_alignment; u32 max_write_same_len; + u32 atomic_max_len; + u32 atomic_alignment; + u32 atomic_granularity; + u32 atomic_max_with_boundary; + u32 atomic_max_boundary; u8 submit_type; struct se_device *da_dev; struct config_group da_group;
This adds atomic fields to the se_device and exports them in configfs. Initially only target_core_iblock will be supported and we will inherit all the settings from the block layer except the alignment which userspace will set. Signed-off-by: Mike Christie <michael.christie@oracle.com> --- drivers/target/target_core_configfs.c | 42 +++++++++++++++++++++++++++ include/target/target_core_base.h | 6 ++++ 2 files changed, 48 insertions(+)