Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 632e3bdc authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Ensure client closes the socket when server initiates a close



 If the server decides to close the RPC socket, we currently don't actually
 respond until either another RPC call is scheduled, or until xprt_autoclose()
 gets called by the socket expiry timer (which may be up to 5 minutes
 later).

 This patch ensures that xprt_autoclose() is called much sooner if the
 server closes the socket.

 Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent eadb8c14
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -254,6 +254,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
#define XPRT_LOCKED		(0)
#define XPRT_CONNECTED		(1)
#define XPRT_CONNECTING		(2)
#define XPRT_CLOSE_WAIT		(3)

static inline void xprt_set_connected(struct rpc_xprt *xprt)
{
+16 −17
Original line number Diff line number Diff line
@@ -119,6 +119,17 @@ out_sleep:
	return 0;
}

static void xprt_clear_locked(struct rpc_xprt *xprt)
{
	xprt->snd_task = NULL;
	if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) {
		smp_mb__before_clear_bit();
		clear_bit(XPRT_LOCKED, &xprt->state);
		smp_mb__after_clear_bit();
	} else
		schedule_work(&xprt->task_cleanup);
}

/*
 * xprt_reserve_xprt_cong - serialize write access to transports
 * @task: task that is requesting access to the transport
@@ -145,9 +156,7 @@ int xprt_reserve_xprt_cong(struct rpc_task *task)
		}
		return 1;
	}
	smp_mb__before_clear_bit();
	clear_bit(XPRT_LOCKED, &xprt->state);
	smp_mb__after_clear_bit();
	xprt_clear_locked(xprt);
out_sleep:
	dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
	task->tk_timeout = 0;
@@ -193,9 +202,7 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt)
	return;

out_unlock:
	smp_mb__before_clear_bit();
	clear_bit(XPRT_LOCKED, &xprt->state);
	smp_mb__after_clear_bit();
	xprt_clear_locked(xprt);
}

static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
@@ -222,9 +229,7 @@ static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
		return;
	}
out_unlock:
	smp_mb__before_clear_bit();
	clear_bit(XPRT_LOCKED, &xprt->state);
	smp_mb__after_clear_bit();
	xprt_clear_locked(xprt);
}

/**
@@ -237,10 +242,7 @@ out_unlock:
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
{
	if (xprt->snd_task == task) {
		xprt->snd_task = NULL;
		smp_mb__before_clear_bit();
		clear_bit(XPRT_LOCKED, &xprt->state);
		smp_mb__after_clear_bit();
		xprt_clear_locked(xprt);
		__xprt_lock_write_next(xprt);
	}
}
@@ -256,10 +258,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
{
	if (xprt->snd_task == task) {
		xprt->snd_task = NULL;
		smp_mb__before_clear_bit();
		clear_bit(XPRT_LOCKED, &xprt->state);
		smp_mb__after_clear_bit();
		xprt_clear_locked(xprt);
		__xprt_lock_write_next_cong(xprt);
	}
}
+10 −2
Original line number Diff line number Diff line
@@ -425,7 +425,7 @@ static void xs_close(struct rpc_xprt *xprt)
	struct sock *sk = xprt->inet;

	if (!sk)
		return;
		goto clear_close_wait;

	dprintk("RPC:      xs_close xprt %p\n", xprt);

@@ -442,6 +442,10 @@ static void xs_close(struct rpc_xprt *xprt)
	sk->sk_no_check = 0;

	sock_release(sock);
clear_close_wait:
	smp_mb__before_clear_bit();
	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
	smp_mb__after_clear_bit();
}

/**
@@ -801,9 +805,13 @@ static void xs_tcp_state_change(struct sock *sk)
	case TCP_SYN_SENT:
	case TCP_SYN_RECV:
		break;
	case TCP_CLOSE_WAIT:
		/* Try to schedule an autoclose RPC calls */
		set_bit(XPRT_CLOSE_WAIT, &xprt->state);
		if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
			schedule_work(&xprt->task_cleanup);
	default:
		xprt_disconnect(xprt);
		break;
	}
 out:
	read_unlock(&sk->sk_callback_lock);