diff --git a/scst/README b/scst/README index 8da5009cc..f54953803 100644 --- a/scst/README +++ b/scst/README @@ -353,6 +353,15 @@ 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. Disabled by default for safety. + HIGHMEM kernel configurations are fully supported, but not recommended for performance reasons, except for scst_user, where they are not supported, because this module deals with user supplied memory on a diff --git a/scst/README_in-tree b/scst/README_in-tree index 669f97f44..defac1e6d 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -243,6 +243,15 @@ your favorite kernel configuration Makefile target, e.g. "make xconfig": 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. Disabled by default for safety. + HIGHMEM kernel configurations are fully supported, but not recommended for performance reasons. diff --git a/scst/include/scst.h b/scst/include/scst.h index 728db0f19..4dc8db2ff 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -29,6 +29,7 @@ /** See README for description of those conditional defines **/ #define CONFIG_SCST_DIF_INJECT_CORRUPTED_TAGS +/* #define CONFIG_SCST_FORWARD_MODE_PASS_THROUGH */ #include #ifndef INSIDE_KERNEL_TREE diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index 56ac72903..13edb3528 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -268,6 +268,20 @@ 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)) { + switch (cmd->cdb[0]) { + case COMPARE_AND_WRITE: + case EXTENDED_COPY: + case RECEIVE_COPY_RESULTS: + TRACE_DBG("Clearing LOCAL CMD flag for cmd %p " + "(op %s)", cmd, cmd->op_name); + cmd->op_flags &= ~SCST_LOCAL_CMD; + break; + } + } +#endif + cmd->retries = SCST_PASSTHROUGH_RETRIES; out: return res; @@ -398,6 +412,24 @@ static int disk_exec(struct scst_cmd *cmd) TRACE_ENTRY(); +#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + if (unlikely(cmd->op_flags & SCST_LOCAL_CMD)) { + switch (cmd->cdb[0]) { + case RESERVE: + case RESERVE_10: + case RELEASE: + case RELEASE_10: + TRACE_DBG("Skipping LOCAL cmd %p (op %s)", + cmd, cmd->op_name); + goto out_done; + case PERSISTENT_RESERVE_IN: + case PERSISTENT_RESERVE_OUT: + sBUG(); + break; + } + } +#endif + /* * For PC requests we are going to submit max_hw_sectors used instead * of max_sectors. diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 47e458f9e..d52fe3f42 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -1178,6 +1178,17 @@ static int scst_register_device(struct scsi_device *scsidp) dev->scsi_dev = scsidp; +#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + res = scst_pr_set_file_name(dev, NULL, "%s/%s", SCST_PR_DIR, + dev->virt_name); + if (res != 0) + goto out_free_dev; + + res = scst_pr_init_dev(dev); + if (res != 0) + goto out_free_dev; +#endif + list_add_tail(&dev->dev_list_entry, &scst_dev_list); #ifdef CONFIG_SCST_PROC @@ -1225,6 +1236,10 @@ out_del_locked: list_del_init(&dev->dev_list_entry); #endif +#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + scst_pr_clear_dev(dev); +#endif + out_free_dev: scst_free_device(dev); @@ -1284,6 +1299,10 @@ static void scst_unregister_device(struct scsi_device *scsidp) list_del_init(&dev->dev_list_entry); +#ifdef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH + scst_pr_clear_dev(dev); +#endif + scst_dg_dev_remove_by_dev(dev); scst_assign_dev_handler(dev, &scst_null_devtype); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 2620b5461..47698297f 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2959,6 +2959,7 @@ static int scst_persistent_reserve_in_local(struct scst_cmd *cmd) goto out_done; } +#ifndef CONFIG_SCST_FORWARD_MODE_PASS_THROUGH if (dev->scsi_dev != NULL) { PRINT_WARNING("PR commands for pass-through devices not " "supported (device %s)", dev->virt_name); @@ -2966,6 +2967,7 @@ static int scst_persistent_reserve_in_local(struct scst_cmd *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))