diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 2bedfae17..2337334d8 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -2458,9 +2458,9 @@ static int cmnd_abort_pre_checks(struct iscsi_cmnd *req, int *status) * Management function request is outside the valid CmdSN window, * then targets must return the "Task does not exist" response. * - * 128 seems to be a good "window". + * 2048 seems to be a good "window". */ - if (between(req_hdr->ref_cmd_sn, req_hdr->cmd_sn - 128, + if (between(req_hdr->ref_cmd_sn, req_hdr->cmd_sn - 2048, req_hdr->cmd_sn)) { *status = ISCSI_RESPONSE_FUNCTION_COMPLETE; res = 0; diff --git a/iscsi-scst/usr/target.c b/iscsi-scst/usr/target.c index 030d9afa2..334d19e13 100644 --- a/iscsi-scst/usr/target.c +++ b/iscsi-scst/usr/target.c @@ -357,6 +357,13 @@ int target_del(u32 tid, u32 cookie) /* We might need to handle session(s) removal event(s) from the kernel */ while (handle_iscsi_events(nl_fd, false) == 0); + /* Someone else may have already freed the target object by now. */ + target = target_find_by_id(tid); + if (!target) { + log_info("%s: the target with tid = %u was already freed", __func__, tid); + return 0; + } + if (list_empty(&target->sessions_list)) break; diff --git a/scst/README.dlm b/scst/README.dlm index 435e6d8bb..56597a149 100644 --- a/scst/README.dlm +++ b/scst/README.dlm @@ -13,6 +13,7 @@ with a DLM lock object is called the Lock Value Block or LVB. The code in scst_dlm.c uses the DLM to keep PR data synchronized across all nodes in a cluster. + Software Components ------------------- @@ -29,6 +30,11 @@ The following software components are needed by the code in scst_dlm.c: On most Linux distributions the software packages that contain this software have the names kernel, dlm, corosync and pacemaker. +NOTE! You might need to apply a DLM bugfix patch, see scst-devel mailing list +thread https://sourceforge.net/p/scst/mailman/scst-devel/thread/CADHfD59FK6seaammL8b9LM3U3tw5HvYp3kPTk_r1OYkPR7bPhg@mail.gmail.com/#msg34761854 +for more details. + + DLM Configuration ----------------- @@ -74,6 +80,7 @@ configure and start the DLM control daemon: 12. Check the Pacemaker status: pcs status + Startup and Shutdown -------------------- @@ -127,6 +134,7 @@ The proper shutdown order is as follows: * Unload the SCST kernel modules * Unload the DLM kernel driver + Lockspace names --------------- @@ -134,12 +142,14 @@ The names of the DLM lockspaces used by SCST follow the following pattern: scst- where t10_dev_id is the T10 device ID of the SCST device associated with this lockspace. + Notes ----- Since the lockspace name depends on the t10_dev_id it is not allowed to change the t10_dev_id if cluster mode has been enabled. + Testing ------- @@ -148,11 +158,13 @@ Two examples of test suites for the cluster PR support code are: * The Windows Cluster Validation Tests (https://technet.microsoft.com/en-us/library/Cc726064.aspx). + To do ----- -Ensure that PREEMPT AND ABORT affects all cluster nodes instead of only the -cluster node that received this command. + * Ensure that PREEMPT AND ABORT affects all cluster nodes instead of + only the cluster node that received this command. + See also -------- diff --git a/scst/src/scst_dlm.c b/scst/src/scst_dlm.c index 342941d96..783da4d99 100644 --- a/scst/src/scst_dlm.c +++ b/scst/src/scst_dlm.c @@ -356,6 +356,10 @@ static int scst_copy_from_dlm(struct scst_device *dev, dlm_lockspace_t *ls, if (reg->lksb.lksb.sb_lkid == 0) scst_pr_remove_registrant(dev, reg); +#ifndef CONFIG_SCST_PROC + scst_pr_sync_device_file(dev); +#endif + scst_pr_write_unlock(dev); res = 0; @@ -1363,9 +1367,15 @@ create_st_wq(const char *fmt, ...) static int scst_pr_dlm_init(struct scst_device *dev, const char *cl_dev_id) { struct scst_pr_dlm_data *pr_dlm; + struct scst_dev_registrant *reg; int res = -ENOMEM; compile_time_size_checks(); + + list_for_each_entry(reg, &dev->dev_registrants_list, + dev_registrants_list_entry) + scst_dlm_pr_init_reg(dev, reg); + pr_dlm = kzalloc(sizeof(*dev->pr_dlm), GFP_KERNEL); if (!pr_dlm) goto out; @@ -1417,6 +1427,13 @@ static int scst_pr_dlm_init(struct scst_device *dev, const char *cl_dev_id) goto err_free; } + /* + * Instantiate the lockspace such that APTPL registration information + * is also made persistent on this node even if this node does not + * receive any medium or PR SCSI commands. + */ + get_lockspace(dev); + res = 0; out: diff --git a/scst/src/scst_pres.c b/scst/src/scst_pres.c index dff5620e1..1acabcd4c 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -870,10 +870,8 @@ out: return res; } -static void scst_pr_remove_device_files(struct scst_tgt_dev *tgt_dev) +static void scst_pr_remove_device_files(struct scst_device *dev) { - struct scst_device *dev = tgt_dev->dev; - TRACE_ENTRY(); scst_assert_pr_mutex_held(dev); @@ -888,10 +886,9 @@ static void scst_pr_remove_device_files(struct scst_tgt_dev *tgt_dev) } /* Must be called under dev_pr_mutex */ -void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd) +void scst_pr_sync_device_file(struct scst_device *dev) { int res = 0; - struct scst_device *dev = tgt_dev->dev; struct file *file; mm_segment_t old_fs = get_fs(); loff_t pos = 0; @@ -905,7 +902,7 @@ void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd scst_assert_pr_mutex_held(dev); if ((dev->pr_aptpl == 0) || list_empty(&dev->dev_registrants_list)) { - scst_pr_remove_device_files(tgt_dev); + scst_pr_remove_device_files(dev); goto out; } @@ -1024,21 +1021,15 @@ out_set_fs: out: if (res != 0) { PRINT_CRIT_ERROR("Unable to save persistent information " - "(target %s, initiator %s, device %s)", - tgt_dev->sess->tgt->tgt_name, - tgt_dev->sess->initiator_name, dev->virt_name); -#if 0 /* - * Looks like it's safer to return SUCCESS and expect operator's - * intervention to be able to save the PR's state next time, than - * to return HARDWARE ERROR and screw up all the interaction with - * the affected initiator. - */ - if (cmd != NULL) - scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); -#endif + "(device %s)", dev->virt_name); + /* + * It's safer to not return any error to the initiator and expect + * operator's intervention to be able to save the PR's state next + * time, than to screw up all the interactions with this initiator. + */ } - TRACE_EXIT_RES(res); + TRACE_EXIT(); return; write_error: diff --git a/scst/src/scst_pres.h b/scst/src/scst_pres.h index 5ee98a3ef..1380701ad 100644 --- a/scst/src/scst_pres.h +++ b/scst/src/scst_pres.h @@ -148,7 +148,7 @@ void scst_pr_set_holder(struct scst_device *dev, void scst_pr_clear_holder(struct scst_device *dev); #ifndef CONFIG_SCST_PROC -void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd); +void scst_pr_sync_device_file(struct scst_device *dev); #endif #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 3f3ee4d24..97883c5ff 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3151,7 +3151,7 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd) #ifndef CONFIG_SCST_PROC if (cmd->status == SAM_STAT_GOOD) - scst_pr_sync_device_file(tgt_dev, cmd); + scst_pr_sync_device_file(dev); #endif if ((cmd->devt->pr_cmds_notifications) && @@ -3448,10 +3448,6 @@ static int scst_do_real_exec(struct scst_cmd *cmd) scsi_dev = dev->scsi_dev; - TRACE_DBG("Sending cmd %p to SCSI mid-level dev %d:%d:%d:%lld", cmd, - scsi_dev->host->host_no, scsi_dev->channel, scsi_dev->id, - (u64)scsi_dev->lun); - if (unlikely(scsi_dev == NULL)) { PRINT_ERROR("Command for virtual device must be " "processed by device handler (LUN %lld)!", @@ -3459,6 +3455,10 @@ static int scst_do_real_exec(struct scst_cmd *cmd) goto out_error; } + TRACE_DBG("Sending cmd %p to SCSI mid-level dev %d:%d:%d:%lld", cmd, + scsi_dev->host->host_no, scsi_dev->channel, scsi_dev->id, + (u64)scsi_dev->lun); + scst_set_exec_start(cmd); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) diff --git a/scstadmin/init.d/scst b/scstadmin/init.d/scst index 5e609c26f..f736fd1fa 100755 --- a/scstadmin/init.d/scst +++ b/scstadmin/init.d/scst @@ -54,6 +54,7 @@ cat <<"EOF" if [ -e /lib/lsb/init-functions ]; then # Debian, RHEL, Fedora, SLES and openSUSE. SYSTEMD_NO_WRAP="true" + _SYSTEMCTL_SKIP_REDIRECT=1 . /lib/lsb/init-functions else # Slackware (Gentoo has these functions). diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 4c4716628..e68edd5df 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -419,7 +419,11 @@ static void srpt_get_class_port_info(struct ib_dm_mad *mad) memset(cif, 0, sizeof(*cif)); cif->base_version = 1; cif->class_version = 1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) cif->resp_time_value = 20; +#else + ib_set_cpi_resp_time(cif, 20); +#endif mad->mad_hdr.status = 0; }