Skip to content

Commit 7de62bc

Browse files
Olga KornievskaiaTrond Myklebust
authored andcommitted
SUNRPC dont update timeout value on connection reset
Current behaviour: every time a v3 operation is re-sent to the server we update (double) the timeout. There is no distinction between whether or not the previous timer had expired before the re-sent happened. Here's the scenario: 1. Client sends a v3 operation 2. Server RST-s the connection (prior to the timeout) (eg., connection is immediately reset) 3. Client re-sends a v3 operation but the timeout is now 120sec. As a result, an application sees 2mins pause before a retry in case server again does not reply. Instead, this patch proposes to keep track off when the minor timeout should happen and if it didn't, then don't update the new timeout. Value is updated based on the previous value to make timeouts predictable. Signed-off-by: Olga Kornievskaia <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent ce36853 commit 7de62bc

File tree

2 files changed

+10
-0
lines changed

2 files changed

+10
-0
lines changed

include/linux/sunrpc/xprt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct rpc_rqst {
101101
* used in the softirq.
102102
*/
103103
unsigned long rq_majortimeo; /* major timeout alarm */
104+
unsigned long rq_minortimeo; /* minor timeout alarm */
104105
unsigned long rq_timeout; /* Current timeout value */
105106
ktime_t rq_rtt; /* round-trip time */
106107
unsigned int rq_retries; /* # of retries */

net/sunrpc/xprt.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,11 @@ static void xprt_reset_majortimeo(struct rpc_rqst *req)
607607
req->rq_majortimeo += xprt_calc_majortimeo(req);
608608
}
609609

610+
static void xprt_reset_minortimeo(struct rpc_rqst *req)
611+
{
612+
req->rq_minortimeo += req->rq_timeout;
613+
}
614+
610615
static void xprt_init_majortimeo(struct rpc_task *task, struct rpc_rqst *req)
611616
{
612617
unsigned long time_init;
@@ -618,6 +623,7 @@ static void xprt_init_majortimeo(struct rpc_task *task, struct rpc_rqst *req)
618623
time_init = xprt_abs_ktime_to_jiffies(task->tk_start);
619624
req->rq_timeout = task->tk_client->cl_timeout->to_initval;
620625
req->rq_majortimeo = time_init + xprt_calc_majortimeo(req);
626+
req->rq_minortimeo = time_init + req->rq_timeout;
621627
}
622628

623629
/**
@@ -631,6 +637,8 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
631637
const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout;
632638
int status = 0;
633639

640+
if (time_before(jiffies, req->rq_minortimeo))
641+
return status;
634642
if (time_before(jiffies, req->rq_majortimeo)) {
635643
if (to->to_exponential)
636644
req->rq_timeout <<= 1;
@@ -649,6 +657,7 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
649657
spin_unlock(&xprt->transport_lock);
650658
status = -ETIMEDOUT;
651659
}
660+
xprt_reset_minortimeo(req);
652661

653662
if (req->rq_timeout == 0) {
654663
printk(KERN_WARNING "xprt_adjust_timeout: rq_timeout = 0!\n");

0 commit comments

Comments
 (0)