Skip to content

Commit e7f5581

Browse files
committed
sunrpc: skip svc_xprt_enqueue when transport is busy
svc_xprt_resource_released() calls svc_xprt_enqueue() whenever XPT_DATA or XPT_DEFERRED is set. During RPC processing, svc_reserve_auth() reduces the reservation counter and triggers this path while the current thread still holds XPT_BUSY. The enqueue enters svc_xprt_ready(), executes an smp_rmb(), READ_ONCE(), and tracepoint, then returns false on seeing XPT_BUSY. Trace data from a 256KB NFSv3 WRITE workload over TCP shows this pattern generates roughly 195,000 wasted enqueue calls -- approximately one per RPC -- each paying the full svc_xprt_ready() cost for no benefit. Add a BUSY check alongside the existing DATA|DEFERRED check in svc_xprt_resource_released(). When the transport is BUSY, the holder will call svc_xprt_received() upon completion, which already checks for pending work flags and re-enqueues. Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 0a5d7be commit e7f5581

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

net/sunrpc/svc_xprt.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,16 +440,23 @@ static bool svc_xprt_reserve_slot(struct svc_rqst *rqstp, struct svc_xprt *xprt)
440440
/*
441441
* After a caller releases write-space or a request slot,
442442
* re-enqueue the transport only when there is pending
443-
* work that a thread could act on. The smp_mb() pairs
443+
* work that a thread could act on. The smp_mb() pairs
444444
* with the smp_rmb() in svc_xprt_ready() and orders the
445445
* preceding counter update before the flags read so a
446446
* concurrent set_bit(XPT_DATA) is visible here.
447+
*
448+
* When the transport is BUSY, the thread holding it will
449+
* call svc_xprt_received() upon completion, which checks
450+
* for pending work and re-enqueues as needed.
447451
*/
448452
static void svc_xprt_resource_released(struct svc_xprt *xprt)
449453
{
454+
unsigned long xpt_flags;
455+
450456
smp_mb();
451-
if (READ_ONCE(xprt->xpt_flags) &
452-
(BIT(XPT_DATA) | BIT(XPT_DEFERRED)))
457+
xpt_flags = READ_ONCE(xprt->xpt_flags);
458+
if (xpt_flags & (BIT(XPT_DATA) | BIT(XPT_DEFERRED)) &&
459+
!(xpt_flags & BIT(XPT_BUSY)))
453460
svc_xprt_enqueue(xprt);
454461
}
455462

0 commit comments

Comments
 (0)