From: shaodenghui shaodenghui@huawei.com
virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I94XYA
----------------------------------------------------------------------
Add CONFIG_SCSI_KWORKER to control scsi kworker code compile or not.
Signed-off-by: shaodenghui shaodenghui@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/configs/openeuler_defconfig | 1 + drivers/scsi/Kconfig | 17 +++++++++++++++++ drivers/scsi/iscsi_tcp.c | 4 ++++ drivers/scsi/libiscsi.c | 13 +++++++++++++ kernel/workqueue.c | 13 +++++++++++++ 6 files changed, 49 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 17246843f657..e793d0844a50 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -2478,6 +2478,7 @@ CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_ENCLOSURE=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_KWORKER=y CONFIG_SCSI_SCAN_ASYNC=y
# diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index d6d640f30dd1..60b81b4aa648 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -2476,6 +2476,7 @@ CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_ENCLOSURE=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_KWORKER=y CONFIG_SCSI_SCAN_ASYNC=y
# diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 695a57d894cd..cc44558fd1f6 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -218,6 +218,23 @@ config SCSI_LOGGING there should be no noticeable performance impact as long as you have logging turned off.
+config SCSI_KWORKER + tristate "kworker NUMA affinity " + default n + help + kworker: Fix the problem of ipsan performance degradation on ARM + architecture. + + When the current downstream FS tests IPSAN, it is found that the + performance on ARM is much worse than that on X86, and the test data + of IPSAN fluctuates greatly. After analysis, the reason is that when + iscsi issues IO, the task is sent to kworker for processing by + iscsi_xmitworker. + + The workqueue created by iscsi can automatically identify the CPU of + the soft interrupt currently processed by iscsi, and automatically + schedule the workqueue to the corresponding NUMA node. + config SCSI_SCAN_ASYNC bool "Asynchronous SCSI scanning" depends on SCSI diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 54d01b9d330d..de6dfb1a47bb 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -170,7 +170,9 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk) struct iscsi_sw_tcp_conn *tcp_sw_conn; struct iscsi_tcp_conn *tcp_conn; struct iscsi_conn *conn; +#ifdef CONFIG_SCSI_KWORKER int current_cpu; +#endif
trace_sk_data_ready(sk);
@@ -182,12 +184,14 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk) } tcp_conn = conn->dd_data;
+#ifdef CONFIG_SCSI_KWORKER /* save intimate cpu when in softirq */ if (!sock_owned_by_user_nocheck(sk)) { current_cpu = smp_processor_id(); if (conn->intimate_cpu != current_cpu) conn->intimate_cpu = current_cpu; } +#endif
tcp_sw_conn = tcp_conn->dd_data;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 2d585f80e122..a64922409be8 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -89,6 +89,7 @@ inline void iscsi_conn_queue_xmit(struct iscsi_conn *conn) { struct Scsi_Host *shost = conn->session->host; struct iscsi_host *ihost = shost_priv(shost); +#ifdef CONFIG_SCSI_KWORKER int intimate_cpu = conn->intimate_cpu;
if (ihost->workq) { @@ -98,6 +99,10 @@ inline void iscsi_conn_queue_xmit(struct iscsi_conn *conn) else queue_work(ihost->workq, &conn->xmitwork); } +#else + if (ihost->workq) + queue_work(ihost->workq, &conn->xmitwork); +#endif } EXPORT_SYMBOL_GPL(iscsi_conn_queue_xmit);
@@ -2913,9 +2918,15 @@ struct Scsi_Host *iscsi_host_alloc(const struct scsi_host_template *sht, ihost = shost_priv(shost);
if (xmit_can_sleep) { +#ifdef CONFIG_SCSI_KWORKER /* this kind of workqueue only support single work */ ihost->workq = alloc_ordered_workqueue("iscsi_q_%d", __WQ_LEGACY | WQ_MEM_RECLAIM | __WQ_DYNAMIC, shost->host_no); +#else + ihost->workq = alloc_workqueue("iscsi_q_%d", + WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND, + 1, shost->host_no); +#endif if (!ihost->workq) goto free_host; } @@ -3196,7 +3207,9 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; +#ifdef CONFIG_SCSI_KWORKER conn->intimate_cpu = -1; +#endif
timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index fc733366d5f4..2ee454ae898c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4355,8 +4355,10 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, * it even if we don't use it immediately. */ copy_workqueue_attrs(new_attrs, attrs); +#ifdef CONFIG_SCSI_KWORKER if (wq->flags & __WQ_DYNAMIC) new_attrs->ordered = false; +#endif
wqattrs_actualize_cpumask(new_attrs, unbound_cpumask); cpumask_copy(new_attrs->__pod_cpumask, new_attrs->cpumask); @@ -4594,12 +4596,19 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) cpus_read_lock(); if (wq->flags & __WQ_ORDERED) { ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]); +#ifdef CONFIG_SCSI_KWORKER if (!(wq->flags & __WQ_DYNAMIC)) { /* there should only be single pwq for ordering guarantee */ WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node || wq->pwqs.prev != &wq->dfl_pwq->pwqs_node), "ordering guarantee broken for workqueue %s\n", wq->name); } +#else + /* there should only be single pwq for ordering guarantee */ + WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node || + wq->pwqs.prev != &wq->dfl_pwq->pwqs_node), + "ordering guarantee broken for workqueue %s\n", wq->name); +#endif } else { ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]); } @@ -5803,7 +5812,11 @@ static int workqueue_apply_unbound_cpumask(const cpumask_var_t unbound_cpumask) continue;
/* creating multiple pwqs breaks ordering guarantee */ +#ifdef CONFIG_SCSI_KWORKER if (!list_empty(&wq->pwqs) && !(wq->flags & __WQ_DYNAMIC)) { +#else + if (!list_empty(&wq->pwqs)) { +#endif if (wq->flags & __WQ_ORDERED_EXPLICIT) continue; wq->flags &= ~__WQ_ORDERED;