Commit adcffc17 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-5.18-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

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
...@@ -363,6 +363,14 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent ...@@ -363,6 +363,14 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
kunmap_atomic(start); 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, static void nfs4_test_and_free_stateid(struct nfs_server *server,
nfs4_stateid *stateid, nfs4_stateid *stateid,
const struct cred *cred) const struct cred *cred)
...@@ -6553,7 +6561,9 @@ static void nfs4_delegreturn_release(void *calldata) ...@@ -6553,7 +6561,9 @@ static void nfs4_delegreturn_release(void *calldata)
pnfs_roc_release(&data->lr.arg, &data->lr.res, pnfs_roc_release(&data->lr.arg, &data->lr.res,
data->res.lr_ret); data->res.lr_ret);
if (inode) { 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); nfs_iput_and_deactive(inode);
} }
kfree(calldata); kfree(calldata);
......
...@@ -160,6 +160,7 @@ struct rpc_add_xprt_test { ...@@ -160,6 +160,7 @@ struct rpc_add_xprt_test {
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9) #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
#define RPC_CLNT_CREATE_SOFTERR (1UL << 10) #define RPC_CLNT_CREATE_SOFTERR (1UL << 10)
#define RPC_CLNT_CREATE_REUSEPORT (1UL << 11) #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_create(struct rpc_create_args *args);
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
......
...@@ -97,7 +97,7 @@ static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt) ...@@ -97,7 +97,7 @@ static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt)
* timeout, which would result in reconnections being * timeout, which would result in reconnections being
* done without the correct namespace: * done without the correct namespace:
*/ */
.flags = RPC_CLNT_CREATE_NOPING | .flags = RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL |
RPC_CLNT_CREATE_NO_IDLE_TIMEOUT RPC_CLNT_CREATE_NO_IDLE_TIMEOUT
}; };
struct rpc_clnt *clnt; struct rpc_clnt *clnt;
......
...@@ -479,6 +479,9 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, ...@@ -479,6 +479,9 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
int err = rpc_ping(clnt); int err = rpc_ping(clnt);
if ((args->flags & RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL) &&
err == -EOPNOTSUPP)
err = 0;
if (err != 0) { if (err != 0) {
rpc_shutdown_client(clnt); rpc_shutdown_client(clnt);
return ERR_PTR(err); return ERR_PTR(err);
...@@ -1065,10 +1068,13 @@ rpc_task_get_next_xprt(struct rpc_clnt *clnt) ...@@ -1065,10 +1068,13 @@ rpc_task_get_next_xprt(struct rpc_clnt *clnt)
static static
void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt) void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
{ {
if (task->tk_xprt && if (task->tk_xprt) {
!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) && if (!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) &&
(task->tk_flags & RPC_TASK_MOVEABLE))) (task->tk_flags & RPC_TASK_MOVEABLE)))
return; return;
xprt_release(task);
xprt_put(task->tk_xprt);
}
if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN) if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN)
task->tk_xprt = rpc_task_get_first_xprt(clnt); task->tk_xprt = rpc_task_get_first_xprt(clnt);
else else
......
...@@ -1418,6 +1418,26 @@ static size_t xs_tcp_bc_maxpayload(struct rpc_xprt *xprt) ...@@ -1418,6 +1418,26 @@ static size_t xs_tcp_bc_maxpayload(struct rpc_xprt *xprt)
} }
#endif /* CONFIG_SUNRPC_BACKCHANNEL */ #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 * xs_tcp_state_change - callback to handle TCP socket state changes
* @sk: socket whose state has changed * @sk: socket whose state has changed
...@@ -1866,6 +1886,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, ...@@ -1866,6 +1886,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
sk->sk_user_data = xprt; sk->sk_user_data = xprt;
sk->sk_data_ready = xs_data_ready; sk->sk_data_ready = xs_data_ready;
sk->sk_write_space = xs_udp_write_space; sk->sk_write_space = xs_udp_write_space;
sk->sk_state_change = xs_local_state_change;
sk->sk_error_report = xs_error_report; sk->sk_error_report = xs_error_report;
xprt_clear_connected(xprt); xprt_clear_connected(xprt);
...@@ -1950,6 +1971,9 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task) ...@@ -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); struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
int ret; int ret;
if (transport->file)
goto force_disconnect;
if (RPC_IS_ASYNC(task)) { if (RPC_IS_ASYNC(task)) {
/* /*
* We want the AF_LOCAL connect to be resolved in the * 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) ...@@ -1962,11 +1986,17 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
*/ */
task->tk_rpc_status = -ENOTCONN; task->tk_rpc_status = -ENOTCONN;
rpc_exit(task, -ENOTCONN); rpc_exit(task, -ENOTCONN);
return; goto out_wake;
} }
ret = xs_local_setup_socket(transport); ret = xs_local_setup_socket(transport);
if (ret && !RPC_IS_SOFTCONN(task)) if (ret && !RPC_IS_SOFTCONN(task))
msleep_interruptible(15000); 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) #if IS_ENABLED(CONFIG_SUNRPC_SWAP)
...@@ -2845,9 +2875,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args) ...@@ -2845,9 +2875,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
} }
xprt_set_bound(xprt); xprt_set_bound(xprt);
xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL); xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
ret = ERR_PTR(xs_local_setup_socket(transport));
if (ret)
goto out_err;
break; break;
default: default:
ret = ERR_PTR(-EAFNOSUPPORT); ret = ERR_PTR(-EAFNOSUPPORT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment