diff --git a/scst/README b/scst/README index 889227b15..e9da11b69 100644 --- a/scst/README +++ b/scst/README @@ -665,6 +665,10 @@ Every target should have at least the following entries: until rel_tgt_id becomes unique. This attribute initialized unique by SCST by default. + - forwarding - if set this target is forwarding target, i.e. does not check + any local SCSI events (reservations, etc.). Those event supposed to + be checked on the another, requester's side. + - *count*, e.g. read_io_count_kb, - statistics about executed commands and transferred data. Those attributes have speaking names built from parts: diff --git a/scst/README_in-tree b/scst/README_in-tree index 43efb16aa..9b71342de 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -541,6 +541,10 @@ Every target should have at least the following entries: until rel_tgt_id becomes unique. This attribute initialized unique by SCST by default. + - forwarding - if set this target is forwarding target, i.e. does not check + any local SCSI events (reservations, etc.). Those event supposed to + be checked on the another, requester's side. + - *count*, e.g. read_io_count_kb, - statistics about executed commands and transferred data. Those attributes have speaking names built from parts: diff --git a/scst/include/scst.h b/scst/include/scst.h index 688f6d074..412423004 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -702,6 +702,9 @@ enum scst_exec_context { /* Cache of acg->acg_black_hole_type */ #define SCST_TGT_DEV_BLACK_HOLE 1 +/* Cache of tgt->tgt_forwarding */ +#define SCST_TGT_DEV_FORWARDING 5 + /************************************************************* ** I/O grouping types. Changing them don't forget to change ** the corresponding *_STR values in scst_const.h! @@ -1926,6 +1929,13 @@ struct scst_tgt { struct list_head tgt_acg_list; /* target ACG groups */ #endif + /* + * Set, if this target is forwarding target, i.e. does not check + * any local SCSI events (reservations, etc.). Those event supposed + * to be checked on the another, requester's side. + */ + unsigned tgt_forwarding: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 8f6b598a1..000a543c2 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4858,6 +4858,10 @@ static int scst_alloc_add_tgt_dev(struct scst_session *sess, tgt_dev->lun = acg_dev->lun; tgt_dev->acg_dev = acg_dev; tgt_dev->tgt_dev_rd_only = acg_dev->acg_dev_rd_only || dev->dev_rd_only; + if (sess->tgt->tgt_forwarding) + set_bit(SCST_TGT_DEV_FORWARDING, &tgt_dev->tgt_dev_flags); + else + clear_bit(SCST_TGT_DEV_FORWARDING, &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_pres.c b/scst/src/scst_pres.c index bec46df08..282939f45 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -1535,6 +1535,11 @@ static int scst_pr_register_all_tg_pt(struct scst_cmd *cmd, uint8_t *buffer, continue; if (tgt->rel_tgt_id == 0) continue; + if (tgt->tgt_forwarding) { + TRACE_PR("ALL_TG_PT: skipping forwarding " + "target %s", tgt->tgt_name); + continue; + } TRACE_PR("tgt %s, rel_tgt_id %d", tgt->tgt_name, tgt->rel_tgt_id); res = scst_pr_register_on_tgt_id(cmd, tgt->rel_tgt_id, diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index a1a267607..29ca48730 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -2498,6 +2498,95 @@ static struct kobj_attribute scst_rel_tgt_id = __ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show, scst_rel_tgt_id_store); +static ssize_t scst_tgt_forwarding_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_forwarding, + tgt->tgt_forwarding ? SCST_SYSFS_KEY_MARK "\n" : ""); + + TRACE_EXIT_RES(res); + return res; +} + +static ssize_t scst_tgt_forwarding_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_forwarding; + + switch (buf[0]) { + case '0': + tgt->tgt_forwarding = 0; + break; + case '1': + tgt->tgt_forwarding = 1; + break; + default: + PRINT_ERROR("%s: Requested action not understood: %s", + __func__, buf); + res = -EINVAL; + goto out_unlock; + } + + if (tgt->tgt_forwarding == old) + goto out_unlock; + + list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { + int i; + 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(tgt_dev, head, sess_tgt_dev_list_entry) { + if (tgt->tgt_forwarding) + set_bit(SCST_TGT_DEV_FORWARDING, &tgt_dev->tgt_dev_flags); + else + clear_bit(SCST_TGT_DEV_FORWARDING, &tgt_dev->tgt_dev_flags); + } + } + } + + if (tgt->tgt_forwarding) + PRINT_INFO("Set target %s as forwarding", tgt->tgt_name); + else + PRINT_INFO("Clear target %s as forwarding", 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_forwarding = + __ATTR(forwarding, S_IRUGO | S_IWUSR, scst_tgt_forwarding_show, + scst_tgt_forwarding_store); + static ssize_t scst_tgt_comment_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -2769,6 +2858,7 @@ SCST_TGT_SYSFS_STAT_ATTR(cmd_count, none_cmd_count, SCST_DATA_NONE, >> 0); static struct attribute *scst_tgt_attrs[] = { &scst_rel_tgt_id.attr, + &scst_tgt_forwarding.attr, &scst_tgt_comment.attr, &scst_tgt_addr_method.attr, &scst_tgt_io_grouping_type.attr, diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 62755aa13..9672752ca 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2789,6 +2789,15 @@ int __scst_check_local_events(struct scst_cmd *cmd, bool preempt_tests_only) goto out; } + if (unlikely(test_bit(SCST_TGT_DEV_FORWARDING, &cmd->tgt_dev->tgt_dev_flags))) { + /* + * All the checks are supposed to be done on the + * forwarding requester's side. + */ + res = 0; + goto out; + } + /* * There's no race here, because we need to trace commands sent * *after* dev_double_ua_possible flag was set.