aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svc_xprt.c
diff options
context:
space:
mode:
authorScott Mayhew <smayhew@redhat.com>2015-12-11 16:45:58 -0500
committerJ. Bruce Fields <bfields@redhat.com>2015-12-23 10:08:15 -0500
commitc3d4879e01bec484f50a78c108341f039d470e96 (patch)
tree5c879cdf84dc41569ec890574e5f07476c892705 /net/sunrpc/svc_xprt.c
parentd4f72cb7fa4a3705f6675f2740f9713dc3400dd3 (diff)
sunrpc: Add a function to close temporary transports immediately
Add a function svc_age_temp_xprts_now() to close temporary transports whose xpt_local matches the address passed in server_addr immediately instead of waiting for them to be closed by the timer function. The function is intended to be used by notifier_blocks that will be added to nfsd and lockd that will run when an ip address is deleted. This will eliminate the ACK storms and client hangs that occur in HA-NFS configurations where nfsd & lockd is left running on the cluster nodes all the time and the NFS 'service' is migrated back and forth within a short timeframe. Signed-off-by: Scott Mayhew <smayhew@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc/svc_xprt.c')
-rw-r--r--net/sunrpc/svc_xprt.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index a6cbb2104667..7422f28818b2 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -10,11 +10,13 @@
10#include <linux/kthread.h> 10#include <linux/kthread.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <net/sock.h> 12#include <net/sock.h>
13#include <linux/sunrpc/addr.h>
13#include <linux/sunrpc/stats.h> 14#include <linux/sunrpc/stats.h>
14#include <linux/sunrpc/svc_xprt.h> 15#include <linux/sunrpc/svc_xprt.h>
15#include <linux/sunrpc/svcsock.h> 16#include <linux/sunrpc/svcsock.h>
16#include <linux/sunrpc/xprt.h> 17#include <linux/sunrpc/xprt.h>
17#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/netdevice.h>
18#include <trace/events/sunrpc.h> 20#include <trace/events/sunrpc.h>
19 21
20#define RPCDBG_FACILITY RPCDBG_SVCXPRT 22#define RPCDBG_FACILITY RPCDBG_SVCXPRT
@@ -938,6 +940,49 @@ static void svc_age_temp_xprts(unsigned long closure)
938 mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); 940 mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
939} 941}
940 942
943/* Close temporary transports whose xpt_local matches server_addr immediately
944 * instead of waiting for them to be picked up by the timer.
945 *
946 * This is meant to be called from a notifier_block that runs when an ip
947 * address is deleted.
948 */
949void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
950{
951 struct svc_xprt *xprt;
952 struct svc_sock *svsk;
953 struct socket *sock;
954 struct list_head *le, *next;
955 LIST_HEAD(to_be_closed);
956 struct linger no_linger = {
957 .l_onoff = 1,
958 .l_linger = 0,
959 };
960
961 spin_lock_bh(&serv->sv_lock);
962 list_for_each_safe(le, next, &serv->sv_tempsocks) {
963 xprt = list_entry(le, struct svc_xprt, xpt_list);
964 if (rpc_cmp_addr(server_addr, (struct sockaddr *)
965 &xprt->xpt_local)) {
966 dprintk("svc_age_temp_xprts_now: found %p\n", xprt);
967 list_move(le, &to_be_closed);
968 }
969 }
970 spin_unlock_bh(&serv->sv_lock);
971
972 while (!list_empty(&to_be_closed)) {
973 le = to_be_closed.next;
974 list_del_init(le);
975 xprt = list_entry(le, struct svc_xprt, xpt_list);
976 dprintk("svc_age_temp_xprts_now: closing %p\n", xprt);
977 svsk = container_of(xprt, struct svc_sock, sk_xprt);
978 sock = svsk->sk_sock;
979 kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
980 (char *)&no_linger, sizeof(no_linger));
981 svc_close_xprt(xprt);
982 }
983}
984EXPORT_SYMBOL_GPL(svc_age_temp_xprts_now);
985
941static void call_xpt_users(struct svc_xprt *xprt) 986static void call_xpt_users(struct svc_xprt *xprt)
942{ 987{
943 struct svc_xpt_user *u; 988 struct svc_xpt_user *u;