aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/Makefile2
-rw-r--r--fs/lockd/clntlock.c13
-rw-r--r--fs/lockd/grace.c59
-rw-r--r--fs/lockd/host.c350
-rw-r--r--fs/lockd/mon.c2
-rw-r--r--fs/lockd/svc.c88
-rw-r--r--fs/lockd/svc4proc.c31
-rw-r--r--fs/lockd/svclock.c18
-rw-r--r--fs/lockd/svcproc.c31
-rw-r--r--fs/lockd/svcsubs.c2
-rw-r--r--fs/lockd/xdr.c2
-rw-r--r--fs/lockd/xdr4.c2
12 files changed, 397 insertions, 203 deletions
diff --git a/fs/lockd/Makefile b/fs/lockd/Makefile
index 7725a0a9a555..97f6073ab339 100644
--- a/fs/lockd/Makefile
+++ b/fs/lockd/Makefile
@@ -5,6 +5,6 @@
5obj-$(CONFIG_LOCKD) += lockd.o 5obj-$(CONFIG_LOCKD) += lockd.o
6 6
7lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \ 7lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \
8 svcproc.o svcsubs.o mon.o xdr.o 8 svcproc.o svcsubs.o mon.o xdr.o grace.o
9lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o 9lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o
10lockd-objs := $(lockd-objs-y) 10lockd-objs := $(lockd-objs-y)
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 0b45fd3a4bfd..8307dd64bf46 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -54,14 +54,13 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
54 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; 54 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4;
55 int status; 55 int status;
56 56
57 status = lockd_up(nlm_init->protocol); 57 status = lockd_up();
58 if (status < 0) 58 if (status < 0)
59 return ERR_PTR(status); 59 return ERR_PTR(status);
60 60
61 host = nlmclnt_lookup_host((struct sockaddr_in *)nlm_init->address, 61 host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen,
62 nlm_init->protocol, nlm_version, 62 nlm_init->protocol, nlm_version,
63 nlm_init->hostname, 63 nlm_init->hostname);
64 strlen(nlm_init->hostname));
65 if (host == NULL) { 64 if (host == NULL) {
66 lockd_down(); 65 lockd_down();
67 return ERR_PTR(-ENOLCK); 66 return ERR_PTR(-ENOLCK);
@@ -142,7 +141,7 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
142/* 141/*
143 * The server lockd has called us back to tell us the lock was granted 142 * The server lockd has called us back to tell us the lock was granted
144 */ 143 */
145__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) 144__be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
146{ 145{
147 const struct file_lock *fl = &lock->fl; 146 const struct file_lock *fl = &lock->fl;
148 const struct nfs_fh *fh = &lock->fh; 147 const struct nfs_fh *fh = &lock->fh;
@@ -166,7 +165,7 @@ __be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock
166 */ 165 */
167 if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) 166 if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
168 continue; 167 continue;
169 if (!nlm_cmp_addr(&block->b_host->h_addr, addr)) 168 if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
170 continue; 169 continue;
171 if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) 170 if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
172 continue; 171 continue;
@@ -216,7 +215,7 @@ reclaimer(void *ptr)
216 /* This one ensures that our parent doesn't terminate while the 215 /* This one ensures that our parent doesn't terminate while the
217 * reclaim is in progress */ 216 * reclaim is in progress */
218 lock_kernel(); 217 lock_kernel();
219 lockd_up(0); /* note: this cannot fail as lockd is already running */ 218 lockd_up(); /* note: this cannot fail as lockd is already running */
220 219
221 dprintk("lockd: reclaiming locks for host %s\n", host->h_name); 220 dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
222 221
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c
new file mode 100644
index 000000000000..183cc1f0af1c
--- /dev/null
+++ b/fs/lockd/grace.c
@@ -0,0 +1,59 @@
1/*
2 * Common code for control of lockd and nfsv4 grace periods.
3 */
4
5#include <linux/module.h>
6#include <linux/lockd/bind.h>
7
8static LIST_HEAD(grace_list);
9static DEFINE_SPINLOCK(grace_lock);
10
11/**
12 * locks_start_grace
13 * @lm: who this grace period is for
14 *
15 * A grace period is a period during which locks should not be given
16 * out. Currently grace periods are only enforced by the two lock
17 * managers (lockd and nfsd), using the locks_in_grace() function to
18 * check when they are in a grace period.
19 *
20 * This function is called to start a grace period.
21 */
22void locks_start_grace(struct lock_manager *lm)
23{
24 spin_lock(&grace_lock);
25 list_add(&lm->list, &grace_list);
26 spin_unlock(&grace_lock);
27}
28EXPORT_SYMBOL_GPL(locks_start_grace);
29
30/**
31 * locks_end_grace
32 * @lm: who this grace period is for
33 *
34 * Call this function to state that the given lock manager is ready to
35 * resume regular locking. The grace period will not end until all lock
36 * managers that called locks_start_grace() also call locks_end_grace().
37 * Note that callers count on it being safe to call this more than once,
38 * and the second call should be a no-op.
39 */
40void locks_end_grace(struct lock_manager *lm)
41{
42 spin_lock(&grace_lock);
43 list_del_init(&lm->list);
44 spin_unlock(&grace_lock);
45}
46EXPORT_SYMBOL_GPL(locks_end_grace);
47
48/**
49 * locks_in_grace
50 *
51 * Lock managers call this function to determine when it is OK for them
52 * to answer ordinary lock requests, and when they should accept only
53 * lock reclaims.
54 */
55int locks_in_grace(void)
56{
57 return !list_empty(&grace_list);
58}
59EXPORT_SYMBOL_GPL(locks_in_grace);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index a17664c7eacc..9fd8889097b7 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -11,16 +11,17 @@
11#include <linux/types.h> 11#include <linux/types.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/in.h> 13#include <linux/in.h>
14#include <linux/in6.h>
14#include <linux/sunrpc/clnt.h> 15#include <linux/sunrpc/clnt.h>
15#include <linux/sunrpc/svc.h> 16#include <linux/sunrpc/svc.h>
16#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
17#include <linux/lockd/sm_inter.h> 18#include <linux/lockd/sm_inter.h>
18#include <linux/mutex.h> 19#include <linux/mutex.h>
19 20
21#include <net/ipv6.h>
20 22
21#define NLMDBG_FACILITY NLMDBG_HOSTCACHE 23#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
22#define NLM_HOST_NRHASH 32 24#define NLM_HOST_NRHASH 32
23#define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
24#define NLM_HOST_REBIND (60 * HZ) 25#define NLM_HOST_REBIND (60 * HZ)
25#define NLM_HOST_EXPIRE (300 * HZ) 26#define NLM_HOST_EXPIRE (300 * HZ)
26#define NLM_HOST_COLLECT (120 * HZ) 27#define NLM_HOST_COLLECT (120 * HZ)
@@ -30,42 +31,115 @@ static unsigned long next_gc;
30static int nrhosts; 31static int nrhosts;
31static DEFINE_MUTEX(nlm_host_mutex); 32static DEFINE_MUTEX(nlm_host_mutex);
32 33
33
34static void nlm_gc_hosts(void); 34static void nlm_gc_hosts(void);
35static struct nsm_handle * __nsm_find(const struct sockaddr_in *, 35static struct nsm_handle *nsm_find(const struct sockaddr *sap,
36 const char *, unsigned int, int); 36 const size_t salen,
37static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, 37 const char *hostname,
38 const char *hostname, 38 const size_t hostname_len,
39 unsigned int hostname_len); 39 const int create);
40
41struct nlm_lookup_host_info {
42 const int server; /* search for server|client */
43 const struct sockaddr *sap; /* address to search for */
44 const size_t salen; /* it's length */
45 const unsigned short protocol; /* transport to search for*/
46 const u32 version; /* NLM version to search for */
47 const char *hostname; /* remote's hostname */
48 const size_t hostname_len; /* it's length */
49 const struct sockaddr *src_sap; /* our address (optional) */
50 const size_t src_len; /* it's length */
51};
52
53/*
54 * Hash function must work well on big- and little-endian platforms
55 */
56static unsigned int __nlm_hash32(const __be32 n)
57{
58 unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16);
59 return hash ^ (hash >> 8);
60}
61
62static unsigned int __nlm_hash_addr4(const struct sockaddr *sap)
63{
64 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
65 return __nlm_hash32(sin->sin_addr.s_addr);
66}
67
68static unsigned int __nlm_hash_addr6(const struct sockaddr *sap)
69{
70 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
71 const struct in6_addr addr = sin6->sin6_addr;
72 return __nlm_hash32(addr.s6_addr32[0]) ^
73 __nlm_hash32(addr.s6_addr32[1]) ^
74 __nlm_hash32(addr.s6_addr32[2]) ^
75 __nlm_hash32(addr.s6_addr32[3]);
76}
77
78static unsigned int nlm_hash_address(const struct sockaddr *sap)
79{
80 unsigned int hash;
81
82 switch (sap->sa_family) {
83 case AF_INET:
84 hash = __nlm_hash_addr4(sap);
85 break;
86 case AF_INET6:
87 hash = __nlm_hash_addr6(sap);
88 break;
89 default:
90 hash = 0;
91 }
92 return hash & (NLM_HOST_NRHASH - 1);
93}
94
95static void nlm_clear_port(struct sockaddr *sap)
96{
97 switch (sap->sa_family) {
98 case AF_INET:
99 ((struct sockaddr_in *)sap)->sin_port = 0;
100 break;
101 case AF_INET6:
102 ((struct sockaddr_in6 *)sap)->sin6_port = 0;
103 break;
104 }
105}
106
107static void nlm_display_address(const struct sockaddr *sap,
108 char *buf, const size_t len)
109{
110 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
111 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
112
113 switch (sap->sa_family) {
114 case AF_UNSPEC:
115 snprintf(buf, len, "unspecified");
116 break;
117 case AF_INET:
118 snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
119 break;
120 case AF_INET6:
121 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
122 snprintf(buf, len, NIPQUAD_FMT,
123 NIPQUAD(sin6->sin6_addr.s6_addr32[3]));
124 else
125 snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr));
126 break;
127 default:
128 snprintf(buf, len, "unsupported address family");
129 break;
130 }
131}
40 132
41/* 133/*
42 * Common host lookup routine for server & client 134 * Common host lookup routine for server & client
43 */ 135 */
44static struct nlm_host *nlm_lookup_host(int server, 136static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
45 const struct sockaddr_in *sin,
46 int proto, u32 version,
47 const char *hostname,
48 unsigned int hostname_len,
49 const struct sockaddr_in *ssin)
50{ 137{
51 struct hlist_head *chain; 138 struct hlist_head *chain;
52 struct hlist_node *pos; 139 struct hlist_node *pos;
53 struct nlm_host *host; 140 struct nlm_host *host;
54 struct nsm_handle *nsm = NULL; 141 struct nsm_handle *nsm = NULL;
55 int hash;
56
57 dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
58 ", p=%d, v=%u, my role=%s, name=%.*s)\n",
59 NIPQUAD(ssin->sin_addr.s_addr),
60 NIPQUAD(sin->sin_addr.s_addr), proto, version,
61 server? "server" : "client",
62 hostname_len,
63 hostname? hostname : "<none>");
64 142
65
66 hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
67
68 /* Lock hash table */
69 mutex_lock(&nlm_host_mutex); 143 mutex_lock(&nlm_host_mutex);
70 144
71 if (time_after_eq(jiffies, next_gc)) 145 if (time_after_eq(jiffies, next_gc))
@@ -78,22 +152,22 @@ static struct nlm_host *nlm_lookup_host(int server,
78 * different NLM rpc_clients into one single nlm_host object. 152 * different NLM rpc_clients into one single nlm_host object.
79 * This would allow us to have one nlm_host per address. 153 * This would allow us to have one nlm_host per address.
80 */ 154 */
81 chain = &nlm_hosts[hash]; 155 chain = &nlm_hosts[nlm_hash_address(ni->sap)];
82 hlist_for_each_entry(host, pos, chain, h_hash) { 156 hlist_for_each_entry(host, pos, chain, h_hash) {
83 if (!nlm_cmp_addr(&host->h_addr, sin)) 157 if (!nlm_cmp_addr(nlm_addr(host), ni->sap))
84 continue; 158 continue;
85 159
86 /* See if we have an NSM handle for this client */ 160 /* See if we have an NSM handle for this client */
87 if (!nsm) 161 if (!nsm)
88 nsm = host->h_nsmhandle; 162 nsm = host->h_nsmhandle;
89 163
90 if (host->h_proto != proto) 164 if (host->h_proto != ni->protocol)
91 continue; 165 continue;
92 if (host->h_version != version) 166 if (host->h_version != ni->version)
93 continue; 167 continue;
94 if (host->h_server != server) 168 if (host->h_server != ni->server)
95 continue; 169 continue;
96 if (!nlm_cmp_addr(&host->h_saddr, ssin)) 170 if (!nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap))
97 continue; 171 continue;
98 172
99 /* Move to head of hash chain. */ 173 /* Move to head of hash chain. */
@@ -101,30 +175,41 @@ static struct nlm_host *nlm_lookup_host(int server,
101 hlist_add_head(&host->h_hash, chain); 175 hlist_add_head(&host->h_hash, chain);
102 176
103 nlm_get_host(host); 177 nlm_get_host(host);
178 dprintk("lockd: nlm_lookup_host found host %s (%s)\n",
179 host->h_name, host->h_addrbuf);
104 goto out; 180 goto out;
105 } 181 }
106 if (nsm)
107 atomic_inc(&nsm->sm_count);
108
109 host = NULL;
110 182
111 /* Sadly, the host isn't in our hash table yet. See if 183 /*
112 * we have an NSM handle for it. If not, create one. 184 * The host wasn't in our hash table. If we don't
185 * have an NSM handle for it yet, create one.
113 */ 186 */
114 if (!nsm && !(nsm = nsm_find(sin, hostname, hostname_len))) 187 if (nsm)
115 goto out; 188 atomic_inc(&nsm->sm_count);
189 else {
190 host = NULL;
191 nsm = nsm_find(ni->sap, ni->salen,
192 ni->hostname, ni->hostname_len, 1);
193 if (!nsm) {
194 dprintk("lockd: nlm_lookup_host failed; "
195 "no nsm handle\n");
196 goto out;
197 }
198 }
116 199
117 host = kzalloc(sizeof(*host), GFP_KERNEL); 200 host = kzalloc(sizeof(*host), GFP_KERNEL);
118 if (!host) { 201 if (!host) {
119 nsm_release(nsm); 202 nsm_release(nsm);
203 dprintk("lockd: nlm_lookup_host failed; no memory\n");
120 goto out; 204 goto out;
121 } 205 }
122 host->h_name = nsm->sm_name; 206 host->h_name = nsm->sm_name;
123 host->h_addr = *sin; 207 memcpy(nlm_addr(host), ni->sap, ni->salen);
124 host->h_addr.sin_port = 0; /* ouch! */ 208 host->h_addrlen = ni->salen;
125 host->h_saddr = *ssin; 209 nlm_clear_port(nlm_addr(host));
126 host->h_version = version; 210 memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len);
127 host->h_proto = proto; 211 host->h_version = ni->version;
212 host->h_proto = ni->protocol;
128 host->h_rpcclnt = NULL; 213 host->h_rpcclnt = NULL;
129 mutex_init(&host->h_mutex); 214 mutex_init(&host->h_mutex);
130 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 215 host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -135,7 +220,7 @@ static struct nlm_host *nlm_lookup_host(int server,
135 host->h_state = 0; /* pseudo NSM state */ 220 host->h_state = 0; /* pseudo NSM state */
136 host->h_nsmstate = 0; /* real NSM state */ 221 host->h_nsmstate = 0; /* real NSM state */
137 host->h_nsmhandle = nsm; 222 host->h_nsmhandle = nsm;
138 host->h_server = server; 223 host->h_server = ni->server;
139 hlist_add_head(&host->h_hash, chain); 224 hlist_add_head(&host->h_hash, chain);
140 INIT_LIST_HEAD(&host->h_lockowners); 225 INIT_LIST_HEAD(&host->h_lockowners);
141 spin_lock_init(&host->h_lock); 226 spin_lock_init(&host->h_lock);
@@ -143,6 +228,15 @@ static struct nlm_host *nlm_lookup_host(int server,
143 INIT_LIST_HEAD(&host->h_reclaim); 228 INIT_LIST_HEAD(&host->h_reclaim);
144 229
145 nrhosts++; 230 nrhosts++;
231
232 nlm_display_address((struct sockaddr *)&host->h_addr,
233 host->h_addrbuf, sizeof(host->h_addrbuf));
234 nlm_display_address((struct sockaddr *)&host->h_srcaddr,
235 host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf));
236
237 dprintk("lockd: nlm_lookup_host created host %s\n",
238 host->h_name);
239
146out: 240out:
147 mutex_unlock(&nlm_host_mutex); 241 mutex_unlock(&nlm_host_mutex);
148 return host; 242 return host;
@@ -170,33 +264,103 @@ nlm_destroy_host(struct nlm_host *host)
170 kfree(host); 264 kfree(host);
171} 265}
172 266
173/* 267/**
174 * Find an NLM server handle in the cache. If there is none, create it. 268 * nlmclnt_lookup_host - Find an NLM host handle matching a remote server
269 * @sap: network address of server
270 * @salen: length of server address
271 * @protocol: transport protocol to use
272 * @version: NLM protocol version
273 * @hostname: '\0'-terminated hostname of server
274 *
275 * Returns an nlm_host structure that matches the passed-in
276 * [server address, transport protocol, NLM version, server hostname].
277 * If one doesn't already exist in the host cache, a new handle is
278 * created and returned.
175 */ 279 */
176struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin, 280struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
177 int proto, u32 version, 281 const size_t salen,
178 const char *hostname, 282 const unsigned short protocol,
179 unsigned int hostname_len) 283 const u32 version, const char *hostname)
180{ 284{
181 struct sockaddr_in ssin = {0}; 285 const struct sockaddr source = {
182 286 .sa_family = AF_UNSPEC,
183 return nlm_lookup_host(0, sin, proto, version, 287 };
184 hostname, hostname_len, &ssin); 288 struct nlm_lookup_host_info ni = {
289 .server = 0,
290 .sap = sap,
291 .salen = salen,
292 .protocol = protocol,
293 .version = version,
294 .hostname = hostname,
295 .hostname_len = strlen(hostname),
296 .src_sap = &source,
297 .src_len = sizeof(source),
298 };
299
300 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
301 (hostname ? hostname : "<none>"), version,
302 (protocol == IPPROTO_UDP ? "udp" : "tcp"));
303
304 return nlm_lookup_host(&ni);
185} 305}
186 306
187/* 307/**
188 * Find an NLM client handle in the cache. If there is none, create it. 308 * nlmsvc_lookup_host - Find an NLM host handle matching a remote client
309 * @rqstp: incoming NLM request
310 * @hostname: name of client host
311 * @hostname_len: length of client hostname
312 *
313 * Returns an nlm_host structure that matches the [client address,
314 * transport protocol, NLM version, client hostname] of the passed-in
315 * NLM request. If one doesn't already exist in the host cache, a
316 * new handle is created and returned.
317 *
318 * Before possibly creating a new nlm_host, construct a sockaddr
319 * for a specific source address in case the local system has
320 * multiple network addresses. The family of the address in
321 * rq_daddr is guaranteed to be the same as the family of the
322 * address in rq_addr, so it's safe to use the same family for
323 * the source address.
189 */ 324 */
190struct nlm_host * 325struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
191nlmsvc_lookup_host(struct svc_rqst *rqstp, 326 const char *hostname,
192 const char *hostname, unsigned int hostname_len) 327 const size_t hostname_len)
193{ 328{
194 struct sockaddr_in ssin = {0}; 329 struct sockaddr_in sin = {
330 .sin_family = AF_INET,
331 };
332 struct sockaddr_in6 sin6 = {
333 .sin6_family = AF_INET6,
334 };
335 struct nlm_lookup_host_info ni = {
336 .server = 1,
337 .sap = svc_addr(rqstp),
338 .salen = rqstp->rq_addrlen,
339 .protocol = rqstp->rq_prot,
340 .version = rqstp->rq_vers,
341 .hostname = hostname,
342 .hostname_len = hostname_len,
343 .src_len = rqstp->rq_addrlen,
344 };
345
346 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
347 (int)hostname_len, hostname, rqstp->rq_vers,
348 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
349
350 switch (ni.sap->sa_family) {
351 case AF_INET:
352 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
353 ni.src_sap = (struct sockaddr *)&sin;
354 break;
355 case AF_INET6:
356 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
357 ni.src_sap = (struct sockaddr *)&sin6;
358 break;
359 default:
360 return NULL;
361 }
195 362
196 ssin.sin_addr = rqstp->rq_daddr.addr; 363 return nlm_lookup_host(&ni);
197 return nlm_lookup_host(1, svc_addr_in(rqstp),
198 rqstp->rq_prot, rqstp->rq_vers,
199 hostname, hostname_len, &ssin);
200} 364}
201 365
202/* 366/*
@@ -207,9 +371,8 @@ nlm_bind_host(struct nlm_host *host)
207{ 371{
208 struct rpc_clnt *clnt; 372 struct rpc_clnt *clnt;
209 373
210 dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n", 374 dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n",
211 NIPQUAD(host->h_saddr.sin_addr), 375 host->h_name, host->h_addrbuf, host->h_srcaddrbuf);
212 NIPQUAD(host->h_addr.sin_addr));
213 376
214 /* Lock host handle */ 377 /* Lock host handle */
215 mutex_lock(&host->h_mutex); 378 mutex_lock(&host->h_mutex);
@@ -221,7 +384,7 @@ nlm_bind_host(struct nlm_host *host)
221 if (time_after_eq(jiffies, host->h_nextrebind)) { 384 if (time_after_eq(jiffies, host->h_nextrebind)) {
222 rpc_force_rebind(clnt); 385 rpc_force_rebind(clnt);
223 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 386 host->h_nextrebind = jiffies + NLM_HOST_REBIND;
224 dprintk("lockd: next rebind in %ld jiffies\n", 387 dprintk("lockd: next rebind in %lu jiffies\n",
225 host->h_nextrebind - jiffies); 388 host->h_nextrebind - jiffies);
226 } 389 }
227 } else { 390 } else {
@@ -234,9 +397,9 @@ nlm_bind_host(struct nlm_host *host)
234 }; 397 };
235 struct rpc_create_args args = { 398 struct rpc_create_args args = {
236 .protocol = host->h_proto, 399 .protocol = host->h_proto,
237 .address = (struct sockaddr *)&host->h_addr, 400 .address = nlm_addr(host),
238 .addrsize = sizeof(host->h_addr), 401 .addrsize = host->h_addrlen,
239 .saddress = (struct sockaddr *)&host->h_saddr, 402 .saddress = nlm_srcaddr(host),
240 .timeout = &timeparms, 403 .timeout = &timeparms,
241 .servername = host->h_name, 404 .servername = host->h_name,
242 .program = &nlm_program, 405 .program = &nlm_program,
@@ -324,12 +487,16 @@ void nlm_host_rebooted(const struct sockaddr_in *sin,
324 struct nsm_handle *nsm; 487 struct nsm_handle *nsm;
325 struct nlm_host *host; 488 struct nlm_host *host;
326 489
327 dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n", 490 nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin),
328 hostname, NIPQUAD(sin->sin_addr)); 491 hostname, hostname_len, 0);
329 492 if (nsm == NULL) {
330 /* Find the NSM handle for this peer */ 493 dprintk("lockd: never saw rebooted peer '%.*s' before\n",
331 if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0))) 494 hostname_len, hostname);
332 return; 495 return;
496 }
497
498 dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n",
499 hostname_len, hostname, nsm->sm_addrbuf);
333 500
334 /* When reclaiming locks on this peer, make sure that 501 /* When reclaiming locks on this peer, make sure that
335 * we set up a new notification */ 502 * we set up a new notification */
@@ -461,22 +628,23 @@ nlm_gc_hosts(void)
461static LIST_HEAD(nsm_handles); 628static LIST_HEAD(nsm_handles);
462static DEFINE_SPINLOCK(nsm_lock); 629static DEFINE_SPINLOCK(nsm_lock);
463 630
464static struct nsm_handle * 631static struct nsm_handle *nsm_find(const struct sockaddr *sap,
465__nsm_find(const struct sockaddr_in *sin, 632 const size_t salen,
466 const char *hostname, unsigned int hostname_len, 633 const char *hostname,
467 int create) 634 const size_t hostname_len,
635 const int create)
468{ 636{
469 struct nsm_handle *nsm = NULL; 637 struct nsm_handle *nsm = NULL;
470 struct nsm_handle *pos; 638 struct nsm_handle *pos;
471 639
472 if (!sin) 640 if (!sap)
473 return NULL; 641 return NULL;
474 642
475 if (hostname && memchr(hostname, '/', hostname_len) != NULL) { 643 if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
476 if (printk_ratelimit()) { 644 if (printk_ratelimit()) {
477 printk(KERN_WARNING "Invalid hostname \"%.*s\" " 645 printk(KERN_WARNING "Invalid hostname \"%.*s\" "
478 "in NFS lock request\n", 646 "in NFS lock request\n",
479 hostname_len, hostname); 647 (int)hostname_len, hostname);
480 } 648 }
481 return NULL; 649 return NULL;
482 } 650 }
@@ -489,7 +657,7 @@ retry:
489 if (strlen(pos->sm_name) != hostname_len 657 if (strlen(pos->sm_name) != hostname_len
490 || memcmp(pos->sm_name, hostname, hostname_len)) 658 || memcmp(pos->sm_name, hostname, hostname_len))
491 continue; 659 continue;
492 } else if (!nlm_cmp_addr(&pos->sm_addr, sin)) 660 } else if (!nlm_cmp_addr(nsm_addr(pos), sap))
493 continue; 661 continue;
494 atomic_inc(&pos->sm_count); 662 atomic_inc(&pos->sm_count);
495 kfree(nsm); 663 kfree(nsm);
@@ -509,10 +677,13 @@ retry:
509 if (nsm == NULL) 677 if (nsm == NULL)
510 return NULL; 678 return NULL;
511 679
512 nsm->sm_addr = *sin; 680 memcpy(nsm_addr(nsm), sap, salen);
681 nsm->sm_addrlen = salen;
513 nsm->sm_name = (char *) (nsm + 1); 682 nsm->sm_name = (char *) (nsm + 1);
514 memcpy(nsm->sm_name, hostname, hostname_len); 683 memcpy(nsm->sm_name, hostname, hostname_len);
515 nsm->sm_name[hostname_len] = '\0'; 684 nsm->sm_name[hostname_len] = '\0';
685 nlm_display_address((struct sockaddr *)&nsm->sm_addr,
686 nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
516 atomic_set(&nsm->sm_count, 1); 687 atomic_set(&nsm->sm_count, 1);
517 goto retry; 688 goto retry;
518 689
@@ -521,13 +692,6 @@ found:
521 return nsm; 692 return nsm;
522} 693}
523 694
524static struct nsm_handle *
525nsm_find(const struct sockaddr_in *sin, const char *hostname,
526 unsigned int hostname_len)
527{
528 return __nsm_find(sin, hostname, hostname_len, 1);
529}
530
531/* 695/*
532 * Release an NSM handle 696 * Release an NSM handle
533 */ 697 */
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index e4d563543b11..4e7e958e8f67 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -51,7 +51,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
51 51
52 memset(&args, 0, sizeof(args)); 52 memset(&args, 0, sizeof(args));
53 args.mon_name = nsm->sm_name; 53 args.mon_name = nsm->sm_name;
54 args.addr = nsm->sm_addr.sin_addr.s_addr; 54 args.addr = nsm_addr_in(nsm)->sin_addr.s_addr;
55 args.prog = NLM_PROGRAM; 55 args.prog = NLM_PROGRAM;
56 args.vers = 3; 56 args.vers = 3;
57 args.proc = NLMPROC_NSM_NOTIFY; 57 args.proc = NLMPROC_NSM_NOTIFY;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 5bd9bf0fa9df..c631a83931ce 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -51,7 +51,6 @@ static DEFINE_MUTEX(nlmsvc_mutex);
51static unsigned int nlmsvc_users; 51static unsigned int nlmsvc_users;
52static struct task_struct *nlmsvc_task; 52static struct task_struct *nlmsvc_task;
53static struct svc_rqst *nlmsvc_rqst; 53static struct svc_rqst *nlmsvc_rqst;
54int nlmsvc_grace_period;
55unsigned long nlmsvc_timeout; 54unsigned long nlmsvc_timeout;
56 55
57/* 56/*
@@ -85,27 +84,23 @@ static unsigned long get_lockd_grace_period(void)
85 return nlm_timeout * 5 * HZ; 84 return nlm_timeout * 5 * HZ;
86} 85}
87 86
88unsigned long get_nfs_grace_period(void) 87static struct lock_manager lockd_manager = {
89{ 88};
90 unsigned long lockdgrace = get_lockd_grace_period();
91 unsigned long nfsdgrace = 0;
92
93 if (nlmsvc_ops)
94 nfsdgrace = nlmsvc_ops->get_grace_period();
95
96 return max(lockdgrace, nfsdgrace);
97}
98EXPORT_SYMBOL(get_nfs_grace_period);
99 89
100static unsigned long set_grace_period(void) 90static void grace_ender(struct work_struct *not_used)
101{ 91{
102 nlmsvc_grace_period = 1; 92 locks_end_grace(&lockd_manager);
103 return get_nfs_grace_period() + jiffies;
104} 93}
105 94
106static inline void clear_grace_period(void) 95static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
96
97static void set_grace_period(void)
107{ 98{
108 nlmsvc_grace_period = 0; 99 unsigned long grace_period = get_lockd_grace_period();
100
101 locks_start_grace(&lockd_manager);
102 cancel_delayed_work_sync(&grace_period_end);
103 schedule_delayed_work(&grace_period_end, grace_period);
109} 104}
110 105
111/* 106/*
@@ -116,7 +111,6 @@ lockd(void *vrqstp)
116{ 111{
117 int err = 0, preverr = 0; 112 int err = 0, preverr = 0;
118 struct svc_rqst *rqstp = vrqstp; 113 struct svc_rqst *rqstp = vrqstp;
119 unsigned long grace_period_expire;
120 114
121 /* try_to_freeze() is called from svc_recv() */ 115 /* try_to_freeze() is called from svc_recv() */
122 set_freezable(); 116 set_freezable();
@@ -139,7 +133,7 @@ lockd(void *vrqstp)
139 nlm_timeout = LOCKD_DFLT_TIMEO; 133 nlm_timeout = LOCKD_DFLT_TIMEO;
140 nlmsvc_timeout = nlm_timeout * HZ; 134 nlmsvc_timeout = nlm_timeout * HZ;
141 135
142 grace_period_expire = set_grace_period(); 136 set_grace_period();
143 137
144 /* 138 /*
145 * The main request loop. We don't terminate until the last 139 * The main request loop. We don't terminate until the last
@@ -153,21 +147,12 @@ lockd(void *vrqstp)
153 flush_signals(current); 147 flush_signals(current);
154 if (nlmsvc_ops) { 148 if (nlmsvc_ops) {
155 nlmsvc_invalidate_all(); 149 nlmsvc_invalidate_all();
156 grace_period_expire = set_grace_period(); 150 set_grace_period();
157 } 151 }
158 continue; 152 continue;
159 } 153 }
160 154
161 /* 155 timeout = nlmsvc_retry_blocked();
162 * Retry any blocked locks that have been notified by
163 * the VFS. Don't do this during grace period.
164 * (Theoretically, there shouldn't even be blocked locks
165 * during grace period).
166 */
167 if (!nlmsvc_grace_period) {
168 timeout = nlmsvc_retry_blocked();
169 } else if (time_before(grace_period_expire, jiffies))
170 clear_grace_period();
171 156
172 /* 157 /*
173 * Find a socket with data available and call its 158 * Find a socket with data available and call its
@@ -195,6 +180,7 @@ lockd(void *vrqstp)
195 svc_process(rqstp); 180 svc_process(rqstp);
196 } 181 }
197 flush_signals(current); 182 flush_signals(current);
183 cancel_delayed_work_sync(&grace_period_end);
198 if (nlmsvc_ops) 184 if (nlmsvc_ops)
199 nlmsvc_invalidate_all(); 185 nlmsvc_invalidate_all();
200 nlm_shutdown_hosts(); 186 nlm_shutdown_hosts();
@@ -203,25 +189,28 @@ lockd(void *vrqstp)
203} 189}
204 190
205/* 191/*
206 * Make any sockets that are needed but not present. 192 * Ensure there are active UDP and TCP listeners for lockd.
207 * If nlm_udpport or nlm_tcpport were set as module 193 *
208 * options, make those sockets unconditionally 194 * Even if we have only TCP NFS mounts and/or TCP NFSDs, some
195 * local services (such as rpc.statd) still require UDP, and
196 * some NFS servers do not yet support NLM over TCP.
197 *
198 * Returns zero if all listeners are available; otherwise a
199 * negative errno value is returned.
209 */ 200 */
210static int make_socks(struct svc_serv *serv, int proto) 201static int make_socks(struct svc_serv *serv)
211{ 202{
212 static int warned; 203 static int warned;
213 struct svc_xprt *xprt; 204 struct svc_xprt *xprt;
214 int err = 0; 205 int err = 0;
215 206
216 if (proto == IPPROTO_UDP || nlm_udpport) { 207 xprt = svc_find_xprt(serv, "udp", 0, 0);
217 xprt = svc_find_xprt(serv, "udp", 0, 0); 208 if (!xprt)
218 if (!xprt) 209 err = svc_create_xprt(serv, "udp", nlm_udpport,
219 err = svc_create_xprt(serv, "udp", nlm_udpport, 210 SVC_SOCK_DEFAULTS);
220 SVC_SOCK_DEFAULTS); 211 else
221 else 212 svc_xprt_put(xprt);
222 svc_xprt_put(xprt); 213 if (err >= 0) {
223 }
224 if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) {
225 xprt = svc_find_xprt(serv, "tcp", 0, 0); 214 xprt = svc_find_xprt(serv, "tcp", 0, 0);
226 if (!xprt) 215 if (!xprt)
227 err = svc_create_xprt(serv, "tcp", nlm_tcpport, 216 err = svc_create_xprt(serv, "tcp", nlm_tcpport,
@@ -241,8 +230,7 @@ static int make_socks(struct svc_serv *serv, int proto)
241/* 230/*
242 * Bring up the lockd process if it's not already up. 231 * Bring up the lockd process if it's not already up.
243 */ 232 */
244int 233int lockd_up(void)
245lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
246{ 234{
247 struct svc_serv *serv; 235 struct svc_serv *serv;
248 int error = 0; 236 int error = 0;
@@ -251,11 +239,8 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
251 /* 239 /*
252 * Check whether we're already up and running. 240 * Check whether we're already up and running.
253 */ 241 */
254 if (nlmsvc_rqst) { 242 if (nlmsvc_rqst)
255 if (proto)
256 error = make_socks(nlmsvc_rqst->rq_server, proto);
257 goto out; 243 goto out;
258 }
259 244
260 /* 245 /*
261 * Sanity check: if there's no pid, 246 * Sanity check: if there's no pid,
@@ -266,13 +251,14 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
266 "lockd_up: no pid, %d users??\n", nlmsvc_users); 251 "lockd_up: no pid, %d users??\n", nlmsvc_users);
267 252
268 error = -ENOMEM; 253 error = -ENOMEM;
269 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); 254 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, AF_INET, NULL);
270 if (!serv) { 255 if (!serv) {
271 printk(KERN_WARNING "lockd_up: create service failed\n"); 256 printk(KERN_WARNING "lockd_up: create service failed\n");
272 goto out; 257 goto out;
273 } 258 }
274 259
275 if ((error = make_socks(serv, proto)) < 0) 260 error = make_socks(serv);
261 if (error < 0)
276 goto destroy_and_out; 262 goto destroy_and_out;
277 263
278 /* 264 /*
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 4a714f64515b..014f6ce48172 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -88,12 +88,6 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
88 dprintk("lockd: TEST4 called\n"); 88 dprintk("lockd: TEST4 called\n");
89 resp->cookie = argp->cookie; 89 resp->cookie = argp->cookie;
90 90
91 /* Don't accept test requests during grace period */
92 if (nlmsvc_grace_period) {
93 resp->status = nlm_lck_denied_grace_period;
94 return rc;
95 }
96
97 /* Obtain client and file */ 91 /* Obtain client and file */
98 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 92 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
99 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 93 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -122,12 +116,6 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
122 116
123 resp->cookie = argp->cookie; 117 resp->cookie = argp->cookie;
124 118
125 /* Don't accept new lock requests during grace period */
126 if (nlmsvc_grace_period && !argp->reclaim) {
127 resp->status = nlm_lck_denied_grace_period;
128 return rc;
129 }
130
131 /* Obtain client and file */ 119 /* Obtain client and file */
132 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 120 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
133 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 121 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -146,7 +134,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
146 134
147 /* Now try to lock the file */ 135 /* Now try to lock the file */
148 resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock, 136 resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
149 argp->block, &argp->cookie); 137 argp->block, &argp->cookie,
138 argp->reclaim);
150 if (resp->status == nlm_drop_reply) 139 if (resp->status == nlm_drop_reply)
151 rc = rpc_drop_reply; 140 rc = rpc_drop_reply;
152 else 141 else
@@ -169,7 +158,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
169 resp->cookie = argp->cookie; 158 resp->cookie = argp->cookie;
170 159
171 /* Don't accept requests during grace period */ 160 /* Don't accept requests during grace period */
172 if (nlmsvc_grace_period) { 161 if (locks_in_grace()) {
173 resp->status = nlm_lck_denied_grace_period; 162 resp->status = nlm_lck_denied_grace_period;
174 return rpc_success; 163 return rpc_success;
175 } 164 }
@@ -202,7 +191,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
202 resp->cookie = argp->cookie; 191 resp->cookie = argp->cookie;
203 192
204 /* Don't accept new lock requests during grace period */ 193 /* Don't accept new lock requests during grace period */
205 if (nlmsvc_grace_period) { 194 if (locks_in_grace()) {
206 resp->status = nlm_lck_denied_grace_period; 195 resp->status = nlm_lck_denied_grace_period;
207 return rpc_success; 196 return rpc_success;
208 } 197 }
@@ -231,7 +220,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
231 resp->cookie = argp->cookie; 220 resp->cookie = argp->cookie;
232 221
233 dprintk("lockd: GRANTED called\n"); 222 dprintk("lockd: GRANTED called\n");
234 resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); 223 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
235 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 224 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
236 return rpc_success; 225 return rpc_success;
237} 226}
@@ -341,7 +330,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
341 resp->cookie = argp->cookie; 330 resp->cookie = argp->cookie;
342 331
343 /* Don't accept new lock requests during grace period */ 332 /* Don't accept new lock requests during grace period */
344 if (nlmsvc_grace_period && !argp->reclaim) { 333 if (locks_in_grace() && !argp->reclaim) {
345 resp->status = nlm_lck_denied_grace_period; 334 resp->status = nlm_lck_denied_grace_period;
346 return rpc_success; 335 return rpc_success;
347 } 336 }
@@ -374,7 +363,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
374 resp->cookie = argp->cookie; 363 resp->cookie = argp->cookie;
375 364
376 /* Don't accept requests during grace period */ 365 /* Don't accept requests during grace period */
377 if (nlmsvc_grace_period) { 366 if (locks_in_grace()) {
378 resp->status = nlm_lck_denied_grace_period; 367 resp->status = nlm_lck_denied_grace_period;
379 return rpc_success; 368 return rpc_success;
380 } 369 }
@@ -432,11 +421,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
432{ 421{
433 struct sockaddr_in saddr; 422 struct sockaddr_in saddr;
434 423
435 memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
436
437 dprintk("lockd: SM_NOTIFY called\n"); 424 dprintk("lockd: SM_NOTIFY called\n");
438 if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 425
439 || ntohs(saddr.sin_port) >= 1024) { 426 if (!nlm_privileged_requester(rqstp)) {
440 char buf[RPC_MAX_ADDRBUFLEN]; 427 char buf[RPC_MAX_ADDRBUFLEN];
441 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 428 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
442 svc_print_addr(rqstp, buf, sizeof(buf))); 429 svc_print_addr(rqstp, buf, sizeof(buf)));
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index cf0d5c2c318d..6063a8e4b9f3 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -360,7 +360,7 @@ nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
360__be32 360__be32
361nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, 361nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
362 struct nlm_host *host, struct nlm_lock *lock, int wait, 362 struct nlm_host *host, struct nlm_lock *lock, int wait,
363 struct nlm_cookie *cookie) 363 struct nlm_cookie *cookie, int reclaim)
364{ 364{
365 struct nlm_block *block = NULL; 365 struct nlm_block *block = NULL;
366 int error; 366 int error;
@@ -406,6 +406,15 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
406 goto out; 406 goto out;
407 } 407 }
408 408
409 if (locks_in_grace() && !reclaim) {
410 ret = nlm_lck_denied_grace_period;
411 goto out;
412 }
413 if (reclaim && !locks_in_grace()) {
414 ret = nlm_lck_denied_grace_period;
415 goto out;
416 }
417
409 if (!wait) 418 if (!wait)
410 lock->fl.fl_flags &= ~FL_SLEEP; 419 lock->fl.fl_flags &= ~FL_SLEEP;
411 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); 420 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
@@ -502,6 +511,10 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
502 goto out; 511 goto out;
503 } 512 }
504 513
514 if (locks_in_grace()) {
515 ret = nlm_lck_denied_grace_period;
516 goto out;
517 }
505 error = vfs_test_lock(file->f_file, &lock->fl); 518 error = vfs_test_lock(file->f_file, &lock->fl);
506 if (error == FILE_LOCK_DEFERRED) { 519 if (error == FILE_LOCK_DEFERRED) {
507 ret = nlmsvc_defer_lock_rqst(rqstp, block); 520 ret = nlmsvc_defer_lock_rqst(rqstp, block);
@@ -582,6 +595,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
582 (long long)lock->fl.fl_start, 595 (long long)lock->fl.fl_start,
583 (long long)lock->fl.fl_end); 596 (long long)lock->fl.fl_end);
584 597
598 if (locks_in_grace())
599 return nlm_lck_denied_grace_period;
600
585 mutex_lock(&file->f_mutex); 601 mutex_lock(&file->f_mutex);
586 block = nlmsvc_lookup_block(file, lock); 602 block = nlmsvc_lookup_block(file, lock);
587 mutex_unlock(&file->f_mutex); 603 mutex_unlock(&file->f_mutex);
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 76262c1986f2..548b0bb2b84d 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -117,12 +117,6 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
117 dprintk("lockd: TEST called\n"); 117 dprintk("lockd: TEST called\n");
118 resp->cookie = argp->cookie; 118 resp->cookie = argp->cookie;
119 119
120 /* Don't accept test requests during grace period */
121 if (nlmsvc_grace_period) {
122 resp->status = nlm_lck_denied_grace_period;
123 return rc;
124 }
125
126 /* Obtain client and file */ 120 /* Obtain client and file */
127 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 121 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
128 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 122 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -152,12 +146,6 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
152 146
153 resp->cookie = argp->cookie; 147 resp->cookie = argp->cookie;
154 148
155 /* Don't accept new lock requests during grace period */
156 if (nlmsvc_grace_period && !argp->reclaim) {
157 resp->status = nlm_lck_denied_grace_period;
158 return rc;
159 }
160
161 /* Obtain client and file */ 149 /* Obtain client and file */
162 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 150 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
163 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 151 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -176,7 +164,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
176 164
177 /* Now try to lock the file */ 165 /* Now try to lock the file */
178 resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock, 166 resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
179 argp->block, &argp->cookie)); 167 argp->block, &argp->cookie,
168 argp->reclaim));
180 if (resp->status == nlm_drop_reply) 169 if (resp->status == nlm_drop_reply)
181 rc = rpc_drop_reply; 170 rc = rpc_drop_reply;
182 else 171 else
@@ -199,7 +188,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
199 resp->cookie = argp->cookie; 188 resp->cookie = argp->cookie;
200 189
201 /* Don't accept requests during grace period */ 190 /* Don't accept requests during grace period */
202 if (nlmsvc_grace_period) { 191 if (locks_in_grace()) {
203 resp->status = nlm_lck_denied_grace_period; 192 resp->status = nlm_lck_denied_grace_period;
204 return rpc_success; 193 return rpc_success;
205 } 194 }
@@ -232,7 +221,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
232 resp->cookie = argp->cookie; 221 resp->cookie = argp->cookie;
233 222
234 /* Don't accept new lock requests during grace period */ 223 /* Don't accept new lock requests during grace period */
235 if (nlmsvc_grace_period) { 224 if (locks_in_grace()) {
236 resp->status = nlm_lck_denied_grace_period; 225 resp->status = nlm_lck_denied_grace_period;
237 return rpc_success; 226 return rpc_success;
238 } 227 }
@@ -261,7 +250,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
261 resp->cookie = argp->cookie; 250 resp->cookie = argp->cookie;
262 251
263 dprintk("lockd: GRANTED called\n"); 252 dprintk("lockd: GRANTED called\n");
264 resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); 253 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
265 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 254 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
266 return rpc_success; 255 return rpc_success;
267} 256}
@@ -373,7 +362,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
373 resp->cookie = argp->cookie; 362 resp->cookie = argp->cookie;
374 363
375 /* Don't accept new lock requests during grace period */ 364 /* Don't accept new lock requests during grace period */
376 if (nlmsvc_grace_period && !argp->reclaim) { 365 if (locks_in_grace() && !argp->reclaim) {
377 resp->status = nlm_lck_denied_grace_period; 366 resp->status = nlm_lck_denied_grace_period;
378 return rpc_success; 367 return rpc_success;
379 } 368 }
@@ -406,7 +395,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
406 resp->cookie = argp->cookie; 395 resp->cookie = argp->cookie;
407 396
408 /* Don't accept requests during grace period */ 397 /* Don't accept requests during grace period */
409 if (nlmsvc_grace_period) { 398 if (locks_in_grace()) {
410 resp->status = nlm_lck_denied_grace_period; 399 resp->status = nlm_lck_denied_grace_period;
411 return rpc_success; 400 return rpc_success;
412 } 401 }
@@ -464,11 +453,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
464{ 453{
465 struct sockaddr_in saddr; 454 struct sockaddr_in saddr;
466 455
467 memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
468
469 dprintk("lockd: SM_NOTIFY called\n"); 456 dprintk("lockd: SM_NOTIFY called\n");
470 if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 457
471 || ntohs(saddr.sin_port) >= 1024) { 458 if (!nlm_privileged_requester(rqstp)) {
472 char buf[RPC_MAX_ADDRBUFLEN]; 459 char buf[RPC_MAX_ADDRBUFLEN];
473 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 460 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
474 svc_print_addr(rqstp, buf, sizeof(buf))); 461 svc_print_addr(rqstp, buf, sizeof(buf)));
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 198b4e55b373..34c2766e27c7 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
418static int 418static int
419nlmsvc_match_ip(void *datap, struct nlm_host *host) 419nlmsvc_match_ip(void *datap, struct nlm_host *host)
420{ 420{
421 return nlm_cmp_addr(&host->h_saddr, datap); 421 return nlm_cmp_addr(nlm_srcaddr(host), datap);
422} 422}
423 423
424/** 424/**
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 3e459e18cc31..1f226290c67c 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -351,8 +351,6 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
351 argp->state = ntohl(*p++); 351 argp->state = ntohl(*p++);
352 /* Preserve the address in network byte order */ 352 /* Preserve the address in network byte order */
353 argp->addr = *p++; 353 argp->addr = *p++;
354 argp->vers = *p++;
355 argp->proto = *p++;
356 return xdr_argsize_check(rqstp, p); 354 return xdr_argsize_check(rqstp, p);
357} 355}
358 356
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 43ff9397e6c6..50c493a8ad8e 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -358,8 +358,6 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp
358 argp->state = ntohl(*p++); 358 argp->state = ntohl(*p++);
359 /* Preserve the address in network byte order */ 359 /* Preserve the address in network byte order */
360 argp->addr = *p++; 360 argp->addr = *p++;
361 argp->vers = *p++;
362 argp->proto = *p++;
363 return xdr_argsize_check(rqstp, p); 361 return xdr_argsize_check(rqstp, p);
364} 362}
365 363