xref: /linux/fs/lockd/svc4proc.c (revision 6ee738610f41b59733f63718f0bdbcba7d3a3f12)
1 /*
2  * linux/fs/lockd/svc4proc.c
3  *
4  * Lockd server procedures. We don't implement the NLM_*_RES
5  * procedures because we don't use the async procedures.
6  *
7  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
8  */
9 
10 #include <linux/types.h>
11 #include <linux/time.h>
12 #include <linux/slab.h>
13 #include <linux/smp_lock.h>
14 #include <linux/in.h>
15 #include <linux/sunrpc/svc.h>
16 #include <linux/sunrpc/clnt.h>
17 #include <linux/nfsd/nfsd.h>
18 #include <linux/lockd/lockd.h>
19 #include <linux/lockd/share.h>
20 
21 #define NLMDBG_FACILITY		NLMDBG_CLIENT
22 
23 /*
24  * Obtain client and file from arguments
25  */
26 static __be32
27 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
28 			struct nlm_host **hostp, struct nlm_file **filp)
29 {
30 	struct nlm_host		*host = NULL;
31 	struct nlm_file		*file = NULL;
32 	struct nlm_lock		*lock = &argp->lock;
33 	__be32			error = 0;
34 
35 	/* nfsd callbacks must have been installed for this procedure */
36 	if (!nlmsvc_ops)
37 		return nlm_lck_denied_nolocks;
38 
39 	/* Obtain host handle */
40 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
41 	 || (argp->monitor && nsm_monitor(host) < 0))
42 		goto no_locks;
43 	*hostp = host;
44 
45 	/* Obtain file pointer. Not used by FREE_ALL call. */
46 	if (filp != NULL) {
47 		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
48 			goto no_locks;
49 		*filp = file;
50 
51 		/* Set up the missing parts of the file_lock structure */
52 		lock->fl.fl_file  = file->f_file;
53 		lock->fl.fl_owner = (fl_owner_t) host;
54 		lock->fl.fl_lmops = &nlmsvc_lock_operations;
55 	}
56 
57 	return 0;
58 
59 no_locks:
60 	nlm_release_host(host);
61  	if (error)
62 		return error;
63 	return nlm_lck_denied_nolocks;
64 }
65 
66 /*
67  * NULL: Test for presence of service
68  */
69 static __be32
70 nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
71 {
72 	dprintk("lockd: NULL          called\n");
73 	return rpc_success;
74 }
75 
76 /*
77  * TEST: Check for conflicting lock
78  */
79 static __be32
80 nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
81 				         struct nlm_res  *resp)
82 {
83 	struct nlm_host	*host;
84 	struct nlm_file	*file;
85 	__be32 rc = rpc_success;
86 
87 	dprintk("lockd: TEST4        called\n");
88 	resp->cookie = argp->cookie;
89 
90 	/* Obtain client and file */
91 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
92 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
93 
94 	/* Now check for conflicting locks */
95 	resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
96 	if (resp->status == nlm_drop_reply)
97 		rc = rpc_drop_reply;
98 	else
99 		dprintk("lockd: TEST4        status %d\n", ntohl(resp->status));
100 
101 	nlm_release_host(host);
102 	nlm_release_file(file);
103 	return rc;
104 }
105 
106 static __be32
107 nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
108 				         struct nlm_res  *resp)
109 {
110 	struct nlm_host	*host;
111 	struct nlm_file	*file;
112 	__be32 rc = rpc_success;
113 
114 	dprintk("lockd: LOCK          called\n");
115 
116 	resp->cookie = argp->cookie;
117 
118 	/* Obtain client and file */
119 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
120 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
121 
122 #if 0
123 	/* If supplied state doesn't match current state, we assume it's
124 	 * an old request that time-warped somehow. Any error return would
125 	 * do in this case because it's irrelevant anyway.
126 	 *
127 	 * NB: We don't retrieve the remote host's state yet.
128 	 */
129 	if (host->h_nsmstate && host->h_nsmstate != argp->state) {
130 		resp->status = nlm_lck_denied_nolocks;
131 	} else
132 #endif
133 
134 	/* Now try to lock the file */
135 	resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
136 					argp->block, &argp->cookie,
137 					argp->reclaim);
138 	if (resp->status == nlm_drop_reply)
139 		rc = rpc_drop_reply;
140 	else
141 		dprintk("lockd: LOCK         status %d\n", ntohl(resp->status));
142 
143 	nlm_release_host(host);
144 	nlm_release_file(file);
145 	return rc;
146 }
147 
148 static __be32
149 nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
150 				           struct nlm_res  *resp)
151 {
152 	struct nlm_host	*host;
153 	struct nlm_file	*file;
154 
155 	dprintk("lockd: CANCEL        called\n");
156 
157 	resp->cookie = argp->cookie;
158 
159 	/* Don't accept requests during grace period */
160 	if (locks_in_grace()) {
161 		resp->status = nlm_lck_denied_grace_period;
162 		return rpc_success;
163 	}
164 
165 	/* Obtain client and file */
166 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
167 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
168 
169 	/* Try to cancel request. */
170 	resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
171 
172 	dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
173 	nlm_release_host(host);
174 	nlm_release_file(file);
175 	return rpc_success;
176 }
177 
178 /*
179  * UNLOCK: release a lock
180  */
181 static __be32
182 nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
183 				           struct nlm_res  *resp)
184 {
185 	struct nlm_host	*host;
186 	struct nlm_file	*file;
187 
188 	dprintk("lockd: UNLOCK        called\n");
189 
190 	resp->cookie = argp->cookie;
191 
192 	/* Don't accept new lock requests during grace period */
193 	if (locks_in_grace()) {
194 		resp->status = nlm_lck_denied_grace_period;
195 		return rpc_success;
196 	}
197 
198 	/* Obtain client and file */
199 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
200 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
201 
202 	/* Now try to remove the lock */
203 	resp->status = nlmsvc_unlock(file, &argp->lock);
204 
205 	dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
206 	nlm_release_host(host);
207 	nlm_release_file(file);
208 	return rpc_success;
209 }
210 
211 /*
212  * GRANTED: A server calls us to tell that a process' lock request
213  * was granted
214  */
215 static __be32
216 nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
217 				            struct nlm_res  *resp)
218 {
219 	resp->cookie = argp->cookie;
220 
221 	dprintk("lockd: GRANTED       called\n");
222 	resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
223 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
224 	return rpc_success;
225 }
226 
227 /*
228  * This is the generic lockd callback for async RPC calls
229  */
230 static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
231 {
232 	dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
233 			-task->tk_status);
234 }
235 
236 static void nlm4svc_callback_release(void *data)
237 {
238 	lock_kernel();
239 	nlm_release_call(data);
240 	unlock_kernel();
241 }
242 
243 static const struct rpc_call_ops nlm4svc_callback_ops = {
244 	.rpc_call_done = nlm4svc_callback_exit,
245 	.rpc_release = nlm4svc_callback_release,
246 };
247 
248 /*
249  * `Async' versions of the above service routines. They aren't really,
250  * because we send the callback before the reply proper. I hope this
251  * doesn't break any clients.
252  */
253 static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
254 		__be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
255 {
256 	struct nlm_host	*host;
257 	struct nlm_rqst	*call;
258 	__be32 stat;
259 
260 	host = nlmsvc_lookup_host(rqstp,
261 				  argp->lock.caller,
262 				  argp->lock.len);
263 	if (host == NULL)
264 		return rpc_system_err;
265 
266 	call = nlm_alloc_call(host);
267 	if (call == NULL)
268 		return rpc_system_err;
269 
270 	stat = func(rqstp, argp, &call->a_res);
271 	if (stat != 0) {
272 		nlm_release_call(call);
273 		return stat;
274 	}
275 
276 	call->a_flags = RPC_TASK_ASYNC;
277 	if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0)
278 		return rpc_system_err;
279 	return rpc_success;
280 }
281 
282 static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
283 					     void	     *resp)
284 {
285 	dprintk("lockd: TEST_MSG      called\n");
286 	return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test);
287 }
288 
289 static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
290 					     void	     *resp)
291 {
292 	dprintk("lockd: LOCK_MSG      called\n");
293 	return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock);
294 }
295 
296 static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
297 					       void	       *resp)
298 {
299 	dprintk("lockd: CANCEL_MSG    called\n");
300 	return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel);
301 }
302 
303 static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
304                                                void            *resp)
305 {
306 	dprintk("lockd: UNLOCK_MSG    called\n");
307 	return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock);
308 }
309 
310 static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
311                                                 void            *resp)
312 {
313 	dprintk("lockd: GRANTED_MSG   called\n");
314 	return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, argp, nlm4svc_proc_granted);
315 }
316 
317 /*
318  * SHARE: create a DOS share or alter existing share.
319  */
320 static __be32
321 nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
322 				          struct nlm_res  *resp)
323 {
324 	struct nlm_host	*host;
325 	struct nlm_file	*file;
326 
327 	dprintk("lockd: SHARE         called\n");
328 
329 	resp->cookie = argp->cookie;
330 
331 	/* Don't accept new lock requests during grace period */
332 	if (locks_in_grace() && !argp->reclaim) {
333 		resp->status = nlm_lck_denied_grace_period;
334 		return rpc_success;
335 	}
336 
337 	/* Obtain client and file */
338 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
339 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
340 
341 	/* Now try to create the share */
342 	resp->status = nlmsvc_share_file(host, file, argp);
343 
344 	dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
345 	nlm_release_host(host);
346 	nlm_release_file(file);
347 	return rpc_success;
348 }
349 
350 /*
351  * UNSHARE: Release a DOS share.
352  */
353 static __be32
354 nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
355 				            struct nlm_res  *resp)
356 {
357 	struct nlm_host	*host;
358 	struct nlm_file	*file;
359 
360 	dprintk("lockd: UNSHARE       called\n");
361 
362 	resp->cookie = argp->cookie;
363 
364 	/* Don't accept requests during grace period */
365 	if (locks_in_grace()) {
366 		resp->status = nlm_lck_denied_grace_period;
367 		return rpc_success;
368 	}
369 
370 	/* Obtain client and file */
371 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
372 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
373 
374 	/* Now try to lock the file */
375 	resp->status = nlmsvc_unshare_file(host, file, argp);
376 
377 	dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
378 	nlm_release_host(host);
379 	nlm_release_file(file);
380 	return rpc_success;
381 }
382 
383 /*
384  * NM_LOCK: Create an unmonitored lock
385  */
386 static __be32
387 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
388 				            struct nlm_res  *resp)
389 {
390 	dprintk("lockd: NM_LOCK       called\n");
391 
392 	argp->monitor = 0;		/* just clean the monitor flag */
393 	return nlm4svc_proc_lock(rqstp, argp, resp);
394 }
395 
396 /*
397  * FREE_ALL: Release all locks and shares held by client
398  */
399 static __be32
400 nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
401 					     void            *resp)
402 {
403 	struct nlm_host	*host;
404 
405 	/* Obtain client */
406 	if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL))
407 		return rpc_success;
408 
409 	nlmsvc_free_host_resources(host);
410 	nlm_release_host(host);
411 	return rpc_success;
412 }
413 
414 /*
415  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
416  */
417 static __be32
418 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
419 					      void	        *resp)
420 {
421 	dprintk("lockd: SM_NOTIFY     called\n");
422 
423 	if (!nlm_privileged_requester(rqstp)) {
424 		char buf[RPC_MAX_ADDRBUFLEN];
425 		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
426 				svc_print_addr(rqstp, buf, sizeof(buf)));
427 		return rpc_system_err;
428 	}
429 
430 	nlm_host_rebooted(argp);
431 	return rpc_success;
432 }
433 
434 /*
435  * client sent a GRANTED_RES, let's remove the associated block
436  */
437 static __be32
438 nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res  *argp,
439                                                 void            *resp)
440 {
441         if (!nlmsvc_ops)
442                 return rpc_success;
443 
444         dprintk("lockd: GRANTED_RES   called\n");
445 
446         nlmsvc_grant_reply(&argp->cookie, argp->status);
447         return rpc_success;
448 }
449 
450 
451 /*
452  * NLM Server procedures.
453  */
454 
455 #define nlm4svc_encode_norep	nlm4svc_encode_void
456 #define nlm4svc_decode_norep	nlm4svc_decode_void
457 #define nlm4svc_decode_testres	nlm4svc_decode_void
458 #define nlm4svc_decode_lockres	nlm4svc_decode_void
459 #define nlm4svc_decode_unlockres	nlm4svc_decode_void
460 #define nlm4svc_decode_cancelres	nlm4svc_decode_void
461 #define nlm4svc_decode_grantedres	nlm4svc_decode_void
462 
463 #define nlm4svc_proc_none	nlm4svc_proc_null
464 #define nlm4svc_proc_test_res	nlm4svc_proc_null
465 #define nlm4svc_proc_lock_res	nlm4svc_proc_null
466 #define nlm4svc_proc_cancel_res	nlm4svc_proc_null
467 #define nlm4svc_proc_unlock_res	nlm4svc_proc_null
468 
469 struct nlm_void			{ int dummy; };
470 
471 #define PROC(name, xargt, xrest, argt, rest, respsize)	\
472  { .pc_func	= (svc_procfunc) nlm4svc_proc_##name,	\
473    .pc_decode	= (kxdrproc_t) nlm4svc_decode_##xargt,	\
474    .pc_encode	= (kxdrproc_t) nlm4svc_encode_##xrest,	\
475    .pc_release	= NULL,					\
476    .pc_argsize	= sizeof(struct nlm_##argt),		\
477    .pc_ressize	= sizeof(struct nlm_##rest),		\
478    .pc_xdrressize = respsize,				\
479  }
480 #define	Ck	(1+XDR_QUADLEN(NLM_MAXCOOKIELEN))	/* cookie */
481 #define	No	(1+1024/4)				/* netobj */
482 #define	St	1					/* status */
483 #define	Rg	4					/* range (offset + length) */
484 struct svc_procedure		nlmsvc_procedures4[] = {
485   PROC(null,		void,		void,		void,	void, 1),
486   PROC(test,		testargs,	testres,	args,	res, Ck+St+2+No+Rg),
487   PROC(lock,		lockargs,	res,		args,	res, Ck+St),
488   PROC(cancel,		cancargs,	res,		args,	res, Ck+St),
489   PROC(unlock,		unlockargs,	res,		args,	res, Ck+St),
490   PROC(granted,		testargs,	res,		args,	res, Ck+St),
491   PROC(test_msg,	testargs,	norep,		args,	void, 1),
492   PROC(lock_msg,	lockargs,	norep,		args,	void, 1),
493   PROC(cancel_msg,	cancargs,	norep,		args,	void, 1),
494   PROC(unlock_msg,	unlockargs,	norep,		args,	void, 1),
495   PROC(granted_msg,	testargs,	norep,		args,	void, 1),
496   PROC(test_res,	testres,	norep,		res,	void, 1),
497   PROC(lock_res,	lockres,	norep,		res,	void, 1),
498   PROC(cancel_res,	cancelres,	norep,		res,	void, 1),
499   PROC(unlock_res,	unlockres,	norep,		res,	void, 1),
500   PROC(granted_res,	res,		norep,		res,	void, 1),
501   /* statd callback */
502   PROC(sm_notify,	reboot,		void,		reboot,	void, 1),
503   PROC(none,		void,		void,		void,	void, 0),
504   PROC(none,		void,		void,		void,	void, 0),
505   PROC(none,		void,		void,		void,	void, 0),
506   PROC(share,		shareargs,	shareres,	args,	res, Ck+St+1),
507   PROC(unshare,		shareargs,	shareres,	args,	res, Ck+St+1),
508   PROC(nm_lock,		lockargs,	res,		args,	res, Ck+St),
509   PROC(free_all,	notify,		void,		args,	void, 1),
510 
511 };
512