|
From: Gleb C. <lna...@ya...> - 2023-04-17 17:32:28
|
Commit: c326e96 GitHub URL: https://github.com/SCST-project/scst/commit/c326e96886ba29895fed8d259cb0123df94d0ef9 Author: Brian Meagher Date: 2023-04-17T20:31:58+03:00 Log Message: ----------- scst_lib,scst_sysfs: Add aen_disabled setting Add a setting to scst_tgt that can prevent scst_gen_aen_or_ua from generating an AEN, even if the underlying transport is capable of transmitting them. It will instead generate a UA. Modified Paths: -------------- scst/README | 7 ++ scst/include/scst.h | 9 ++ scst/src/scst_lib.c | 13 ++ scst/src/scst_sysfs.c | 98 +++++++++++++++ 4 files changed, 127 insertions(+) =================================================================== diff --git a/scst/README b/scst/README index f01dbb7..4e6e8ef 100644 --- a/scst/README +++ b/scst/README @@ -825,6 +825,13 @@ Every target should have at least the following entries: For instance, read_unaligned_cmd_count means number of 4K unaligned IOs. + - aen_disabled - if set this target port is not to send AEN (Asynchronous + Event Notification), but rather generate a Unit Attention - even if the + underlying transport does support AEN. + + This could prove useful in different situations including when the target + is also a forward_dst. + A target driver may have also the following entries: - "hw_target" - if the target driver supports both hardware and virtual diff --git a/scst/include/scst.h b/scst/include/scst.h index 1e754cb..0e9d299 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -481,6 +481,9 @@ enum scst_exec_res { /* Cache of tgt->tgt_forward_dst */ #define SCST_TGT_DEV_FORWARD_DST 5 +/* Cache of tgt->tgt_aen_disabled */ +#define SCST_TGT_DEV_AEN_DISABLED 6 + /************************************************************* ** I/O grouping types. Changing them don't forget to change ** the corresponding *_STR values in scst_const.h! @@ -1694,6 +1697,12 @@ struct scst_tgt { */ unsigned tgt_forward_dst:1; + /* + * Set if do not to wish to send AEN from this target port, even if + * supported by the transport. Send a UA instead. + */ + unsigned int tgt_aen_disabled:1; + /* Per target analog of the corresponding driver's fields */ unsigned tgt_dif_supported:1; unsigned tgt_hw_dif_type1_supported:1; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index bc41c71..722a3cb 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -2511,6 +2511,15 @@ void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev, sess->shut_phase != SCST_SESS_SPH_READY) goto out; + if (unlikely(test_bit(SCST_TGT_DEV_AEN_DISABLED, + &tgt_dev->tgt_dev_flags))) { + /* + * We have decided not to generate an AEN + * even if supported by the transport. + */ + goto queue_ua; + } + if (tgtt->report_aen != NULL) { struct scst_aen *aen; int rc; @@ -5300,6 +5309,10 @@ static int scst_alloc_add_tgt_dev(struct scst_session *sess, set_bit(SCST_TGT_DEV_FORWARD_DST, &tgt_dev->tgt_dev_flags); else clear_bit(SCST_TGT_DEV_FORWARD_DST, &tgt_dev->tgt_dev_flags); + if (sess->tgt->tgt_aen_disabled) + set_bit(SCST_TGT_DEV_AEN_DISABLED, &tgt_dev->tgt_dev_flags); + else + clear_bit(SCST_TGT_DEV_AEN_DISABLED, &tgt_dev->tgt_dev_flags); tgt_dev->hw_dif_same_sg_layout_required = sess->tgt->tgt_hw_dif_same_sg_layout_required; tgt_dev->tgt_dev_dif_guard_format = acg_dev->acg_dev_dif_guard_format; if (tgt_dev->tgt_dev_dif_guard_format == SCST_DIF_GUARD_FORMAT_IP) diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 14db134..4fadd86 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -2601,6 +2601,103 @@ static struct kobj_attribute scst_tgt_forwarding = __ATTR(forwarding, S_IRUGO | S_IWUSR, scst_tgt_forward_dst_show, scst_tgt_forward_dst_store); +static ssize_t scst_tgt_aen_disabled_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct scst_tgt *tgt; + int res; + + TRACE_ENTRY(); + + tgt = container_of(kobj, struct scst_tgt, tgt_kobj); + + res = sprintf(buf, "%d\n%s", tgt->tgt_aen_disabled, + tgt->tgt_aen_disabled ? SCST_SYSFS_KEY_MARK "\n" : ""); + + TRACE_EXIT_RES(res); + return res; +} + +static ssize_t scst_tgt_aen_disabled_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int res = 0; + struct scst_tgt *tgt; + struct scst_session *sess; + int old; + + TRACE_ENTRY(); + + if ((buf == NULL) || (count == 0)) { + res = 0; + goto out; + } + + tgt = container_of(kobj, struct scst_tgt, tgt_kobj); + + mutex_lock(&scst_mutex); + + old = tgt->tgt_aen_disabled; + + switch (buf[0]) { + case '0': + tgt->tgt_aen_disabled = 0; + break; + case '1': + tgt->tgt_aen_disabled = 1; + break; + default: + PRINT_ERROR("%s: Requested action not understood: %s", + __func__, buf); + res = -EINVAL; + goto out_unlock; + } + + if (tgt->tgt_aen_disabled == old) + goto out_unlock; + + list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { + int i; + + rcu_read_lock(); + for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { + struct list_head *head = &sess->sess_tgt_dev_list[i]; + struct scst_tgt_dev *tgt_dev; + + list_for_each_entry_rcu(tgt_dev, head, sess_tgt_dev_list_entry) { + if (tgt->tgt_aen_disabled) + set_bit(SCST_TGT_DEV_AEN_DISABLED, + &tgt_dev->tgt_dev_flags); + else + clear_bit(SCST_TGT_DEV_AEN_DISABLED, + &tgt_dev->tgt_dev_flags); + } + } + rcu_read_unlock(); + } + + if (tgt->tgt_aen_disabled) + PRINT_INFO("Set AEN disabled for target %s", + tgt->tgt_name); + else + PRINT_INFO("Clear AEN disabled for target %s", + tgt->tgt_name); + +out_unlock: + mutex_unlock(&scst_mutex); + + if (res == 0) + res = count; + +out: + TRACE_EXIT_RES(res); + return res; +} + +static struct kobj_attribute scst_tgt_aen_disabled = + __ATTR(aen_disabled, 0644, scst_tgt_aen_disabled_show, + scst_tgt_aen_disabled_store); + static ssize_t scst_tgt_comment_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -2875,6 +2972,7 @@ static struct attribute *scst_tgt_attrs[] = { &scst_rel_tgt_id.attr, &scst_tgt_forward_src.attr, &scst_tgt_forward_dst.attr, + &scst_tgt_aen_disabled.attr, &scst_tgt_forwarding.attr, &scst_tgt_comment.attr, &scst_tgt_addr_method.attr, |