Merge tag 'nfs-for-4.11-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client updates from Anna Schumaker: "Highlights include: Stable bugfixes: - NFSv4: Fix memory and state leak in _nfs4_open_and_get_state - xprtrdma: Fix Read chunk padding - xprtrdma: Per-connection pad optimization - xprtrdma: Disable pad optimization by default - xprtrdma: Reduce required number of send SGEs - nlm: Ensure callback code also checks that the files match - pNFS/flexfiles: If the layout is invalid, it must be updated before retrying - NFSv4: Fix reboot recovery in copy offload - Revert "NFSv4.1: Handle NFS4ERR_BADSESSION/NFS4ERR_DEADSESSION replies to OP_SEQUENCE" - NFSv4: fix getacl head length estimation - NFSv4: fix getacl ERANGE for sum ACL buffer sizes Features: - Add and use dprintk_cont macros - Various cleanups to NFS v4.x to reduce code duplication and complexity - Remove unused cr_magic related code - Improvements to sunrpc "read from buffer" code - Clean up sunrpc timeout code and allow changing TCP timeout parameters - Remove duplicate mw_list management code in xprtrdma - Add generic functions for encoding and decoding xdr streams Bugfixes: - Clean up nfs_show_mountd_netid - Make layoutreturn_ops static and use NULL instead of 0 to fix sparse warnings - Properly handle -ERESTARTSYS in nfs_rename() - Check if register_shrinker() failed during rpcauth_init() - Properly clean up procfs/pipefs entries - Various NFS over RDMA related fixes - Silence unititialized variable warning in sunrpc" * tag 'nfs-for-4.11-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (64 commits) NFSv4: fix getacl ERANGE for some ACL buffer sizes NFSv4: fix getacl head length estimation Revert "NFSv4.1: Handle NFS4ERR_BADSESSION/NFS4ERR_DEADSESSION replies to OP_SEQUENCE" NFSv4: Fix reboot recovery in copy offload pNFS/flexfiles: If the layout is invalid, it must be updated before retrying NFSv4: Clean up owner/group attribute decode SUNRPC: Add a helper function xdr_stream_decode_string_dup() NFSv4: Remove bogus "struct nfs_client" argument from decode_ace() NFSv4: Fix the underestimation of delegation XDR space reservation NFSv4: Replace callback string decode function with a generic NFSv4: Replace the open coded decode_opaque_inline() with the new generic NFSv4: Replace ad-hoc xdr encode/decode helpers with xdr_stream_* generics SUNRPC: Add generic helpers for xdr_stream encode/decode sunrpc: silence uninitialized variable warning nlm: Ensure callback code also checks that the files match sunrpc: Allow xprt->ops->timer method to sleep xprtrdma: Refactor management of mw_list field xprtrdma: Handle stale connection rejection xprtrdma: Properly recover FRWRs with in-flight FASTREG WRs xprtrdma: Shrink send SGEs array ...
This commit is contained in:
@@ -52,6 +52,8 @@
|
||||
#include "sunrpc.h"
|
||||
|
||||
static void xs_close(struct rpc_xprt *xprt);
|
||||
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
|
||||
struct socket *sock);
|
||||
|
||||
/*
|
||||
* xprtsock tunables
|
||||
@@ -666,6 +668,9 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
||||
if (task->tk_flags & RPC_TASK_SENT)
|
||||
zerocopy = false;
|
||||
|
||||
if (test_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state))
|
||||
xs_tcp_set_socket_timeouts(xprt, transport->sock);
|
||||
|
||||
/* Continue transmitting the packet/record. We must be careful
|
||||
* to cope with writespace callbacks arriving _after_ we have
|
||||
* called sendmsg(). */
|
||||
@@ -1734,7 +1739,9 @@ static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t
|
||||
*/
|
||||
static void xs_udp_timer(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||
{
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
xprt_adjust_cwnd(xprt, task, -ETIMEDOUT);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
}
|
||||
|
||||
static unsigned short xs_get_random_port(void)
|
||||
@@ -2235,6 +2242,66 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
|
||||
xs_reset_transport(transport);
|
||||
}
|
||||
|
||||
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
|
||||
struct socket *sock)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
unsigned int keepidle;
|
||||
unsigned int keepcnt;
|
||||
unsigned int opt_on = 1;
|
||||
unsigned int timeo;
|
||||
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
keepidle = DIV_ROUND_UP(xprt->timeout->to_initval, HZ);
|
||||
keepcnt = xprt->timeout->to_retries + 1;
|
||||
timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
|
||||
(xprt->timeout->to_retries + 1);
|
||||
clear_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
|
||||
/* TCP Keepalive options */
|
||||
kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *)&opt_on, sizeof(opt_on));
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
|
||||
(char *)&keepidle, sizeof(keepidle));
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
|
||||
(char *)&keepidle, sizeof(keepidle));
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
|
||||
(char *)&keepcnt, sizeof(keepcnt));
|
||||
|
||||
/* TCP user timeout (see RFC5482) */
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
|
||||
(char *)&timeo, sizeof(timeo));
|
||||
}
|
||||
|
||||
static void xs_tcp_set_connect_timeout(struct rpc_xprt *xprt,
|
||||
unsigned long connect_timeout,
|
||||
unsigned long reconnect_timeout)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
struct rpc_timeout to;
|
||||
unsigned long initval;
|
||||
|
||||
spin_lock_bh(&xprt->transport_lock);
|
||||
if (reconnect_timeout < xprt->max_reconnect_timeout)
|
||||
xprt->max_reconnect_timeout = reconnect_timeout;
|
||||
if (connect_timeout < xprt->connect_timeout) {
|
||||
memcpy(&to, xprt->timeout, sizeof(to));
|
||||
initval = DIV_ROUND_UP(connect_timeout, to.to_retries + 1);
|
||||
/* Arbitrary lower limit */
|
||||
if (initval < XS_TCP_INIT_REEST_TO << 1)
|
||||
initval = XS_TCP_INIT_REEST_TO << 1;
|
||||
to.to_initval = initval;
|
||||
to.to_maxval = initval;
|
||||
memcpy(&transport->tcp_timeout, &to,
|
||||
sizeof(transport->tcp_timeout));
|
||||
xprt->timeout = &transport->tcp_timeout;
|
||||
xprt->connect_timeout = connect_timeout;
|
||||
}
|
||||
set_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
|
||||
spin_unlock_bh(&xprt->transport_lock);
|
||||
}
|
||||
|
||||
static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
{
|
||||
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
|
||||
@@ -2242,22 +2309,8 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
|
||||
if (!transport->inet) {
|
||||
struct sock *sk = sock->sk;
|
||||
unsigned int keepidle = xprt->timeout->to_initval / HZ;
|
||||
unsigned int keepcnt = xprt->timeout->to_retries + 1;
|
||||
unsigned int opt_on = 1;
|
||||
unsigned int timeo;
|
||||
unsigned int addr_pref = IPV6_PREFER_SRC_PUBLIC;
|
||||
|
||||
/* TCP Keepalive options */
|
||||
kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *)&opt_on, sizeof(opt_on));
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
|
||||
(char *)&keepidle, sizeof(keepidle));
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
|
||||
(char *)&keepidle, sizeof(keepidle));
|
||||
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
|
||||
(char *)&keepcnt, sizeof(keepcnt));
|
||||
|
||||
/* Avoid temporary address, they are bad for long-lived
|
||||
* connections such as NFS mounts.
|
||||
* RFC4941, section 3.6 suggests that:
|
||||
@@ -2268,11 +2321,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||
kernel_setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES,
|
||||
(char *)&addr_pref, sizeof(addr_pref));
|
||||
|
||||
/* 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));
|
||||
xs_tcp_set_socket_timeouts(xprt, sock);
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
|
||||
@@ -2721,6 +2770,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
|
||||
.set_retrans_timeout = xprt_set_retrans_timeout_def,
|
||||
.close = xs_tcp_shutdown,
|
||||
.destroy = xs_destroy,
|
||||
.set_connect_timeout = xs_tcp_set_connect_timeout,
|
||||
.print_stats = xs_tcp_print_stats,
|
||||
.enable_swap = xs_enable_swap,
|
||||
.disable_swap = xs_disable_swap,
|
||||
@@ -3007,6 +3057,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
|
||||
xprt->timeout = &xs_tcp_default_timeout;
|
||||
|
||||
xprt->max_reconnect_timeout = xprt->timeout->to_maxval;
|
||||
xprt->connect_timeout = xprt->timeout->to_initval *
|
||||
(xprt->timeout->to_retries + 1);
|
||||
|
||||
INIT_WORK(&transport->recv_worker, xs_tcp_data_receive_workfn);
|
||||
INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);
|
||||
@@ -3209,7 +3261,9 @@ static int param_set_uint_minmax(const char *val,
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
ret = kstrtouint(val, 0, &num);
|
||||
if (ret == -EINVAL || num < min || num > max)
|
||||
if (ret)
|
||||
return ret;
|
||||
if (num < min || num > max)
|
||||
return -EINVAL;
|
||||
*((unsigned int *)kp->arg) = num;
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user