SUNRPC: Fix up socket autodisconnect
Ensure that we don't forget to set up the disconnection timer for the case when a connect request is fulfilled after the RPC request that initiated it has timed out or been interrupted. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
This commit is contained in:
parent
1f4c17a03b
commit
ad3331acb1
|
@ -680,6 +680,20 @@ out:
|
||||||
spin_unlock_bh(&xprt->transport_lock);
|
spin_unlock_bh(&xprt->transport_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
xprt_has_timer(const struct rpc_xprt *xprt)
|
||||||
|
{
|
||||||
|
return xprt->idle_timeout != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xprt_schedule_autodisconnect(struct rpc_xprt *xprt)
|
||||||
|
__must_hold(&xprt->transport_lock)
|
||||||
|
{
|
||||||
|
if (list_empty(&xprt->recv) && xprt_has_timer(xprt))
|
||||||
|
mod_timer(&xprt->timer, xprt->last_used + xprt->idle_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xprt_init_autodisconnect(unsigned long data)
|
xprt_init_autodisconnect(unsigned long data)
|
||||||
{
|
{
|
||||||
|
@ -688,6 +702,8 @@ xprt_init_autodisconnect(unsigned long data)
|
||||||
spin_lock(&xprt->transport_lock);
|
spin_lock(&xprt->transport_lock);
|
||||||
if (!list_empty(&xprt->recv))
|
if (!list_empty(&xprt->recv))
|
||||||
goto out_abort;
|
goto out_abort;
|
||||||
|
/* Reset xprt->last_used to avoid connect/autodisconnect cycling */
|
||||||
|
xprt->last_used = jiffies;
|
||||||
if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
|
if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
|
||||||
goto out_abort;
|
goto out_abort;
|
||||||
spin_unlock(&xprt->transport_lock);
|
spin_unlock(&xprt->transport_lock);
|
||||||
|
@ -725,6 +741,7 @@ void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
|
||||||
goto out;
|
goto out;
|
||||||
xprt->snd_task =NULL;
|
xprt->snd_task =NULL;
|
||||||
xprt->ops->release_xprt(xprt, NULL);
|
xprt->ops->release_xprt(xprt, NULL);
|
||||||
|
xprt_schedule_autodisconnect(xprt);
|
||||||
out:
|
out:
|
||||||
spin_unlock_bh(&xprt->transport_lock);
|
spin_unlock_bh(&xprt->transport_lock);
|
||||||
wake_up_bit(&xprt->state, XPRT_LOCKED);
|
wake_up_bit(&xprt->state, XPRT_LOCKED);
|
||||||
|
@ -888,11 +905,6 @@ static void xprt_timer(struct rpc_task *task)
|
||||||
spin_unlock_bh(&xprt->transport_lock);
|
spin_unlock_bh(&xprt->transport_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int xprt_has_timer(struct rpc_xprt *xprt)
|
|
||||||
{
|
|
||||||
return xprt->idle_timeout != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xprt_prepare_transmit - reserve the transport before sending a request
|
* xprt_prepare_transmit - reserve the transport before sending a request
|
||||||
* @task: RPC task about to send a request
|
* @task: RPC task about to send a request
|
||||||
|
@ -1280,9 +1292,7 @@ void xprt_release(struct rpc_task *task)
|
||||||
if (!list_empty(&req->rq_list))
|
if (!list_empty(&req->rq_list))
|
||||||
list_del(&req->rq_list);
|
list_del(&req->rq_list);
|
||||||
xprt->last_used = jiffies;
|
xprt->last_used = jiffies;
|
||||||
if (list_empty(&xprt->recv) && xprt_has_timer(xprt))
|
xprt_schedule_autodisconnect(xprt);
|
||||||
mod_timer(&xprt->timer,
|
|
||||||
xprt->last_used + xprt->idle_timeout);
|
|
||||||
spin_unlock_bh(&xprt->transport_lock);
|
spin_unlock_bh(&xprt->transport_lock);
|
||||||
if (req->rq_buffer)
|
if (req->rq_buffer)
|
||||||
xprt->ops->buf_free(req->rq_buffer);
|
xprt->ops->buf_free(req->rq_buffer);
|
||||||
|
|
Loading…
Reference in a new issue