From 3ad0566ac7158994ca2c2b35c158ce19b6305dda Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 22:55:59 +0000 Subject: [PATCH 1/8] scst/README: Fix spelling git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8771 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scst/README b/scst/README index b58f9baa2..66004be40 100644 --- a/scst/README +++ b/scst/README @@ -1788,7 +1788,7 @@ attribute. closes open handles on all affected SCST devices and after transition reopens them, if the new state is active or nonoptimized. Alternatively, set "bind_alua_state=0" for SCST BLOCKIO devices and ALUA state changes -will not open/close the backing block device, the user will neeed to handle +will not open/close the backing block device, the user will need to handle this manually or via a cluster RA in an HA setup. Thus, the recommended implicit ALUA state change procedure for primary From 88711323dc904044c08d7bc16c086c84f87f6605 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 22:57:43 +0000 Subject: [PATCH 2/8] scst: Use bitmap_parse() instead of __bitmap_parse() __bitmap_parse() has been removed from kernel v5.6. See also commit 2d6261583be0 ("lib: rework bitmap_parse()") # v5.6-rc1. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8772 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/scst_sysfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 3d6bc0432..bab2baa00 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -2072,10 +2072,10 @@ static ssize_t __scst_acg_cpu_mask_store(struct scst_acg *acg, * We can't use cpumask_parse_user() here, because it expects * buffer in the user space. */ - res = __bitmap_parse(buf, count, 0, cpumask_bits(&work->cpu_mask), - nr_cpumask_bits); + res = bitmap_parse(buf, count, cpumask_bits(&work->cpu_mask), + nr_cpumask_bits); if (res != 0) { - PRINT_ERROR("__bitmap_parse() failed: %d", res); + PRINT_ERROR("bitmap_parse() failed: %d", res); goto out_release; } From dc670b9c072f6aab05dd589524a2770e5998faf6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 22:58:25 +0000 Subject: [PATCH 3/8] scst_vdisk: Clean up show() functions Leave out "? 1 : 0" from after single bit variables. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8773 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 7e320d069..d80808b08 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -8217,7 +8217,7 @@ static ssize_t vdisk_sysfs_rd_only_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n%s", virt_dev->rd_only ? 1 : 0, + pos = sprintf(buf, "%d\n%s", virt_dev->rd_only, (virt_dev->rd_only == DEF_RD_ONLY) ? "" : SCST_SYSFS_KEY_MARK "\n"); @@ -8237,7 +8237,7 @@ static ssize_t vdisk_sysfs_wt_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n%s", virt_dev->wt_flag ? 1 : 0, + pos = sprintf(buf, "%d\n%s", virt_dev->wt_flag, (virt_dev->wt_flag == DEF_WRITE_THROUGH) ? "" : SCST_SYSFS_KEY_MARK "\n"); @@ -8257,7 +8257,7 @@ static ssize_t vdisk_sysfs_tp_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n%s", virt_dev->thin_provisioned ? 1 : 0, + pos = sprintf(buf, "%d\n%s", virt_dev->thin_provisioned, virt_dev->thin_provisioned_manually_set && (virt_dev->thin_provisioned != virt_dev->dev_thin_provisioned) ? @@ -8355,7 +8355,7 @@ static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n%s", virt_dev->nv_cache ? 1 : 0, + pos = sprintf(buf, "%d\n%s", virt_dev->nv_cache, (virt_dev->nv_cache == DEF_NV_CACHE) ? "" : SCST_SYSFS_KEY_MARK "\n"); @@ -8375,7 +8375,7 @@ static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n%s", virt_dev->o_direct_flag ? 1 : 0, + pos = sprintf(buf, "%d\n%s", virt_dev->o_direct_flag, (virt_dev->o_direct_flag == DEF_O_DIRECT) ? "" : SCST_SYSFS_KEY_MARK "\n"); @@ -8447,7 +8447,7 @@ static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n", virt_dev->removable ? 1 : 0); + pos = sprintf(buf, "%d\n", virt_dev->removable); if ((virt_dev->dev->type != TYPE_ROM) && (virt_dev->removable != DEF_REMOVABLE)) @@ -8490,7 +8490,7 @@ static ssize_t vdisk_sysfs_rotational_show(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n", virt_dev->rotational ? 1 : 0); + pos = sprintf(buf, "%d\n", virt_dev->rotational); if (virt_dev->rotational != DEF_ROTATIONAL) pos += sprintf(&buf[pos], "%s\n", SCST_SYSFS_KEY_MARK); From bf2393ff01f9f177c3fbe3bc039347f2a8587732 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 22:59:32 +0000 Subject: [PATCH 4/8] scst: Split scst_tg_set_group_info() Since scst_tg_set_group_info() is too long, split it into two functions. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8774 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/scst_tg.c | 333 ++++++++++++++++++++++++--------------------- 1 file changed, 179 insertions(+), 154 deletions(-) diff --git a/scst/src/scst_tg.c b/scst/src/scst_tg.c index 0f0fb9fcf..8b6b1a6f6 100644 --- a/scst/src/scst_tg.c +++ b/scst/src/scst_tg.c @@ -1663,6 +1663,169 @@ static void scst_stpg_ext_blocking_done(struct scst_device *dev, scst_stpg_check_blocking_done(*((struct scst_stpg_wait **)data)); } +/** + * struct osi - Information needed to process an STPG command. + * + * The 'on' in 'osi' refers to 'on_stpg', a concept from the ION SCST code base + * that has not yet been ported. + * + * @group_id: Target port group ID. + * @tg: Target port group. + * @prev_state: previous target port group ALUA state. + * @new_state: new target port group ALUA state. + */ +struct osi { + uint16_t group_id; + struct scst_target_group *tg; + enum scst_tg_state prev_state; + enum scst_tg_state new_state; +}; + +static int scst_emit_stpg_event(struct scst_cmd *cmd, struct scst_dev_group *dg, + struct osi *osi, int tpg_desc_count) +{ + int j, payload_len, event_entry_len, valid_desc_count, res; + struct scst_event_stpg_payload *payload; + struct scst_event_entry *event_entry; + struct scst_event_stpg_descr *descr; + struct scst_device *dev = cmd->dev; + struct scst_stpg_wait *wait; + struct scst_event *event; + struct scst_dg_dev *dgd; + + payload_len = sizeof(*payload) + sizeof(*descr) * tpg_desc_count; + event_entry_len = sizeof(*event_entry) + payload_len; + event_entry = kzalloc(event_entry_len, GFP_KERNEL); + if (event_entry == NULL) { + PRINT_ERROR("Unable to allocate event (size %d)", event_entry_len); + res = -ENOMEM; + goto out; + } + + TRACE_MEM("event_entry %p (len %d) allocated", event_entry, + event_entry_len); + + event = &event_entry->event; + event->payload_len = payload_len; + + payload = (struct scst_event_stpg_payload *)event->payload; + payload->stpg_cmd_tag = cmd->tag; + + res = 1; + + if (strlcpy(payload->device_name, dev->virt_name, + sizeof(payload->device_name)) >= + sizeof(payload->device_name)) { + PRINT_ERROR("Device name %s too long", dev->virt_name); + goto out_too_long; + } + + valid_desc_count = 0; + for (j = 0, descr = &payload->stpg_descriptors[0]; j < tpg_desc_count; + j++) { + if (osi[j].prev_state == osi[j].new_state) + continue; + + if (strlcpy(descr->prev_state, + scst_alua_state_name(osi[j].prev_state), + sizeof(descr->prev_state)) >= + sizeof(descr->prev_state) || + strlcpy(descr->new_state, + scst_alua_state_name(osi[j].new_state), + sizeof(descr->new_state)) >= + sizeof(descr->new_state) || + strlcpy(descr->dg_name, dg->name, sizeof(descr->dg_name)) + >= sizeof(descr->dg_name) || + strlcpy(descr->tg_name, osi[j].tg->name, + sizeof(descr->tg_name)) >= + sizeof(descr->tg_name)) + goto out_too_long; + + descr->group_id = osi[j].group_id; + + TRACE_DBG("group_id %u, prev_state %s, new_state %s, dg_name %s, tg_name %s", + descr->group_id, descr->prev_state, descr->new_state, + descr->dg_name, descr->tg_name); + + valid_desc_count++; + descr++; + } + + payload->stpg_descriptors_cnt = valid_desc_count; + + if (valid_desc_count == 0) { + TRACE_DBG("Nothing to do"); + goto out; + } + + dg->stpg_rel_tgt_id = cmd->tgt->rel_tgt_id; + dg->stpg_transport_id = kmemdup(cmd->sess->transport_id, + scst_tid_size(cmd->sess->transport_id), GFP_KERNEL); + if (dg->stpg_transport_id == NULL) { + PRINT_ERROR("Unable to duplicate stpg_transport_id"); + goto out; + } + + wait = kzalloc(sizeof(*wait), GFP_KERNEL); + if (wait == NULL) { + PRINT_ERROR("Unable to allocate STPG wait struct " + "(size %zd)", sizeof(*wait)); + res = -ENOMEM; + goto out; + } + + atomic_set(&wait->stpg_wait_left, 1); + wait->event_entry = event_entry; + + event_entry->event_notify_fn = scst_event_stpg_notify_fn; + event_entry->notify_fn_priv = cmd; + + mutex_lock(&scst_dg_mutex); + list_for_each_entry(dgd, &dg->dev_list, entry) { + int rc; + + if (dgd->dev == dev) + continue; + + TRACE_DBG("STPG: ext blocking dev %s", + dgd->dev->virt_name); + + atomic_inc(&wait->stpg_wait_left); + + rc = scst_ext_block_dev(dgd->dev, + scst_stpg_ext_blocking_done, + (uint8_t *)&wait, sizeof(wait), + SCST_EXT_BLOCK_STPG); + if (rc != 0) { + TRACE_DBG("scst_ext_block_dev() failed " + "with %d, reverting (cmd %p)", rc, cmd); + wait->status = rc; + wait->dg = dg; + atomic_dec(&wait->stpg_wait_left); + spin_lock_bh(&dev->dev_lock); + WARN_ON(dgd->dev->stpg_ext_blocked); + dgd->dev->stpg_ext_blocked = 0; + spin_unlock_bh(&dev->dev_lock); + break; + } + } + mutex_unlock(&scst_dg_mutex); + + scst_stpg_check_blocking_done(wait); + /* !! cmd can be already dead here !! */ + + return 0; + +out_too_long: + res = -EOVERFLOW; + +out: + kfree(dg->stpg_transport_id); + dg->stpg_transport_id = NULL; + kfree(event_entry); + return res; +} + /* * scst_tg_set_group_info - SET TARGET PORT GROUPS implementation. * @@ -1679,19 +1842,9 @@ int scst_tg_set_group_info(struct scst_cmd *cmd) struct scst_device *dev = cmd->dev; uint8_t *buf; int len; - int i, j, res = 1, tpg_desc_count, valid_desc_count; + int i, j, res = 1, tpg_desc_count; struct scst_dev_group *dg; - struct osi { - uint16_t group_id; - struct scst_target_group *tg; - enum scst_tg_state prev_state; - enum scst_tg_state new_state; - } *osi = NULL; - int event_entry_len, payload_len; - struct scst_event_entry *event_entry; - struct scst_event *event; - struct scst_event_stpg_payload *payload; - struct scst_event_stpg_descr *descr; + struct osi *osi = NULL; TRACE_ENTRY(); @@ -1816,140 +1969,23 @@ int scst_tg_set_group_info(struct scst_cmd *cmd) scst_put_buf_full(cmd, buf); - payload_len = sizeof(*payload) + sizeof(*descr) * tpg_desc_count; - event_entry_len = sizeof(*event_entry) + payload_len; - event_entry = kzalloc(event_entry_len, GFP_KERNEL); - if (event_entry == NULL) { - PRINT_ERROR("Unable to allocate event (size %d)", event_entry_len); - res = -ENOMEM; + res = scst_emit_stpg_event(cmd, dg, osi, tpg_desc_count); + switch (res) { + case 1: + case 0: + break; + case -ENOMEM: scst_set_busy(cmd); - goto out_free; + break; + default: + WARN_ONCE(true, "res = %d\n", res); + /* fall through */ + case -EOVERFLOW: + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_set_target_pgs_failed)); + break; } - TRACE_MEM("event_entry %p (len %d) allocated", event_entry, - event_entry_len); - - event = &event_entry->event; - event->payload_len = payload_len; - - payload = (struct scst_event_stpg_payload *)event->payload; - payload->stpg_cmd_tag = cmd->tag; - - res = 1; - - if (strlen(dev->virt_name) >= sizeof(payload->device_name)) { - PRINT_ERROR("Device name %s too long", dev->virt_name); - goto out_too_long; - } - strlcpy(payload->device_name, dev->virt_name, sizeof(payload->device_name)); - - valid_desc_count = 0; - for (j = 0, descr = &payload->stpg_descriptors[0]; j < tpg_desc_count; j++) { - if (osi[j].prev_state == osi[j].new_state) - continue; - - if (strlen(scst_alua_state_name(osi[j].prev_state)) >= sizeof(descr->prev_state)) { - PRINT_ERROR("prev state too long (%d)", osi[j].prev_state); - goto out_too_long; - } - strlcpy(descr->prev_state, scst_alua_state_name(osi[j].prev_state), - sizeof(descr->prev_state)); - - if (strlen(scst_alua_state_name(osi[j].new_state)) >= sizeof(descr->new_state)) { - PRINT_ERROR("new state too long (%d)", osi[j].new_state); - goto out_too_long; - } - strlcpy(descr->new_state, scst_alua_state_name(osi[j].new_state), - sizeof(descr->new_state)); - - if (strlen(dg->name) >= sizeof(descr->dg_name)) { - PRINT_ERROR("dg_name too long (%s)", dg->name); - goto out_too_long; - } - strlcpy(descr->dg_name, dg->name, sizeof(descr->dg_name)); - - if (strlen(osi[j].tg->name) >= sizeof(descr->tg_name)) { - PRINT_ERROR("tg_name too long (%s)", osi[j].tg->name); - goto out_too_long; - } - strlcpy(descr->tg_name, osi[j].tg->name, - sizeof(descr->tg_name)); - - descr->group_id = osi[j].group_id; - - TRACE_DBG("group_id %u, prev_state %s, new_state %s, dg_name %s, " - "tg_name %s", descr->group_id, descr->prev_state, - descr->new_state, descr->dg_name, descr->tg_name); - - valid_desc_count++; - descr++; - } - - payload->stpg_descriptors_cnt = valid_desc_count; - - if (valid_desc_count > 0) { - struct scst_dg_dev *dgd; - struct scst_stpg_wait *wait; - int rc; - - dg->stpg_rel_tgt_id = cmd->tgt->rel_tgt_id; - dg->stpg_transport_id = kmemdup(cmd->sess->transport_id, - scst_tid_size(cmd->sess->transport_id), GFP_KERNEL); - if (dg->stpg_transport_id == NULL) { - PRINT_ERROR("Unable to duplicate stpg_transport_id"); - goto out_free_event; - } - - wait = kzalloc(sizeof(*wait), GFP_KERNEL); - if (wait == NULL) { - PRINT_ERROR("Unable to allocate STPG wait struct " - "(size %zd)", sizeof(*wait)); - scst_set_busy(cmd); - res = -ENOMEM; - goto out_free_tr_id; - } - - atomic_set(&wait->stpg_wait_left, 1); - wait->event_entry = event_entry; - - event_entry->event_notify_fn = scst_event_stpg_notify_fn; - event_entry->notify_fn_priv = cmd; - - mutex_lock(&scst_dg_mutex); - list_for_each_entry(dgd, &dg->dev_list, entry) { - if (dgd->dev == dev) - continue; - - TRACE_DBG("STPG: ext blocking dev %s", dgd->dev->virt_name); - - atomic_inc(&wait->stpg_wait_left); - - rc = scst_ext_block_dev(dgd->dev, scst_stpg_ext_blocking_done, - (uint8_t *)&wait, sizeof(wait), SCST_EXT_BLOCK_STPG); - if (rc != 0) { - TRACE_DBG("scst_ext_block_dev() failed " - "with %d, reverting (cmd %p)", rc, cmd); - wait->status = rc; - wait->dg = dg; - atomic_dec(&wait->stpg_wait_left); - spin_lock_bh(&dev->dev_lock); - WARN_ON(dgd->dev->stpg_ext_blocked); - dgd->dev->stpg_ext_blocked = 0; - spin_unlock_bh(&dev->dev_lock); - break; - } - } - mutex_unlock(&scst_dg_mutex); - - scst_stpg_check_blocking_done(wait); - /* !! cmd can be already dead here !! */ - } else { - TRACE_DBG("Nothing to do"); - goto out_free_event; - } - - res = 0; - out_free: kfree(osi); @@ -1968,16 +2004,5 @@ out_unlock_sm_fail: out_put: scst_put_buf_full(cmd, buf); goto out_free; - -out_too_long: - scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_set_target_pgs_failed)); - res = -EOVERFLOW; - -out_free_tr_id: - kfree(dg->stpg_transport_id); - -out_free_event: - kfree(event_entry); - goto out_free; } EXPORT_SYMBOL_GPL(scst_tg_set_group_info); From 2e5620098c7b686fa102692d6395b1982c601b4d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 23:04:11 +0000 Subject: [PATCH 5/8] scst: Add the 'forward_dst' sysfs attribute Add the 'forward_dst' sysfs attribute next to the 'forwarding' attribute. The plan is to remove the 'forwarding' attribute at some time in the future. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8775 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/README | 8 +++++--- scst/include/scst.h | 12 ++++++------ scst/src/scst_lib.c | 6 +++--- scst/src/scst_pres.c | 2 +- scst/src/scst_sysfs.c | 42 ++++++++++++++++++++++++++---------------- scst/src/scst_targ.c | 3 ++- 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/scst/README b/scst/README index 66004be40..6091a9c06 100644 --- a/scst/README +++ b/scst/README @@ -807,9 +807,11 @@ 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. + - forward_dst - if set this target port is a forwarding destination. This means + that it does not check any local SCSI events (reservations, etc.). Those + event are supposed to be checked at the forwarding source side. + + - forwarding - obsolete synonym for forward_dst. - *count*, e.g. read_io_count_kb, - statistics about executed commands and transferred data. Those attributes have speaking names diff --git a/scst/include/scst.h b/scst/include/scst.h index 118629bb6..f64caec8d 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -479,8 +479,8 @@ enum scst_exec_res { /* 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 +/* Cache of tgt->tgt_forward_dst */ +#define SCST_TGT_DEV_FORWARD_DST 5 /************************************************************* ** I/O grouping types. Changing them don't forget to change @@ -1688,11 +1688,11 @@ struct scst_tgt { struct list_head tgt_acg_list; /* target ACG groups */ /* - * 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. + * Set, if this target is forwarding destination, i.e. does not check + * any local SCSI events (reservations, etc.). Those events are + * supposed to be checked at the side of the forwarding source. */ - unsigned tgt_forwarding:1; + unsigned tgt_forward_dst:1; /* Per target analog of the corresponding driver's fields */ unsigned tgt_dif_supported:1; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index e3c832110..8380794dc 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -5337,10 +5337,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); + if (sess->tgt->tgt_forward_dst) + set_bit(SCST_TGT_DEV_FORWARD_DST, &tgt_dev->tgt_dev_flags); else - clear_bit(SCST_TGT_DEV_FORWARDING, &tgt_dev->tgt_dev_flags); + clear_bit(SCST_TGT_DEV_FORWARD_DST, &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 b3022c644..99c9e44db 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -1594,7 +1594,7 @@ 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) { + if (tgt->tgt_forward_dst) { TRACE_PR("ALL_TG_PT: skipping forwarding " "target %s", tgt->tgt_name); continue; diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index bab2baa00..f47154620 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -2513,7 +2513,7 @@ 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, +static ssize_t scst_tgt_forward_dst_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct scst_tgt *tgt; @@ -2523,14 +2523,14 @@ static ssize_t scst_tgt_forwarding_show(struct kobject *kobj, 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" : ""); + res = sprintf(buf, "%d\n%s", tgt->tgt_forward_dst, + tgt->tgt_forward_dst ? SCST_SYSFS_KEY_MARK "\n" : ""); TRACE_EXIT_RES(res); return res; } -static ssize_t scst_tgt_forwarding_store(struct kobject *kobj, +static ssize_t scst_tgt_forward_dst_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int res = 0; @@ -2549,14 +2549,14 @@ static ssize_t scst_tgt_forwarding_store(struct kobject *kobj, mutex_lock(&scst_mutex); - old = tgt->tgt_forwarding; + old = tgt->tgt_forward_dst; switch (buf[0]) { case '0': - tgt->tgt_forwarding = 0; + tgt->tgt_forward_dst = 0; break; case '1': - tgt->tgt_forwarding = 1; + tgt->tgt_forward_dst = 1; break; default: PRINT_ERROR("%s: Requested action not understood: %s", @@ -2565,7 +2565,7 @@ static ssize_t scst_tgt_forwarding_store(struct kobject *kobj, goto out_unlock; } - if (tgt->tgt_forwarding == old) + if (tgt->tgt_forward_dst == old) goto out_unlock; list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { @@ -2576,18 +2576,22 @@ static ssize_t scst_tgt_forwarding_store(struct kobject *kobj, 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); + if (tgt->tgt_forward_dst) + set_bit(SCST_TGT_DEV_FORWARD_DST, + &tgt_dev->tgt_dev_flags); else - clear_bit(SCST_TGT_DEV_FORWARDING, &tgt_dev->tgt_dev_flags); + clear_bit(SCST_TGT_DEV_FORWARD_DST, + &tgt_dev->tgt_dev_flags); } } } - if (tgt->tgt_forwarding) - PRINT_INFO("Set target %s as forwarding", tgt->tgt_name); + if (tgt->tgt_forward_dst) + PRINT_INFO("Set target %s as forwarding destination", + tgt->tgt_name); else - PRINT_INFO("Clear target %s as forwarding", tgt->tgt_name); + PRINT_INFO("Clear target %s as forwarding destination", + tgt->tgt_name); out_unlock: mutex_unlock(&scst_mutex); @@ -2600,9 +2604,14 @@ out: return res; } +static struct kobj_attribute scst_tgt_forward_dst = + __ATTR(forward_dst, S_IRUGO | S_IWUSR, scst_tgt_forward_dst_show, + scst_tgt_forward_dst_store); + +// To do: remove the 'forwarding' sysfs attribute and keep 'forward_dst'. static struct kobj_attribute scst_tgt_forwarding = - __ATTR(forwarding, S_IRUGO | S_IWUSR, scst_tgt_forwarding_show, - scst_tgt_forwarding_store); + __ATTR(forwarding, S_IRUGO | S_IWUSR, scst_tgt_forward_dst_show, + scst_tgt_forward_dst_store); static ssize_t scst_tgt_comment_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -2876,6 +2885,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_forward_dst.attr, &scst_tgt_forwarding.attr, &scst_tgt_comment.attr, &scst_tgt_addr_method.attr, diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 12ea2ce1e..565536286 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2363,7 +2363,8 @@ 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))) { + if (unlikely(test_bit(SCST_TGT_DEV_FORWARD_DST, + &cmd->tgt_dev->tgt_dev_flags))) { /* * All the checks are supposed to be done on the * forwarding requester's side. From 785e721cf3489cc376f8c05c47bb7d175da9503b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 23:05:13 +0000 Subject: [PATCH 6/8] scst: Add the 'forward_src' sysfs attribute Make forwarding source mode configurable per target port instead of having a compile-time global option. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8776 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/ChangeLog | 5 ++++ scst/README | 25 ++++++++++---------- scst/include/backport.h | 14 +++++++++++ scst/include/scst.h | 13 ++++++++++- scst/src/dev_handlers/scst_disk.c | 10 ++++---- scst/src/scst_local_cmd.c | 4 +--- scst/src/scst_main.c | 13 +++-------- scst/src/scst_sysfs.c | 39 +++++++++++++++++++++++++++++++ 8 files changed, 90 insertions(+), 33 deletions(-) diff --git a/scst/ChangeLog b/scst/ChangeLog index 8176681bd..140030676 100644 --- a/scst/ChangeLog +++ b/scst/ChangeLog @@ -1,3 +1,8 @@ +Summary of changes between versions 3.4 and 3.5 +----------------------------------------------- +- Added the forward_src and forward_dst sysfs attributes. Removed + CONFIG_SCST_FORWARD_MODE_PASS_THROUGH. + Summary of changes between versions 3.3 and 3.4 ----------------------------------------------- - I/O keeps running at full speed if a LUN is added or removed and also if diff --git a/scst/README b/scst/README index 6091a9c06..64b7ea8e5 100644 --- a/scst/README +++ b/scst/README @@ -343,16 +343,6 @@ in/out in Makefile and scst.h: functionality is working only if dif_mode doesn't contain dev_store and dif_type is 1. - - CONFIG_SCST_FORWARD_MODE_PASS_THROUGH - if defined, the pass-through - subsystem starts working in the forwarding mode, where reservation - commands processed locally and not passed to the backend SCSI device, - while COMPARE AND WRITE, EXTENDED COPY and RECEIVE COPY RESULTS - commands, which normally processed locally by the SCST core, not - processed locally, but passed to the backend device. Intended to be - used to implement NON-OPTIMIZED ALUA state together with "forwarding" - target attribute on the remote node. See below for more details. - Disabled by default for safety. - - CONFIG_SCST_NO_TOTAL_MEM_CHECKS - disables checks of allocated memory, see scst_max_cmd_mem below. Allows to avoid 2 global variables on the fast path, hence get better multi-queue performance. @@ -807,6 +797,14 @@ Every target should have at least the following entries: until rel_tgt_id becomes unique. This attribute initialized unique by SCST by default. + - forward_src - if set this target port is a forwarding source. This means + that commands like COMPARE AND WRITE, EXTENDED COPY and RECEIVE COPY + RESULTS are submitted to the SCSI device instead of being handled inside + the SCST core. PERSISTENT RESERVE IN and OUT commands are processed by the + SCST core, whether or not this mode is enabled. The name 'forwarding_src' + refers to the use case where SCSI passthrough is used to send SCSI commands + to another H.A. node. + - forward_dst - if set this target port is a forwarding destination. This means that it does not check any local SCSI events (reservations, etc.). Those event are supposed to be checked at the forwarding source side. @@ -1986,13 +1984,13 @@ The link between block devices I and J stands for synchronous replication. Such a setup can be configured as follows: -1. Build SCST with CONFIG_SCST_FORWARD_MODE_PASS_THROUGH enabled in scst.h +1. Build SCST. 2. Setup on active node internal redirect target, which is going to accept redirected commands from the passive node. It must be visible only to the passive node. -3. Set "forwarding" attribute for this target to 1. This is necessary to +3. Set "forward_dst" attribute for this target to 1. This is necessary to correctly handle PRs. 4. Export through this target the SAME backend SCST device as being @@ -2007,7 +2005,8 @@ device on the passive side pointing to the active node. *pass-through* handler (scst_disk). Pass-though is needed to redirect non-block commands as well: ATS, XCOPY, etc. -7. Set ALUA state to this target as "nonoptimized". +7. Set ALUA state to this target as "nonoptimized". Set the forward_src +attribute to one. That's it on the normal path. Now the initiator(s) would see 2 paths: OPTIMIZED going to the active node and NON-OPTIMIZED going to the diff --git a/scst/include/backport.h b/scst/include/backport.h index 32d624d5d..566ad0112 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -674,6 +674,20 @@ static inline int __must_check kstrtol(const char *s, unsigned int base, { return strict_strtol(s, base, res); } + +static inline int __must_check kstrtoint(const char *s, unsigned int base, + int *result) +{ + long val; + int ret = strict_strtol(s, base, &val); + + if (ret) + return ret; + *result = val; + if (*result != val) + return -EINVAL; + return 0; +} #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) diff --git a/scst/include/scst.h b/scst/include/scst.h index f64caec8d..17939b18a 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -28,7 +28,6 @@ /** See README for description of those conditional defines **/ #define CONFIG_SCST_DIF_INJECT_CORRUPTED_TAGS -/* #define CONFIG_SCST_FORWARD_MODE_PASS_THROUGH */ #define CONFIG_SCST_NO_TOTAL_MEM_CHECKS #include @@ -1687,6 +1686,18 @@ struct scst_tgt { struct list_head tgt_acg_list; /* target ACG groups */ + /* + * Set if and only if this target port is a forwarding source. If + * enabled, the dev_disk handler submits COMPARE AND WRITE, EXTENDED + * COPY and RECEIVE COPY RESULTS commands to the SCSI device instead + * of handling these inside the SCST core. PERSISTENT RESERVE IN and + * OUT commands are processed by the SCST core, whether or not this + * mode is enabled. The name 'forwarding_src' refers to the use case + * where SCSI passthrough is used to send SCSI commands to another + * H.A. node. + */ + unsigned tgt_forward_src:1; + /* * Set, if this target is forwarding destination, i.e. does not check * any local SCSI events (reservations, etc.). Those events are diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index cd2ab0bff..785d4bcf7 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -144,6 +144,7 @@ static void disk_detach(struct scst_device *dev) static int disk_parse(struct scst_cmd *cmd) { + struct scst_tgt *tgt = cmd->tgt; int res = SCST_CMD_STATE_DEFAULT, rc; rc = scst_sbc_generic_parse(cmd); @@ -152,8 +153,7 @@ static int disk_parse(struct scst_cmd *cmd) goto out; } -#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH - if (unlikely(cmd->op_flags & SCST_LOCAL_CMD)) { + if (unlikely(tgt->tgt_forward_src && cmd->op_flags & SCST_LOCAL_CMD)) { switch (cmd->cdb[0]) { case COMPARE_AND_WRITE: case EXTENDED_COPY: @@ -164,7 +164,6 @@ static int disk_parse(struct scst_cmd *cmd) break; } } -#endif cmd->retries = SCST_PASSTHROUGH_RETRIES; out: @@ -286,6 +285,7 @@ out_complete: /* Executes command and split CDB, if necessary */ static enum scst_exec_res disk_exec(struct scst_cmd *cmd) { + struct scst_tgt *tgt = cmd->tgt; enum scst_exec_res res; int rc; struct disk_work work; @@ -299,8 +299,7 @@ static enum scst_exec_res disk_exec(struct scst_cmd *cmd) TRACE_ENTRY(); -#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH - if (unlikely(cmd->op_flags & SCST_LOCAL_CMD)) { + if (unlikely(tgt->tgt_forward_src && cmd->op_flags & SCST_LOCAL_CMD)) { switch (cmd->cdb[0]) { case RESERVE: case RESERVE_10: @@ -315,7 +314,6 @@ static enum scst_exec_res disk_exec(struct scst_cmd *cmd) break; } } -#endif /* * For PC requests we are going to submit max_hw_sectors used instead diff --git a/scst/src/scst_local_cmd.c b/scst/src/scst_local_cmd.c index 2abea3b0b..757edba71 100644 --- a/scst/src/scst_local_cmd.c +++ b/scst/src/scst_local_cmd.c @@ -714,15 +714,13 @@ enum scst_exec_res scst_persistent_reserve_in_local(struct scst_cmd *cmd) goto out_done; } -#ifndef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH - if (dev->scsi_dev != NULL) { + if (cmd->tgt->tgt_forward_src && dev->scsi_dev) { PRINT_WARNING("PR commands for pass-through devices not " "supported (device %s)", dev->virt_name); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode)); goto out_done; } -#endif buffer_size = scst_get_buf_full_sense(cmd, &buffer); if (unlikely(buffer_size <= 0)) diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index f03210d4e..21c1fd517 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -1111,7 +1111,7 @@ static int scst_register_device(struct scsi_device *scsidp) dev->scsi_dev = scsidp; -#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + /* For target ports that function as forwarding source. */ res = scst_pr_set_file_name(dev, NULL, "%s/%s", SCST_PR_DIR, dev->virt_name); if (res != 0) @@ -1120,7 +1120,6 @@ static int scst_register_device(struct scsi_device *scsidp) res = scst_pr_init_dev(dev); if (res != 0) goto out_free_dev; -#endif list_add_tail(&dev->dev_list_entry, &scst_dev_list); @@ -1143,14 +1142,9 @@ out: out_del_unlocked: mutex_lock(&scst_mutex); list_del_init(&dev->dev_list_entry); - mutex_unlock(&scst_mutex); - percpu_ref_kill(&dev->refcnt); - goto out; - -#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + /* If used as a forwarding source (see also tgt_forward_src). */ scst_pr_clear_dev(dev); -#endif out_free_dev: percpu_ref_kill(&dev->refcnt); @@ -1193,9 +1187,8 @@ static void scst_unregister_device(struct scsi_device *scsidp) list_del_init(&dev->dev_list_entry); -#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + /* For forwarding sources (see also tgt_forward_src). */ scst_pr_clear_dev(dev); -#endif scst_dg_dev_remove_by_dev(dev); diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index f47154620..7381dee96 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -2513,6 +2513,44 @@ 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_forward_src_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct scst_tgt *tgt = container_of(kobj, struct scst_tgt, tgt_kobj); + + return sprintf(buf, "%d\n%s", tgt->tgt_forward_src, + tgt->tgt_forward_src ? SCST_SYSFS_KEY_MARK "\n" : ""); +} + +static ssize_t scst_tgt_forward_src_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + struct scst_tgt *tgt = container_of(kobj, struct scst_tgt, tgt_kobj); + int res, old, new; + + res = kstrtoint(buf, 0, &new); + if (res < 0) + return res; + if (new < 0 || new > 1) + return -EINVAL; + + mutex_lock(&scst_mutex); + old = tgt->tgt_forward_src; + if (old != new) { + tgt->tgt_forward_src = new; + PRINT_INFO("%s target %s as forwarding source", + tgt->tgt_forward_src ? "Set" : "Clear", + tgt->tgt_name); + } + mutex_unlock(&scst_mutex); + + return count; +} + +static struct kobj_attribute scst_tgt_forward_src = + __ATTR(forward_src, S_IRUGO | S_IWUSR, scst_tgt_forward_src_show, + scst_tgt_forward_src_store); + static ssize_t scst_tgt_forward_dst_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -2885,6 +2923,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_forward_src.attr, &scst_tgt_forward_dst.attr, &scst_tgt_forwarding.attr, &scst_tgt_comment.attr, From 6d4c15da22e753f26e9c79d6f62378c4de283040 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 23:05:43 +0000 Subject: [PATCH 7/8] scst: Move the expl_alua member variable from scst_vdisk_dev into scst_device This patch does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8777 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 5 +++ scst/src/dev_handlers/scst_vdisk.c | 52 +++++++++--------------------- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 17939b18a..4797753df 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2873,6 +2873,11 @@ struct scst_device { */ int dev_scsi_atomic_cmd_active; + /* + * Whether or not explicit ALUA has been enabled. Protected by dev_lock. + */ + unsigned int expl_alua:1; + /* * List of all being executed on the dev commands. * Protected by dev_lock. diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index d80808b08..e9cac69fd 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -184,7 +184,6 @@ struct scst_vdisk_dev { unsigned int tst:3; unsigned int format_active:1; unsigned int discard_zeroes_data:1; - unsigned int expl_alua:1; unsigned int reexam_pending:1; unsigned int size_key:1; unsigned int opt_trans_len_set:1; @@ -2554,7 +2553,6 @@ static int vdisk_get_supported_opcodes(struct scst_cmd *cmd, int *out_supp_opcodes_cnt) { struct scst_device *dev = cmd->dev; - struct scst_vdisk_dev *virt_dev = dev->dh_priv; if (cmd->dev->dev_dif_type != 2) { *out_supp_opcodes = vdisk_opcode_descriptors; @@ -2563,7 +2561,7 @@ static int vdisk_get_supported_opcodes(struct scst_cmd *cmd, *out_supp_opcodes = vdisk_opcode_descriptors_type2; *out_supp_opcodes_cnt = ARRAY_SIZE(vdisk_opcode_descriptors_type2); } - if (!virt_dev->expl_alua) { + if (!dev->expl_alua) { (*out_supp_opcodes_cnt)--; sBUG_ON((*out_supp_opcodes)[*out_supp_opcodes_cnt]->od_serv_action != MO_SET_TARGET_PGS); } @@ -3981,6 +3979,7 @@ static int vdisk_tp_vpd(uint8_t *buf, struct scst_cmd *cmd, static int vdisk_inq(uint8_t *buf, struct scst_cmd *cmd, struct scst_vdisk_dev *virt_dev) { + struct scst_device *dev = cmd->dev; int num; if (virt_dev->removable) @@ -3993,7 +3992,7 @@ static int vdisk_inq(uint8_t *buf, struct scst_cmd *cmd, buf[5] |= 1; /* PROTECT */ if (scst_alua_configured(cmd->dev)) { buf[5] |= SCST_INQ_TPGS_MODE_IMPLICIT; - if (virt_dev->expl_alua) + if (dev->expl_alua) buf[5] |= SCST_INQ_TPGS_MODE_EXPLICIT; } buf[5] |= 8; /* 3PC */ @@ -5157,12 +5156,11 @@ static enum compl_status_e vdisk_exec_set_tpgs(struct vdisk_cmd_params *p) { struct scst_cmd *cmd = p->cmd; struct scst_device *dev = cmd->dev; - struct scst_vdisk_dev *virt_dev = dev->dh_priv; int res = CMD_SUCCEEDED, rc; TRACE_ENTRY(); - if (!virt_dev->expl_alua) { + if (!dev->expl_alua) { PRINT_ERROR("SET TARGET PORT GROUPS: not explicit ALUA mode " "(dev %s)", dev->virt_name); /* Invalid opcode, i.e. SA field */ @@ -7010,7 +7008,6 @@ static int vdev_create_node(struct scst_dev_type *devt, virt_dev->rotational = DEF_ROTATIONAL; virt_dev->thin_provisioned = DEF_THIN_PROVISIONED; virt_dev->tst = DEF_TST; - virt_dev->expl_alua = DEF_EXPL_ALUA; INIT_WORK(&virt_dev->vdev_inq_changed_work, vdev_inq_changed_fn); virt_dev->blk_shift = DEF_DISK_BLOCK_SHIFT; @@ -8297,50 +8294,33 @@ static ssize_t vdisk_sysfs_expl_alua_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - struct scst_device *dev; - struct scst_vdisk_dev *virt_dev; - int pos; + struct scst_device *dev = container_of(kobj, struct scst_device, + dev_kobj); - TRACE_ENTRY(); - - dev = container_of(kobj, struct scst_device, dev_kobj); - virt_dev = dev->dh_priv; - pos = sprintf(buf, "%d\n%s", virt_dev->expl_alua, - virt_dev->expl_alua != DEF_EXPL_ALUA ? + return sprintf(buf, "%d\n%s", dev->expl_alua, + dev->expl_alua != DEF_EXPL_ALUA ? SCST_SYSFS_KEY_MARK "\n" : ""); - TRACE_EXIT_RES(pos); - return pos; } static ssize_t vdisk_sysfs_expl_alua_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { - struct scst_device *dev; - struct scst_vdisk_dev *virt_dev; - char ch[16]; + struct scst_device *dev = container_of(kobj, struct scst_device, + dev_kobj); unsigned long expl_alua; int res; - TRACE_ENTRY(); - - dev = container_of(kobj, struct scst_device, dev_kobj); - virt_dev = dev->dh_priv; - sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf); - res = kstrtoul(ch, 0, &expl_alua); + res = kstrtoul(buf, 0, &expl_alua); if (res < 0) - goto out; + return res; - spin_lock(&virt_dev->flags_lock); - virt_dev->expl_alua = !!expl_alua; - spin_unlock(&virt_dev->flags_lock); + spin_lock_bh(&dev->dev_lock); + dev->expl_alua = !!expl_alua; + spin_unlock_bh(&dev->dev_lock); - res = count; - -out: - TRACE_EXIT_RES(res); - return res; + return count; } static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj, From e8de615950aa61d76879b09d6e8f0ad18dfd18ec Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 23 Feb 2020 23:07:18 +0000 Subject: [PATCH 8/8] scst: Move RTPG and STPG handling into the SCST core This patch does not change the behavior when using one of the vdisk handlers. When using dev_disk to forward SCSI commands from one SCST node to another, this patch causes RTPG and STPG commands to be processed on the source SCST node (as it should) instead of on the destination SCST node. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8778 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 96 ++---------------------------- scst/src/scst_lib.c | 4 +- scst/src/scst_local_cmd.c | 95 +++++++++++++++++++++++++++++ scst/src/scst_local_cmd.h | 1 + scst/src/scst_targ.c | 1 + 5 files changed, 105 insertions(+), 92 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index e9cac69fd..84f08d2f9 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -5106,80 +5106,6 @@ static enum compl_status_e vdisk_exec_get_lba_status(struct vdisk_cmd_params *p) return CMD_SUCCEEDED; } -/* SPC-4 REPORT TARGET PORT GROUPS command */ -static enum compl_status_e vdisk_exec_report_tpgs(struct vdisk_cmd_params *p) -{ - struct scst_cmd *cmd = p->cmd; - struct scst_device *dev; - uint8_t *address; - void *buf; - int32_t buf_len; - uint32_t data_length, length; - uint8_t data_format; - int res; - - TRACE_ENTRY(); - - buf_len = scst_get_buf_full_sense(cmd, &address); - if (buf_len <= 0) - goto out; - - dev = cmd->dev; - data_format = cmd->cdb[1] >> 5; - - res = scst_tg_get_group_info(&buf, &data_length, dev, data_format); - if (res == -ENOMEM) { - scst_set_busy(cmd); - goto out_put; - } else if (res < 0) { - scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); - goto out_put; - } - - length = min_t(uint32_t, data_length, buf_len); - memcpy(address, buf, length); - kfree(buf); - if (length < cmd->resp_data_len) - scst_set_resp_data_len(cmd, length); - -out_put: - scst_put_buf_full(cmd, address); - -out: - TRACE_EXIT(); - return CMD_SUCCEEDED; -} - -/* SPC-4 SET TARGET PORT GROUPS command */ -static enum compl_status_e vdisk_exec_set_tpgs(struct vdisk_cmd_params *p) -{ - struct scst_cmd *cmd = p->cmd; - struct scst_device *dev = cmd->dev; - int res = CMD_SUCCEEDED, rc; - - TRACE_ENTRY(); - - if (!dev->expl_alua) { - PRINT_ERROR("SET TARGET PORT GROUPS: not explicit ALUA mode " - "(dev %s)", dev->virt_name); - /* Invalid opcode, i.e. SA field */ - scst_set_invalid_field_in_cdb(cmd, 1, - 0 | SCST_INVAL_FIELD_BIT_OFFS_VALID); - goto out; - } - - rc = scst_tg_set_group_info(cmd); - if (rc == 0) - res = RUNNING_ASYNC; - else - scst_stpg_del_unblock_next(cmd); - -out: - TRACE_EXIT_RES(res); - return res; -} - static enum compl_status_e vdisk_exec_sai_16(struct vdisk_cmd_params *p) { switch (p->cmd->cdb[1] & 0x1f) { @@ -5196,25 +5122,15 @@ static enum compl_status_e vdisk_exec_sai_16(struct vdisk_cmd_params *p) static enum compl_status_e vdisk_exec_maintenance_in(struct vdisk_cmd_params *p) { - switch (p->cmd->cdb[1] & 0x1f) { - case MI_REPORT_TARGET_PGS: - vdisk_exec_report_tpgs(p); - return CMD_SUCCEEDED; - } - scst_set_invalid_field_in_cdb(p->cmd, 1, - 0 | SCST_INVAL_FIELD_BIT_OFFS_VALID); - return CMD_SUCCEEDED; + /* For the code that handles RTPG, see also scst_local_cmd.c. */ + return CMD_FAILED; } -static enum compl_status_e vdisk_exec_maintenance_out(struct vdisk_cmd_params *p) +static enum compl_status_e +vdisk_exec_maintenance_out(struct vdisk_cmd_params *p) { - switch (p->cmd->cdb[1] & 0x1f) { - case MO_SET_TARGET_PGS: - return vdisk_exec_set_tpgs(p); - } - scst_set_invalid_field_in_cdb(p->cmd, 1, - 0 | SCST_INVAL_FIELD_BIT_OFFS_VALID); - return CMD_SUCCEEDED; + /* For the code that handles RTPG, see also scst_local_cmd.c. */ + return CMD_FAILED; } static enum compl_status_e vdisk_exec_read_toc(struct vdisk_cmd_params *p) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 8380794dc..9675cea8c 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -11936,7 +11936,7 @@ static int get_cdb_info_min(struct scst_cmd *cmd, break; case MI_REPORT_TARGET_PGS: cmd->op_name = "REPORT TARGET PORT GROUPS"; - cmd->op_flags |= SCST_REG_RESERVE_ALLOWED | + cmd->op_flags |= SCST_LOCAL_CMD | SCST_REG_RESERVE_ALLOWED | SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED; break; case MI_REPORT_SUPPORTED_OPERATION_CODES: @@ -11967,7 +11967,7 @@ static int get_cdb_info_mo(struct scst_cmd *cmd, unsigned long flags; cmd->op_name = "SET TARGET PORT GROUPS"; - cmd->op_flags |= SCST_STRICTLY_SERIALIZED; + cmd->op_flags |= SCST_LOCAL_CMD | SCST_STRICTLY_SERIALIZED; spin_lock_irqsave(&scst_global_stpg_list_lock, flags); TRACE_DBG("Adding STPG cmd %p to global_stpg_list", cmd); cmd->cmd_on_global_stpg_list = 1; diff --git a/scst/src/scst_local_cmd.c b/scst/src/scst_local_cmd.c index 757edba71..845207509 100644 --- a/scst/src/scst_local_cmd.c +++ b/scst/src/scst_local_cmd.c @@ -253,6 +253,82 @@ out_unlock_put_not_completed: goto out; } +/* SPC-4 REPORT TARGET PORT GROUPS command */ +static enum scst_exec_res scst_report_tpgs(struct scst_cmd *cmd) +{ + struct scst_device *dev; + uint8_t *address; + void *buf; + int32_t buf_len; + uint32_t data_length, length; + uint8_t data_format; + int res; + + TRACE_ENTRY(); + + buf_len = scst_get_buf_full_sense(cmd, &address); + if (buf_len <= 0) + goto out; + + dev = cmd->dev; + data_format = cmd->cdb[1] >> 5; + + res = scst_tg_get_group_info(&buf, &data_length, dev, data_format); + if (res == -ENOMEM) { + scst_set_busy(cmd); + goto out_put; + } else if (res < 0) { + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb)); + goto out_put; + } + + length = min_t(uint32_t, data_length, buf_len); + memcpy(address, buf, length); + kfree(buf); + if (length < cmd->resp_data_len) + scst_set_resp_data_len(cmd, length); + +out_put: + scst_put_buf_full(cmd, address); + +out: + cmd->completed = 1; + + /* Report the result */ + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); + + return SCST_EXEC_COMPLETED; +} + +/* SPC-4 SET TARGET PORT GROUPS command */ +static enum scst_exec_res scst_exec_set_tpgs(struct scst_cmd *cmd) +{ + struct scst_device *dev = cmd->dev; + int rc; + + if (!dev->expl_alua) { + PRINT_ERROR("SET TARGET PORT GROUPS: not explicit ALUA mode " + "(dev %s)", dev->virt_name); + /* Invalid opcode, i.e. SA field */ + scst_set_invalid_field_in_cdb(cmd, 1, + 0 | SCST_INVAL_FIELD_BIT_OFFS_VALID); + goto out; + } + + rc = scst_tg_set_group_info(cmd); + if (rc == 0) { + /* Running async */ + return SCST_CMD_STATE_RES_CONT_NEXT; + } + scst_stpg_del_unblock_next(cmd); + +out: + cmd->completed = 1; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); + return SCST_EXEC_COMPLETED; +} + static enum scst_exec_res scst_report_supported_tm_fns(struct scst_cmd *cmd) { const enum scst_exec_res res = SCST_EXEC_COMPLETED; @@ -505,6 +581,9 @@ enum scst_exec_res scst_maintenance_in(struct scst_cmd *cmd) TRACE_ENTRY(); switch (cmd->cdb[1] & 0x1f) { + case MI_REPORT_TARGET_PGS: + res = scst_report_tpgs(cmd); + break; case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS: res = scst_report_supported_tm_fns(cmd); break; @@ -520,6 +599,22 @@ enum scst_exec_res scst_maintenance_in(struct scst_cmd *cmd) return res; } +enum scst_exec_res scst_maintenance_out(struct scst_cmd *cmd) +{ + enum scst_exec_res res; + + switch (cmd->cdb[1] & 0x1f) { + case MO_SET_TARGET_PGS: + res = scst_exec_set_tpgs(cmd); + break; + default: + res = SCST_EXEC_NOT_COMPLETED; + break; + } + + return res; +} + enum scst_exec_res scst_reserve_local(struct scst_cmd *cmd) { enum scst_exec_res res = SCST_EXEC_NOT_COMPLETED; diff --git a/scst/src/scst_local_cmd.h b/scst/src/scst_local_cmd.h index 89809167b..a058aa131 100644 --- a/scst/src/scst_local_cmd.h +++ b/scst/src/scst_local_cmd.h @@ -8,6 +8,7 @@ enum scst_exec_res scst_cm_ext_copy_exec(struct scst_cmd *cmd); enum scst_exec_res scst_cm_rcv_copy_res_exec(struct scst_cmd *cmd); enum scst_exec_res scst_cmp_wr_local(struct scst_cmd *cmd); enum scst_exec_res scst_maintenance_in(struct scst_cmd *cmd); +enum scst_exec_res scst_maintenance_out(struct scst_cmd *cmd); enum scst_exec_res scst_persistent_reserve_in_local(struct scst_cmd *cmd); enum scst_exec_res scst_persistent_reserve_out_local(struct scst_cmd *cmd); enum scst_exec_res scst_release_local(struct scst_cmd *cmd); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 565536286..6726d4845 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2708,6 +2708,7 @@ static scst_local_exec_fn scst_local_fns[256] = { [EXTENDED_COPY] = scst_cm_ext_copy_exec, [RECEIVE_COPY_RESULTS] = scst_cm_rcv_copy_res_exec, [MAINTENANCE_IN] = scst_maintenance_in, + [MAINTENANCE_OUT] = scst_maintenance_out, }; static enum scst_exec_res scst_do_local_exec(struct scst_cmd *cmd)