diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 10:52:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 10:52:35 -0400 |
commit | df632d3ce7eacf92ad9b642301c7b53a1d95b8d8 (patch) | |
tree | 848c39ed4f7cfdb582bf2e0a0a03147efaa5198d /fs/lockd | |
parent | 2474542f64432398f503373f53bdf620491bcfa8 (diff) | |
parent | af283885b70248268617955a5ea5476647bd556b (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.c | 86 | ||||
-rw-r--r-- | fs/lockd/netns.h | 4 | ||||
-rw-r--r-- | fs/lockd/svc.c | 1 |
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 | ||
45 | struct nsm_res { | 47 | struct 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 | ||
86 | static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, | 88 | static 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); | ||
111 | out: | ||
112 | return clnt; | ||
113 | } | ||
114 | |||
115 | 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 | |||
133 | static 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 | ||
17 | extern int lockd_net_id; | 21 | extern 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 | ||