From b5fde4d6c02324a8511afe30d02eb2cf46ea799d Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Tue, 17 Oct 2023 22:54:59 -0500 Subject: [PATCH] LU-17197 obdclass: preserve fairness when waiting for rpc slot When obd_get_mod_rpc_slot() waits for an available slot it places the waiting thread at the HEAD of the queue, so it will be woken before anything else that is already queued. This is clearly unfair and can hurt performance. So change to always add to the tail to ensure a FIFO ordering (except that CLOSE might sometimes be woken a bit early). This regression was introduced in a rewrite that was supposed to make waiting more fair - by avoiding a broadcast wakeup for "close" requests. Also fix some stale comments and expose __add_wait_queue_entry_tail Running mdtest with the patch applied shows about a 3% improvement: master patched mdtest-easy-write 350.585906 kIOPS 353.783545 kIOPS mdtest-easy-stat 1320.329353 kIOPS 1408.320419 kIOPS mdtest-easy-delete 285.084103 kIOPS 289.625900 kIOPS [SCORE] 509.115803 kiops 524.516113 kiops Fixes: 5243630b09d2 ("LU-15947 obdclass: improve precision of wakeups for mod_rpcs") Signed-off-by: Mr NeilBrown Signed-off-by: Shaun Tancheff Change-Id: If767c4299bcbab71589b0f3c01e85bf461686ca5 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52738 Reviewed-by: James Simmons Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- libcfs/include/libcfs/linux/linux-wait.h | 4 ++++ libcfs/libcfs/linux/linux-wait.c | 2 -- lustre/obdclass/genops.c | 5 ++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libcfs/include/libcfs/linux/linux-wait.h b/libcfs/include/libcfs/linux/linux-wait.h index aa257fc..b54370f 100644 --- a/libcfs/include/libcfs/linux/linux-wait.h +++ b/libcfs/include/libcfs/linux/linux-wait.h @@ -16,6 +16,10 @@ #define wait_queue_entry_t wait_queue_t #endif +#ifndef HAVE_PREPARE_TO_WAIT_EVENT +#define __add_wait_queue_entry_tail __add_wait_queue_tail +#endif + #ifndef HAVE_WAIT_BIT_HEADER_H struct wait_bit_queue_entry { struct wait_bit_key key; diff --git a/libcfs/libcfs/linux/linux-wait.c b/libcfs/libcfs/linux/linux-wait.c index 94467b9..8f17078 100644 --- a/libcfs/libcfs/linux/linux-wait.c +++ b/libcfs/libcfs/linux/linux-wait.c @@ -10,8 +10,6 @@ #ifndef HAVE_PREPARE_TO_WAIT_EVENT -#define __add_wait_queue_entry_tail __add_wait_queue_tail - long prepare_to_wait_event(wait_queue_head_t *wq_head, wait_queue_entry_t *wq_entry, int state) { diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 2c094fb..ff1d7b4 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -2217,13 +2217,12 @@ __u16 obd_get_mod_rpc_slot(struct client_obd *cli, __u32 opc) wait.wqe.func = claim_mod_rpc_function; spin_lock_irq(&cli->cl_mod_rpcs_waitq.lock); - __add_wait_queue(&cli->cl_mod_rpcs_waitq, &wait.wqe); + __add_wait_queue_entry_tail(&cli->cl_mod_rpcs_waitq, &wait.wqe); /* This wakeup will only succeed if the maximums haven't - * been reached. If that happens, WQ_FLAG_WOKEN will be cleared + * been reached. If that happens, wait.woken will be set * and there will be no need to wait. */ wake_up_locked(&cli->cl_mod_rpcs_waitq); - /* XXX: handle spurious wakeups (from unknown yet source */ while (wait.woken == false) { spin_unlock_irq(&cli->cl_mod_rpcs_waitq.lock); wait_woken(&wait.wqe, TASK_UNINTERRUPTIBLE, -- 1.8.3.1