aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-09-18 05:37:12 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-01 18:27:34 -0400
commite9406db20fecbfcab646bad157b4cfdc7cadddfb (patch)
tree292fcb0062d86eb7170de559fdd211b21dbe40da
parent1dc42e04b75779d321f1d17dca3873004066f667 (diff)
lockd: per-net NSM client creation and destruction helpers introduced
NSM RPC client can be required on NFSv3 umount, when child reaper is dying (and destroying it's mount namespace). It means, that current nsproxy is set to NULL already, but creation of RPC client requires UTS namespace for gaining hostname string. This patch introduces reference counted NFS RPC clients creation and destruction helpers (similar to RPCBIND RPC clients). Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Cc: <stable@vger.kernel.org> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/lockd/mon.c51
-rw-r--r--fs/lockd/netns.h4
-rw-r--r--fs/lockd/svc.c1
3 files changed, 54 insertions, 2 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 7ef14b3c5bee..38f240e104ce 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -19,6 +19,8 @@
19 19
20#include <asm/unaligned.h> 20#include <asm/unaligned.h>
21 21
22#include "netns.h"
23
22#define NLMDBG_FACILITY NLMDBG_MONITOR 24#define NLMDBG_FACILITY NLMDBG_MONITOR
23#define NSM_PROGRAM 100024 25#define NSM_PROGRAM 100024
24#define NSM_VERSION 1 26#define NSM_VERSION 1
@@ -70,7 +72,7 @@ static struct rpc_clnt *nsm_create(struct net *net)
70 }; 72 };
71 struct rpc_create_args args = { 73 struct rpc_create_args args = {
72 .net = net, 74 .net = net,
73 .protocol = XPRT_TRANSPORT_UDP, 75 .protocol = XPRT_TRANSPORT_TCP,
74 .address = (struct sockaddr *)&sin, 76 .address = (struct sockaddr *)&sin,
75 .addrsize = sizeof(sin), 77 .addrsize = sizeof(sin),
76 .servername = "rpc.statd", 78 .servername = "rpc.statd",
@@ -83,6 +85,51 @@ static struct rpc_clnt *nsm_create(struct net *net)
83 return rpc_create(&args); 85 return rpc_create(&args);
84} 86}
85 87
88__maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net)
89{
90 static DEFINE_MUTEX(nsm_create_mutex);
91 struct rpc_clnt *clnt;
92 struct lockd_net *ln = net_generic(net, lockd_net_id);
93
94 spin_lock(&ln->nsm_clnt_lock);
95 if (ln->nsm_users) {
96 ln->nsm_users++;
97 clnt = ln->nsm_clnt;
98 spin_unlock(&ln->nsm_clnt_lock);
99 goto out;
100 }
101 spin_unlock(&ln->nsm_clnt_lock);
102
103 mutex_lock(&nsm_create_mutex);
104 clnt = nsm_create(net);
105 if (!IS_ERR(clnt)) {
106 ln->nsm_clnt = clnt;
107 smp_wmb();
108 ln->nsm_users = 1;
109 }
110 mutex_unlock(&nsm_create_mutex);
111out:
112 return clnt;
113}
114
115__maybe_unused static void nsm_client_put(struct net *net)
116{
117 struct lockd_net *ln = net_generic(net, lockd_net_id);
118 struct rpc_clnt *clnt = ln->nsm_clnt;
119 int shutdown = 0;
120
121 spin_lock(&ln->nsm_clnt_lock);
122 if (ln->nsm_users) {
123 if (--ln->nsm_users)
124 ln->nsm_clnt = NULL;
125 shutdown = !ln->nsm_users;
126 }
127 spin_unlock(&ln->nsm_clnt_lock);
128
129 if (shutdown)
130 rpc_shutdown_client(clnt);
131}
132
86static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, 133static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
87 struct net *net) 134 struct net *net)
88{ 135{
@@ -111,7 +158,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
111 memset(res, 0, sizeof(*res)); 158 memset(res, 0, sizeof(*res));
112 159
113 msg.rpc_proc = &clnt->cl_procinfo[proc]; 160 msg.rpc_proc = &clnt->cl_procinfo[proc];
114 status = rpc_call_sync(clnt, &msg, 0); 161 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
115 if (status < 0) 162 if (status < 0)
116 dprintk("lockd: NSM upcall RPC failed, status=%d\n", 163 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
117 status); 164 status);
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h
index 4eee248ba96e..5010b55628b4 100644
--- a/fs/lockd/netns.h
+++ b/fs/lockd/netns.h
@@ -12,6 +12,10 @@ struct lockd_net {
12 struct delayed_work grace_period_end; 12 struct delayed_work grace_period_end;
13 struct lock_manager lockd_manager; 13 struct lock_manager lockd_manager;
14 struct list_head grace_list; 14 struct list_head grace_list;
15
16 spinlock_t nsm_clnt_lock;
17 unsigned int nsm_users;
18 struct rpc_clnt *nsm_clnt;
15}; 19};
16 20
17extern int lockd_net_id; 21extern int lockd_net_id;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 31a63f87b806..7e355870d519 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -596,6 +596,7 @@ static int lockd_init_net(struct net *net)
596 596
597 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); 597 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
598 INIT_LIST_HEAD(&ln->grace_list); 598 INIT_LIST_HEAD(&ln->grace_list);
599 spin_lock_init(&ln->nsm_clnt_lock);
599 return 0; 600 return 0;
600} 601}
601 602