Commit adcffc17 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client fixes from Trond Myklebust:
 "Highlights include:

  Stable fixes:

   - Fix a socket leak when setting up an AF_LOCAL RPC client

   - Ensure that knfsd connects to the gss-proxy daemon on setup

  Bugfixes:

   - Fix a refcount leak when migrating a task off an offlined transport

   - Don't gratuitously invalidate inode attributes on delegation return

   - Don't leak sockets in xs_local_connect()

   - Ensure timely close of disconnected AF_LOCAL sockets"

* tag 'nfs-for-5.18-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  Revert "SUNRPC: attempt AF_LOCAL connect on setup"
  SUNRPC: Ensure gss-proxy connects on setup
  SUNRPC: Ensure timely close of disconnected AF_LOCAL sockets
  SUNRPC: Don't leak sockets in xs_local_connect()
  NFSv4: Don't invalidate inode attributes on delegation return
  SUNRPC release the transport of a relocated task with an assigned transport
parents bce58da1 a3d0562d
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -363,6 +363,14 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
	kunmap_atomic(start);
}

static void nfs4_fattr_set_prechange(struct nfs_fattr *fattr, u64 version)
{
	if (!(fattr->valid & NFS_ATTR_FATTR_PRECHANGE)) {
		fattr->pre_change_attr = version;
		fattr->valid |= NFS_ATTR_FATTR_PRECHANGE;
	}
}

static void nfs4_test_and_free_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		const struct cred *cred)
@@ -6553,7 +6561,9 @@ static void nfs4_delegreturn_release(void *calldata)
		pnfs_roc_release(&data->lr.arg, &data->lr.res,
				 data->res.lr_ret);
	if (inode) {
		nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
		nfs4_fattr_set_prechange(&data->fattr,
					 inode_peek_iversion_raw(inode));
		nfs_refresh_inode(inode, &data->fattr);
		nfs_iput_and_deactive(inode);
	}
	kfree(calldata);
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct rpc_add_xprt_test {
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT	(1UL << 9)
#define RPC_CLNT_CREATE_SOFTERR		(1UL << 10)
#define RPC_CLNT_CREATE_REUSEPORT	(1UL << 11)
#define RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL (1UL << 12)

struct rpc_clnt *rpc_create(struct rpc_create_args *args);
struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
+1 −1
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt)
		 * timeout, which would result in reconnections being
		 * done without the correct namespace:
		 */
		.flags		= RPC_CLNT_CREATE_NOPING |
		.flags		= RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL |
				  RPC_CLNT_CREATE_NO_IDLE_TIMEOUT
	};
	struct rpc_clnt *clnt;
+10 −4
Original line number Diff line number Diff line
@@ -479,6 +479,9 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,

	if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
		int err = rpc_ping(clnt);
		if ((args->flags & RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL) &&
		    err == -EOPNOTSUPP)
			err = 0;
		if (err != 0) {
			rpc_shutdown_client(clnt);
			return ERR_PTR(err);
@@ -1065,10 +1068,13 @@ rpc_task_get_next_xprt(struct rpc_clnt *clnt)
static
void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
{
	if (task->tk_xprt &&
			!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) &&
	if (task->tk_xprt) {
		if (!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) &&
		      (task->tk_flags & RPC_TASK_MOVEABLE)))
			return;
		xprt_release(task);
		xprt_put(task->tk_xprt);
	}
	if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
		task->tk_xprt = rpc_task_get_first_xprt(clnt);
	else
+31 −4
Original line number Diff line number Diff line
@@ -1418,6 +1418,26 @@ static size_t xs_tcp_bc_maxpayload(struct rpc_xprt *xprt)
}
#endif /* CONFIG_SUNRPC_BACKCHANNEL */

/**
 * xs_local_state_change - callback to handle AF_LOCAL socket state changes
 * @sk: socket whose state has changed
 *
 */
static void xs_local_state_change(struct sock *sk)
{
	struct rpc_xprt *xprt;
	struct sock_xprt *transport;

	if (!(xprt = xprt_from_sock(sk)))
		return;
	transport = container_of(xprt, struct sock_xprt, xprt);
	if (sk->sk_shutdown & SHUTDOWN_MASK) {
		clear_bit(XPRT_CONNECTED, &xprt->state);
		/* Trigger the socket release */
		xs_run_error_worker(transport, XPRT_SOCK_WAKE_DISCONNECT);
	}
}

/**
 * xs_tcp_state_change - callback to handle TCP socket state changes
 * @sk: socket whose state has changed
@@ -1866,6 +1886,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
		sk->sk_user_data = xprt;
		sk->sk_data_ready = xs_data_ready;
		sk->sk_write_space = xs_udp_write_space;
		sk->sk_state_change = xs_local_state_change;
		sk->sk_error_report = xs_error_report;

		xprt_clear_connected(xprt);
@@ -1950,6 +1971,9 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
	int ret;

	if (transport->file)
		goto force_disconnect;

	if (RPC_IS_ASYNC(task)) {
		/*
		 * We want the AF_LOCAL connect to be resolved in the
@@ -1962,11 +1986,17 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
		 */
		task->tk_rpc_status = -ENOTCONN;
		rpc_exit(task, -ENOTCONN);
		return;
		goto out_wake;
	}
	ret = xs_local_setup_socket(transport);
	if (ret && !RPC_IS_SOFTCONN(task))
		msleep_interruptible(15000);
	return;
force_disconnect:
	xprt_force_disconnect(xprt);
out_wake:
	xprt_clear_connecting(xprt);
	xprt_wake_pending_tasks(xprt, -ENOTCONN);
}

#if IS_ENABLED(CONFIG_SUNRPC_SWAP)
@@ -2845,9 +2875,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
		}
		xprt_set_bound(xprt);
		xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
		ret = ERR_PTR(xs_local_setup_socket(transport));
		if (ret)
			goto out_err;
		break;
	default:
		ret = ERR_PTR(-EAFNOSUPPORT);