aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 10:52:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 10:52:35 -0400
commitdf632d3ce7eacf92ad9b642301c7b53a1d95b8d8 (patch)
tree848c39ed4f7cfdb582bf2e0a0a03147efaa5198d /fs/lockd
parent2474542f64432398f503373f53bdf620491bcfa8 (diff)
parentaf283885b70248268617955a5ea5476647bd556b (diff)
Merge tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Features include: - Remove CONFIG_EXPERIMENTAL dependency from NFSv4.1 Aside from the issues discussed at the LKS, distros are shipping NFSv4.1 with all the trimmings. - Fix fdatasync()/fsync() for the corner case of a server reboot. - NFSv4 OPEN access fix: finally distinguish correctly between open-for-read and open-for-execute permissions in all situations. - Ensure that the TCP socket is closed when we're in CLOSE_WAIT - More idmapper bugfixes - Lots of pNFS bugfixes and cleanups to remove unnecessary state and make the code easier to read. - In cases where a pNFS read or write fails, allow the client to resume trying layoutgets after two minutes of read/write- through-mds. - More net namespace fixes to the NFSv4 callback code. - More net namespace fixes to the NFSv3 locking code. - More NFSv4 migration preparatory patches. Including patches to detect network trunking in both NFSv4 and NFSv4.1 - pNFS block updates to optimise LAYOUTGET calls." * tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (113 commits) pnfsblock: cleanup nfs4_blkdev_get NFS41: send real read size in layoutget NFS41: send real write size in layoutget NFS: track direct IO left bytes NFSv4.1: Cleanup ugliness in pnfs_layoutgets_blocked() NFSv4.1: Ensure that the layout sequence id stays 'close' to the current NFSv4.1: Deal with seqid wraparound in the pNFS return-on-close code NFSv4 set open access operation call flag in nfs4_init_opendata_res NFSv4.1: Remove the dependency on CONFIG_EXPERIMENTAL NFSv4 reduce attribute requests for open reclaim NFSv4: nfs4_open_done first must check that GETATTR decoded a file type NFSv4.1: Deal with wraparound when updating the layout "barrier" seqid NFSv4.1: Deal with wraparound issues when updating the layout stateid NFSv4.1: Always set the layout stateid if this is the first layoutget NFSv4.1: Fix another refcount issue in pnfs_find_alloc_layout NFSv4: don't put ACCESS in OPEN compound if O_EXCL NFSv4: don't check MAY_WRITE access bit in OPEN NFS: Set key construction data for the legacy upcall NFSv4.1: don't do two EXCHANGE_IDs on mount NFS: nfs41_walk_client_list(): re-lock before iterating ...
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/mon.c86
-rw-r--r--fs/lockd/netns.h4
-rw-r--r--fs/lockd/svc.c1
3 files changed, 74 insertions, 17 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 7ef14b3c5bee..e4fb3ba5a58a 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -7,7 +7,6 @@
7 */ 7 */
8 8
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/utsname.h>
11#include <linux/kernel.h> 10#include <linux/kernel.h>
12#include <linux/ktime.h> 11#include <linux/ktime.h>
13#include <linux/slab.h> 12#include <linux/slab.h>
@@ -19,6 +18,8 @@
19 18
20#include <asm/unaligned.h> 19#include <asm/unaligned.h>
21 20
21#include "netns.h"
22
22#define NLMDBG_FACILITY NLMDBG_MONITOR 23#define NLMDBG_FACILITY NLMDBG_MONITOR
23#define NSM_PROGRAM 100024 24#define NSM_PROGRAM 100024
24#define NSM_VERSION 1 25#define NSM_VERSION 1
@@ -40,6 +41,7 @@ struct nsm_args {
40 u32 proc; 41 u32 proc;
41 42
42 char *mon_name; 43 char *mon_name;
44 char *nodename;
43}; 45};
44 46
45struct nsm_res { 47struct nsm_res {
@@ -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,10 +85,54 @@ static struct rpc_clnt *nsm_create(struct net *net)
83 return rpc_create(&args); 85 return rpc_create(&args);
84} 86}
85 87
86static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, 88static struct rpc_clnt *nsm_client_get(struct net *net)
87 struct net *net)
88{ 89{
90 static DEFINE_MUTEX(nsm_create_mutex);
89 struct rpc_clnt *clnt; 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
115static 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
133static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
134 struct rpc_clnt *clnt)
135{
90 int status; 136 int status;
91 struct nsm_args args = { 137 struct nsm_args args = {
92 .priv = &nsm->sm_priv, 138 .priv = &nsm->sm_priv,
@@ -94,31 +140,24 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
94 .vers = 3, 140 .vers = 3,
95 .proc = NLMPROC_NSM_NOTIFY, 141 .proc = NLMPROC_NSM_NOTIFY,
96 .mon_name = nsm->sm_mon_name, 142 .mon_name = nsm->sm_mon_name,
143 .nodename = clnt->cl_nodename,
97 }; 144 };
98 struct rpc_message msg = { 145 struct rpc_message msg = {
99 .rpc_argp = &args, 146 .rpc_argp = &args,
100 .rpc_resp = res, 147 .rpc_resp = res,
101 }; 148 };
102 149
103 clnt = nsm_create(net); 150 BUG_ON(clnt == NULL);
104 if (IS_ERR(clnt)) {
105 status = PTR_ERR(clnt);
106 dprintk("lockd: failed to create NSM upcall transport, "
107 "status=%d\n", status);
108 goto out;
109 }
110 151
111 memset(res, 0, sizeof(*res)); 152 memset(res, 0, sizeof(*res));
112 153
113 msg.rpc_proc = &clnt->cl_procinfo[proc]; 154 msg.rpc_proc = &clnt->cl_procinfo[proc];
114 status = rpc_call_sync(clnt, &msg, 0); 155 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
115 if (status < 0) 156 if (status < 0)
116 dprintk("lockd: NSM upcall RPC failed, status=%d\n", 157 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
117 status); 158 status);
118 else 159 else
119 status = 0; 160 status = 0;
120 rpc_shutdown_client(clnt);
121 out:
122 return status; 161 return status;
123} 162}
124 163
@@ -138,6 +177,7 @@ int nsm_monitor(const struct nlm_host *host)
138 struct nsm_handle *nsm = host->h_nsmhandle; 177 struct nsm_handle *nsm = host->h_nsmhandle;
139 struct nsm_res res; 178 struct nsm_res res;
140 int status; 179 int status;
180 struct rpc_clnt *clnt;
141 181
142 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); 182 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
143 183
@@ -150,7 +190,15 @@ int nsm_monitor(const struct nlm_host *host)
150 */ 190 */
151 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; 191 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
152 192
153 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net); 193 clnt = nsm_client_get(host->net);
194 if (IS_ERR(clnt)) {
195 status = PTR_ERR(clnt);
196 dprintk("lockd: failed to create NSM upcall transport, "
197 "status=%d, net=%p\n", status, host->net);
198 return status;
199 }
200
201 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
154 if (unlikely(res.status != 0)) 202 if (unlikely(res.status != 0))
155 status = -EIO; 203 status = -EIO;
156 if (unlikely(status < 0)) { 204 if (unlikely(status < 0)) {
@@ -182,9 +230,11 @@ void nsm_unmonitor(const struct nlm_host *host)
182 230
183 if (atomic_read(&nsm->sm_count) == 1 231 if (atomic_read(&nsm->sm_count) == 1
184 && nsm->sm_monitored && !nsm->sm_sticky) { 232 && nsm->sm_monitored && !nsm->sm_sticky) {
233 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
234
185 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 235 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
186 236
187 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net); 237 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
188 if (res.status != 0) 238 if (res.status != 0)
189 status = -EIO; 239 status = -EIO;
190 if (status < 0) 240 if (status < 0)
@@ -192,6 +242,8 @@ void nsm_unmonitor(const struct nlm_host *host)
192 nsm->sm_name); 242 nsm->sm_name);
193 else 243 else
194 nsm->sm_monitored = 0; 244 nsm->sm_monitored = 0;
245
246 nsm_client_put(host->net);
195 } 247 }
196} 248}
197 249
@@ -430,7 +482,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
430{ 482{
431 __be32 *p; 483 __be32 *p;
432 484
433 encode_nsm_string(xdr, utsname()->nodename); 485 encode_nsm_string(xdr, argp->nodename);
434 p = xdr_reserve_space(xdr, 4 + 4 + 4); 486 p = xdr_reserve_space(xdr, 4 + 4 + 4);
435 *p++ = cpu_to_be32(argp->prog); 487 *p++ = cpu_to_be32(argp->prog);
436 *p++ = cpu_to_be32(argp->vers); 488 *p++ = cpu_to_be32(argp->vers);
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