Commit 7ee91ec14bd4def036b4084da29869382078e44b

Authored by Steve Dickson
Committed by Linus Torvalds
1 parent 068e1b94bb

[PATCH] NFS: procfs/sysctl interfaces for lockd do not work on x86_64

Allow the setting of NLM timeouts and grace periods through the proc and
sysclt interfaces on x86_64 architectures

Signed-off-by: Steve Dickson <steved@redhat.com>
Acked-by: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 2 additions and 2 deletions Inline Diff

1 /* 1 /*
2 * linux/fs/lockd/svc.c 2 * linux/fs/lockd/svc.c
3 * 3 *
4 * This is the central lockd service. 4 * This is the central lockd service.
5 * 5 *
6 * FIXME: Separate the lockd NFS server functionality from the lockd NFS 6 * FIXME: Separate the lockd NFS server functionality from the lockd NFS
7 * client functionality. Oh why didn't Sun create two separate 7 * client functionality. Oh why didn't Sun create two separate
8 * services in the first place? 8 * services in the first place?
9 * 9 *
10 * Authors: Olaf Kirch (okir@monad.swb.de) 10 * Authors: Olaf Kirch (okir@monad.swb.de)
11 * 11 *
12 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 12 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
13 */ 13 */
14 14
15 #include <linux/config.h> 15 #include <linux/config.h>
16 #include <linux/module.h> 16 #include <linux/module.h>
17 #include <linux/init.h> 17 #include <linux/init.h>
18 #include <linux/sysctl.h> 18 #include <linux/sysctl.h>
19 #include <linux/moduleparam.h> 19 #include <linux/moduleparam.h>
20 20
21 #include <linux/sched.h> 21 #include <linux/sched.h>
22 #include <linux/errno.h> 22 #include <linux/errno.h>
23 #include <linux/in.h> 23 #include <linux/in.h>
24 #include <linux/uio.h> 24 #include <linux/uio.h>
25 #include <linux/slab.h> 25 #include <linux/slab.h>
26 #include <linux/smp.h> 26 #include <linux/smp.h>
27 #include <linux/smp_lock.h> 27 #include <linux/smp_lock.h>
28 28
29 #include <linux/sunrpc/types.h> 29 #include <linux/sunrpc/types.h>
30 #include <linux/sunrpc/stats.h> 30 #include <linux/sunrpc/stats.h>
31 #include <linux/sunrpc/clnt.h> 31 #include <linux/sunrpc/clnt.h>
32 #include <linux/sunrpc/svc.h> 32 #include <linux/sunrpc/svc.h>
33 #include <linux/sunrpc/svcsock.h> 33 #include <linux/sunrpc/svcsock.h>
34 #include <linux/lockd/lockd.h> 34 #include <linux/lockd/lockd.h>
35 #include <linux/nfs.h> 35 #include <linux/nfs.h>
36 36
37 #define NLMDBG_FACILITY NLMDBG_SVC 37 #define NLMDBG_FACILITY NLMDBG_SVC
38 #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE) 38 #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
39 #define ALLOWED_SIGS (sigmask(SIGKILL)) 39 #define ALLOWED_SIGS (sigmask(SIGKILL))
40 40
41 static struct svc_program nlmsvc_program; 41 static struct svc_program nlmsvc_program;
42 42
43 struct nlmsvc_binding * nlmsvc_ops; 43 struct nlmsvc_binding * nlmsvc_ops;
44 EXPORT_SYMBOL(nlmsvc_ops); 44 EXPORT_SYMBOL(nlmsvc_ops);
45 45
46 static DECLARE_MUTEX(nlmsvc_sema); 46 static DECLARE_MUTEX(nlmsvc_sema);
47 static unsigned int nlmsvc_users; 47 static unsigned int nlmsvc_users;
48 static pid_t nlmsvc_pid; 48 static pid_t nlmsvc_pid;
49 int nlmsvc_grace_period; 49 int nlmsvc_grace_period;
50 unsigned long nlmsvc_timeout; 50 unsigned long nlmsvc_timeout;
51 51
52 static DECLARE_MUTEX_LOCKED(lockd_start); 52 static DECLARE_MUTEX_LOCKED(lockd_start);
53 static DECLARE_WAIT_QUEUE_HEAD(lockd_exit); 53 static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
54 54
55 /* 55 /*
56 * These can be set at insmod time (useful for NFS as root filesystem), 56 * These can be set at insmod time (useful for NFS as root filesystem),
57 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003 57 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
58 */ 58 */
59 static unsigned long nlm_grace_period; 59 static unsigned long nlm_grace_period;
60 static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; 60 static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
61 static int nlm_udpport, nlm_tcpport; 61 static int nlm_udpport, nlm_tcpport;
62 62
63 /* 63 /*
64 * Constants needed for the sysctl interface. 64 * Constants needed for the sysctl interface.
65 */ 65 */
66 static const unsigned long nlm_grace_period_min = 0; 66 static const unsigned long nlm_grace_period_min = 0;
67 static const unsigned long nlm_grace_period_max = 240; 67 static const unsigned long nlm_grace_period_max = 240;
68 static const unsigned long nlm_timeout_min = 3; 68 static const unsigned long nlm_timeout_min = 3;
69 static const unsigned long nlm_timeout_max = 20; 69 static const unsigned long nlm_timeout_max = 20;
70 static const int nlm_port_min = 0, nlm_port_max = 65535; 70 static const int nlm_port_min = 0, nlm_port_max = 65535;
71 71
72 static struct ctl_table_header * nlm_sysctl_table; 72 static struct ctl_table_header * nlm_sysctl_table;
73 73
74 static unsigned long set_grace_period(void) 74 static unsigned long set_grace_period(void)
75 { 75 {
76 unsigned long grace_period; 76 unsigned long grace_period;
77 77
78 /* Note: nlm_timeout should always be nonzero */ 78 /* Note: nlm_timeout should always be nonzero */
79 if (nlm_grace_period) 79 if (nlm_grace_period)
80 grace_period = ((nlm_grace_period + nlm_timeout - 1) 80 grace_period = ((nlm_grace_period + nlm_timeout - 1)
81 / nlm_timeout) * nlm_timeout * HZ; 81 / nlm_timeout) * nlm_timeout * HZ;
82 else 82 else
83 grace_period = nlm_timeout * 5 * HZ; 83 grace_period = nlm_timeout * 5 * HZ;
84 nlmsvc_grace_period = 1; 84 nlmsvc_grace_period = 1;
85 return grace_period + jiffies; 85 return grace_period + jiffies;
86 } 86 }
87 87
88 static inline void clear_grace_period(void) 88 static inline void clear_grace_period(void)
89 { 89 {
90 nlmsvc_grace_period = 0; 90 nlmsvc_grace_period = 0;
91 } 91 }
92 92
93 /* 93 /*
94 * This is the lockd kernel thread 94 * This is the lockd kernel thread
95 */ 95 */
96 static void 96 static void
97 lockd(struct svc_rqst *rqstp) 97 lockd(struct svc_rqst *rqstp)
98 { 98 {
99 struct svc_serv *serv = rqstp->rq_server; 99 struct svc_serv *serv = rqstp->rq_server;
100 int err = 0; 100 int err = 0;
101 unsigned long grace_period_expire; 101 unsigned long grace_period_expire;
102 102
103 /* Lock module and set up kernel thread */ 103 /* Lock module and set up kernel thread */
104 /* lockd_up is waiting for us to startup, so will 104 /* lockd_up is waiting for us to startup, so will
105 * be holding a reference to this module, so it 105 * be holding a reference to this module, so it
106 * is safe to just claim another reference 106 * is safe to just claim another reference
107 */ 107 */
108 __module_get(THIS_MODULE); 108 __module_get(THIS_MODULE);
109 lock_kernel(); 109 lock_kernel();
110 110
111 /* 111 /*
112 * Let our maker know we're running. 112 * Let our maker know we're running.
113 */ 113 */
114 nlmsvc_pid = current->pid; 114 nlmsvc_pid = current->pid;
115 up(&lockd_start); 115 up(&lockd_start);
116 116
117 daemonize("lockd"); 117 daemonize("lockd");
118 118
119 /* Process request with signals blocked, but allow SIGKILL. */ 119 /* Process request with signals blocked, but allow SIGKILL. */
120 allow_signal(SIGKILL); 120 allow_signal(SIGKILL);
121 121
122 /* kick rpciod */ 122 /* kick rpciod */
123 rpciod_up(); 123 rpciod_up();
124 124
125 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n"); 125 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
126 126
127 if (!nlm_timeout) 127 if (!nlm_timeout)
128 nlm_timeout = LOCKD_DFLT_TIMEO; 128 nlm_timeout = LOCKD_DFLT_TIMEO;
129 nlmsvc_timeout = nlm_timeout * HZ; 129 nlmsvc_timeout = nlm_timeout * HZ;
130 130
131 grace_period_expire = set_grace_period(); 131 grace_period_expire = set_grace_period();
132 132
133 /* 133 /*
134 * The main request loop. We don't terminate until the last 134 * The main request loop. We don't terminate until the last
135 * NFS mount or NFS daemon has gone away, and we've been sent a 135 * NFS mount or NFS daemon has gone away, and we've been sent a
136 * signal, or else another process has taken over our job. 136 * signal, or else another process has taken over our job.
137 */ 137 */
138 while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) { 138 while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
139 long timeout = MAX_SCHEDULE_TIMEOUT; 139 long timeout = MAX_SCHEDULE_TIMEOUT;
140 140
141 if (signalled()) { 141 if (signalled()) {
142 flush_signals(current); 142 flush_signals(current);
143 if (nlmsvc_ops) { 143 if (nlmsvc_ops) {
144 nlmsvc_invalidate_all(); 144 nlmsvc_invalidate_all();
145 grace_period_expire = set_grace_period(); 145 grace_period_expire = set_grace_period();
146 } 146 }
147 } 147 }
148 148
149 /* 149 /*
150 * Retry any blocked locks that have been notified by 150 * Retry any blocked locks that have been notified by
151 * the VFS. Don't do this during grace period. 151 * the VFS. Don't do this during grace period.
152 * (Theoretically, there shouldn't even be blocked locks 152 * (Theoretically, there shouldn't even be blocked locks
153 * during grace period). 153 * during grace period).
154 */ 154 */
155 if (!nlmsvc_grace_period) { 155 if (!nlmsvc_grace_period) {
156 timeout = nlmsvc_retry_blocked(); 156 timeout = nlmsvc_retry_blocked();
157 } else if (time_before(grace_period_expire, jiffies)) 157 } else if (time_before(grace_period_expire, jiffies))
158 clear_grace_period(); 158 clear_grace_period();
159 159
160 /* 160 /*
161 * Find a socket with data available and call its 161 * Find a socket with data available and call its
162 * recvfrom routine. 162 * recvfrom routine.
163 */ 163 */
164 err = svc_recv(serv, rqstp, timeout); 164 err = svc_recv(serv, rqstp, timeout);
165 if (err == -EAGAIN || err == -EINTR) 165 if (err == -EAGAIN || err == -EINTR)
166 continue; 166 continue;
167 if (err < 0) { 167 if (err < 0) {
168 printk(KERN_WARNING 168 printk(KERN_WARNING
169 "lockd: terminating on error %d\n", 169 "lockd: terminating on error %d\n",
170 -err); 170 -err);
171 break; 171 break;
172 } 172 }
173 173
174 dprintk("lockd: request from %08x\n", 174 dprintk("lockd: request from %08x\n",
175 (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); 175 (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
176 176
177 svc_process(serv, rqstp); 177 svc_process(serv, rqstp);
178 178
179 } 179 }
180 180
181 /* 181 /*
182 * Check whether there's a new lockd process before 182 * Check whether there's a new lockd process before
183 * shutting down the hosts and clearing the slot. 183 * shutting down the hosts and clearing the slot.
184 */ 184 */
185 if (!nlmsvc_pid || current->pid == nlmsvc_pid) { 185 if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
186 if (nlmsvc_ops) 186 if (nlmsvc_ops)
187 nlmsvc_invalidate_all(); 187 nlmsvc_invalidate_all();
188 nlm_shutdown_hosts(); 188 nlm_shutdown_hosts();
189 nlmsvc_pid = 0; 189 nlmsvc_pid = 0;
190 } else 190 } else
191 printk(KERN_DEBUG 191 printk(KERN_DEBUG
192 "lockd: new process, skipping host shutdown\n"); 192 "lockd: new process, skipping host shutdown\n");
193 wake_up(&lockd_exit); 193 wake_up(&lockd_exit);
194 194
195 flush_signals(current); 195 flush_signals(current);
196 196
197 /* Exit the RPC thread */ 197 /* Exit the RPC thread */
198 svc_exit_thread(rqstp); 198 svc_exit_thread(rqstp);
199 199
200 /* release rpciod */ 200 /* release rpciod */
201 rpciod_down(); 201 rpciod_down();
202 202
203 /* Release module */ 203 /* Release module */
204 unlock_kernel(); 204 unlock_kernel();
205 module_put_and_exit(0); 205 module_put_and_exit(0);
206 } 206 }
207 207
208 /* 208 /*
209 * Bring up the lockd process if it's not already up. 209 * Bring up the lockd process if it's not already up.
210 */ 210 */
211 int 211 int
212 lockd_up(void) 212 lockd_up(void)
213 { 213 {
214 static int warned; 214 static int warned;
215 struct svc_serv * serv; 215 struct svc_serv * serv;
216 int error = 0; 216 int error = 0;
217 217
218 down(&nlmsvc_sema); 218 down(&nlmsvc_sema);
219 /* 219 /*
220 * Unconditionally increment the user count ... this is 220 * Unconditionally increment the user count ... this is
221 * the number of clients who _want_ a lockd process. 221 * the number of clients who _want_ a lockd process.
222 */ 222 */
223 nlmsvc_users++; 223 nlmsvc_users++;
224 /* 224 /*
225 * Check whether we're already up and running. 225 * Check whether we're already up and running.
226 */ 226 */
227 if (nlmsvc_pid) 227 if (nlmsvc_pid)
228 goto out; 228 goto out;
229 229
230 /* 230 /*
231 * Sanity check: if there's no pid, 231 * Sanity check: if there's no pid,
232 * we should be the first user ... 232 * we should be the first user ...
233 */ 233 */
234 if (nlmsvc_users > 1) 234 if (nlmsvc_users > 1)
235 printk(KERN_WARNING 235 printk(KERN_WARNING
236 "lockd_up: no pid, %d users??\n", nlmsvc_users); 236 "lockd_up: no pid, %d users??\n", nlmsvc_users);
237 237
238 error = -ENOMEM; 238 error = -ENOMEM;
239 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE); 239 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE);
240 if (!serv) { 240 if (!serv) {
241 printk(KERN_WARNING "lockd_up: create service failed\n"); 241 printk(KERN_WARNING "lockd_up: create service failed\n");
242 goto out; 242 goto out;
243 } 243 }
244 244
245 if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0 245 if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0
246 #ifdef CONFIG_NFSD_TCP 246 #ifdef CONFIG_NFSD_TCP
247 || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0 247 || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0
248 #endif 248 #endif
249 ) { 249 ) {
250 if (warned++ == 0) 250 if (warned++ == 0)
251 printk(KERN_WARNING 251 printk(KERN_WARNING
252 "lockd_up: makesock failed, error=%d\n", error); 252 "lockd_up: makesock failed, error=%d\n", error);
253 goto destroy_and_out; 253 goto destroy_and_out;
254 } 254 }
255 warned = 0; 255 warned = 0;
256 256
257 /* 257 /*
258 * Create the kernel thread and wait for it to start. 258 * Create the kernel thread and wait for it to start.
259 */ 259 */
260 error = svc_create_thread(lockd, serv); 260 error = svc_create_thread(lockd, serv);
261 if (error) { 261 if (error) {
262 printk(KERN_WARNING 262 printk(KERN_WARNING
263 "lockd_up: create thread failed, error=%d\n", error); 263 "lockd_up: create thread failed, error=%d\n", error);
264 goto destroy_and_out; 264 goto destroy_and_out;
265 } 265 }
266 down(&lockd_start); 266 down(&lockd_start);
267 267
268 /* 268 /*
269 * Note: svc_serv structures have an initial use count of 1, 269 * Note: svc_serv structures have an initial use count of 1,
270 * so we exit through here on both success and failure. 270 * so we exit through here on both success and failure.
271 */ 271 */
272 destroy_and_out: 272 destroy_and_out:
273 svc_destroy(serv); 273 svc_destroy(serv);
274 out: 274 out:
275 up(&nlmsvc_sema); 275 up(&nlmsvc_sema);
276 return error; 276 return error;
277 } 277 }
278 EXPORT_SYMBOL(lockd_up); 278 EXPORT_SYMBOL(lockd_up);
279 279
280 /* 280 /*
281 * Decrement the user count and bring down lockd if we're the last. 281 * Decrement the user count and bring down lockd if we're the last.
282 */ 282 */
283 void 283 void
284 lockd_down(void) 284 lockd_down(void)
285 { 285 {
286 static int warned; 286 static int warned;
287 287
288 down(&nlmsvc_sema); 288 down(&nlmsvc_sema);
289 if (nlmsvc_users) { 289 if (nlmsvc_users) {
290 if (--nlmsvc_users) 290 if (--nlmsvc_users)
291 goto out; 291 goto out;
292 } else 292 } else
293 printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid); 293 printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
294 294
295 if (!nlmsvc_pid) { 295 if (!nlmsvc_pid) {
296 if (warned++ == 0) 296 if (warned++ == 0)
297 printk(KERN_WARNING "lockd_down: no lockd running.\n"); 297 printk(KERN_WARNING "lockd_down: no lockd running.\n");
298 goto out; 298 goto out;
299 } 299 }
300 warned = 0; 300 warned = 0;
301 301
302 kill_proc(nlmsvc_pid, SIGKILL, 1); 302 kill_proc(nlmsvc_pid, SIGKILL, 1);
303 /* 303 /*
304 * Wait for the lockd process to exit, but since we're holding 304 * Wait for the lockd process to exit, but since we're holding
305 * the lockd semaphore, we can't wait around forever ... 305 * the lockd semaphore, we can't wait around forever ...
306 */ 306 */
307 clear_thread_flag(TIF_SIGPENDING); 307 clear_thread_flag(TIF_SIGPENDING);
308 interruptible_sleep_on_timeout(&lockd_exit, HZ); 308 interruptible_sleep_on_timeout(&lockd_exit, HZ);
309 if (nlmsvc_pid) { 309 if (nlmsvc_pid) {
310 printk(KERN_WARNING 310 printk(KERN_WARNING
311 "lockd_down: lockd failed to exit, clearing pid\n"); 311 "lockd_down: lockd failed to exit, clearing pid\n");
312 nlmsvc_pid = 0; 312 nlmsvc_pid = 0;
313 } 313 }
314 spin_lock_irq(&current->sighand->siglock); 314 spin_lock_irq(&current->sighand->siglock);
315 recalc_sigpending(); 315 recalc_sigpending();
316 spin_unlock_irq(&current->sighand->siglock); 316 spin_unlock_irq(&current->sighand->siglock);
317 out: 317 out:
318 up(&nlmsvc_sema); 318 up(&nlmsvc_sema);
319 } 319 }
320 EXPORT_SYMBOL(lockd_down); 320 EXPORT_SYMBOL(lockd_down);
321 321
322 /* 322 /*
323 * Sysctl parameters (same as module parameters, different interface). 323 * Sysctl parameters (same as module parameters, different interface).
324 */ 324 */
325 325
326 /* Something that isn't CTL_ANY, CTL_NONE or a value that may clash. */ 326 /* Something that isn't CTL_ANY, CTL_NONE or a value that may clash. */
327 #define CTL_UNNUMBERED -2 327 #define CTL_UNNUMBERED -2
328 328
329 static ctl_table nlm_sysctls[] = { 329 static ctl_table nlm_sysctls[] = {
330 { 330 {
331 .ctl_name = CTL_UNNUMBERED, 331 .ctl_name = CTL_UNNUMBERED,
332 .procname = "nlm_grace_period", 332 .procname = "nlm_grace_period",
333 .data = &nlm_grace_period, 333 .data = &nlm_grace_period,
334 .maxlen = sizeof(int), 334 .maxlen = sizeof(unsigned long),
335 .mode = 0644, 335 .mode = 0644,
336 .proc_handler = &proc_doulongvec_minmax, 336 .proc_handler = &proc_doulongvec_minmax,
337 .extra1 = (unsigned long *) &nlm_grace_period_min, 337 .extra1 = (unsigned long *) &nlm_grace_period_min,
338 .extra2 = (unsigned long *) &nlm_grace_period_max, 338 .extra2 = (unsigned long *) &nlm_grace_period_max,
339 }, 339 },
340 { 340 {
341 .ctl_name = CTL_UNNUMBERED, 341 .ctl_name = CTL_UNNUMBERED,
342 .procname = "nlm_timeout", 342 .procname = "nlm_timeout",
343 .data = &nlm_timeout, 343 .data = &nlm_timeout,
344 .maxlen = sizeof(int), 344 .maxlen = sizeof(unsigned long),
345 .mode = 0644, 345 .mode = 0644,
346 .proc_handler = &proc_doulongvec_minmax, 346 .proc_handler = &proc_doulongvec_minmax,
347 .extra1 = (unsigned long *) &nlm_timeout_min, 347 .extra1 = (unsigned long *) &nlm_timeout_min,
348 .extra2 = (unsigned long *) &nlm_timeout_max, 348 .extra2 = (unsigned long *) &nlm_timeout_max,
349 }, 349 },
350 { 350 {
351 .ctl_name = CTL_UNNUMBERED, 351 .ctl_name = CTL_UNNUMBERED,
352 .procname = "nlm_udpport", 352 .procname = "nlm_udpport",
353 .data = &nlm_udpport, 353 .data = &nlm_udpport,
354 .maxlen = sizeof(int), 354 .maxlen = sizeof(int),
355 .mode = 0644, 355 .mode = 0644,
356 .proc_handler = &proc_dointvec_minmax, 356 .proc_handler = &proc_dointvec_minmax,
357 .extra1 = (int *) &nlm_port_min, 357 .extra1 = (int *) &nlm_port_min,
358 .extra2 = (int *) &nlm_port_max, 358 .extra2 = (int *) &nlm_port_max,
359 }, 359 },
360 { 360 {
361 .ctl_name = CTL_UNNUMBERED, 361 .ctl_name = CTL_UNNUMBERED,
362 .procname = "nlm_tcpport", 362 .procname = "nlm_tcpport",
363 .data = &nlm_tcpport, 363 .data = &nlm_tcpport,
364 .maxlen = sizeof(int), 364 .maxlen = sizeof(int),
365 .mode = 0644, 365 .mode = 0644,
366 .proc_handler = &proc_dointvec_minmax, 366 .proc_handler = &proc_dointvec_minmax,
367 .extra1 = (int *) &nlm_port_min, 367 .extra1 = (int *) &nlm_port_min,
368 .extra2 = (int *) &nlm_port_max, 368 .extra2 = (int *) &nlm_port_max,
369 }, 369 },
370 { .ctl_name = 0 } 370 { .ctl_name = 0 }
371 }; 371 };
372 372
373 static ctl_table nlm_sysctl_dir[] = { 373 static ctl_table nlm_sysctl_dir[] = {
374 { 374 {
375 .ctl_name = CTL_UNNUMBERED, 375 .ctl_name = CTL_UNNUMBERED,
376 .procname = "nfs", 376 .procname = "nfs",
377 .mode = 0555, 377 .mode = 0555,
378 .child = nlm_sysctls, 378 .child = nlm_sysctls,
379 }, 379 },
380 { .ctl_name = 0 } 380 { .ctl_name = 0 }
381 }; 381 };
382 382
383 static ctl_table nlm_sysctl_root[] = { 383 static ctl_table nlm_sysctl_root[] = {
384 { 384 {
385 .ctl_name = CTL_FS, 385 .ctl_name = CTL_FS,
386 .procname = "fs", 386 .procname = "fs",
387 .mode = 0555, 387 .mode = 0555,
388 .child = nlm_sysctl_dir, 388 .child = nlm_sysctl_dir,
389 }, 389 },
390 { .ctl_name = 0 } 390 { .ctl_name = 0 }
391 }; 391 };
392 392
393 /* 393 /*
394 * Module (and driverfs) parameters. 394 * Module (and driverfs) parameters.
395 */ 395 */
396 396
397 #define param_set_min_max(name, type, which_strtol, min, max) \ 397 #define param_set_min_max(name, type, which_strtol, min, max) \
398 static int param_set_##name(const char *val, struct kernel_param *kp) \ 398 static int param_set_##name(const char *val, struct kernel_param *kp) \
399 { \ 399 { \
400 char *endp; \ 400 char *endp; \
401 __typeof__(type) num = which_strtol(val, &endp, 0); \ 401 __typeof__(type) num = which_strtol(val, &endp, 0); \
402 if (endp == val || *endp || num < (min) || num > (max)) \ 402 if (endp == val || *endp || num < (min) || num > (max)) \
403 return -EINVAL; \ 403 return -EINVAL; \
404 *((int *) kp->arg) = num; \ 404 *((int *) kp->arg) = num; \
405 return 0; \ 405 return 0; \
406 } 406 }
407 407
408 static inline int is_callback(u32 proc) 408 static inline int is_callback(u32 proc)
409 { 409 {
410 return proc == NLMPROC_GRANTED 410 return proc == NLMPROC_GRANTED
411 || proc == NLMPROC_GRANTED_MSG 411 || proc == NLMPROC_GRANTED_MSG
412 || proc == NLMPROC_TEST_RES 412 || proc == NLMPROC_TEST_RES
413 || proc == NLMPROC_LOCK_RES 413 || proc == NLMPROC_LOCK_RES
414 || proc == NLMPROC_CANCEL_RES 414 || proc == NLMPROC_CANCEL_RES
415 || proc == NLMPROC_UNLOCK_RES 415 || proc == NLMPROC_UNLOCK_RES
416 || proc == NLMPROC_NSM_NOTIFY; 416 || proc == NLMPROC_NSM_NOTIFY;
417 } 417 }
418 418
419 419
420 static int lockd_authenticate(struct svc_rqst *rqstp) 420 static int lockd_authenticate(struct svc_rqst *rqstp)
421 { 421 {
422 rqstp->rq_client = NULL; 422 rqstp->rq_client = NULL;
423 switch (rqstp->rq_authop->flavour) { 423 switch (rqstp->rq_authop->flavour) {
424 case RPC_AUTH_NULL: 424 case RPC_AUTH_NULL:
425 case RPC_AUTH_UNIX: 425 case RPC_AUTH_UNIX:
426 if (rqstp->rq_proc == 0) 426 if (rqstp->rq_proc == 0)
427 return SVC_OK; 427 return SVC_OK;
428 if (is_callback(rqstp->rq_proc)) { 428 if (is_callback(rqstp->rq_proc)) {
429 /* Leave it to individual procedures to 429 /* Leave it to individual procedures to
430 * call nlmsvc_lookup_host(rqstp) 430 * call nlmsvc_lookup_host(rqstp)
431 */ 431 */
432 return SVC_OK; 432 return SVC_OK;
433 } 433 }
434 return svc_set_client(rqstp); 434 return svc_set_client(rqstp);
435 } 435 }
436 return SVC_DENIED; 436 return SVC_DENIED;
437 } 437 }
438 438
439 439
440 param_set_min_max(port, int, simple_strtol, 0, 65535) 440 param_set_min_max(port, int, simple_strtol, 0, 65535)
441 param_set_min_max(grace_period, unsigned long, simple_strtoul, 441 param_set_min_max(grace_period, unsigned long, simple_strtoul,
442 nlm_grace_period_min, nlm_grace_period_max) 442 nlm_grace_period_min, nlm_grace_period_max)
443 param_set_min_max(timeout, unsigned long, simple_strtoul, 443 param_set_min_max(timeout, unsigned long, simple_strtoul,
444 nlm_timeout_min, nlm_timeout_max) 444 nlm_timeout_min, nlm_timeout_max)
445 445
446 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); 446 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
447 MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION "."); 447 MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
448 MODULE_LICENSE("GPL"); 448 MODULE_LICENSE("GPL");
449 449
450 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong, 450 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
451 &nlm_grace_period, 0644); 451 &nlm_grace_period, 0644);
452 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong, 452 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
453 &nlm_timeout, 0644); 453 &nlm_timeout, 0644);
454 module_param_call(nlm_udpport, param_set_port, param_get_int, 454 module_param_call(nlm_udpport, param_set_port, param_get_int,
455 &nlm_udpport, 0644); 455 &nlm_udpport, 0644);
456 module_param_call(nlm_tcpport, param_set_port, param_get_int, 456 module_param_call(nlm_tcpport, param_set_port, param_get_int,
457 &nlm_tcpport, 0644); 457 &nlm_tcpport, 0644);
458 458
459 /* 459 /*
460 * Initialising and terminating the module. 460 * Initialising and terminating the module.
461 */ 461 */
462 462
463 static int __init init_nlm(void) 463 static int __init init_nlm(void)
464 { 464 {
465 nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0); 465 nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0);
466 return nlm_sysctl_table ? 0 : -ENOMEM; 466 return nlm_sysctl_table ? 0 : -ENOMEM;
467 } 467 }
468 468
469 static void __exit exit_nlm(void) 469 static void __exit exit_nlm(void)
470 { 470 {
471 /* FIXME: delete all NLM clients */ 471 /* FIXME: delete all NLM clients */
472 nlm_shutdown_hosts(); 472 nlm_shutdown_hosts();
473 unregister_sysctl_table(nlm_sysctl_table); 473 unregister_sysctl_table(nlm_sysctl_table);
474 } 474 }
475 475
476 module_init(init_nlm); 476 module_init(init_nlm);
477 module_exit(exit_nlm); 477 module_exit(exit_nlm);
478 478
479 /* 479 /*
480 * Define NLM program and procedures 480 * Define NLM program and procedures
481 */ 481 */
482 static struct svc_version nlmsvc_version1 = { 482 static struct svc_version nlmsvc_version1 = {
483 .vs_vers = 1, 483 .vs_vers = 1,
484 .vs_nproc = 17, 484 .vs_nproc = 17,
485 .vs_proc = nlmsvc_procedures, 485 .vs_proc = nlmsvc_procedures,
486 .vs_xdrsize = NLMSVC_XDRSIZE, 486 .vs_xdrsize = NLMSVC_XDRSIZE,
487 }; 487 };
488 static struct svc_version nlmsvc_version3 = { 488 static struct svc_version nlmsvc_version3 = {
489 .vs_vers = 3, 489 .vs_vers = 3,
490 .vs_nproc = 24, 490 .vs_nproc = 24,
491 .vs_proc = nlmsvc_procedures, 491 .vs_proc = nlmsvc_procedures,
492 .vs_xdrsize = NLMSVC_XDRSIZE, 492 .vs_xdrsize = NLMSVC_XDRSIZE,
493 }; 493 };
494 #ifdef CONFIG_LOCKD_V4 494 #ifdef CONFIG_LOCKD_V4
495 static struct svc_version nlmsvc_version4 = { 495 static struct svc_version nlmsvc_version4 = {
496 .vs_vers = 4, 496 .vs_vers = 4,
497 .vs_nproc = 24, 497 .vs_nproc = 24,
498 .vs_proc = nlmsvc_procedures4, 498 .vs_proc = nlmsvc_procedures4,
499 .vs_xdrsize = NLMSVC_XDRSIZE, 499 .vs_xdrsize = NLMSVC_XDRSIZE,
500 }; 500 };
501 #endif 501 #endif
502 static struct svc_version * nlmsvc_version[] = { 502 static struct svc_version * nlmsvc_version[] = {
503 [1] = &nlmsvc_version1, 503 [1] = &nlmsvc_version1,
504 [3] = &nlmsvc_version3, 504 [3] = &nlmsvc_version3,
505 #ifdef CONFIG_LOCKD_V4 505 #ifdef CONFIG_LOCKD_V4
506 [4] = &nlmsvc_version4, 506 [4] = &nlmsvc_version4,
507 #endif 507 #endif
508 }; 508 };
509 509
510 static struct svc_stat nlmsvc_stats; 510 static struct svc_stat nlmsvc_stats;
511 511
512 #define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0])) 512 #define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
513 static struct svc_program nlmsvc_program = { 513 static struct svc_program nlmsvc_program = {
514 .pg_prog = NLM_PROGRAM, /* program number */ 514 .pg_prog = NLM_PROGRAM, /* program number */
515 .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */ 515 .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
516 .pg_vers = nlmsvc_version, /* version table */ 516 .pg_vers = nlmsvc_version, /* version table */
517 .pg_name = "lockd", /* service name */ 517 .pg_name = "lockd", /* service name */
518 .pg_class = "nfsd", /* share authentication with nfsd */ 518 .pg_class = "nfsd", /* share authentication with nfsd */
519 .pg_stats = &nlmsvc_stats, /* stats table */ 519 .pg_stats = &nlmsvc_stats, /* stats table */
520 .pg_authenticate = &lockd_authenticate /* export authentication */ 520 .pg_authenticate = &lockd_authenticate /* export authentication */
521 }; 521 };
522 522