aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/clntproc.c7
-rw-r--r--fs/lockd/host.c170
-rw-r--r--fs/lockd/mon.c569
-rw-r--r--fs/lockd/svc.c72
-rw-r--r--fs/lockd/svc4proc.c13
-rw-r--r--fs/lockd/svcproc.c13
-rw-r--r--fs/lockd/svcsubs.c1
-rw-r--r--fs/lockd/xdr.c5
-rw-r--r--fs/lockd/xdr4.c5
9 files changed, 497 insertions, 358 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 31668b690e03..dd7957064a8c 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -16,7 +16,6 @@
16#include <linux/sunrpc/clnt.h> 16#include <linux/sunrpc/clnt.h>
17#include <linux/sunrpc/svc.h> 17#include <linux/sunrpc/svc.h>
18#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
19#include <linux/lockd/sm_inter.h>
20 19
21#define NLMDBG_FACILITY NLMDBG_CLIENT 20#define NLMDBG_FACILITY NLMDBG_CLIENT
22#define NLMCLNT_GRACE_WAIT (5*HZ) 21#define NLMCLNT_GRACE_WAIT (5*HZ)
@@ -518,11 +517,9 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
518 unsigned char fl_type; 517 unsigned char fl_type;
519 int status = -ENOLCK; 518 int status = -ENOLCK;
520 519
521 if (nsm_monitor(host) < 0) { 520 if (nsm_monitor(host) < 0)
522 printk(KERN_NOTICE "lockd: failed to monitor %s\n",
523 host->h_name);
524 goto out; 521 goto out;
525 } 522
526 fl->fl_flags |= FL_ACCESS; 523 fl->fl_flags |= FL_ACCESS;
527 status = do_vfs_lock(fl); 524 status = do_vfs_lock(fl);
528 fl->fl_flags = fl_flags; 525 fl->fl_flags = fl_flags;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index abdebf76b820..99d737bd4325 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -15,7 +15,6 @@
15#include <linux/sunrpc/clnt.h> 15#include <linux/sunrpc/clnt.h>
16#include <linux/sunrpc/svc.h> 16#include <linux/sunrpc/svc.h>
17#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
18#include <linux/lockd/sm_inter.h>
19#include <linux/mutex.h> 18#include <linux/mutex.h>
20 19
21#include <net/ipv6.h> 20#include <net/ipv6.h>
@@ -32,11 +31,6 @@ static int nrhosts;
32static DEFINE_MUTEX(nlm_host_mutex); 31static DEFINE_MUTEX(nlm_host_mutex);
33 32
34static void nlm_gc_hosts(void); 33static void nlm_gc_hosts(void);
35static struct nsm_handle *nsm_find(const struct sockaddr *sap,
36 const size_t salen,
37 const char *hostname,
38 const size_t hostname_len,
39 const int create);
40 34
41struct nlm_lookup_host_info { 35struct nlm_lookup_host_info {
42 const int server; /* search for server|client */ 36 const int server; /* search for server|client */
@@ -105,32 +99,6 @@ static void nlm_clear_port(struct sockaddr *sap)
105 } 99 }
106} 100}
107 101
108static void nlm_display_address(const struct sockaddr *sap,
109 char *buf, const size_t len)
110{
111 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
112 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
113
114 switch (sap->sa_family) {
115 case AF_UNSPEC:
116 snprintf(buf, len, "unspecified");
117 break;
118 case AF_INET:
119 snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
120 break;
121 case AF_INET6:
122 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
123 snprintf(buf, len, "%pI4",
124 &sin6->sin6_addr.s6_addr32[3]);
125 else
126 snprintf(buf, len, "%pI6", &sin6->sin6_addr);
127 break;
128 default:
129 snprintf(buf, len, "unsupported address family");
130 break;
131 }
132}
133
134/* 102/*
135 * Common host lookup routine for server & client 103 * Common host lookup routine for server & client
136 */ 104 */
@@ -190,8 +158,8 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
190 atomic_inc(&nsm->sm_count); 158 atomic_inc(&nsm->sm_count);
191 else { 159 else {
192 host = NULL; 160 host = NULL;
193 nsm = nsm_find(ni->sap, ni->salen, 161 nsm = nsm_get_handle(ni->sap, ni->salen,
194 ni->hostname, ni->hostname_len, 1); 162 ni->hostname, ni->hostname_len);
195 if (!nsm) { 163 if (!nsm) {
196 dprintk("lockd: nlm_lookup_host failed; " 164 dprintk("lockd: nlm_lookup_host failed; "
197 "no nsm handle\n"); 165 "no nsm handle\n");
@@ -206,6 +174,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
206 goto out; 174 goto out;
207 } 175 }
208 host->h_name = nsm->sm_name; 176 host->h_name = nsm->sm_name;
177 host->h_addrbuf = nsm->sm_addrbuf;
209 memcpy(nlm_addr(host), ni->sap, ni->salen); 178 memcpy(nlm_addr(host), ni->sap, ni->salen);
210 host->h_addrlen = ni->salen; 179 host->h_addrlen = ni->salen;
211 nlm_clear_port(nlm_addr(host)); 180 nlm_clear_port(nlm_addr(host));
@@ -232,11 +201,6 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
232 201
233 nrhosts++; 202 nrhosts++;
234 203
235 nlm_display_address((struct sockaddr *)&host->h_addr,
236 host->h_addrbuf, sizeof(host->h_addrbuf));
237 nlm_display_address((struct sockaddr *)&host->h_srcaddr,
238 host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf));
239
240 dprintk("lockd: nlm_lookup_host created host %s\n", 204 dprintk("lockd: nlm_lookup_host created host %s\n",
241 host->h_name); 205 host->h_name);
242 206
@@ -256,10 +220,8 @@ nlm_destroy_host(struct nlm_host *host)
256 BUG_ON(!list_empty(&host->h_lockowners)); 220 BUG_ON(!list_empty(&host->h_lockowners));
257 BUG_ON(atomic_read(&host->h_count)); 221 BUG_ON(atomic_read(&host->h_count));
258 222
259 /*
260 * Release NSM handle and unmonitor host.
261 */
262 nsm_unmonitor(host); 223 nsm_unmonitor(host);
224 nsm_release(host->h_nsmhandle);
263 225
264 clnt = host->h_rpcclnt; 226 clnt = host->h_rpcclnt;
265 if (clnt != NULL) 227 if (clnt != NULL)
@@ -378,8 +340,8 @@ nlm_bind_host(struct nlm_host *host)
378{ 340{
379 struct rpc_clnt *clnt; 341 struct rpc_clnt *clnt;
380 342
381 dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", 343 dprintk("lockd: nlm_bind_host %s (%s)\n",
382 host->h_name, host->h_addrbuf, host->h_srcaddrbuf); 344 host->h_name, host->h_addrbuf);
383 345
384 /* Lock host handle */ 346 /* Lock host handle */
385 mutex_lock(&host->h_mutex); 347 mutex_lock(&host->h_mutex);
@@ -481,35 +443,23 @@ void nlm_release_host(struct nlm_host *host)
481 } 443 }
482} 444}
483 445
484/* 446/**
485 * We were notified that the host indicated by address &sin 447 * nlm_host_rebooted - Release all resources held by rebooted host
486 * has rebooted. 448 * @info: pointer to decoded results of NLM_SM_NOTIFY call
487 * Release all resources held by that peer. 449 *
450 * We were notified that the specified host has rebooted. Release
451 * all resources held by that peer.
488 */ 452 */
489void nlm_host_rebooted(const struct sockaddr_in *sin, 453void nlm_host_rebooted(const struct nlm_reboot *info)
490 const char *hostname,
491 unsigned int hostname_len,
492 u32 new_state)
493{ 454{
494 struct hlist_head *chain; 455 struct hlist_head *chain;
495 struct hlist_node *pos; 456 struct hlist_node *pos;
496 struct nsm_handle *nsm; 457 struct nsm_handle *nsm;
497 struct nlm_host *host; 458 struct nlm_host *host;
498 459
499 nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin), 460 nsm = nsm_reboot_lookup(info);
500 hostname, hostname_len, 0); 461 if (unlikely(nsm == NULL))
501 if (nsm == NULL) {
502 dprintk("lockd: never saw rebooted peer '%.*s' before\n",
503 hostname_len, hostname);
504 return; 462 return;
505 }
506
507 dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n",
508 hostname_len, hostname, nsm->sm_addrbuf);
509
510 /* When reclaiming locks on this peer, make sure that
511 * we set up a new notification */
512 nsm->sm_monitored = 0;
513 463
514 /* Mark all hosts tied to this NSM state as having rebooted. 464 /* Mark all hosts tied to this NSM state as having rebooted.
515 * We run the loop repeatedly, because we drop the host table 465 * We run the loop repeatedly, because we drop the host table
@@ -520,8 +470,8 @@ again: mutex_lock(&nlm_host_mutex);
520 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 470 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
521 hlist_for_each_entry(host, pos, chain, h_hash) { 471 hlist_for_each_entry(host, pos, chain, h_hash) {
522 if (host->h_nsmhandle == nsm 472 if (host->h_nsmhandle == nsm
523 && host->h_nsmstate != new_state) { 473 && host->h_nsmstate != info->state) {
524 host->h_nsmstate = new_state; 474 host->h_nsmstate = info->state;
525 host->h_state++; 475 host->h_state++;
526 476
527 nlm_get_host(host); 477 nlm_get_host(host);
@@ -629,89 +579,3 @@ nlm_gc_hosts(void)
629 579
630 next_gc = jiffies + NLM_HOST_COLLECT; 580 next_gc = jiffies + NLM_HOST_COLLECT;
631} 581}
632
633
634/*
635 * Manage NSM handles
636 */
637static LIST_HEAD(nsm_handles);
638static DEFINE_SPINLOCK(nsm_lock);
639
640static struct nsm_handle *nsm_find(const struct sockaddr *sap,
641 const size_t salen,
642 const char *hostname,
643 const size_t hostname_len,
644 const int create)
645{
646 struct nsm_handle *nsm = NULL;
647 struct nsm_handle *pos;
648
649 if (!sap)
650 return NULL;
651
652 if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
653 if (printk_ratelimit()) {
654 printk(KERN_WARNING "Invalid hostname \"%.*s\" "
655 "in NFS lock request\n",
656 (int)hostname_len, hostname);
657 }
658 return NULL;
659 }
660
661retry:
662 spin_lock(&nsm_lock);
663 list_for_each_entry(pos, &nsm_handles, sm_link) {
664
665 if (hostname && nsm_use_hostnames) {
666 if (strlen(pos->sm_name) != hostname_len
667 || memcmp(pos->sm_name, hostname, hostname_len))
668 continue;
669 } else if (!nlm_cmp_addr(nsm_addr(pos), sap))
670 continue;
671 atomic_inc(&pos->sm_count);
672 kfree(nsm);
673 nsm = pos;
674 goto found;
675 }
676 if (nsm) {
677 list_add(&nsm->sm_link, &nsm_handles);
678 goto found;
679 }
680 spin_unlock(&nsm_lock);
681
682 if (!create)
683 return NULL;
684
685 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
686 if (nsm == NULL)
687 return NULL;
688
689 memcpy(nsm_addr(nsm), sap, salen);
690 nsm->sm_addrlen = salen;
691 nsm->sm_name = (char *) (nsm + 1);
692 memcpy(nsm->sm_name, hostname, hostname_len);
693 nsm->sm_name[hostname_len] = '\0';
694 nlm_display_address((struct sockaddr *)&nsm->sm_addr,
695 nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
696 atomic_set(&nsm->sm_count, 1);
697 goto retry;
698
699found:
700 spin_unlock(&nsm_lock);
701 return nsm;
702}
703
704/*
705 * Release an NSM handle
706 */
707void
708nsm_release(struct nsm_handle *nsm)
709{
710 if (!nsm)
711 return;
712 if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
713 list_del(&nsm->sm_link);
714 spin_unlock(&nsm_lock);
715 kfree(nsm);
716 }
717}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index ffd3461f75ef..5e2c4d5ac827 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -9,35 +9,123 @@
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/utsname.h> 10#include <linux/utsname.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/ktime.h>
13
12#include <linux/sunrpc/clnt.h> 14#include <linux/sunrpc/clnt.h>
13#include <linux/sunrpc/xprtsock.h> 15#include <linux/sunrpc/xprtsock.h>
14#include <linux/sunrpc/svc.h> 16#include <linux/sunrpc/svc.h>
15#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
16#include <linux/lockd/sm_inter.h>
17
18 18
19#define NLMDBG_FACILITY NLMDBG_MONITOR 19#define NLMDBG_FACILITY NLMDBG_MONITOR
20#define NSM_PROGRAM 100024
21#define NSM_VERSION 1
22
23enum {
24 NSMPROC_NULL,
25 NSMPROC_STAT,
26 NSMPROC_MON,
27 NSMPROC_UNMON,
28 NSMPROC_UNMON_ALL,
29 NSMPROC_SIMU_CRASH,
30 NSMPROC_NOTIFY,
31};
32
33struct nsm_args {
34 struct nsm_private *priv;
35 u32 prog; /* RPC callback info */
36 u32 vers;
37 u32 proc;
20 38
21#define XDR_ADDRBUF_LEN (20) 39 char *mon_name;
40};
22 41
23static struct rpc_clnt * nsm_create(void); 42struct nsm_res {
43 u32 status;
44 u32 state;
45};
24 46
25static struct rpc_program nsm_program; 47static struct rpc_program nsm_program;
48static LIST_HEAD(nsm_handles);
49static DEFINE_SPINLOCK(nsm_lock);
26 50
27/* 51/*
28 * Local NSM state 52 * Local NSM state
29 */ 53 */
30int nsm_local_state; 54int __read_mostly nsm_local_state;
55int __read_mostly nsm_use_hostnames;
31 56
32/* 57static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
33 * Common procedure for SM_MON/SM_UNMON calls 58{
34 */ 59 return (struct sockaddr *)&nsm->sm_addr;
35static int 60}
36nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) 61
62static void nsm_display_ipv4_address(const struct sockaddr *sap, char *buf,
63 const size_t len)
64{
65 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
66 snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
67}
68
69static void nsm_display_ipv6_address(const struct sockaddr *sap, char *buf,
70 const size_t len)
71{
72 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
73
74 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
75 snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]);
76 else if (sin6->sin6_scope_id != 0)
77 snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr,
78 sin6->sin6_scope_id);
79 else
80 snprintf(buf, len, "%pI6", &sin6->sin6_addr);
81}
82
83static void nsm_display_address(const struct sockaddr *sap,
84 char *buf, const size_t len)
85{
86 switch (sap->sa_family) {
87 case AF_INET:
88 nsm_display_ipv4_address(sap, buf, len);
89 break;
90 case AF_INET6:
91 nsm_display_ipv6_address(sap, buf, len);
92 break;
93 default:
94 snprintf(buf, len, "unsupported address family");
95 break;
96 }
97}
98
99static struct rpc_clnt *nsm_create(void)
100{
101 struct sockaddr_in sin = {
102 .sin_family = AF_INET,
103 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
104 };
105 struct rpc_create_args args = {
106 .protocol = XPRT_TRANSPORT_UDP,
107 .address = (struct sockaddr *)&sin,
108 .addrsize = sizeof(sin),
109 .servername = "rpc.statd",
110 .program = &nsm_program,
111 .version = NSM_VERSION,
112 .authflavor = RPC_AUTH_NULL,
113 };
114
115 return rpc_create(&args);
116}
117
118static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
37{ 119{
38 struct rpc_clnt *clnt; 120 struct rpc_clnt *clnt;
39 int status; 121 int status;
40 struct nsm_args args; 122 struct nsm_args args = {
123 .priv = &nsm->sm_priv,
124 .prog = NLM_PROGRAM,
125 .vers = 3,
126 .proc = NLMPROC_NSM_NOTIFY,
127 .mon_name = nsm->sm_mon_name,
128 };
41 struct rpc_message msg = { 129 struct rpc_message msg = {
42 .rpc_argp = &args, 130 .rpc_argp = &args,
43 .rpc_resp = res, 131 .rpc_resp = res,
@@ -46,22 +134,18 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
46 clnt = nsm_create(); 134 clnt = nsm_create();
47 if (IS_ERR(clnt)) { 135 if (IS_ERR(clnt)) {
48 status = PTR_ERR(clnt); 136 status = PTR_ERR(clnt);
137 dprintk("lockd: failed to create NSM upcall transport, "
138 "status=%d\n", status);
49 goto out; 139 goto out;
50 } 140 }
51 141
52 memset(&args, 0, sizeof(args));
53 args.mon_name = nsm->sm_name;
54 args.addr = nsm_addr_in(nsm)->sin_addr.s_addr;
55 args.prog = NLM_PROGRAM;
56 args.vers = 3;
57 args.proc = NLMPROC_NSM_NOTIFY;
58 memset(res, 0, sizeof(*res)); 142 memset(res, 0, sizeof(*res));
59 143
60 msg.rpc_proc = &clnt->cl_procinfo[proc]; 144 msg.rpc_proc = &clnt->cl_procinfo[proc];
61 status = rpc_call_sync(clnt, &msg, 0); 145 status = rpc_call_sync(clnt, &msg, 0);
62 if (status < 0) 146 if (status < 0)
63 printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", 147 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
64 status); 148 status);
65 else 149 else
66 status = 0; 150 status = 0;
67 rpc_shutdown_client(clnt); 151 rpc_shutdown_client(clnt);
@@ -69,82 +153,272 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
69 return status; 153 return status;
70} 154}
71 155
72/* 156/**
73 * Set up monitoring of a remote host 157 * nsm_monitor - Notify a peer in case we reboot
158 * @host: pointer to nlm_host of peer to notify
159 *
160 * If this peer is not already monitored, this function sends an
161 * upcall to the local rpc.statd to record the name/address of
162 * the peer to notify in case we reboot.
163 *
164 * Returns zero if the peer is monitored by the local rpc.statd;
165 * otherwise a negative errno value is returned.
74 */ 166 */
75int 167int nsm_monitor(const struct nlm_host *host)
76nsm_monitor(struct nlm_host *host)
77{ 168{
78 struct nsm_handle *nsm = host->h_nsmhandle; 169 struct nsm_handle *nsm = host->h_nsmhandle;
79 struct nsm_res res; 170 struct nsm_res res;
80 int status; 171 int status;
81 172
82 dprintk("lockd: nsm_monitor(%s)\n", host->h_name); 173 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
83 BUG_ON(nsm == NULL);
84 174
85 if (nsm->sm_monitored) 175 if (nsm->sm_monitored)
86 return 0; 176 return 0;
87 177
88 status = nsm_mon_unmon(nsm, SM_MON, &res); 178 /*
179 * Choose whether to record the caller_name or IP address of
180 * this peer in the local rpc.statd's database.
181 */
182 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
89 183
90 if (status < 0 || res.status != 0) 184 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
91 printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); 185 if (res.status != 0)
186 status = -EIO;
187 if (status < 0)
188 printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
92 else 189 else
93 nsm->sm_monitored = 1; 190 nsm->sm_monitored = 1;
94 return status; 191 return status;
95} 192}
96 193
97/* 194/**
98 * Cease to monitor remote host 195 * nsm_unmonitor - Unregister peer notification
196 * @host: pointer to nlm_host of peer to stop monitoring
197 *
198 * If this peer is monitored, this function sends an upcall to
199 * tell the local rpc.statd not to send this peer a notification
200 * when we reboot.
99 */ 201 */
100int 202void nsm_unmonitor(const struct nlm_host *host)
101nsm_unmonitor(struct nlm_host *host)
102{ 203{
103 struct nsm_handle *nsm = host->h_nsmhandle; 204 struct nsm_handle *nsm = host->h_nsmhandle;
104 struct nsm_res res; 205 struct nsm_res res;
105 int status = 0; 206 int status;
106
107 if (nsm == NULL)
108 return 0;
109 host->h_nsmhandle = NULL;
110 207
111 if (atomic_read(&nsm->sm_count) == 1 208 if (atomic_read(&nsm->sm_count) == 1
112 && nsm->sm_monitored && !nsm->sm_sticky) { 209 && nsm->sm_monitored && !nsm->sm_sticky) {
113 dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); 210 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
114 211
115 status = nsm_mon_unmon(nsm, SM_UNMON, &res); 212 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res);
213 if (res.status != 0)
214 status = -EIO;
116 if (status < 0) 215 if (status < 0)
117 printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", 216 printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
118 host->h_name); 217 nsm->sm_name);
119 else 218 else
120 nsm->sm_monitored = 0; 219 nsm->sm_monitored = 0;
121 } 220 }
122 nsm_release(nsm); 221}
123 return status; 222
223static struct nsm_handle *nsm_lookup_hostname(const char *hostname,
224 const size_t len)
225{
226 struct nsm_handle *nsm;
227
228 list_for_each_entry(nsm, &nsm_handles, sm_link)
229 if (strlen(nsm->sm_name) == len &&
230 memcmp(nsm->sm_name, hostname, len) == 0)
231 return nsm;
232 return NULL;
233}
234
235static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap)
236{
237 struct nsm_handle *nsm;
238
239 list_for_each_entry(nsm, &nsm_handles, sm_link)
240 if (nlm_cmp_addr(nsm_addr(nsm), sap))
241 return nsm;
242 return NULL;
243}
244
245static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv)
246{
247 struct nsm_handle *nsm;
248
249 list_for_each_entry(nsm, &nsm_handles, sm_link)
250 if (memcmp(nsm->sm_priv.data, priv->data,
251 sizeof(priv->data)) == 0)
252 return nsm;
253 return NULL;
124} 254}
125 255
126/* 256/*
127 * Create NSM client for the local host 257 * Construct a unique cookie to match this nsm_handle to this monitored
258 * host. It is passed to the local rpc.statd via NSMPROC_MON, and
259 * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these
260 * requests.
261 *
262 * The NSM protocol requires that these cookies be unique while the
263 * system is running. We prefer a stronger requirement of making them
264 * unique across reboots. If user space bugs cause a stale cookie to
265 * be sent to the kernel, it could cause the wrong host to lose its
266 * lock state if cookies were not unique across reboots.
267 *
268 * The cookies are exposed only to local user space via loopback. They
269 * do not appear on the physical network. If we want greater security
270 * for some reason, nsm_init_private() could perform a one-way hash to
271 * obscure the contents of the cookie.
128 */ 272 */
129static struct rpc_clnt * 273static void nsm_init_private(struct nsm_handle *nsm)
130nsm_create(void)
131{ 274{
132 struct sockaddr_in sin = { 275 u64 *p = (u64 *)&nsm->sm_priv.data;
133 .sin_family = AF_INET, 276 struct timespec ts;
134 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
135 .sin_port = 0,
136 };
137 struct rpc_create_args args = {
138 .protocol = XPRT_TRANSPORT_UDP,
139 .address = (struct sockaddr *)&sin,
140 .addrsize = sizeof(sin),
141 .servername = "localhost",
142 .program = &nsm_program,
143 .version = SM_VERSION,
144 .authflavor = RPC_AUTH_NULL,
145 };
146 277
147 return rpc_create(&args); 278 ktime_get_ts(&ts);
279 *p++ = timespec_to_ns(&ts);
280 *p = (unsigned long)nsm;
281}
282
283static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
284 const size_t salen,
285 const char *hostname,
286 const size_t hostname_len)
287{
288 struct nsm_handle *new;
289
290 new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL);
291 if (unlikely(new == NULL))
292 return NULL;
293
294 atomic_set(&new->sm_count, 1);
295 new->sm_name = (char *)(new + 1);
296 memcpy(nsm_addr(new), sap, salen);
297 new->sm_addrlen = salen;
298 nsm_init_private(new);
299 nsm_display_address((const struct sockaddr *)&new->sm_addr,
300 new->sm_addrbuf, sizeof(new->sm_addrbuf));
301 memcpy(new->sm_name, hostname, hostname_len);
302 new->sm_name[hostname_len] = '\0';
303
304 return new;
305}
306
307/**
308 * nsm_get_handle - Find or create a cached nsm_handle
309 * @sap: pointer to socket address of handle to find
310 * @salen: length of socket address
311 * @hostname: pointer to C string containing hostname to find
312 * @hostname_len: length of C string
313 *
314 * Behavior is modulated by the global nsm_use_hostnames variable.
315 *
316 * Returns a cached nsm_handle after bumping its ref count, or
317 * returns a fresh nsm_handle if a handle that matches @sap and/or
318 * @hostname cannot be found in the handle cache. Returns NULL if
319 * an error occurs.
320 */
321struct nsm_handle *nsm_get_handle(const struct sockaddr *sap,
322 const size_t salen, const char *hostname,
323 const size_t hostname_len)
324{
325 struct nsm_handle *cached, *new = NULL;
326
327 if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
328 if (printk_ratelimit()) {
329 printk(KERN_WARNING "Invalid hostname \"%.*s\" "
330 "in NFS lock request\n",
331 (int)hostname_len, hostname);
332 }
333 return NULL;
334 }
335
336retry:
337 spin_lock(&nsm_lock);
338
339 if (nsm_use_hostnames && hostname != NULL)
340 cached = nsm_lookup_hostname(hostname, hostname_len);
341 else
342 cached = nsm_lookup_addr(sap);
343
344 if (cached != NULL) {
345 atomic_inc(&cached->sm_count);
346 spin_unlock(&nsm_lock);
347 kfree(new);
348 dprintk("lockd: found nsm_handle for %s (%s), "
349 "cnt %d\n", cached->sm_name,
350 cached->sm_addrbuf,
351 atomic_read(&cached->sm_count));
352 return cached;
353 }
354
355 if (new != NULL) {
356 list_add(&new->sm_link, &nsm_handles);
357 spin_unlock(&nsm_lock);
358 dprintk("lockd: created nsm_handle for %s (%s)\n",
359 new->sm_name, new->sm_addrbuf);
360 return new;
361 }
362
363 spin_unlock(&nsm_lock);
364
365 new = nsm_create_handle(sap, salen, hostname, hostname_len);
366 if (unlikely(new == NULL))
367 return NULL;
368 goto retry;
369}
370
371/**
372 * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
373 * @info: pointer to NLMPROC_SM_NOTIFY arguments
374 *
375 * Returns a matching nsm_handle if found in the nsm cache; the returned
376 * nsm_handle's reference count is bumped and sm_monitored is cleared.
377 * Otherwise returns NULL if some error occurred.
378 */
379struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
380{
381 struct nsm_handle *cached;
382
383 spin_lock(&nsm_lock);
384
385 cached = nsm_lookup_priv(&info->priv);
386 if (unlikely(cached == NULL)) {
387 spin_unlock(&nsm_lock);
388 dprintk("lockd: never saw rebooted peer '%.*s' before\n",
389 info->len, info->mon);
390 return cached;
391 }
392
393 atomic_inc(&cached->sm_count);
394 spin_unlock(&nsm_lock);
395
396 /*
397 * During subsequent lock activity, force a fresh
398 * notification to be set up for this host.
399 */
400 cached->sm_monitored = 0;
401
402 dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
403 cached->sm_name, cached->sm_addrbuf,
404 atomic_read(&cached->sm_count));
405 return cached;
406}
407
408/**
409 * nsm_release - Release an NSM handle
410 * @nsm: pointer to handle to be released
411 *
412 */
413void nsm_release(struct nsm_handle *nsm)
414{
415 if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
416 list_del(&nsm->sm_link);
417 spin_unlock(&nsm_lock);
418 dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
419 nsm->sm_name, nsm->sm_addrbuf);
420 kfree(nsm);
421 }
148} 422}
149 423
150/* 424/*
@@ -154,127 +428,132 @@ nsm_create(void)
154 * Status Monitor wire protocol. 428 * Status Monitor wire protocol.
155 */ 429 */
156 430
157static __be32 *xdr_encode_nsm_string(__be32 *p, char *string) 431static int encode_nsm_string(struct xdr_stream *xdr, const char *string)
158{ 432{
159 size_t len = strlen(string); 433 const u32 len = strlen(string);
160 434 __be32 *p;
161 if (len > SM_MAXSTRLEN) 435
162 len = SM_MAXSTRLEN; 436 if (unlikely(len > SM_MAXSTRLEN))
163 return xdr_encode_opaque(p, string, len); 437 return -EIO;
438 p = xdr_reserve_space(xdr, sizeof(u32) + len);
439 if (unlikely(p == NULL))
440 return -EIO;
441 xdr_encode_opaque(p, string, len);
442 return 0;
164} 443}
165 444
166/* 445/*
167 * "mon_name" specifies the host to be monitored. 446 * "mon_name" specifies the host to be monitored.
168 *
169 * Linux uses a text version of the IP address of the remote
170 * host as the host identifier (the "mon_name" argument).
171 *
172 * Linux statd always looks up the canonical hostname first for
173 * whatever remote hostname it receives, so this works alright.
174 */ 447 */
175static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) 448static int encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
176{ 449{
177 char buffer[XDR_ADDRBUF_LEN + 1]; 450 return encode_nsm_string(xdr, argp->mon_name);
178 char *name = argp->mon_name;
179
180 if (!nsm_use_hostnames) {
181 snprintf(buffer, XDR_ADDRBUF_LEN,
182 "%pI4", &argp->addr);
183 name = buffer;
184 }
185
186 return xdr_encode_nsm_string(p, name);
187} 451}
188 452
189/* 453/*
190 * The "my_id" argument specifies the hostname and RPC procedure 454 * The "my_id" argument specifies the hostname and RPC procedure
191 * to be called when the status manager receives notification 455 * to be called when the status manager receives notification
192 * (via the SM_NOTIFY call) that the state of host "mon_name" 456 * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
193 * has changed. 457 * has changed.
194 */ 458 */
195static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp) 459static int encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
196{ 460{
197 p = xdr_encode_nsm_string(p, utsname()->nodename); 461 int status;
198 if (!p) 462 __be32 *p;
199 return ERR_PTR(-EIO); 463
200 464 status = encode_nsm_string(xdr, utsname()->nodename);
465 if (unlikely(status != 0))
466 return status;
467 p = xdr_reserve_space(xdr, 3 * sizeof(u32));
468 if (unlikely(p == NULL))
469 return -EIO;
201 *p++ = htonl(argp->prog); 470 *p++ = htonl(argp->prog);
202 *p++ = htonl(argp->vers); 471 *p++ = htonl(argp->vers);
203 *p++ = htonl(argp->proc); 472 *p++ = htonl(argp->proc);
204 473 return 0;
205 return p;
206} 474}
207 475
208/* 476/*
209 * The "mon_id" argument specifies the non-private arguments 477 * The "mon_id" argument specifies the non-private arguments
210 * of an SM_MON or SM_UNMON call. 478 * of an NSMPROC_MON or NSMPROC_UNMON call.
211 */ 479 */
212static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp) 480static int encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
213{ 481{
214 p = xdr_encode_mon_name(p, argp); 482 int status;
215 if (!p)
216 return ERR_PTR(-EIO);
217 483
218 return xdr_encode_my_id(p, argp); 484 status = encode_mon_name(xdr, argp);
485 if (unlikely(status != 0))
486 return status;
487 return encode_my_id(xdr, argp);
219} 488}
220 489
221/* 490/*
222 * The "priv" argument may contain private information required 491 * The "priv" argument may contain private information required
223 * by the SM_MON call. This information will be supplied in the 492 * by the NSMPROC_MON call. This information will be supplied in the
224 * SM_NOTIFY call. 493 * NLMPROC_SM_NOTIFY call.
225 *
226 * Linux provides the raw IP address of the monitored host,
227 * left in network byte order.
228 */ 494 */
229static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp) 495static int encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
230{ 496{
231 *p++ = argp->addr; 497 __be32 *p;
232 *p++ = 0;
233 *p++ = 0;
234 *p++ = 0;
235 498
236 return p; 499 p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
500 if (unlikely(p == NULL))
501 return -EIO;
502 xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE);
503 return 0;
237} 504}
238 505
239static int 506static int xdr_enc_mon(struct rpc_rqst *req, __be32 *p,
240xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) 507 const struct nsm_args *argp)
241{ 508{
242 p = xdr_encode_mon_id(p, argp); 509 struct xdr_stream xdr;
243 if (IS_ERR(p)) 510 int status;
244 return PTR_ERR(p); 511
245 512 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
246 p = xdr_encode_priv(p, argp); 513 status = encode_mon_id(&xdr, argp);
247 if (IS_ERR(p)) 514 if (unlikely(status))
248 return PTR_ERR(p); 515 return status;
249 516 return encode_priv(&xdr, argp);
250 rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
251 return 0;
252} 517}
253 518
254static int 519static int xdr_enc_unmon(struct rpc_rqst *req, __be32 *p,
255xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) 520 const struct nsm_args *argp)
256{ 521{
257 p = xdr_encode_mon_id(p, argp); 522 struct xdr_stream xdr;
258 if (IS_ERR(p)) 523
259 return PTR_ERR(p); 524 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
260 rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); 525 return encode_mon_id(&xdr, argp);
261 return 0;
262} 526}
263 527
264static int 528static int xdr_dec_stat_res(struct rpc_rqst *rqstp, __be32 *p,
265xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) 529 struct nsm_res *resp)
266{ 530{
531 struct xdr_stream xdr;
532
533 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
534 p = xdr_inline_decode(&xdr, 2 * sizeof(u32));
535 if (unlikely(p == NULL))
536 return -EIO;
267 resp->status = ntohl(*p++); 537 resp->status = ntohl(*p++);
268 resp->state = ntohl(*p++); 538 resp->state = ntohl(*p);
269 dprintk("nsm: xdr_decode_stat_res status %d state %d\n", 539
540 dprintk("lockd: xdr_dec_stat_res status %d state %d\n",
270 resp->status, resp->state); 541 resp->status, resp->state);
271 return 0; 542 return 0;
272} 543}
273 544
274static int 545static int xdr_dec_stat(struct rpc_rqst *rqstp, __be32 *p,
275xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) 546 struct nsm_res *resp)
276{ 547{
277 resp->state = ntohl(*p++); 548 struct xdr_stream xdr;
549
550 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
551 p = xdr_inline_decode(&xdr, sizeof(u32));
552 if (unlikely(p == NULL))
553 return -EIO;
554 resp->state = ntohl(*p);
555
556 dprintk("lockd: xdr_dec_stat state %d\n", resp->state);
278 return 0; 557 return 0;
279} 558}
280 559
@@ -288,22 +567,22 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
288#define SM_unmonres_sz 1 567#define SM_unmonres_sz 1
289 568
290static struct rpc_procinfo nsm_procedures[] = { 569static struct rpc_procinfo nsm_procedures[] = {
291[SM_MON] = { 570[NSMPROC_MON] = {
292 .p_proc = SM_MON, 571 .p_proc = NSMPROC_MON,
293 .p_encode = (kxdrproc_t) xdr_encode_mon, 572 .p_encode = (kxdrproc_t)xdr_enc_mon,
294 .p_decode = (kxdrproc_t) xdr_decode_stat_res, 573 .p_decode = (kxdrproc_t)xdr_dec_stat_res,
295 .p_arglen = SM_mon_sz, 574 .p_arglen = SM_mon_sz,
296 .p_replen = SM_monres_sz, 575 .p_replen = SM_monres_sz,
297 .p_statidx = SM_MON, 576 .p_statidx = NSMPROC_MON,
298 .p_name = "MONITOR", 577 .p_name = "MONITOR",
299 }, 578 },
300[SM_UNMON] = { 579[NSMPROC_UNMON] = {
301 .p_proc = SM_UNMON, 580 .p_proc = NSMPROC_UNMON,
302 .p_encode = (kxdrproc_t) xdr_encode_unmon, 581 .p_encode = (kxdrproc_t)xdr_enc_unmon,
303 .p_decode = (kxdrproc_t) xdr_decode_stat, 582 .p_decode = (kxdrproc_t)xdr_dec_stat,
304 .p_arglen = SM_mon_id_sz, 583 .p_arglen = SM_mon_id_sz,
305 .p_replen = SM_unmonres_sz, 584 .p_replen = SM_unmonres_sz,
306 .p_statidx = SM_UNMON, 585 .p_statidx = NSMPROC_UNMON,
307 .p_name = "UNMONITOR", 586 .p_name = "UNMONITOR",
308 }, 587 },
309}; 588};
@@ -322,7 +601,7 @@ static struct rpc_stat nsm_stats;
322 601
323static struct rpc_program nsm_program = { 602static struct rpc_program nsm_program = {
324 .name = "statd", 603 .name = "statd",
325 .number = SM_PROGRAM, 604 .number = NSM_PROGRAM,
326 .nrvers = ARRAY_SIZE(nsm_version), 605 .nrvers = ARRAY_SIZE(nsm_version),
327 .version = nsm_version, 606 .version = nsm_version,
328 .stats = &nsm_stats 607 .stats = &nsm_stats
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 252d80163d02..64f1c31b5853 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -35,7 +35,6 @@
35#include <linux/sunrpc/svcsock.h> 35#include <linux/sunrpc/svcsock.h>
36#include <net/ip.h> 36#include <net/ip.h>
37#include <linux/lockd/lockd.h> 37#include <linux/lockd/lockd.h>
38#include <linux/lockd/sm_inter.h>
39#include <linux/nfs.h> 38#include <linux/nfs.h>
40 39
41#define NLMDBG_FACILITY NLMDBG_SVC 40#define NLMDBG_FACILITY NLMDBG_SVC
@@ -54,13 +53,26 @@ static struct svc_rqst *nlmsvc_rqst;
54unsigned long nlmsvc_timeout; 53unsigned long nlmsvc_timeout;
55 54
56/* 55/*
56 * If the kernel has IPv6 support available, always listen for
57 * both AF_INET and AF_INET6 requests.
58 */
59#if (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) && \
60 defined(CONFIG_SUNRPC_REGISTER_V4)
61static const sa_family_t nlmsvc_family = AF_INET6;
62#else /* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */
63static const sa_family_t nlmsvc_family = AF_INET;
64#endif /* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */
65
66/*
57 * These can be set at insmod time (useful for NFS as root filesystem), 67 * These can be set at insmod time (useful for NFS as root filesystem),
58 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003 68 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
59 */ 69 */
60static unsigned long nlm_grace_period; 70static unsigned long nlm_grace_period;
61static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; 71static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
62static int nlm_udpport, nlm_tcpport; 72static int nlm_udpport, nlm_tcpport;
63int nsm_use_hostnames = 0; 73
74/* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */
75static unsigned int nlm_max_connections = 1024;
64 76
65/* 77/*
66 * Constants needed for the sysctl interface. 78 * Constants needed for the sysctl interface.
@@ -143,6 +155,9 @@ lockd(void *vrqstp)
143 long timeout = MAX_SCHEDULE_TIMEOUT; 155 long timeout = MAX_SCHEDULE_TIMEOUT;
144 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); 156 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
145 157
158 /* update sv_maxconn if it has changed */
159 rqstp->rq_server->sv_maxconn = nlm_max_connections;
160
146 if (signalled()) { 161 if (signalled()) {
147 flush_signals(current); 162 flush_signals(current);
148 if (nlmsvc_ops) { 163 if (nlmsvc_ops) {
@@ -189,6 +204,19 @@ lockd(void *vrqstp)
189 return 0; 204 return 0;
190} 205}
191 206
207static int create_lockd_listener(struct svc_serv *serv, char *name,
208 unsigned short port)
209{
210 struct svc_xprt *xprt;
211
212 xprt = svc_find_xprt(serv, name, 0, 0);
213 if (xprt == NULL)
214 return svc_create_xprt(serv, name, port, SVC_SOCK_DEFAULTS);
215
216 svc_xprt_put(xprt);
217 return 0;
218}
219
192/* 220/*
193 * Ensure there are active UDP and TCP listeners for lockd. 221 * Ensure there are active UDP and TCP listeners for lockd.
194 * 222 *
@@ -202,29 +230,23 @@ lockd(void *vrqstp)
202static int make_socks(struct svc_serv *serv) 230static int make_socks(struct svc_serv *serv)
203{ 231{
204 static int warned; 232 static int warned;
205 struct svc_xprt *xprt; 233 int err;
206 int err = 0;
207 234
208 xprt = svc_find_xprt(serv, "udp", 0, 0); 235 err = create_lockd_listener(serv, "udp", nlm_udpport);
209 if (!xprt) 236 if (err < 0)
210 err = svc_create_xprt(serv, "udp", nlm_udpport, 237 goto out_err;
211 SVC_SOCK_DEFAULTS); 238
212 else 239 err = create_lockd_listener(serv, "tcp", nlm_tcpport);
213 svc_xprt_put(xprt); 240 if (err < 0)
214 if (err >= 0) { 241 goto out_err;
215 xprt = svc_find_xprt(serv, "tcp", 0, 0); 242
216 if (!xprt) 243 warned = 0;
217 err = svc_create_xprt(serv, "tcp", nlm_tcpport, 244 return 0;
218 SVC_SOCK_DEFAULTS); 245
219 else 246out_err:
220 svc_xprt_put(xprt); 247 if (warned++ == 0)
221 }
222 if (err >= 0) {
223 warned = 0;
224 err = 0;
225 } else if (warned++ == 0)
226 printk(KERN_WARNING 248 printk(KERN_WARNING
227 "lockd_up: makesock failed, error=%d\n", err); 249 "lockd_up: makesock failed, error=%d\n", err);
228 return err; 250 return err;
229} 251}
230 252
@@ -252,7 +274,7 @@ int lockd_up(void)
252 "lockd_up: no pid, %d users??\n", nlmsvc_users); 274 "lockd_up: no pid, %d users??\n", nlmsvc_users);
253 275
254 error = -ENOMEM; 276 error = -ENOMEM;
255 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, AF_INET, NULL); 277 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, nlmsvc_family, NULL);
256 if (!serv) { 278 if (!serv) {
257 printk(KERN_WARNING "lockd_up: create service failed\n"); 279 printk(KERN_WARNING "lockd_up: create service failed\n");
258 goto out; 280 goto out;
@@ -276,6 +298,7 @@ int lockd_up(void)
276 } 298 }
277 299
278 svc_sock_update_bufs(serv); 300 svc_sock_update_bufs(serv);
301 serv->sv_maxconn = nlm_max_connections;
279 302
280 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name); 303 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
281 if (IS_ERR(nlmsvc_task)) { 304 if (IS_ERR(nlmsvc_task)) {
@@ -485,6 +508,7 @@ module_param_call(nlm_udpport, param_set_port, param_get_int,
485module_param_call(nlm_tcpport, param_set_port, param_get_int, 508module_param_call(nlm_tcpport, param_set_port, param_get_int,
486 &nlm_tcpport, 0644); 509 &nlm_tcpport, 0644);
487module_param(nsm_use_hostnames, bool, 0644); 510module_param(nsm_use_hostnames, bool, 0644);
511module_param(nlm_max_connections, uint, 0644);
488 512
489/* 513/*
490 * Initialising and terminating the module. 514 * Initialising and terminating the module.
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 4dfdcbc6bf68..1725037374c5 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -16,8 +16,6 @@
16#include <linux/nfsd/nfsd.h> 16#include <linux/nfsd/nfsd.h>
17#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
18#include <linux/lockd/share.h> 18#include <linux/lockd/share.h>
19#include <linux/lockd/sm_inter.h>
20
21 19
22#define NLMDBG_FACILITY NLMDBG_CLIENT 20#define NLMDBG_FACILITY NLMDBG_CLIENT
23 21
@@ -419,8 +417,6 @@ static __be32
419nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 417nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
420 void *resp) 418 void *resp)
421{ 419{
422 struct sockaddr_in saddr;
423
424 dprintk("lockd: SM_NOTIFY called\n"); 420 dprintk("lockd: SM_NOTIFY called\n");
425 421
426 if (!nlm_privileged_requester(rqstp)) { 422 if (!nlm_privileged_requester(rqstp)) {
@@ -430,14 +426,7 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
430 return rpc_system_err; 426 return rpc_system_err;
431 } 427 }
432 428
433 /* Obtain the host pointer for this NFS server and try to 429 nlm_host_rebooted(argp);
434 * reclaim all locks we hold on this server.
435 */
436 memset(&saddr, 0, sizeof(saddr));
437 saddr.sin_family = AF_INET;
438 saddr.sin_addr.s_addr = argp->addr;
439 nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
440
441 return rpc_success; 430 return rpc_success;
442} 431}
443 432
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 3ca89e2a9381..3688e55901fc 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -16,8 +16,6 @@
16#include <linux/nfsd/nfsd.h> 16#include <linux/nfsd/nfsd.h>
17#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
18#include <linux/lockd/share.h> 18#include <linux/lockd/share.h>
19#include <linux/lockd/sm_inter.h>
20
21 19
22#define NLMDBG_FACILITY NLMDBG_CLIENT 20#define NLMDBG_FACILITY NLMDBG_CLIENT
23 21
@@ -451,8 +449,6 @@ static __be32
451nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 449nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
452 void *resp) 450 void *resp)
453{ 451{
454 struct sockaddr_in saddr;
455
456 dprintk("lockd: SM_NOTIFY called\n"); 452 dprintk("lockd: SM_NOTIFY called\n");
457 453
458 if (!nlm_privileged_requester(rqstp)) { 454 if (!nlm_privileged_requester(rqstp)) {
@@ -462,14 +458,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
462 return rpc_system_err; 458 return rpc_system_err;
463 } 459 }
464 460
465 /* Obtain the host pointer for this NFS server and try to 461 nlm_host_rebooted(argp);
466 * reclaim all locks we hold on this server.
467 */
468 memset(&saddr, 0, sizeof(saddr));
469 saddr.sin_family = AF_INET;
470 saddr.sin_addr.s_addr = argp->addr;
471 nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
472
473 return rpc_success; 462 return rpc_success;
474} 463}
475 464
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 34c2766e27c7..9e4d6aab611b 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -17,7 +17,6 @@
17#include <linux/nfsd/export.h> 17#include <linux/nfsd/export.h>
18#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
19#include <linux/lockd/share.h> 19#include <linux/lockd/share.h>
20#include <linux/lockd/sm_inter.h>
21#include <linux/module.h> 20#include <linux/module.h>
22#include <linux/mount.h> 21#include <linux/mount.h>
23 22
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 1f226290c67c..0336f2beacde 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -16,7 +16,6 @@
16#include <linux/sunrpc/svc.h> 16#include <linux/sunrpc/svc.h>
17#include <linux/sunrpc/stats.h> 17#include <linux/sunrpc/stats.h>
18#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
19#include <linux/lockd/sm_inter.h>
20 19
21#define NLMDBG_FACILITY NLMDBG_XDR 20#define NLMDBG_FACILITY NLMDBG_XDR
22 21
@@ -349,8 +348,8 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
349 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 348 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
350 return 0; 349 return 0;
351 argp->state = ntohl(*p++); 350 argp->state = ntohl(*p++);
352 /* Preserve the address in network byte order */ 351 memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
353 argp->addr = *p++; 352 p += XDR_QUADLEN(SM_PRIV_SIZE);
354 return xdr_argsize_check(rqstp, p); 353 return xdr_argsize_check(rqstp, p);
355} 354}
356 355
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 50c493a8ad8e..e1d528653192 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -17,7 +17,6 @@
17#include <linux/sunrpc/svc.h> 17#include <linux/sunrpc/svc.h>
18#include <linux/sunrpc/stats.h> 18#include <linux/sunrpc/stats.h>
19#include <linux/lockd/lockd.h> 19#include <linux/lockd/lockd.h>
20#include <linux/lockd/sm_inter.h>
21 20
22#define NLMDBG_FACILITY NLMDBG_XDR 21#define NLMDBG_FACILITY NLMDBG_XDR
23 22
@@ -356,8 +355,8 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp
356 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 355 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
357 return 0; 356 return 0;
358 argp->state = ntohl(*p++); 357 argp->state = ntohl(*p++);
359 /* Preserve the address in network byte order */ 358 memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
360 argp->addr = *p++; 359 p += XDR_QUADLEN(SM_PRIV_SIZE);
361 return xdr_argsize_check(rqstp, p); 360 return xdr_argsize_check(rqstp, p);
362} 361}
363 362