xref: /openbmc/linux/fs/lockd/svc4proc.c (revision a6beb73272b4c0108e41bc7c7b5a447ae6c92863)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * linux/fs/lockd/svc4proc.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Lockd server procedures. We don't implement the NLM_*_RES
51da177e4SLinus Torvalds  * procedures because we don't use the async procedures.
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include <linux/types.h>
111da177e4SLinus Torvalds #include <linux/time.h>
121da177e4SLinus Torvalds #include <linux/lockd/lockd.h>
131da177e4SLinus Torvalds #include <linux/lockd/share.h>
145ccb0066SStanislav Kinsbursky #include <linux/sunrpc/svc_xprt.h>
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #define NLMDBG_FACILITY		NLMDBG_CLIENT
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds /*
191da177e4SLinus Torvalds  * Obtain client and file from arguments
201da177e4SLinus Torvalds  */
2152921e02SAl Viro static __be32
221da177e4SLinus Torvalds nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
231da177e4SLinus Torvalds 			struct nlm_host **hostp, struct nlm_file **filp)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds 	struct nlm_host		*host = NULL;
261da177e4SLinus Torvalds 	struct nlm_file		*file = NULL;
271da177e4SLinus Torvalds 	struct nlm_lock		*lock = &argp->lock;
2852921e02SAl Viro 	__be32			error = 0;
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds 	/* nfsd callbacks must have been installed for this procedure */
311da177e4SLinus Torvalds 	if (!nlmsvc_ops)
321da177e4SLinus Torvalds 		return nlm_lck_denied_nolocks;
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds 	/* Obtain host handle */
35db4e4c9aSOlaf Kirch 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
36977faf39SOlaf Kirch 	 || (argp->monitor && nsm_monitor(host) < 0))
371da177e4SLinus Torvalds 		goto no_locks;
381da177e4SLinus Torvalds 	*hostp = host;
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds 	/* Obtain file pointer. Not used by FREE_ALL call. */
411da177e4SLinus Torvalds 	if (filp != NULL) {
421da177e4SLinus Torvalds 		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
431da177e4SLinus Torvalds 			goto no_locks;
441da177e4SLinus Torvalds 		*filp = file;
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 		/* Set up the missing parts of the file_lock structure */
471da177e4SLinus Torvalds 		lock->fl.fl_file  = file->f_file;
481da177e4SLinus Torvalds 		lock->fl.fl_owner = (fl_owner_t) host;
491da177e4SLinus Torvalds 		lock->fl.fl_lmops = &nlmsvc_lock_operations;
501da177e4SLinus Torvalds 	}
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds 	return 0;
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds no_locks:
5567216b94SChuck Lever 	nlmsvc_release_host(host);
561da177e4SLinus Torvalds  	if (error)
571da177e4SLinus Torvalds 		return error;
581da177e4SLinus Torvalds 	return nlm_lck_denied_nolocks;
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds /*
621da177e4SLinus Torvalds  * NULL: Test for presence of service
631da177e4SLinus Torvalds  */
647111c66eSAl Viro static __be32
65*a6beb732SChristoph Hellwig nlm4svc_proc_null(struct svc_rqst *rqstp)
661da177e4SLinus Torvalds {
671da177e4SLinus Torvalds 	dprintk("lockd: NULL          called\n");
681da177e4SLinus Torvalds 	return rpc_success;
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds /*
721da177e4SLinus Torvalds  * TEST: Check for conflicting lock
731da177e4SLinus Torvalds  */
747111c66eSAl Viro static __be32
75*a6beb732SChristoph Hellwig __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
761da177e4SLinus Torvalds {
77*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
781da177e4SLinus Torvalds 	struct nlm_host	*host;
791da177e4SLinus Torvalds 	struct nlm_file	*file;
80317602f3SHarvey Harrison 	__be32 rc = rpc_success;
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds 	dprintk("lockd: TEST4        called\n");
831da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds 	/* Obtain client and file */
861da177e4SLinus Torvalds 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
87d343fce1SNeilBrown 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds 	/* Now check for conflicting locks */
908f920d5eSJeff Layton 	resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
915ea0d750SMarc Eshel 	if (resp->status == nlm_drop_reply)
92b7e6b869SOleg Drokin 		rc = rpc_drop_reply;
93b7e6b869SOleg Drokin 	else
941da177e4SLinus Torvalds 		dprintk("lockd: TEST4        status %d\n", ntohl(resp->status));
95b7e6b869SOleg Drokin 
9667216b94SChuck Lever 	nlmsvc_release_host(host);
971da177e4SLinus Torvalds 	nlm_release_file(file);
98b7e6b869SOleg Drokin 	return rc;
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds 
1017111c66eSAl Viro static __be32
102*a6beb732SChristoph Hellwig nlm4svc_proc_test(struct svc_rqst *rqstp)
1031da177e4SLinus Torvalds {
104*a6beb732SChristoph Hellwig 	return __nlm4svc_proc_test(rqstp, rqstp->rq_resp);
105*a6beb732SChristoph Hellwig }
106*a6beb732SChristoph Hellwig 
107*a6beb732SChristoph Hellwig static __be32
108*a6beb732SChristoph Hellwig __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
109*a6beb732SChristoph Hellwig {
110*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
1111da177e4SLinus Torvalds 	struct nlm_host	*host;
1121da177e4SLinus Torvalds 	struct nlm_file	*file;
113317602f3SHarvey Harrison 	__be32 rc = rpc_success;
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds 	dprintk("lockd: LOCK          called\n");
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 	/* Obtain client and file */
1201da177e4SLinus Torvalds 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
121d343fce1SNeilBrown 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds #if 0
1241da177e4SLinus Torvalds 	/* If supplied state doesn't match current state, we assume it's
1251da177e4SLinus Torvalds 	 * an old request that time-warped somehow. Any error return would
1261da177e4SLinus Torvalds 	 * do in this case because it's irrelevant anyway.
1271da177e4SLinus Torvalds 	 *
1281da177e4SLinus Torvalds 	 * NB: We don't retrieve the remote host's state yet.
1291da177e4SLinus Torvalds 	 */
1301da177e4SLinus Torvalds 	if (host->h_nsmstate && host->h_nsmstate != argp->state) {
1311da177e4SLinus Torvalds 		resp->status = nlm_lck_denied_nolocks;
1321da177e4SLinus Torvalds 	} else
1331da177e4SLinus Torvalds #endif
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds 	/* Now try to lock the file */
1366cde4de8SJeff Layton 	resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
137b2b50289SJ. Bruce Fields 					argp->block, &argp->cookie,
138b2b50289SJ. Bruce Fields 					argp->reclaim);
1391a8322b2SMarc Eshel 	if (resp->status == nlm_drop_reply)
140b7e6b869SOleg Drokin 		rc = rpc_drop_reply;
141b7e6b869SOleg Drokin 	else
1421da177e4SLinus Torvalds 		dprintk("lockd: LOCK         status %d\n", ntohl(resp->status));
143b7e6b869SOleg Drokin 
14467216b94SChuck Lever 	nlmsvc_release_host(host);
1451da177e4SLinus Torvalds 	nlm_release_file(file);
146b7e6b869SOleg Drokin 	return rc;
1471da177e4SLinus Torvalds }
1481da177e4SLinus Torvalds 
1497111c66eSAl Viro static __be32
150*a6beb732SChristoph Hellwig nlm4svc_proc_lock(struct svc_rqst *rqstp)
1511da177e4SLinus Torvalds {
152*a6beb732SChristoph Hellwig 	return __nlm4svc_proc_lock(rqstp, rqstp->rq_resp);
153*a6beb732SChristoph Hellwig }
154*a6beb732SChristoph Hellwig 
155*a6beb732SChristoph Hellwig static __be32
156*a6beb732SChristoph Hellwig __nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
157*a6beb732SChristoph Hellwig {
158*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
1591da177e4SLinus Torvalds 	struct nlm_host	*host;
1601da177e4SLinus Torvalds 	struct nlm_file	*file;
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds 	dprintk("lockd: CANCEL        called\n");
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds 	/* Don't accept requests during grace period */
1675ccb0066SStanislav Kinsbursky 	if (locks_in_grace(SVC_NET(rqstp))) {
1681da177e4SLinus Torvalds 		resp->status = nlm_lck_denied_grace_period;
1691da177e4SLinus Torvalds 		return rpc_success;
1701da177e4SLinus Torvalds 	}
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds 	/* Obtain client and file */
1731da177e4SLinus Torvalds 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
174d343fce1SNeilBrown 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	/* Try to cancel request. */
1775ccb0066SStanislav Kinsbursky 	resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock);
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds 	dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
18067216b94SChuck Lever 	nlmsvc_release_host(host);
1811da177e4SLinus Torvalds 	nlm_release_file(file);
1821da177e4SLinus Torvalds 	return rpc_success;
1831da177e4SLinus Torvalds }
1841da177e4SLinus Torvalds 
185*a6beb732SChristoph Hellwig static __be32
186*a6beb732SChristoph Hellwig nlm4svc_proc_cancel(struct svc_rqst *rqstp)
187*a6beb732SChristoph Hellwig {
188*a6beb732SChristoph Hellwig 	return __nlm4svc_proc_cancel(rqstp, rqstp->rq_resp);
189*a6beb732SChristoph Hellwig }
190*a6beb732SChristoph Hellwig 
1911da177e4SLinus Torvalds /*
1921da177e4SLinus Torvalds  * UNLOCK: release a lock
1931da177e4SLinus Torvalds  */
1947111c66eSAl Viro static __be32
195*a6beb732SChristoph Hellwig __nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
1961da177e4SLinus Torvalds {
197*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
1981da177e4SLinus Torvalds 	struct nlm_host	*host;
1991da177e4SLinus Torvalds 	struct nlm_file	*file;
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	dprintk("lockd: UNLOCK        called\n");
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
2041da177e4SLinus Torvalds 
2051da177e4SLinus Torvalds 	/* Don't accept new lock requests during grace period */
2065ccb0066SStanislav Kinsbursky 	if (locks_in_grace(SVC_NET(rqstp))) {
2071da177e4SLinus Torvalds 		resp->status = nlm_lck_denied_grace_period;
2081da177e4SLinus Torvalds 		return rpc_success;
2091da177e4SLinus Torvalds 	}
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 	/* Obtain client and file */
2121da177e4SLinus Torvalds 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
213d343fce1SNeilBrown 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds 	/* Now try to remove the lock */
2165ccb0066SStanislav Kinsbursky 	resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock);
2171da177e4SLinus Torvalds 
2181da177e4SLinus Torvalds 	dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
21967216b94SChuck Lever 	nlmsvc_release_host(host);
2201da177e4SLinus Torvalds 	nlm_release_file(file);
2211da177e4SLinus Torvalds 	return rpc_success;
2221da177e4SLinus Torvalds }
2231da177e4SLinus Torvalds 
224*a6beb732SChristoph Hellwig static __be32
225*a6beb732SChristoph Hellwig nlm4svc_proc_unlock(struct svc_rqst *rqstp)
226*a6beb732SChristoph Hellwig {
227*a6beb732SChristoph Hellwig 	return __nlm4svc_proc_unlock(rqstp, rqstp->rq_resp);
228*a6beb732SChristoph Hellwig }
229*a6beb732SChristoph Hellwig 
2301da177e4SLinus Torvalds /*
2311da177e4SLinus Torvalds  * GRANTED: A server calls us to tell that a process' lock request
2321da177e4SLinus Torvalds  * was granted
2331da177e4SLinus Torvalds  */
2347111c66eSAl Viro static __be32
235*a6beb732SChristoph Hellwig __nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp)
2361da177e4SLinus Torvalds {
237*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
238*a6beb732SChristoph Hellwig 
2391da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
2401da177e4SLinus Torvalds 
2411da177e4SLinus Torvalds 	dprintk("lockd: GRANTED       called\n");
242dcff09f1SChuck Lever 	resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
2431da177e4SLinus Torvalds 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
2441da177e4SLinus Torvalds 	return rpc_success;
2451da177e4SLinus Torvalds }
2461da177e4SLinus Torvalds 
247*a6beb732SChristoph Hellwig static __be32
248*a6beb732SChristoph Hellwig nlm4svc_proc_granted(struct svc_rqst *rqstp)
249*a6beb732SChristoph Hellwig {
250*a6beb732SChristoph Hellwig 	return __nlm4svc_proc_granted(rqstp, rqstp->rq_resp);
251*a6beb732SChristoph Hellwig }
252*a6beb732SChristoph Hellwig 
2531da177e4SLinus Torvalds /*
254d4716624STrond Myklebust  * This is the generic lockd callback for async RPC calls
255d4716624STrond Myklebust  */
256d4716624STrond Myklebust static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
257d4716624STrond Myklebust {
258c041b5ffSChuck Lever 	dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
259d4716624STrond Myklebust 			-task->tk_status);
260d4716624STrond Myklebust }
261d4716624STrond Myklebust 
262d4716624STrond Myklebust static void nlm4svc_callback_release(void *data)
263d4716624STrond Myklebust {
2647db836d4SChuck Lever 	nlmsvc_release_call(data);
265d4716624STrond Myklebust }
266d4716624STrond Myklebust 
267d4716624STrond Myklebust static const struct rpc_call_ops nlm4svc_callback_ops = {
268d4716624STrond Myklebust 	.rpc_call_done = nlm4svc_callback_exit,
269d4716624STrond Myklebust 	.rpc_release = nlm4svc_callback_release,
270d4716624STrond Myklebust };
271d4716624STrond Myklebust 
272d4716624STrond Myklebust /*
2731da177e4SLinus Torvalds  * `Async' versions of the above service routines. They aren't really,
2741da177e4SLinus Torvalds  * because we send the callback before the reply proper. I hope this
2751da177e4SLinus Torvalds  * doesn't break any clients.
2761da177e4SLinus Torvalds  */
277*a6beb732SChristoph Hellwig static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc,
278*a6beb732SChristoph Hellwig 		__be32 (*func)(struct svc_rqst *,  struct nlm_res *))
279d4716624STrond Myklebust {
280*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
281d4716624STrond Myklebust 	struct nlm_host	*host;
282d4716624STrond Myklebust 	struct nlm_rqst	*call;
2837111c66eSAl Viro 	__be32 stat;
284d4716624STrond Myklebust 
285db4e4c9aSOlaf Kirch 	host = nlmsvc_lookup_host(rqstp,
286db4e4c9aSOlaf Kirch 				  argp->lock.caller,
287db4e4c9aSOlaf Kirch 				  argp->lock.len);
288d4716624STrond Myklebust 	if (host == NULL)
289d4716624STrond Myklebust 		return rpc_system_err;
290d4716624STrond Myklebust 
291d4716624STrond Myklebust 	call = nlm_alloc_call(host);
292446945abSAl Viro 	nlmsvc_release_host(host);
293d4716624STrond Myklebust 	if (call == NULL)
294d4716624STrond Myklebust 		return rpc_system_err;
295d4716624STrond Myklebust 
296*a6beb732SChristoph Hellwig 	stat = func(rqstp, &call->a_res);
297d4716624STrond Myklebust 	if (stat != 0) {
2987db836d4SChuck Lever 		nlmsvc_release_call(call);
299d4716624STrond Myklebust 		return stat;
300d4716624STrond Myklebust 	}
301d4716624STrond Myklebust 
302d4716624STrond Myklebust 	call->a_flags = RPC_TASK_ASYNC;
303d4716624STrond Myklebust 	if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0)
304d4716624STrond Myklebust 		return rpc_system_err;
305d4716624STrond Myklebust 	return rpc_success;
306d4716624STrond Myklebust }
307d4716624STrond Myklebust 
308*a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp)
3091da177e4SLinus Torvalds {
3101da177e4SLinus Torvalds 	dprintk("lockd: TEST_MSG      called\n");
311*a6beb732SChristoph Hellwig 	return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, __nlm4svc_proc_test);
3121da177e4SLinus Torvalds }
3131da177e4SLinus Torvalds 
314*a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp)
3151da177e4SLinus Torvalds {
3161da177e4SLinus Torvalds 	dprintk("lockd: LOCK_MSG      called\n");
317*a6beb732SChristoph Hellwig 	return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, __nlm4svc_proc_lock);
3181da177e4SLinus Torvalds }
3191da177e4SLinus Torvalds 
320*a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp)
3211da177e4SLinus Torvalds {
3221da177e4SLinus Torvalds 	dprintk("lockd: CANCEL_MSG    called\n");
323*a6beb732SChristoph Hellwig 	return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, __nlm4svc_proc_cancel);
3241da177e4SLinus Torvalds }
3251da177e4SLinus Torvalds 
326*a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp)
3271da177e4SLinus Torvalds {
3281da177e4SLinus Torvalds 	dprintk("lockd: UNLOCK_MSG    called\n");
329*a6beb732SChristoph Hellwig 	return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlm4svc_proc_unlock);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332*a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp)
3331da177e4SLinus Torvalds {
3341da177e4SLinus Torvalds 	dprintk("lockd: GRANTED_MSG   called\n");
335*a6beb732SChristoph Hellwig 	return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, __nlm4svc_proc_granted);
3361da177e4SLinus Torvalds }
3371da177e4SLinus Torvalds 
3381da177e4SLinus Torvalds /*
3391da177e4SLinus Torvalds  * SHARE: create a DOS share or alter existing share.
3401da177e4SLinus Torvalds  */
3417111c66eSAl Viro static __be32
342*a6beb732SChristoph Hellwig nlm4svc_proc_share(struct svc_rqst *rqstp)
3431da177e4SLinus Torvalds {
344*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
345*a6beb732SChristoph Hellwig 	struct nlm_res *resp = rqstp->rq_resp;
3461da177e4SLinus Torvalds 	struct nlm_host	*host;
3471da177e4SLinus Torvalds 	struct nlm_file	*file;
3481da177e4SLinus Torvalds 
3491da177e4SLinus Torvalds 	dprintk("lockd: SHARE         called\n");
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds 	/* Don't accept new lock requests during grace period */
3545ccb0066SStanislav Kinsbursky 	if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
3551da177e4SLinus Torvalds 		resp->status = nlm_lck_denied_grace_period;
3561da177e4SLinus Torvalds 		return rpc_success;
3571da177e4SLinus Torvalds 	}
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds 	/* Obtain client and file */
3601da177e4SLinus Torvalds 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
361d343fce1SNeilBrown 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 	/* Now try to create the share */
3641da177e4SLinus Torvalds 	resp->status = nlmsvc_share_file(host, file, argp);
3651da177e4SLinus Torvalds 
3661da177e4SLinus Torvalds 	dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
36767216b94SChuck Lever 	nlmsvc_release_host(host);
3681da177e4SLinus Torvalds 	nlm_release_file(file);
3691da177e4SLinus Torvalds 	return rpc_success;
3701da177e4SLinus Torvalds }
3711da177e4SLinus Torvalds 
3721da177e4SLinus Torvalds /*
3731da177e4SLinus Torvalds  * UNSHARE: Release a DOS share.
3741da177e4SLinus Torvalds  */
3757111c66eSAl Viro static __be32
376*a6beb732SChristoph Hellwig nlm4svc_proc_unshare(struct svc_rqst *rqstp)
3771da177e4SLinus Torvalds {
378*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
379*a6beb732SChristoph Hellwig 	struct nlm_res *resp = rqstp->rq_resp;
3801da177e4SLinus Torvalds 	struct nlm_host	*host;
3811da177e4SLinus Torvalds 	struct nlm_file	*file;
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	dprintk("lockd: UNSHARE       called\n");
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	resp->cookie = argp->cookie;
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds 	/* Don't accept requests during grace period */
3885ccb0066SStanislav Kinsbursky 	if (locks_in_grace(SVC_NET(rqstp))) {
3891da177e4SLinus Torvalds 		resp->status = nlm_lck_denied_grace_period;
3901da177e4SLinus Torvalds 		return rpc_success;
3911da177e4SLinus Torvalds 	}
3921da177e4SLinus Torvalds 
3931da177e4SLinus Torvalds 	/* Obtain client and file */
3941da177e4SLinus Torvalds 	if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
395d343fce1SNeilBrown 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 	/* Now try to lock the file */
3981da177e4SLinus Torvalds 	resp->status = nlmsvc_unshare_file(host, file, argp);
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 	dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
40167216b94SChuck Lever 	nlmsvc_release_host(host);
4021da177e4SLinus Torvalds 	nlm_release_file(file);
4031da177e4SLinus Torvalds 	return rpc_success;
4041da177e4SLinus Torvalds }
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds /*
4071da177e4SLinus Torvalds  * NM_LOCK: Create an unmonitored lock
4081da177e4SLinus Torvalds  */
4097111c66eSAl Viro static __be32
410*a6beb732SChristoph Hellwig nlm4svc_proc_nm_lock(struct svc_rqst *rqstp)
4111da177e4SLinus Torvalds {
412*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
413*a6beb732SChristoph Hellwig 
4141da177e4SLinus Torvalds 	dprintk("lockd: NM_LOCK       called\n");
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 	argp->monitor = 0;		/* just clean the monitor flag */
417*a6beb732SChristoph Hellwig 	return nlm4svc_proc_lock(rqstp);
4181da177e4SLinus Torvalds }
4191da177e4SLinus Torvalds 
4201da177e4SLinus Torvalds /*
4211da177e4SLinus Torvalds  * FREE_ALL: Release all locks and shares held by client
4221da177e4SLinus Torvalds  */
4237111c66eSAl Viro static __be32
424*a6beb732SChristoph Hellwig nlm4svc_proc_free_all(struct svc_rqst *rqstp)
4251da177e4SLinus Torvalds {
426*a6beb732SChristoph Hellwig 	struct nlm_args *argp = rqstp->rq_argp;
4271da177e4SLinus Torvalds 	struct nlm_host	*host;
4281da177e4SLinus Torvalds 
4291da177e4SLinus Torvalds 	/* Obtain client */
4301da177e4SLinus Torvalds 	if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL))
4311da177e4SLinus Torvalds 		return rpc_success;
4321da177e4SLinus Torvalds 
4331da177e4SLinus Torvalds 	nlmsvc_free_host_resources(host);
43467216b94SChuck Lever 	nlmsvc_release_host(host);
4351da177e4SLinus Torvalds 	return rpc_success;
4361da177e4SLinus Torvalds }
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds /*
4391da177e4SLinus Torvalds  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
4401da177e4SLinus Torvalds  */
4417111c66eSAl Viro static __be32
442*a6beb732SChristoph Hellwig nlm4svc_proc_sm_notify(struct svc_rqst *rqstp)
4431da177e4SLinus Torvalds {
444*a6beb732SChristoph Hellwig 	struct nlm_reboot *argp = rqstp->rq_argp;
445*a6beb732SChristoph Hellwig 
4461da177e4SLinus Torvalds 	dprintk("lockd: SM_NOTIFY     called\n");
447b85e4676SChuck Lever 
448b85e4676SChuck Lever 	if (!nlm_privileged_requester(rqstp)) {
449ad06e4bdSChuck Lever 		char buf[RPC_MAX_ADDRBUFLEN];
450ad06e4bdSChuck Lever 		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
451ad06e4bdSChuck Lever 				svc_print_addr(rqstp, buf, sizeof(buf)));
4521da177e4SLinus Torvalds 		return rpc_system_err;
4531da177e4SLinus Torvalds 	}
4541da177e4SLinus Torvalds 
4550ad95472SAndrey Ryabinin 	nlm_host_rebooted(SVC_NET(rqstp), argp);
4561da177e4SLinus Torvalds 	return rpc_success;
4571da177e4SLinus Torvalds }
4581da177e4SLinus Torvalds 
4591da177e4SLinus Torvalds /*
4601da177e4SLinus Torvalds  * client sent a GRANTED_RES, let's remove the associated block
4611da177e4SLinus Torvalds  */
4627111c66eSAl Viro static __be32
463*a6beb732SChristoph Hellwig nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
4641da177e4SLinus Torvalds {
465*a6beb732SChristoph Hellwig 	struct nlm_res *argp = rqstp->rq_argp;
466*a6beb732SChristoph Hellwig 
4671da177e4SLinus Torvalds         if (!nlmsvc_ops)
4681da177e4SLinus Torvalds                 return rpc_success;
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds         dprintk("lockd: GRANTED_RES   called\n");
4711da177e4SLinus Torvalds 
47239be4502SOlaf Kirch         nlmsvc_grant_reply(&argp->cookie, argp->status);
4731da177e4SLinus Torvalds         return rpc_success;
4741da177e4SLinus Torvalds }
4751da177e4SLinus Torvalds 
4761da177e4SLinus Torvalds 
4771da177e4SLinus Torvalds /*
4781da177e4SLinus Torvalds  * NLM Server procedures.
4791da177e4SLinus Torvalds  */
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds #define nlm4svc_encode_norep	nlm4svc_encode_void
4821da177e4SLinus Torvalds #define nlm4svc_decode_norep	nlm4svc_decode_void
4831da177e4SLinus Torvalds #define nlm4svc_decode_testres	nlm4svc_decode_void
4841da177e4SLinus Torvalds #define nlm4svc_decode_lockres	nlm4svc_decode_void
4851da177e4SLinus Torvalds #define nlm4svc_decode_unlockres	nlm4svc_decode_void
4861da177e4SLinus Torvalds #define nlm4svc_decode_cancelres	nlm4svc_decode_void
4871da177e4SLinus Torvalds #define nlm4svc_decode_grantedres	nlm4svc_decode_void
4881da177e4SLinus Torvalds 
4891da177e4SLinus Torvalds #define nlm4svc_proc_none	nlm4svc_proc_null
4901da177e4SLinus Torvalds #define nlm4svc_proc_test_res	nlm4svc_proc_null
4911da177e4SLinus Torvalds #define nlm4svc_proc_lock_res	nlm4svc_proc_null
4921da177e4SLinus Torvalds #define nlm4svc_proc_cancel_res	nlm4svc_proc_null
4931da177e4SLinus Torvalds #define nlm4svc_proc_unlock_res	nlm4svc_proc_null
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds struct nlm_void			{ int dummy; };
4961da177e4SLinus Torvalds 
4971da177e4SLinus Torvalds #define PROC(name, xargt, xrest, argt, rest, respsize)	\
498*a6beb732SChristoph Hellwig  { .pc_func	= nlm4svc_proc_##name,	\
4991da177e4SLinus Torvalds    .pc_decode	= (kxdrproc_t) nlm4svc_decode_##xargt,	\
5001da177e4SLinus Torvalds    .pc_encode	= (kxdrproc_t) nlm4svc_encode_##xrest,	\
5011da177e4SLinus Torvalds    .pc_release	= NULL,					\
5021da177e4SLinus Torvalds    .pc_argsize	= sizeof(struct nlm_##argt),		\
5031da177e4SLinus Torvalds    .pc_ressize	= sizeof(struct nlm_##rest),		\
5041da177e4SLinus Torvalds    .pc_xdrressize = respsize,				\
5051da177e4SLinus Torvalds  }
5061da177e4SLinus Torvalds #define	Ck	(1+XDR_QUADLEN(NLM_MAXCOOKIELEN))	/* cookie */
5071da177e4SLinus Torvalds #define	No	(1+1024/4)				/* netobj */
5081da177e4SLinus Torvalds #define	St	1					/* status */
5091da177e4SLinus Torvalds #define	Rg	4					/* range (offset + length) */
5101da177e4SLinus Torvalds struct svc_procedure		nlmsvc_procedures4[] = {
5111da177e4SLinus Torvalds   PROC(null,		void,		void,		void,	void, 1),
5121da177e4SLinus Torvalds   PROC(test,		testargs,	testres,	args,	res, Ck+St+2+No+Rg),
5131da177e4SLinus Torvalds   PROC(lock,		lockargs,	res,		args,	res, Ck+St),
5141da177e4SLinus Torvalds   PROC(cancel,		cancargs,	res,		args,	res, Ck+St),
5151da177e4SLinus Torvalds   PROC(unlock,		unlockargs,	res,		args,	res, Ck+St),
5161da177e4SLinus Torvalds   PROC(granted,		testargs,	res,		args,	res, Ck+St),
5171da177e4SLinus Torvalds   PROC(test_msg,	testargs,	norep,		args,	void, 1),
5181da177e4SLinus Torvalds   PROC(lock_msg,	lockargs,	norep,		args,	void, 1),
5191da177e4SLinus Torvalds   PROC(cancel_msg,	cancargs,	norep,		args,	void, 1),
5201da177e4SLinus Torvalds   PROC(unlock_msg,	unlockargs,	norep,		args,	void, 1),
5211da177e4SLinus Torvalds   PROC(granted_msg,	testargs,	norep,		args,	void, 1),
5221da177e4SLinus Torvalds   PROC(test_res,	testres,	norep,		res,	void, 1),
5231da177e4SLinus Torvalds   PROC(lock_res,	lockres,	norep,		res,	void, 1),
5241da177e4SLinus Torvalds   PROC(cancel_res,	cancelres,	norep,		res,	void, 1),
5251da177e4SLinus Torvalds   PROC(unlock_res,	unlockres,	norep,		res,	void, 1),
5261da177e4SLinus Torvalds   PROC(granted_res,	res,		norep,		res,	void, 1),
5271da177e4SLinus Torvalds   /* statd callback */
5281da177e4SLinus Torvalds   PROC(sm_notify,	reboot,		void,		reboot,	void, 1),
5291da177e4SLinus Torvalds   PROC(none,		void,		void,		void,	void, 0),
5301da177e4SLinus Torvalds   PROC(none,		void,		void,		void,	void, 0),
5311da177e4SLinus Torvalds   PROC(none,		void,		void,		void,	void, 0),
5321da177e4SLinus Torvalds   PROC(share,		shareargs,	shareres,	args,	res, Ck+St+1),
5331da177e4SLinus Torvalds   PROC(unshare,		shareargs,	shareres,	args,	res, Ck+St+1),
5341da177e4SLinus Torvalds   PROC(nm_lock,		lockargs,	res,		args,	res, Ck+St),
5351da177e4SLinus Torvalds   PROC(free_all,	notify,		void,		args,	void, 1),
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds };
538