Merge tag 'nfs-for-4.2-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: Stable patches: - Fix a crash in the NFSv4 file locking code. - Fix an fsync() regression, where we were failing to retry I/O in some circumstances. - Fix an infinite loop in NFSv4.0 OPEN stateid recovery - Fix a memory leak when an attempted pnfs fails. - Fix a memory leak in the backchannel code - Large hostnames were not supported correctly in NFSv4.1 - Fix a pNFS/flexfiles bug that was impeding error reporting on I/O. - Fix a couple of credential issues in pNFS/flexfiles Bugfixes + cleanups: - Open flag sanity checks in the NFSv4 atomic open codepath - More NFSv4 delegation related bugfixes - Various NFSv4.1 backchannel bugfixes and cleanups - Fix the NFS swap socket code - Various cleanups of the NFSv4 SETCLIENTID and EXCHANGE_ID code - Fix a UDP transport deadlock issue Features: - More RDMA client transport improvements - NFSv4.2 LAYOUTSTATS functionality for pnfs flexfiles" * tag 'nfs-for-4.2-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (87 commits) nfs: Remove invalid tk_pid from debug message nfs: Remove invalid NFS_ATTR_FATTR_V4_REFERRAL checking in nfs4_get_rootfh nfs: Drop bad comment in nfs41_walk_client_list() nfs: Remove unneeded micro checking of CONFIG_PROC_FS nfs: Don't setting FILE_CREATED flags always nfs: Use remove_proc_subtree() instead remove_proc_entry() nfs: Remove unused argument in nfs_server_set_fsinfo() nfs: Fix a memory leak when meeting an unsupported state protect nfs: take extra reference to fl->fl_file when running a LOCKU operation NFSv4: When returning a delegation, don't reclaim an incompatible open mode. NFSv4.2: LAYOUTSTATS is optional to implement NFSv4.2: Fix up a decoding error in layoutstats pNFS/flexfiles: Fix the reset of struct pgio_header when resending pNFS/flexfiles: Turn off layoutcommit for servers that don't need it pnfs/flexfiles: protect ktime manipulation with mirror lock nfs: provide pnfs_report_layoutstat when NFS42 is disabled nfs: verify open flags before allowing open nfs: always update creds in mirror, even when we have an already connected ds nfs: fix potential credential leak in ff_layout_update_mirror_cred pnfs/flexfiles: report layoutstat regularly ...
This commit is contained in:
@@ -622,24 +622,6 @@ process_status:
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* xs_tcp_shutdown - gracefully shut down a TCP socket
|
||||
* @xprt: transport
|
||||
*
|
||||
* Initiates a graceful shutdown of the TCP socket by calling the
|
||||
* equivalent of shutdown(SHUT_RDWR);
|
||||
*/
|
||||
static void xs_tcp_shutdown(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
struct socket *sock = transport->sock;
|
||||
|
||||
if (sock != NULL) {
|
||||
kernel_sock_shutdown(sock, SHUT_RDWR);
|
||||
trace_rpc_socket_shutdown(xprt, sock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xs_tcp_send_request - write an RPC request to a TCP socket
|
||||
* @task: address of RPC task that manages the state of an RPC request
|
||||
@@ -786,6 +768,7 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)
|
||||
xs_sock_reset_connection_flags(xprt);
|
||||
/* Mark transport as closed and wake up all pending tasks */
|
||||
xprt_disconnect_done(xprt);
|
||||
xprt_force_disconnect(xprt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,6 +810,9 @@ static void xs_reset_transport(struct sock_xprt *transport)
|
||||
if (sk == NULL)
|
||||
return;
|
||||
|
||||
if (atomic_read(&transport->xprt.swapper))
|
||||
sk_clear_memalloc(sk);
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
transport->inet = NULL;
|
||||
transport->sock = NULL;
|
||||
@@ -863,6 +849,13 @@ static void xs_close(struct rpc_xprt *xprt)
|
||||
xprt_disconnect_done(xprt);
|
||||
}
|
||||
|
||||
static void xs_inject_disconnect(struct rpc_xprt *xprt)
|
||||
{
|
||||
dprintk("RPC: injecting transport disconnect on xprt=%p\n",
|
||||
xprt);
|
||||
xprt_disconnect_done(xprt);
|
||||
}
|
||||
|
||||
static void xs_xprt_free(struct rpc_xprt *xprt)
|
||||
{
|
||||
xs_free_peer_addresses(xprt);
|
||||
@@ -901,7 +894,6 @@ static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
|
||||
/**
|
||||
* xs_local_data_ready - "data ready" callback for AF_LOCAL sockets
|
||||
* @sk: socket with data to read
|
||||
* @len: how much data to read
|
||||
*
|
||||
* Currently this assumes we can read the whole reply in a single gulp.
|
||||
*/
|
||||
@@ -965,7 +957,6 @@ static void xs_local_data_ready(struct sock *sk)
|
||||
/**
|
||||
* xs_udp_data_ready - "data ready" callback for UDP sockets
|
||||
* @sk: socket with data to read
|
||||
* @len: how much data to read
|
||||
*
|
||||
*/
|
||||
static void xs_udp_data_ready(struct sock *sk)
|
||||
@@ -1389,7 +1380,6 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
|
||||
/**
|
||||
* xs_tcp_data_ready - "data ready" callback for TCP sockets
|
||||
* @sk: socket with data to read
|
||||
* @bytes: how much data to read
|
||||
*
|
||||
*/
|
||||
static void xs_tcp_data_ready(struct sock *sk)
|
||||
@@ -1886,9 +1876,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
|
||||
|
||||
/**
|
||||
* xs_local_setup_socket - create AF_LOCAL socket, connect to a local endpoint
|
||||
* @xprt: RPC transport to connect
|
||||
* @transport: socket transport to connect
|
||||
* @create_sock: function to create a socket of the correct type
|
||||
*/
|
||||
static int xs_local_setup_socket(struct sock_xprt *transport)
|
||||
{
|
||||
@@ -1960,43 +1948,84 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||
msleep_interruptible(15000);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SUNRPC_SWAP
|
||||
#if IS_ENABLED(CONFIG_SUNRPC_SWAP)
|
||||
/*
|
||||
* Note that this should be called with XPRT_LOCKED held (or when we otherwise
|
||||
* know that we have exclusive access to the socket), to guard against
|
||||
* races with xs_reset_transport.
|
||||
*/
|
||||
static void xs_set_memalloc(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt,
|
||||
xprt);
|
||||
|
||||
if (xprt->swapper)
|
||||
/*
|
||||
* If there's no sock, then we have nothing to set. The
|
||||
* reconnecting process will get it for us.
|
||||
*/
|
||||
if (!transport->inet)
|
||||
return;
|
||||
if (atomic_read(&xprt->swapper))
|
||||
sk_set_memalloc(transport->inet);
|
||||
}
|
||||
|
||||
/**
|
||||
* xs_swapper - Tag this transport as being used for swap.
|
||||
* xs_enable_swap - Tag this transport as being used for swap.
|
||||
* @xprt: transport to tag
|
||||
* @enable: enable/disable
|
||||
*
|
||||
* Take a reference to this transport on behalf of the rpc_clnt, and
|
||||
* optionally mark it for swapping if it wasn't already.
|
||||
*/
|
||||
int xs_swapper(struct rpc_xprt *xprt, int enable)
|
||||
static int
|
||||
xs_enable_swap(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt,
|
||||
xprt);
|
||||
int err = 0;
|
||||
struct sock_xprt *xs = container_of(xprt, struct sock_xprt, xprt);
|
||||
|
||||
if (enable) {
|
||||
xprt->swapper++;
|
||||
xs_set_memalloc(xprt);
|
||||
} else if (xprt->swapper) {
|
||||
xprt->swapper--;
|
||||
sk_clear_memalloc(transport->inet);
|
||||
}
|
||||
|
||||
return err;
|
||||
if (atomic_inc_return(&xprt->swapper) != 1)
|
||||
return 0;
|
||||
if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE))
|
||||
return -ERESTARTSYS;
|
||||
if (xs->inet)
|
||||
sk_set_memalloc(xs->inet);
|
||||
xprt_release_xprt(xprt, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xs_disable_swap - Untag this transport as being used for swap.
|
||||
* @xprt: transport to tag
|
||||
*
|
||||
* Drop a "swapper" reference to this xprt on behalf of the rpc_clnt. If the
|
||||
* swapper refcount goes to 0, untag the socket as a memalloc socket.
|
||||
*/
|
||||
static void
|
||||
xs_disable_swap(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *xs = container_of(xprt, struct sock_xprt, xprt);
|
||||
|
||||
if (!atomic_dec_and_test(&xprt->swapper))
|
||||
return;
|
||||
if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE))
|
||||
return;
|
||||
if (xs->inet)
|
||||
sk_clear_memalloc(xs->inet);
|
||||
xprt_release_xprt(xprt, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xs_swapper);
|
||||
#else
|
||||
static void xs_set_memalloc(struct rpc_xprt *xprt)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
xs_enable_swap(struct rpc_xprt *xprt)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
xs_disable_swap(struct rpc_xprt *xprt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
@@ -2057,6 +2086,27 @@ out:
|
||||
xprt_wake_pending_tasks(xprt, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* xs_tcp_shutdown - gracefully shut down a TCP socket
|
||||
* @xprt: transport
|
||||
*
|
||||
* Initiates a graceful shutdown of the TCP socket by calling the
|
||||
* equivalent of shutdown(SHUT_RDWR);
|
||||
*/
|
||||
static void xs_tcp_shutdown(struct rpc_xprt *xprt)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
struct socket *sock = transport->sock;
|
||||
|
||||
if (sock == NULL)
|
||||
return;
|
||||
if (xprt_connected(xprt)) {
|
||||
kernel_sock_shutdown(sock, SHUT_RDWR);
|
||||
trace_rpc_socket_shutdown(xprt, sock);
|
||||
} else
|
||||
xs_reset_transport(transport);
|
||||
}
|
||||
|
||||
static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
@@ -2067,6 +2117,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
unsigned int keepidle = xprt->timeout->to_initval / HZ;
|
||||
unsigned int keepcnt = xprt->timeout->to_retries + 1;
|
||||
unsigned int opt_on = 1;
|
||||
unsigned int timeo;
|
||||
|
||||
/* TCP Keepalive options */
|
||||
kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
@@ -2078,6 +2129,12 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
|
||||
(char *)&keepcnt, sizeof(keepcnt));
|
||||
|
||||
/* TCP user timeout (see RFC5482) */
|
||||
timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
|
||||
(xprt->timeout->to_retries + 1);
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
|
||||
(char *)&timeo, sizeof(timeo));
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
|
||||
xs_save_old_callbacks(transport, sk);
|
||||
@@ -2125,9 +2182,6 @@ out:
|
||||
|
||||
/**
|
||||
* xs_tcp_setup_socket - create a TCP socket and connect to a remote endpoint
|
||||
* @xprt: RPC transport to connect
|
||||
* @transport: socket transport to connect
|
||||
* @create_sock: function to create a socket of the correct type
|
||||
*
|
||||
* Invoked by a work queue tasklet.
|
||||
*/
|
||||
@@ -2463,6 +2517,8 @@ static struct rpc_xprt_ops xs_local_ops = {
|
||||
.close = xs_close,
|
||||
.destroy = xs_destroy,
|
||||
.print_stats = xs_local_print_stats,
|
||||
.enable_swap = xs_enable_swap,
|
||||
.disable_swap = xs_disable_swap,
|
||||
};
|
||||
|
||||
static struct rpc_xprt_ops xs_udp_ops = {
|
||||
@@ -2482,6 +2538,9 @@ static struct rpc_xprt_ops xs_udp_ops = {
|
||||
.close = xs_close,
|
||||
.destroy = xs_destroy,
|
||||
.print_stats = xs_udp_print_stats,
|
||||
.enable_swap = xs_enable_swap,
|
||||
.disable_swap = xs_disable_swap,
|
||||
.inject_disconnect = xs_inject_disconnect,
|
||||
};
|
||||
|
||||
static struct rpc_xprt_ops xs_tcp_ops = {
|
||||
@@ -2498,6 +2557,9 @@ static struct rpc_xprt_ops xs_tcp_ops = {
|
||||
.close = xs_tcp_shutdown,
|
||||
.destroy = xs_destroy,
|
||||
.print_stats = xs_tcp_print_stats,
|
||||
.enable_swap = xs_enable_swap,
|
||||
.disable_swap = xs_disable_swap,
|
||||
.inject_disconnect = xs_inject_disconnect,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2515,6 +2577,9 @@ static struct rpc_xprt_ops bc_tcp_ops = {
|
||||
.close = bc_close,
|
||||
.destroy = bc_destroy,
|
||||
.print_stats = xs_tcp_print_stats,
|
||||
.enable_swap = xs_enable_swap,
|
||||
.disable_swap = xs_disable_swap,
|
||||
.inject_disconnect = xs_inject_disconnect,
|
||||
};
|
||||
|
||||
static int xs_init_anyaddr(const int family, struct sockaddr *sap)
|
||||
|
Reference in New Issue
Block a user