diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index f91ca9d83..2903ded28 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -2634,7 +2634,8 @@ static void q2t_load_cont_data_segments(struct q2t_prm *prm) (unsigned long long int)pci_dma_lo32(dma_addr), (int)sg_dma_len(prm->sg)); - prm->sg = __sg_next_inline(prm->sg); + /* prm->sg might be last here */ + prm->sg = sg_next_inline(prm->sg); } TRACE_BUFFER("Continuation packet data", @@ -2695,7 +2696,8 @@ static void q2x_load_data_segments(struct q2t_prm *prm) (unsigned long long int)pci_dma_lo32(dma_addr), (int)sg_dma_len(prm->sg)); - prm->sg = __sg_next_inline(prm->sg); + /* prm->sg might be last here */ + prm->sg = sg_next_inline(prm->sg); } TRACE_BUFFER("Scatter/gather, CTIO packet data", pkt, @@ -2756,7 +2758,8 @@ static void q24_load_data_segments(struct q2t_prm *prm) (unsigned long long int)pci_dma_lo32(dma_addr), (int)sg_dma_len(prm->sg)); - prm->sg = __sg_next_inline(prm->sg); + /* prm->sg might be last here */ + prm->sg = sg_next_inline(prm->sg); } q2t_load_cont_data_segments(prm); diff --git a/qla2x00t/qla_bsg.c b/qla2x00t/qla_bsg.c index a2ab0e179..214552766 100644 --- a/qla2x00t/qla_bsg.c +++ b/qla2x00t/qla_bsg.c @@ -987,8 +987,13 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) ql_log(ql_log_warn, vha, 0x702c, "Vendor request %s failed.\n", type); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) + + sizeof(struct fc_bsg_reply); +#else fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); +#endif memcpy(fw_sts_ptr, response, sizeof(response)); fw_sts_ptr += sizeof(response); @@ -1011,8 +1016,13 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) bsg_reply->reply_payload_rcv_len = #endif bsg_job->reply_payload.payload_len; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) + + sizeof(struct fc_bsg_reply); +#else fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); +#endif memcpy(fw_sts_ptr, response, sizeof(response)); fw_sts_ptr += sizeof(response); *fw_sts_ptr = command_sent; diff --git a/qla2x00t/qla_isr.c b/qla2x00t/qla_isr.c index 4835b055d..a24098631 100644 --- a/qla2x00t/qla_isr.c +++ b/qla2x00t/qla_isr.c @@ -1228,7 +1228,12 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, type, sp->handle, comp_status, fw_status[1], fw_status[2], le16_to_cpu(((struct els_sts_entry_24xx *) pkt)->total_byte_count)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) + + sizeof(struct fc_bsg_reply); +#else fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); +#endif memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); } else { @@ -1246,7 +1251,12 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, #else bsg_reply->reply_payload_rcv_len = 0; #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) + + sizeof(struct fc_bsg_reply); +#else fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); +#endif memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); } ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056, diff --git a/scst/README b/scst/README index 752fe3856..389840122 100644 --- a/scst/README +++ b/scst/README @@ -360,7 +360,8 @@ in/out in Makefile and scst.h: 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. + target attribute on the remote node. See below for more details. + 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 @@ -1679,6 +1680,12 @@ DEVICE_GROUP dgroup2 { } } +Note, if you are using "active" BLOCKIO device attribute to prevent open +of the backend block device on the passive node, it is not recommended +to set both active ("active", "nonoptimized") and passive ("standby", +etc.) ALUA states for the same device as shown above to keep internal +"active" state of the BLOCKIO device consistent. + Explicit ALUA ............. @@ -1699,7 +1706,9 @@ secondary transition, if this device is open. SCST BLOCKIO handler has necessary support for such behavior: 1. If you need to prevent an SCST BLOCKIO device from opening its block -device, you need to create it with parameter "active=0" +device, you need to create it with parameter "active=0". In case of DRBD +it would be done automatically, you don't have to use the "active" +attribute. 2. If you write new ALUA state in the "state" attribute, SCST BLOCKIO handler before transition closes open handles on all affected SCST @@ -1851,6 +1860,76 @@ information about ALUA support in Windows Server, see also: * Microsoft, ALUA MPIO Logo Test, MSDN (http://msdn.microsoft.com/en-us/library/gg607458%28v=vs.85%29.aspx). +Active/Non-Optimized via internal redirection +............................................... + +The Active-Standby configuration is simple to understand and setup, +however, it might have serious interoperability issues, because not all +initiators handle Standby state correctly. For instance, some versions +of VMware reported to have such issues. Same for Windows. + +Hence, it is better to use Non-Optimized state on the passive node +instead of Standby with internal commands redirection to the active +node. This is what the vast majority of storage vendors are doing, which +is, actually, the reason why Standby and Unavailable states have all +those initiator issues. Simply, they have had too few testing, because +only marginally used. + +SCST has necessary support for such redirection, it just needs to be +configured correctly. It's a little bit of effort, especially to +understand how it's going to function, but then it would work MUCH more +reliable for full range of initiators. Ever poor initiators, who have no +idea about ALUA (boot from SAN, e.g.) would work now. + +1. Build SCST with CONFIG_SCST_FORWARD_MODE_PASS_THROUGH enabled in scst.h + +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 +correctly handle PRs. + +4. Export through this target the SAME backend SCST device as being +served to initiator(s) (consider for simplicity that there is only one +served device) + +5. Connect to this SCST device through this internal target from the +passive node. Now you have a local SCSI device on the passive side +pointing to the active node. + +6. Export this local device to the initiator(s) using SCST +*path-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". + +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 +passive node, then redirected to the active node. + +On failover (i.e. switching active and passive states): + +1. Setup similar redirect target on the new active node. + +2. Setup connectivity to that new redirect target from the new passive +node + +3. Start ALUA change (see above) on both nodes + +4. !! Exchange in the sysfs security group(s) for the initiator(s) *LUN* +from old SCST device to the new one (blockio -> pass-through on the new +passive and pass-through -> blockio on the new active) using "replace_no_ua" +SCST command. You need to do it directly in the sysfs interface, +scstadmin can't do it. + +5. Set ALUA states to "active" on the new active node and "nonoptimized" +on the new passive node. + +6. Finish ALUA states change. + +If you have any questions, please read this above text at least 3 times +before asking. It might be tricky to understand. VAAI ---- diff --git a/scst/README_in-tree b/scst/README_in-tree index 5b7ec94a0..df4125913 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -250,7 +250,8 @@ your favorite kernel configuration Makefile target, e.g. "make xconfig": 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. + target attribute on the remote node. See below for more details. + Disabled by default for safety. HIGHMEM kernel configurations are fully supported, but not recommended for performance reasons. @@ -1532,6 +1533,12 @@ DEVICE_GROUP dgroup2 { } } +Note, if you are using "active" BLOCKIO device attribute to prevent open +of the backend block device on the passive node, it is not recommended +to set both active ("active", "nonoptimized") and passive ("standby", +etc.) ALUA states for the same device as shown above to keep internal +"active" state of the BLOCKIO device consistent. + Explicit ALUA ............. @@ -1552,7 +1559,9 @@ secondary transition, if this device is open. SCST BLOCKIO handler has necessary support for such behavior: 1. If you need to prevent an SCST BLOCKIO device from opening its block -device, you need to create it with parameter "active=0" +device, you need to create it with parameter "active=0". In case of DRBD +it would be done automatically, you don't have to use the "active" +attribute. 2. If you write new ALUA state in the "state" attribute, SCST BLOCKIO handler before transition closes open handles on all affected SCST @@ -1704,6 +1713,76 @@ information about ALUA support in Windows Server, see also: * Microsoft, ALUA MPIO Logo Test, MSDN (http://msdn.microsoft.com/en-us/library/gg607458%28v=vs.85%29.aspx). +Active/Non-Optimized via internal redirection +............................................... + +The Active-Standby configuration is simple to understand and setup, +however, it might have serious interoperability issues, because not all +initiators handle Standby state correctly. For instance, some versions +of VMware reported to have such issues. Same for Windows. + +Hence, it is better to use Non-Optimized state on the passive node +instead of Standby with internal commands redirection to the active +node. This is what the vast majority of storage vendors are doing, which +is, actually, the reason why Standby and Unavailable states have all +those initiator issues. Simply, they have had too few testing, because +only marginally used. + +SCST has necessary support for such redirection, it just needs to be +configured correctly. It's a little bit of effort, especially to +understand how it's going to function, but then it would work MUCH more +reliable for full range of initiators. Ever poor initiators, who have no +idea about ALUA (boot from SAN, e.g.) would work now. + +1. Build SCST with CONFIG_SCST_FORWARD_MODE_PASS_THROUGH enabled in scst.h + +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 +correctly handle PRs. + +4. Export through this target the SAME backend SCST device as being +served to initiator(s) (consider for simplicity that there is only one +served device) + +5. Connect to this SCST device through this internal target from the +passive node. Now you have a local SCSI device on the passive side +pointing to the active node. + +6. Export this local device to the initiator(s) using SCST +*path-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". + +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 +passive node, then redirected to the active node. + +On failover (i.e. switching active and passive states): + +1. Setup similar redirect target on the new active node. + +2. Setup connectivity to that new redirect target from the new passive +node + +3. Start ALUA change (see above) on both nodes + +4. !! Exchange in the sysfs security group(s) for the initiator(s) *LUN* +from old SCST device to the new one (blockio -> pass-through on the new +passive and pass-through -> blockio on the new active) using "replace_no_ua" +SCST command. You need to do it directly in the sysfs interface, +scstadmin can't do it. + +5. Set ALUA states to "active" on the new active node and "nonoptimized" +on the new passive node. + +6. Finish ALUA states change. + +If you have any questions, please read this above text at least 3 times +before asking. It might be tricky to understand. VAAI ---- diff --git a/scst/include/scst.h b/scst/include/scst.h index 4b412a564..1728ce4c0 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -4942,6 +4942,10 @@ void scst_aen_done(struct scst_aen *aen); static inline struct scatterlist *__sg_next_inline(struct scatterlist *sg) { +#ifdef CONFIG_SCST_EXTRACHECKS + BUG_ON(sg_is_last(sg)); +#endif + sg++; if (unlikely(sg_is_chain(sg))) sg = sg_chain_ptr(sg); @@ -5002,7 +5006,7 @@ static inline int __scst_get_buf(struct scst_cmd *cmd, int sg_cnt, res = sg->length; cmd->get_sg_buf_entry_num++; - cmd->get_sg_buf_cur_sg_entry = __sg_next_inline(sg); + cmd->get_sg_buf_cur_sg_entry = sg_next_inline(sg); out: return res; @@ -5143,7 +5147,7 @@ static inline int __scst_get_sg_page(struct scst_cmd *cmd, int sg_cnt, res = sg->length; cmd->get_sg_buf_entry_num++; - cmd->get_sg_buf_cur_sg_entry = __sg_next_inline(sg); + cmd->get_sg_buf_cur_sg_entry = sg_next_inline(sg); out: return res; diff --git a/scst/kernel/nolockdep-4.11.patch b/scst/kernel/nolockdep-4.11.patch new file mode 100644 index 000000000..21c312e34 --- /dev/null +++ b/scst/kernel/nolockdep-4.11.patch @@ -0,0 +1,114 @@ +=== modified file 'include/linux/lockdep.h' +--- old/include/linux/lockdep.h 2017-06-02 03:24:57 +0000 ++++ new/include/linux/lockdep.h 2017-06-02 03:31:44 +0000 +@@ -373,7 +373,7 @@ extern struct pin_cookie lock_pin_lock(s + extern void lock_repin_lock(struct lockdep_map *lock, struct pin_cookie); + extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); + +-# define INIT_LOCKDEP .lockdep_recursion = 0, .lockdep_reclaim_gfp = 0, ++# define INIT_LOCKDEP .lockdep_recursion = 0, .lockdep_reclaim_gfp = 0, .nolockdep_call = 0, + + #define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0) + + +=== modified file 'include/linux/sched.h' +--- old/include/linux/sched.h 2017-06-02 03:24:57 +0000 ++++ new/include/linux/sched.h 2017-06-02 03:31:44 +0000 +@@ -808,6 +808,9 @@ struct task_struct { + # define MAX_LOCK_DEPTH 48UL + u64 curr_chain_key; + int lockdep_depth; ++# define NOLOCKDEP_SUPPORTED 1 ++ unsigned int nolockdep_call:1; ++ unsigned int nolockdep_call_irq_saved:1; + unsigned int lockdep_recursion; + struct held_lock held_locks[MAX_LOCK_DEPTH]; + gfp_t lockdep_reclaim_gfp; + +=== modified file 'kernel/locking/lockdep.c' +--- old/kernel/locking/lockdep.c 2017-06-02 03:24:57 +0000 ++++ new/kernel/locking/lockdep.c 2017-06-02 03:31:44 +0000 +@@ -3754,9 +3754,11 @@ void lock_acquire(struct lockdep_map *lo + if (unlikely(current->lockdep_recursion)) + return; + ++ if (unlikely(current->nolockdep_call)) ++ return; ++ + raw_local_irq_save(flags); + check_flags(flags); +- + current->lockdep_recursion = 1; + trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip); + __lock_acquire(lock, subclass, trylock, read, check, +@@ -3774,6 +3776,9 @@ void lock_release(struct lockdep_map *lo + if (unlikely(current->lockdep_recursion)) + return; + ++ if (unlikely(current->nolockdep_call)) ++ return; ++ + raw_local_irq_save(flags); + check_flags(flags); + current->lockdep_recursion = 1; +@@ -4022,6 +4027,9 @@ void lock_contended(struct lockdep_map * + if (unlikely(current->lockdep_recursion)) + return; + ++ if (unlikely(current->nolockdep_call)) ++ return; ++ + raw_local_irq_save(flags); + check_flags(flags); + current->lockdep_recursion = 1; +@@ -4042,6 +4050,9 @@ void lock_acquired(struct lockdep_map *l + if (unlikely(current->lockdep_recursion)) + return; + ++ if (unlikely(current->nolockdep_call)) ++ return; ++ + raw_local_irq_save(flags); + check_flags(flags); + current->lockdep_recursion = 1; + +=== modified file 'kernel/softirq.c' +--- old/kernel/softirq.c 2017-06-02 03:24:57 +0000 ++++ new/kernel/softirq.c 2017-06-02 03:31:44 +0000 +@@ -335,6 +335,17 @@ asmlinkage __visible void do_softirq(voi + */ + void irq_enter(void) + { ++#ifdef CONFIG_LOCKDEP ++ if (unlikely(current->nolockdep_call)) { ++ unsigned long flags; ++ local_irq_save(flags); ++ if (current->nolockdep_call) { ++ current->nolockdep_call_irq_saved = 1; ++ current->nolockdep_call = 0; ++ } ++ local_irq_restore(flags); ++ } ++#endif + rcu_irq_enter(); + if (is_idle_task(current) && !in_interrupt()) { + /* +@@ -406,6 +417,17 @@ void irq_exit(void) + + tick_irq_exit(); + rcu_irq_exit(); ++#ifdef CONFIG_LOCKDEP ++ if (unlikely(current->nolockdep_call_irq_saved)) { ++ unsigned long flags; ++ local_irq_save(flags); ++ if (current->nolockdep_call_irq_saved) { ++ current->nolockdep_call_irq_saved = 0; ++ current->nolockdep_call = 1; ++ } ++ local_irq_restore(flags); ++ } ++#endif + trace_hardirq_exit(); /* must be last! */ + } + + diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index aba39097e..78c0f6c8b 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -7964,7 +7964,8 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev, char *params, const char *const allowed_params[]) { int res = 0; - unsigned long long val; + unsigned long long ull_val; + long long ll_val; char *param, *p, *pp; TRACE_ENTRY(); @@ -8096,7 +8097,25 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev, continue; } - res = kstrtoull(pp, 0, &val); + res = kstrtoll(pp, 0, &ll_val); + if (res != 0) { + PRINT_ERROR("strtoll() for %s failed: %d (device %s)", + pp, res, virt_dev->name); + goto out; + } + + if (!strcasecmp("numa_node_id", p)) { + virt_dev->numa_node_id = ll_val; + BUILD_BUG_ON(NUMA_NO_NODE != -1); + if (virt_dev->numa_node_id < NUMA_NO_NODE) { + res = -EINVAL; + goto out; + } + TRACE_DBG("numa_node_id %d", virt_dev->numa_node_id); + continue; + } + + res = kstrtoull(pp, 0, &ull_val); if (res != 0) { PRINT_ERROR("strtoull() for %s failed: %d (device %s)", pp, res, virt_dev->name); @@ -8104,14 +8123,14 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev, } if (!strcasecmp("write_through", p)) { - virt_dev->wt_flag = val; + virt_dev->wt_flag = ull_val; TRACE_DBG("WRITE THROUGH %d", virt_dev->wt_flag); } else if (!strcasecmp("nv_cache", p)) { - virt_dev->nv_cache = val; + virt_dev->nv_cache = ull_val; TRACE_DBG("NON-VOLATILE CACHE %d", virt_dev->nv_cache); } else if (!strcasecmp("o_direct", p)) { #if 0 - virt_dev->o_direct_flag = val; + virt_dev->o_direct_flag = ull_val; TRACE_DBG("O_DIRECT %d", virt_dev->o_direct_flag); #else PRINT_INFO("O_DIRECT flag doesn't currently" @@ -8119,70 +8138,62 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev, "in O_DIRECT mode instead (device %s)", virt_dev->name); #endif } else if (!strcasecmp("read_only", p)) { - virt_dev->rd_only = val; + virt_dev->rd_only = ull_val; TRACE_DBG("READ ONLY %d", virt_dev->rd_only); } else if (!strcasecmp("dummy", p)) { - if (val > 1) { + if (ull_val > 1) { res = -EINVAL; goto out; } - virt_dev->dummy = val; + virt_dev->dummy = ull_val; TRACE_DBG("DUMMY %d", virt_dev->dummy); } else if (!strcasecmp("removable", p)) { - virt_dev->removable = val; + virt_dev->removable = ull_val; TRACE_DBG("REMOVABLE %d", virt_dev->removable); } else if (!strcasecmp("active", p)) { - virt_dev->dev_active = val; + virt_dev->dev_active = ull_val; TRACE_DBG("ACTIVE %d", virt_dev->dev_active); } else if (!strcasecmp("rotational", p)) { - virt_dev->rotational = val; + virt_dev->rotational = ull_val; TRACE_DBG("ROTATIONAL %d", virt_dev->rotational); } else if (!strcasecmp("tst", p)) { - if ((val != SCST_TST_0_SINGLE_TASK_SET) && - (val != SCST_TST_1_SEP_TASK_SETS)) { - PRINT_ERROR("Invalid TST value %lld", val); + if ((ull_val != SCST_TST_0_SINGLE_TASK_SET) && + (ull_val != SCST_TST_1_SEP_TASK_SETS)) { + PRINT_ERROR("Invalid TST value %lld", ull_val); res = -EINVAL; goto out; } - virt_dev->tst = val; + virt_dev->tst = ull_val; TRACE_DBG("TST %d", virt_dev->tst); } else if (!strcasecmp("thin_provisioned", p)) { - virt_dev->thin_provisioned = val; + virt_dev->thin_provisioned = ull_val; virt_dev->thin_provisioned_manually_set = 1; TRACE_DBG("THIN PROVISIONED %d", virt_dev->thin_provisioned); } else if (!strcasecmp("zero_copy", p)) { - virt_dev->zero_copy = !!val; + virt_dev->zero_copy = !!ull_val; } else if (!strcasecmp("size", p)) { - virt_dev->file_size = val; + virt_dev->file_size = ull_val; } else if (!strcasecmp("size_mb", p)) { - virt_dev->file_size = val * 1024 * 1024; + virt_dev->file_size = ull_val * 1024 * 1024; } else if (!strcasecmp("cluster_mode", p)) { - virt_dev->initial_cluster_mode = val; + virt_dev->initial_cluster_mode = ull_val; TRACE_DBG("CLUSTER_MODE %d", virt_dev->initial_cluster_mode); } else if (!strcasecmp("blocksize", p)) { - virt_dev->blk_shift = scst_calc_block_shift(val); + virt_dev->blk_shift = scst_calc_block_shift(ull_val); if (virt_dev->blk_shift < 9) { - PRINT_ERROR("blocksize %llu too small", val); + PRINT_ERROR("blocksize %llu too small", ull_val); res = -EINVAL; goto out; } TRACE_DBG("block size %lld, block shift %d", - val, virt_dev->blk_shift); - } else if (!strcasecmp("numa_node_id", p)) { - virt_dev->numa_node_id = val; - BUILD_BUG_ON(NUMA_NO_NODE != -1); - if (virt_dev->numa_node_id < NUMA_NO_NODE) { - res = -EINVAL; - goto out; - } - TRACE_DBG("numa_node_id %d", virt_dev->numa_node_id); + ull_val, virt_dev->blk_shift); } else if (!strcasecmp("dif_type", p)) { - virt_dev->dif_type = val; + virt_dev->dif_type = ull_val; TRACE_DBG("DIF type %d", virt_dev->dif_type); } else if (!strcasecmp("dif_static_app_tag", p)) { - virt_dev->dif_static_app_tag_combined = cpu_to_be64(val); + virt_dev->dif_static_app_tag_combined = cpu_to_be64(ull_val); TRACE_DBG("DIF static app tag %llx", (long long)be64_to_cpu(virt_dev->dif_static_app_tag_combined)); } else { diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 5c4897e18..99c2d1f24 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -7610,7 +7610,8 @@ static void scst_restore_dif_sg(struct scst_cmd *cmd) left -= sg->length; TRACE_DBG("DIF sg %p, restored len %d (left %d)", sg, sg->length, left); - sg = __sg_next_inline(sg); + /* sg might be last here */ + sg = sg_next_inline(sg); } while (left > 0); out: @@ -7673,8 +7674,9 @@ int scst_alloc_space(struct scst_cmd *cmd) left -= sgt->length; sgt->length = (sgd->length >> block_shift) << SCST_DIF_TAG_SHIFT; TRACE_SG("sgt %p, new len %d", sgt, sgt->length); - sgd = __sg_next_inline(sgd); - sgt = __sg_next_inline(sgt); + /* sgd/sgt might be last here */ + sgd = sg_next_inline(sgd); + sgt = sg_next_inline(sgt); } while (left > 0); cmd->dif_sg_normalized = 1;