aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
commit7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch)
treee730a4565e0318140d2fbd2f0415d18a339d7336 /fs/lockd
parent41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff)
parent0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff)
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/Makefile2
-rw-r--r--fs/lockd/clntlock.c13
-rw-r--r--fs/lockd/clntproc.c10
-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.c117
-rw-r--r--fs/lockd/svc4proc.c42
-rw-r--r--fs/lockd/svclock.c62
-rw-r--r--fs/lockd/svcproc.c42
-rw-r--r--fs/lockd/svcsubs.c32
-rw-r--r--fs/lockd/xdr.c2
-rw-r--r--fs/lockd/xdr4.c2
13 files changed, 462 insertions, 273 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/clntproc.c b/fs/lockd/clntproc.c
index 1f6dc518505c..31668b690e03 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -582,7 +582,15 @@ again:
582 } 582 }
583 if (status < 0) 583 if (status < 0)
584 goto out_unlock; 584 goto out_unlock;
585 status = nlm_stat_to_errno(resp->status); 585 /*
586 * EAGAIN doesn't make sense for sleeping locks, and in some
587 * cases NLM_LCK_DENIED is returned for a permanent error. So
588 * turn it into an ENOLCK.
589 */
590 if (resp->status == nlm_lck_denied && (fl_flags & FL_SLEEP))
591 status = -ENOLCK;
592 else
593 status = nlm_stat_to_errno(resp->status);
586out_unblock: 594out_unblock:
587 nlmclnt_finish_block(block); 595 nlmclnt_finish_block(block);
588out: 596out:
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 2169af4d5455..c631a83931ce 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -50,8 +50,7 @@ EXPORT_SYMBOL(nlmsvc_ops);
50static DEFINE_MUTEX(nlmsvc_mutex); 50static 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_serv *nlmsvc_serv; 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
@@ -194,43 +179,38 @@ lockd(void *vrqstp)
194 179
195 svc_process(rqstp); 180 svc_process(rqstp);
196 } 181 }
197
198 flush_signals(current); 182 flush_signals(current);
183 cancel_delayed_work_sync(&grace_period_end);
199 if (nlmsvc_ops) 184 if (nlmsvc_ops)
200 nlmsvc_invalidate_all(); 185 nlmsvc_invalidate_all();
201 nlm_shutdown_hosts(); 186 nlm_shutdown_hosts();
202
203 unlock_kernel(); 187 unlock_kernel();
204
205 nlmsvc_task = NULL;
206 nlmsvc_serv = NULL;
207
208 /* Exit the RPC thread */
209 svc_exit_thread(rqstp);
210
211 return 0; 188 return 0;
212} 189}
213 190
214/* 191/*
215 * Make any sockets that are needed but not present. 192 * Ensure there are active UDP and TCP listeners for lockd.
216 * If nlm_udpport or nlm_tcpport were set as module 193 *
217 * 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.
218 */ 200 */
219static int make_socks(struct svc_serv *serv, int proto) 201static int make_socks(struct svc_serv *serv)
220{ 202{
221 static int warned; 203 static int warned;
222 struct svc_xprt *xprt; 204 struct svc_xprt *xprt;
223 int err = 0; 205 int err = 0;
224 206
225 if (proto == IPPROTO_UDP || nlm_udpport) { 207 xprt = svc_find_xprt(serv, "udp", 0, 0);
226 xprt = svc_find_xprt(serv, "udp", 0, 0); 208 if (!xprt)
227 if (!xprt) 209 err = svc_create_xprt(serv, "udp", nlm_udpport,
228 err = svc_create_xprt(serv, "udp", nlm_udpport, 210 SVC_SOCK_DEFAULTS);
229 SVC_SOCK_DEFAULTS); 211 else
230 else 212 svc_xprt_put(xprt);
231 svc_xprt_put(xprt); 213 if (err >= 0) {
232 }
233 if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) {
234 xprt = svc_find_xprt(serv, "tcp", 0, 0); 214 xprt = svc_find_xprt(serv, "tcp", 0, 0);
235 if (!xprt) 215 if (!xprt)
236 err = svc_create_xprt(serv, "tcp", nlm_tcpport, 216 err = svc_create_xprt(serv, "tcp", nlm_tcpport,
@@ -250,22 +230,17 @@ static int make_socks(struct svc_serv *serv, int proto)
250/* 230/*
251 * Bring up the lockd process if it's not already up. 231 * Bring up the lockd process if it's not already up.
252 */ 232 */
253int 233int lockd_up(void)
254lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
255{ 234{
256 struct svc_serv *serv; 235 struct svc_serv *serv;
257 struct svc_rqst *rqstp;
258 int error = 0; 236 int error = 0;
259 237
260 mutex_lock(&nlmsvc_mutex); 238 mutex_lock(&nlmsvc_mutex);
261 /* 239 /*
262 * Check whether we're already up and running. 240 * Check whether we're already up and running.
263 */ 241 */
264 if (nlmsvc_serv) { 242 if (nlmsvc_rqst)
265 if (proto)
266 error = make_socks(nlmsvc_serv, proto);
267 goto out; 243 goto out;
268 }
269 244
270 /* 245 /*
271 * Sanity check: if there's no pid, 246 * Sanity check: if there's no pid,
@@ -276,21 +251,23 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
276 "lockd_up: no pid, %d users??\n", nlmsvc_users); 251 "lockd_up: no pid, %d users??\n", nlmsvc_users);
277 252
278 error = -ENOMEM; 253 error = -ENOMEM;
279 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); 254 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, AF_INET, NULL);
280 if (!serv) { 255 if (!serv) {
281 printk(KERN_WARNING "lockd_up: create service failed\n"); 256 printk(KERN_WARNING "lockd_up: create service failed\n");
282 goto out; 257 goto out;
283 } 258 }
284 259
285 if ((error = make_socks(serv, proto)) < 0) 260 error = make_socks(serv);
261 if (error < 0)
286 goto destroy_and_out; 262 goto destroy_and_out;
287 263
288 /* 264 /*
289 * Create the kernel thread and wait for it to start. 265 * Create the kernel thread and wait for it to start.
290 */ 266 */
291 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]); 267 nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
292 if (IS_ERR(rqstp)) { 268 if (IS_ERR(nlmsvc_rqst)) {
293 error = PTR_ERR(rqstp); 269 error = PTR_ERR(nlmsvc_rqst);
270 nlmsvc_rqst = NULL;
294 printk(KERN_WARNING 271 printk(KERN_WARNING
295 "lockd_up: svc_rqst allocation failed, error=%d\n", 272 "lockd_up: svc_rqst allocation failed, error=%d\n",
296 error); 273 error);
@@ -298,16 +275,15 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
298 } 275 }
299 276
300 svc_sock_update_bufs(serv); 277 svc_sock_update_bufs(serv);
301 nlmsvc_serv = rqstp->rq_server;
302 278
303 nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name); 279 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
304 if (IS_ERR(nlmsvc_task)) { 280 if (IS_ERR(nlmsvc_task)) {
305 error = PTR_ERR(nlmsvc_task); 281 error = PTR_ERR(nlmsvc_task);
282 svc_exit_thread(nlmsvc_rqst);
306 nlmsvc_task = NULL; 283 nlmsvc_task = NULL;
307 nlmsvc_serv = NULL; 284 nlmsvc_rqst = NULL;
308 printk(KERN_WARNING 285 printk(KERN_WARNING
309 "lockd_up: kthread_run failed, error=%d\n", error); 286 "lockd_up: kthread_run failed, error=%d\n", error);
310 svc_exit_thread(rqstp);
311 goto destroy_and_out; 287 goto destroy_and_out;
312 } 288 }
313 289
@@ -346,6 +322,9 @@ lockd_down(void)
346 BUG(); 322 BUG();
347 } 323 }
348 kthread_stop(nlmsvc_task); 324 kthread_stop(nlmsvc_task);
325 svc_exit_thread(nlmsvc_rqst);
326 nlmsvc_task = NULL;
327 nlmsvc_rqst = NULL;
349out: 328out:
350 mutex_unlock(&nlmsvc_mutex); 329 mutex_unlock(&nlmsvc_mutex);
351} 330}
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 2e27176ff42f..014f6ce48172 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -58,8 +58,7 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
58 return 0; 58 return 0;
59 59
60no_locks: 60no_locks:
61 if (host) 61 nlm_release_host(host);
62 nlm_release_host(host);
63 if (error) 62 if (error)
64 return error; 63 return error;
65 return nlm_lck_denied_nolocks; 64 return nlm_lck_denied_nolocks;
@@ -84,23 +83,17 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
84{ 83{
85 struct nlm_host *host; 84 struct nlm_host *host;
86 struct nlm_file *file; 85 struct nlm_file *file;
87 int rc = rpc_success; 86 __be32 rc = rpc_success;
88 87
89 dprintk("lockd: TEST4 called\n"); 88 dprintk("lockd: TEST4 called\n");
90 resp->cookie = argp->cookie; 89 resp->cookie = argp->cookie;
91 90
92 /* Don't accept test requests during grace period */
93 if (nlmsvc_grace_period) {
94 resp->status = nlm_lck_denied_grace_period;
95 return rc;
96 }
97
98 /* Obtain client and file */ 91 /* Obtain client and file */
99 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 92 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
100 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 93 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
101 94
102 /* Now check for conflicting locks */ 95 /* Now check for conflicting locks */
103 resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie); 96 resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
104 if (resp->status == nlm_drop_reply) 97 if (resp->status == nlm_drop_reply)
105 rc = rpc_drop_reply; 98 rc = rpc_drop_reply;
106 else 99 else
@@ -117,18 +110,12 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
117{ 110{
118 struct nlm_host *host; 111 struct nlm_host *host;
119 struct nlm_file *file; 112 struct nlm_file *file;
120 int rc = rpc_success; 113 __be32 rc = rpc_success;
121 114
122 dprintk("lockd: LOCK called\n"); 115 dprintk("lockd: LOCK called\n");
123 116
124 resp->cookie = argp->cookie; 117 resp->cookie = argp->cookie;
125 118
126 /* Don't accept new lock requests during grace period */
127 if (nlmsvc_grace_period && !argp->reclaim) {
128 resp->status = nlm_lck_denied_grace_period;
129 return rc;
130 }
131
132 /* Obtain client and file */ 119 /* Obtain client and file */
133 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 120 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
134 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 121 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -146,8 +133,9 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
146#endif 133#endif
147 134
148 /* Now try to lock the file */ 135 /* Now try to lock the file */
149 resp->status = nlmsvc_lock(rqstp, file, &argp->lock, 136 resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
150 argp->block, &argp->cookie); 137 argp->block, &argp->cookie,
138 argp->reclaim);
151 if (resp->status == nlm_drop_reply) 139 if (resp->status == nlm_drop_reply)
152 rc = rpc_drop_reply; 140 rc = rpc_drop_reply;
153 else 141 else
@@ -170,7 +158,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
170 resp->cookie = argp->cookie; 158 resp->cookie = argp->cookie;
171 159
172 /* Don't accept requests during grace period */ 160 /* Don't accept requests during grace period */
173 if (nlmsvc_grace_period) { 161 if (locks_in_grace()) {
174 resp->status = nlm_lck_denied_grace_period; 162 resp->status = nlm_lck_denied_grace_period;
175 return rpc_success; 163 return rpc_success;
176 } 164 }
@@ -203,7 +191,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
203 resp->cookie = argp->cookie; 191 resp->cookie = argp->cookie;
204 192
205 /* Don't accept new lock requests during grace period */ 193 /* Don't accept new lock requests during grace period */
206 if (nlmsvc_grace_period) { 194 if (locks_in_grace()) {
207 resp->status = nlm_lck_denied_grace_period; 195 resp->status = nlm_lck_denied_grace_period;
208 return rpc_success; 196 return rpc_success;
209 } 197 }
@@ -232,7 +220,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
232 resp->cookie = argp->cookie; 220 resp->cookie = argp->cookie;
233 221
234 dprintk("lockd: GRANTED called\n"); 222 dprintk("lockd: GRANTED called\n");
235 resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); 223 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
236 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 224 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
237 return rpc_success; 225 return rpc_success;
238} 226}
@@ -342,7 +330,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
342 resp->cookie = argp->cookie; 330 resp->cookie = argp->cookie;
343 331
344 /* Don't accept new lock requests during grace period */ 332 /* Don't accept new lock requests during grace period */
345 if (nlmsvc_grace_period && !argp->reclaim) { 333 if (locks_in_grace() && !argp->reclaim) {
346 resp->status = nlm_lck_denied_grace_period; 334 resp->status = nlm_lck_denied_grace_period;
347 return rpc_success; 335 return rpc_success;
348 } 336 }
@@ -375,7 +363,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
375 resp->cookie = argp->cookie; 363 resp->cookie = argp->cookie;
376 364
377 /* Don't accept requests during grace period */ 365 /* Don't accept requests during grace period */
378 if (nlmsvc_grace_period) { 366 if (locks_in_grace()) {
379 resp->status = nlm_lck_denied_grace_period; 367 resp->status = nlm_lck_denied_grace_period;
380 return rpc_success; 368 return rpc_success;
381 } 369 }
@@ -433,11 +421,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
433{ 421{
434 struct sockaddr_in saddr; 422 struct sockaddr_in saddr;
435 423
436 memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
437
438 dprintk("lockd: SM_NOTIFY called\n"); 424 dprintk("lockd: SM_NOTIFY called\n");
439 if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 425
440 || ntohs(saddr.sin_port) >= 1024) { 426 if (!nlm_privileged_requester(rqstp)) {
441 char buf[RPC_MAX_ADDRBUFLEN]; 427 char buf[RPC_MAX_ADDRBUFLEN];
442 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 428 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
443 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 56a08ab9a4cb..6063a8e4b9f3 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -129,9 +129,9 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
129 129
130static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b) 130static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
131{ 131{
132 if(a->len != b->len) 132 if (a->len != b->len)
133 return 0; 133 return 0;
134 if(memcmp(a->data,b->data,a->len)) 134 if (memcmp(a->data, b->data, a->len))
135 return 0; 135 return 0;
136 return 1; 136 return 1;
137} 137}
@@ -180,6 +180,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
180 struct nlm_block *block; 180 struct nlm_block *block;
181 struct nlm_rqst *call = NULL; 181 struct nlm_rqst *call = NULL;
182 182
183 nlm_get_host(host);
183 call = nlm_alloc_call(host); 184 call = nlm_alloc_call(host);
184 if (call == NULL) 185 if (call == NULL)
185 return NULL; 186 return NULL;
@@ -358,10 +359,10 @@ nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
358 */ 359 */
359__be32 360__be32
360nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, 361nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
361 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) 362 struct nlm_host *host, struct nlm_lock *lock, int wait,
363 struct nlm_cookie *cookie, int reclaim)
362{ 364{
363 struct nlm_block *block = NULL; 365 struct nlm_block *block = NULL;
364 struct nlm_host *host;
365 int error; 366 int error;
366 __be32 ret; 367 __be32 ret;
367 368
@@ -373,11 +374,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
373 (long long)lock->fl.fl_end, 374 (long long)lock->fl.fl_end,
374 wait); 375 wait);
375 376
376 /* Create host handle for callback */
377 host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len);
378 if (host == NULL)
379 return nlm_lck_denied_nolocks;
380
381 /* Lock file against concurrent access */ 377 /* Lock file against concurrent access */
382 mutex_lock(&file->f_mutex); 378 mutex_lock(&file->f_mutex);
383 /* Get existing block (in case client is busy-waiting) 379 /* Get existing block (in case client is busy-waiting)
@@ -385,8 +381,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
385 */ 381 */
386 block = nlmsvc_lookup_block(file, lock); 382 block = nlmsvc_lookup_block(file, lock);
387 if (block == NULL) { 383 if (block == NULL) {
388 block = nlmsvc_create_block(rqstp, nlm_get_host(host), file, 384 block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
389 lock, cookie);
390 ret = nlm_lck_denied_nolocks; 385 ret = nlm_lck_denied_nolocks;
391 if (block == NULL) 386 if (block == NULL)
392 goto out; 387 goto out;
@@ -411,20 +406,29 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
411 goto out; 406 goto out;
412 } 407 }
413 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
414 if (!wait) 418 if (!wait)
415 lock->fl.fl_flags &= ~FL_SLEEP; 419 lock->fl.fl_flags &= ~FL_SLEEP;
416 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);
417 lock->fl.fl_flags &= ~FL_SLEEP; 421 lock->fl.fl_flags &= ~FL_SLEEP;
418 422
419 dprintk("lockd: vfs_lock_file returned %d\n", error); 423 dprintk("lockd: vfs_lock_file returned %d\n", error);
420 switch(error) { 424 switch (error) {
421 case 0: 425 case 0:
422 ret = nlm_granted; 426 ret = nlm_granted;
423 goto out; 427 goto out;
424 case -EAGAIN: 428 case -EAGAIN:
425 ret = nlm_lck_denied; 429 ret = nlm_lck_denied;
426 break; 430 goto out;
427 case -EINPROGRESS: 431 case FILE_LOCK_DEFERRED:
428 if (wait) 432 if (wait)
429 break; 433 break;
430 /* Filesystem lock operation is in progress 434 /* Filesystem lock operation is in progress
@@ -439,10 +443,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
439 goto out; 443 goto out;
440 } 444 }
441 445
442 ret = nlm_lck_denied;
443 if (!wait)
444 goto out;
445
446 ret = nlm_lck_blocked; 446 ret = nlm_lck_blocked;
447 447
448 /* Append to list of blocked */ 448 /* Append to list of blocked */
@@ -450,7 +450,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
450out: 450out:
451 mutex_unlock(&file->f_mutex); 451 mutex_unlock(&file->f_mutex);
452 nlmsvc_release_block(block); 452 nlmsvc_release_block(block);
453 nlm_release_host(host);
454 dprintk("lockd: nlmsvc_lock returned %u\n", ret); 453 dprintk("lockd: nlmsvc_lock returned %u\n", ret);
455 return ret; 454 return ret;
456} 455}
@@ -460,8 +459,8 @@ out:
460 */ 459 */
461__be32 460__be32
462nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, 461nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
463 struct nlm_lock *lock, struct nlm_lock *conflock, 462 struct nlm_host *host, struct nlm_lock *lock,
464 struct nlm_cookie *cookie) 463 struct nlm_lock *conflock, struct nlm_cookie *cookie)
465{ 464{
466 struct nlm_block *block = NULL; 465 struct nlm_block *block = NULL;
467 int error; 466 int error;
@@ -479,16 +478,9 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
479 478
480 if (block == NULL) { 479 if (block == NULL) {
481 struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL); 480 struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
482 struct nlm_host *host;
483 481
484 if (conf == NULL) 482 if (conf == NULL)
485 return nlm_granted; 483 return nlm_granted;
486 /* Create host handle for callback */
487 host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len);
488 if (host == NULL) {
489 kfree(conf);
490 return nlm_lck_denied_nolocks;
491 }
492 block = nlmsvc_create_block(rqstp, host, file, lock, cookie); 484 block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
493 if (block == NULL) { 485 if (block == NULL) {
494 kfree(conf); 486 kfree(conf);
@@ -519,8 +511,12 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
519 goto out; 511 goto out;
520 } 512 }
521 513
514 if (locks_in_grace()) {
515 ret = nlm_lck_denied_grace_period;
516 goto out;
517 }
522 error = vfs_test_lock(file->f_file, &lock->fl); 518 error = vfs_test_lock(file->f_file, &lock->fl);
523 if (error == -EINPROGRESS) { 519 if (error == FILE_LOCK_DEFERRED) {
524 ret = nlmsvc_defer_lock_rqst(rqstp, block); 520 ret = nlmsvc_defer_lock_rqst(rqstp, block);
525 goto out; 521 goto out;
526 } 522 }
@@ -599,6 +595,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
599 (long long)lock->fl.fl_start, 595 (long long)lock->fl.fl_start,
600 (long long)lock->fl.fl_end); 596 (long long)lock->fl.fl_end);
601 597
598 if (locks_in_grace())
599 return nlm_lck_denied_grace_period;
600
602 mutex_lock(&file->f_mutex); 601 mutex_lock(&file->f_mutex);
603 block = nlmsvc_lookup_block(file, lock); 602 block = nlmsvc_lookup_block(file, lock);
604 mutex_unlock(&file->f_mutex); 603 mutex_unlock(&file->f_mutex);
@@ -744,8 +743,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
744 switch (error) { 743 switch (error) {
745 case 0: 744 case 0:
746 break; 745 break;
747 case -EAGAIN: 746 case FILE_LOCK_DEFERRED:
748 case -EINPROGRESS:
749 dprintk("lockd: lock still blocked error %d\n", error); 747 dprintk("lockd: lock still blocked error %d\n", error);
750 nlmsvc_insert_block(block, NLM_NEVER); 748 nlmsvc_insert_block(block, NLM_NEVER);
751 nlmsvc_release_block(block); 749 nlmsvc_release_block(block);
@@ -897,7 +895,7 @@ nlmsvc_retry_blocked(void)
897 895
898 if (block->b_when == NLM_NEVER) 896 if (block->b_when == NLM_NEVER)
899 break; 897 break;
900 if (time_after(block->b_when,jiffies)) { 898 if (time_after(block->b_when, jiffies)) {
901 timeout = block->b_when - jiffies; 899 timeout = block->b_when - jiffies;
902 break; 900 break;
903 } 901 }
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index ce6952b50a75..548b0bb2b84d 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -87,8 +87,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
87 return 0; 87 return 0;
88 88
89no_locks: 89no_locks:
90 if (host) 90 nlm_release_host(host);
91 nlm_release_host(host);
92 if (error) 91 if (error)
93 return error; 92 return error;
94 return nlm_lck_denied_nolocks; 93 return nlm_lck_denied_nolocks;
@@ -113,23 +112,17 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
113{ 112{
114 struct nlm_host *host; 113 struct nlm_host *host;
115 struct nlm_file *file; 114 struct nlm_file *file;
116 int rc = rpc_success; 115 __be32 rc = rpc_success;
117 116
118 dprintk("lockd: TEST called\n"); 117 dprintk("lockd: TEST called\n");
119 resp->cookie = argp->cookie; 118 resp->cookie = argp->cookie;
120 119
121 /* Don't accept test requests during grace period */
122 if (nlmsvc_grace_period) {
123 resp->status = nlm_lck_denied_grace_period;
124 return rc;
125 }
126
127 /* Obtain client and file */ 120 /* Obtain client and file */
128 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 121 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
129 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 122 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
130 123
131 /* Now check for conflicting locks */ 124 /* Now check for conflicting locks */
132 resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie)); 125 resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
133 if (resp->status == nlm_drop_reply) 126 if (resp->status == nlm_drop_reply)
134 rc = rpc_drop_reply; 127 rc = rpc_drop_reply;
135 else 128 else
@@ -147,18 +140,12 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
147{ 140{
148 struct nlm_host *host; 141 struct nlm_host *host;
149 struct nlm_file *file; 142 struct nlm_file *file;
150 int rc = rpc_success; 143 __be32 rc = rpc_success;
151 144
152 dprintk("lockd: LOCK called\n"); 145 dprintk("lockd: LOCK called\n");
153 146
154 resp->cookie = argp->cookie; 147 resp->cookie = argp->cookie;
155 148
156 /* Don't accept new lock requests during grace period */
157 if (nlmsvc_grace_period && !argp->reclaim) {
158 resp->status = nlm_lck_denied_grace_period;
159 return rc;
160 }
161
162 /* Obtain client and file */ 149 /* Obtain client and file */
163 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 150 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
164 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 151 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -176,8 +163,9 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
176#endif 163#endif
177 164
178 /* Now try to lock the file */ 165 /* Now try to lock the file */
179 resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, 166 resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
180 argp->block, &argp->cookie)); 167 argp->block, &argp->cookie,
168 argp->reclaim));
181 if (resp->status == nlm_drop_reply) 169 if (resp->status == nlm_drop_reply)
182 rc = rpc_drop_reply; 170 rc = rpc_drop_reply;
183 else 171 else
@@ -200,7 +188,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
200 resp->cookie = argp->cookie; 188 resp->cookie = argp->cookie;
201 189
202 /* Don't accept requests during grace period */ 190 /* Don't accept requests during grace period */
203 if (nlmsvc_grace_period) { 191 if (locks_in_grace()) {
204 resp->status = nlm_lck_denied_grace_period; 192 resp->status = nlm_lck_denied_grace_period;
205 return rpc_success; 193 return rpc_success;
206 } 194 }
@@ -233,7 +221,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
233 resp->cookie = argp->cookie; 221 resp->cookie = argp->cookie;
234 222
235 /* Don't accept new lock requests during grace period */ 223 /* Don't accept new lock requests during grace period */
236 if (nlmsvc_grace_period) { 224 if (locks_in_grace()) {
237 resp->status = nlm_lck_denied_grace_period; 225 resp->status = nlm_lck_denied_grace_period;
238 return rpc_success; 226 return rpc_success;
239 } 227 }
@@ -262,7 +250,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
262 resp->cookie = argp->cookie; 250 resp->cookie = argp->cookie;
263 251
264 dprintk("lockd: GRANTED called\n"); 252 dprintk("lockd: GRANTED called\n");
265 resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); 253 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
266 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 254 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
267 return rpc_success; 255 return rpc_success;
268} 256}
@@ -374,7 +362,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
374 resp->cookie = argp->cookie; 362 resp->cookie = argp->cookie;
375 363
376 /* Don't accept new lock requests during grace period */ 364 /* Don't accept new lock requests during grace period */
377 if (nlmsvc_grace_period && !argp->reclaim) { 365 if (locks_in_grace() && !argp->reclaim) {
378 resp->status = nlm_lck_denied_grace_period; 366 resp->status = nlm_lck_denied_grace_period;
379 return rpc_success; 367 return rpc_success;
380 } 368 }
@@ -407,7 +395,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
407 resp->cookie = argp->cookie; 395 resp->cookie = argp->cookie;
408 396
409 /* Don't accept requests during grace period */ 397 /* Don't accept requests during grace period */
410 if (nlmsvc_grace_period) { 398 if (locks_in_grace()) {
411 resp->status = nlm_lck_denied_grace_period; 399 resp->status = nlm_lck_denied_grace_period;
412 return rpc_success; 400 return rpc_success;
413 } 401 }
@@ -465,11 +453,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
465{ 453{
466 struct sockaddr_in saddr; 454 struct sockaddr_in saddr;
467 455
468 memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
469
470 dprintk("lockd: SM_NOTIFY called\n"); 456 dprintk("lockd: SM_NOTIFY called\n");
471 if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 457
472 || ntohs(saddr.sin_port) >= 1024) { 458 if (!nlm_privileged_requester(rqstp)) {
473 char buf[RPC_MAX_ADDRBUFLEN]; 459 char buf[RPC_MAX_ADDRBUFLEN];
474 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 460 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
475 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 d1c48b539df8..34c2766e27c7 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -373,13 +373,16 @@ nlmsvc_free_host_resources(struct nlm_host *host)
373 } 373 }
374} 374}
375 375
376/* 376/**
377 * Remove all locks held for clients 377 * nlmsvc_invalidate_all - remove all locks held for clients
378 *
379 * Release all locks held by NFS clients.
380 *
378 */ 381 */
379void 382void
380nlmsvc_invalidate_all(void) 383nlmsvc_invalidate_all(void)
381{ 384{
382 /* Release all locks held by NFS clients. 385 /*
383 * Previously, the code would call 386 * Previously, the code would call
384 * nlmsvc_free_host_resources for each client in 387 * nlmsvc_free_host_resources for each client in
385 * turn, which is about as inefficient as it gets. 388 * turn, which is about as inefficient as it gets.
@@ -396,6 +399,12 @@ nlmsvc_match_sb(void *datap, struct nlm_file *file)
396 return sb == file->f_file->f_path.mnt->mnt_sb; 399 return sb == file->f_file->f_path.mnt->mnt_sb;
397} 400}
398 401
402/**
403 * nlmsvc_unlock_all_by_sb - release locks held on this file system
404 * @sb: super block
405 *
406 * Release all locks held by clients accessing this file system.
407 */
399int 408int
400nlmsvc_unlock_all_by_sb(struct super_block *sb) 409nlmsvc_unlock_all_by_sb(struct super_block *sb)
401{ 410{
@@ -409,17 +418,22 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
409static int 418static int
410nlmsvc_match_ip(void *datap, struct nlm_host *host) 419nlmsvc_match_ip(void *datap, struct nlm_host *host)
411{ 420{
412 __be32 *server_addr = datap; 421 return nlm_cmp_addr(nlm_srcaddr(host), datap);
413
414 return host->h_saddr.sin_addr.s_addr == *server_addr;
415} 422}
416 423
424/**
425 * nlmsvc_unlock_all_by_ip - release local locks by IP address
426 * @server_addr: server's IP address as seen by clients
427 *
428 * Release all locks held by clients accessing this host
429 * via the passed in IP address.
430 */
417int 431int
418nlmsvc_unlock_all_by_ip(__be32 server_addr) 432nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr)
419{ 433{
420 int ret; 434 int ret;
421 ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL);
422 return ret ? -EIO : 0;
423 435
436 ret = nlm_traverse_files(server_addr, nlmsvc_match_ip, NULL);
437 return ret ? -EIO : 0;
424} 438}
425EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip); 439EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);
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