Commit 5d00837b authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Run rpc timeout functions as callbacks instead of in softirqs



An audit of the current RPC timeout functions shows that they don't really
ever need to run in the softirq context. As long as the softirq is
able to signal that the wakeup is due to a timeout (which it can do by
setting task->tk_status to -ETIMEDOUT) then the callback functions can just
run as standard task->tk_callback functions (in the rpciod/process
context).

The only possible border-line case would be xprt_timer() for the case of
UDP, when the callback is used to reduce the size of the transport
congestion window. In testing, however, the effect of moving that update
to a callback would appear to be minor.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent fda13939
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2765,7 +2765,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_EXPIRED:
			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
			nfs4_schedule_state_recovery(clp);
			if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
				rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
+1 −1
Original line number Diff line number Diff line
@@ -731,7 +731,7 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
		list_add_tail(&seqid->list, &sequence->list);
	if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid)
		goto unlock;
	rpc_sleep_on(&sequence->wait, task, NULL, NULL);
	rpc_sleep_on(&sequence->wait, task, NULL);
	status = -EAGAIN;
unlock:
	spin_unlock(&sequence->lock);
+1 −3
Original line number Diff line number Diff line
@@ -56,12 +56,10 @@ struct rpc_task {
	__u8			tk_cred_retry;

	/*
	 * timeout_fn   to be executed by timer bottom half
	 * callback	to be executed after waking up
	 * action	next procedure for async tasks
	 * tk_ops	caller callbacks
	 */
	void			(*tk_timeout_fn)(struct rpc_task *);
	void			(*tk_callback)(struct rpc_task *);
	void			(*tk_action)(struct rpc_task *);
	const struct rpc_call_ops *tk_ops;
@@ -231,7 +229,7 @@ void rpc_execute(struct rpc_task *);
void		rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
void		rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
void		rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
					rpc_action action, rpc_action timer);
					rpc_action action);
void		rpc_wake_up_queued_task(struct rpc_wait_queue *,
					struct rpc_task *);
void		rpc_wake_up(struct rpc_wait_queue *);
+2 −2
Original line number Diff line number Diff line
@@ -408,13 +408,13 @@ gss_refresh_upcall(struct rpc_task *task)
	}
	spin_lock(&inode->i_lock);
	if (gss_cred->gc_upcall != NULL)
		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
	else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
		task->tk_timeout = 0;
		gss_cred->gc_upcall = gss_msg;
		/* gss_upcall_callback will release the reference to gss_upcall_msg */
		atomic_inc(&gss_msg->count);
		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
	} else
		err = gss_msg->msg.errno;
	spin_unlock(&inode->i_lock);
+1 −1
Original line number Diff line number Diff line
@@ -298,7 +298,7 @@ void rpcb_getport_async(struct rpc_task *task)

	/* Put self on queue before sending rpcbind request, in case
	 * rpcb_getport_done completes before we return from rpc_run_task */
	rpc_sleep_on(&xprt->binding, task, NULL, NULL);
	rpc_sleep_on(&xprt->binding, task, NULL);

	/* Someone else may have bound if we slept */
	if (xprt_bound(xprt)) {
Loading