1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/fs/lockd/svc4proc.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Lockd server procedures. We don't implement the NLM_*_RES 61da177e4SLinus Torvalds * procedures because we don't use the async procedures. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include <linux/types.h> 121da177e4SLinus Torvalds #include <linux/time.h> 131da177e4SLinus Torvalds #include <linux/lockd/lockd.h> 141da177e4SLinus Torvalds #include <linux/lockd/share.h> 155ccb0066SStanislav Kinsbursky #include <linux/sunrpc/svc_xprt.h> 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds #define NLMDBG_FACILITY NLMDBG_CLIENT 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds /* 201da177e4SLinus Torvalds * Obtain client and file from arguments 211da177e4SLinus Torvalds */ 2252921e02SAl Viro static __be32 231da177e4SLinus Torvalds nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, 241da177e4SLinus Torvalds struct nlm_host **hostp, struct nlm_file **filp) 251da177e4SLinus Torvalds { 261da177e4SLinus Torvalds struct nlm_host *host = NULL; 271da177e4SLinus Torvalds struct nlm_file *file = NULL; 281da177e4SLinus Torvalds struct nlm_lock *lock = &argp->lock; 2952921e02SAl Viro __be32 error = 0; 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds /* nfsd callbacks must have been installed for this procedure */ 321da177e4SLinus Torvalds if (!nlmsvc_ops) 331da177e4SLinus Torvalds return nlm_lck_denied_nolocks; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* Obtain host handle */ 36db4e4c9aSOlaf Kirch if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) 37977faf39SOlaf Kirch || (argp->monitor && nsm_monitor(host) < 0)) 381da177e4SLinus Torvalds goto no_locks; 391da177e4SLinus Torvalds *hostp = host; 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds /* Obtain file pointer. Not used by FREE_ALL call. */ 421da177e4SLinus Torvalds if (filp != NULL) { 431da177e4SLinus Torvalds if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) 441da177e4SLinus Torvalds goto no_locks; 451da177e4SLinus Torvalds *filp = file; 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* Set up the missing parts of the file_lock structure */ 481da177e4SLinus Torvalds lock->fl.fl_file = file->f_file; 49646d73e9SBenjamin Coddington lock->fl.fl_pid = current->tgid; 501da177e4SLinus Torvalds lock->fl.fl_lmops = &nlmsvc_lock_operations; 5189e0edfbSBenjamin Coddington nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid); 5289e0edfbSBenjamin Coddington if (!lock->fl.fl_owner) { 5389e0edfbSBenjamin Coddington /* lockowner allocation has failed */ 5489e0edfbSBenjamin Coddington nlmsvc_release_host(host); 5589e0edfbSBenjamin Coddington return nlm_lck_denied_nolocks; 5689e0edfbSBenjamin Coddington } 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds return 0; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds no_locks: 6267216b94SChuck Lever nlmsvc_release_host(host); 631da177e4SLinus Torvalds if (error) 641da177e4SLinus Torvalds return error; 651da177e4SLinus Torvalds return nlm_lck_denied_nolocks; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds /* 691da177e4SLinus Torvalds * NULL: Test for presence of service 701da177e4SLinus Torvalds */ 717111c66eSAl Viro static __be32 72a6beb732SChristoph Hellwig nlm4svc_proc_null(struct svc_rqst *rqstp) 731da177e4SLinus Torvalds { 741da177e4SLinus Torvalds dprintk("lockd: NULL called\n"); 751da177e4SLinus Torvalds return rpc_success; 761da177e4SLinus Torvalds } 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds /* 791da177e4SLinus Torvalds * TEST: Check for conflicting lock 801da177e4SLinus Torvalds */ 817111c66eSAl Viro static __be32 82a6beb732SChristoph Hellwig __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp) 831da177e4SLinus Torvalds { 84a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 851da177e4SLinus Torvalds struct nlm_host *host; 861da177e4SLinus Torvalds struct nlm_file *file; 87317602f3SHarvey Harrison __be32 rc = rpc_success; 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds dprintk("lockd: TEST4 called\n"); 901da177e4SLinus Torvalds resp->cookie = argp->cookie; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* Obtain client and file */ 931da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 94d343fce1SNeilBrown return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* Now check for conflicting locks */ 978f920d5eSJeff Layton resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie); 985ea0d750SMarc Eshel if (resp->status == nlm_drop_reply) 99b7e6b869SOleg Drokin rc = rpc_drop_reply; 100b7e6b869SOleg Drokin else 1011da177e4SLinus Torvalds dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); 102b7e6b869SOleg Drokin 10389e0edfbSBenjamin Coddington nlmsvc_release_lockowner(&argp->lock); 10467216b94SChuck Lever nlmsvc_release_host(host); 1051da177e4SLinus Torvalds nlm_release_file(file); 106b7e6b869SOleg Drokin return rc; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1097111c66eSAl Viro static __be32 110a6beb732SChristoph Hellwig nlm4svc_proc_test(struct svc_rqst *rqstp) 1111da177e4SLinus Torvalds { 112a6beb732SChristoph Hellwig return __nlm4svc_proc_test(rqstp, rqstp->rq_resp); 113a6beb732SChristoph Hellwig } 114a6beb732SChristoph Hellwig 115a6beb732SChristoph Hellwig static __be32 116a6beb732SChristoph Hellwig __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp) 117a6beb732SChristoph Hellwig { 118a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 1191da177e4SLinus Torvalds struct nlm_host *host; 1201da177e4SLinus Torvalds struct nlm_file *file; 121317602f3SHarvey Harrison __be32 rc = rpc_success; 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds dprintk("lockd: LOCK called\n"); 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds resp->cookie = argp->cookie; 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds /* Obtain client and file */ 1281da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 129d343fce1SNeilBrown return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds #if 0 1321da177e4SLinus Torvalds /* If supplied state doesn't match current state, we assume it's 1331da177e4SLinus Torvalds * an old request that time-warped somehow. Any error return would 1341da177e4SLinus Torvalds * do in this case because it's irrelevant anyway. 1351da177e4SLinus Torvalds * 1361da177e4SLinus Torvalds * NB: We don't retrieve the remote host's state yet. 1371da177e4SLinus Torvalds */ 1381da177e4SLinus Torvalds if (host->h_nsmstate && host->h_nsmstate != argp->state) { 1391da177e4SLinus Torvalds resp->status = nlm_lck_denied_nolocks; 1401da177e4SLinus Torvalds } else 1411da177e4SLinus Torvalds #endif 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds /* Now try to lock the file */ 1446cde4de8SJeff Layton resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock, 145b2b50289SJ. Bruce Fields argp->block, &argp->cookie, 146b2b50289SJ. Bruce Fields argp->reclaim); 1471a8322b2SMarc Eshel if (resp->status == nlm_drop_reply) 148b7e6b869SOleg Drokin rc = rpc_drop_reply; 149b7e6b869SOleg Drokin else 1501da177e4SLinus Torvalds dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 151b7e6b869SOleg Drokin 15289e0edfbSBenjamin Coddington nlmsvc_release_lockowner(&argp->lock); 15367216b94SChuck Lever nlmsvc_release_host(host); 1541da177e4SLinus Torvalds nlm_release_file(file); 155b7e6b869SOleg Drokin return rc; 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds 1587111c66eSAl Viro static __be32 159a6beb732SChristoph Hellwig nlm4svc_proc_lock(struct svc_rqst *rqstp) 1601da177e4SLinus Torvalds { 161a6beb732SChristoph Hellwig return __nlm4svc_proc_lock(rqstp, rqstp->rq_resp); 162a6beb732SChristoph Hellwig } 163a6beb732SChristoph Hellwig 164a6beb732SChristoph Hellwig static __be32 165a6beb732SChristoph Hellwig __nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp) 166a6beb732SChristoph Hellwig { 167a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 1681da177e4SLinus Torvalds struct nlm_host *host; 1691da177e4SLinus Torvalds struct nlm_file *file; 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds dprintk("lockd: CANCEL called\n"); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds resp->cookie = argp->cookie; 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds /* Don't accept requests during grace period */ 1765ccb0066SStanislav Kinsbursky if (locks_in_grace(SVC_NET(rqstp))) { 1771da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 1781da177e4SLinus Torvalds return rpc_success; 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds /* Obtain client and file */ 1821da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 183d343fce1SNeilBrown return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds /* Try to cancel request. */ 1865ccb0066SStanislav Kinsbursky resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock); 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 18989e0edfbSBenjamin Coddington nlmsvc_release_lockowner(&argp->lock); 19067216b94SChuck Lever nlmsvc_release_host(host); 1911da177e4SLinus Torvalds nlm_release_file(file); 1921da177e4SLinus Torvalds return rpc_success; 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 195a6beb732SChristoph Hellwig static __be32 196a6beb732SChristoph Hellwig nlm4svc_proc_cancel(struct svc_rqst *rqstp) 197a6beb732SChristoph Hellwig { 198a6beb732SChristoph Hellwig return __nlm4svc_proc_cancel(rqstp, rqstp->rq_resp); 199a6beb732SChristoph Hellwig } 200a6beb732SChristoph Hellwig 2011da177e4SLinus Torvalds /* 2021da177e4SLinus Torvalds * UNLOCK: release a lock 2031da177e4SLinus Torvalds */ 2047111c66eSAl Viro static __be32 205a6beb732SChristoph Hellwig __nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp) 2061da177e4SLinus Torvalds { 207a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 2081da177e4SLinus Torvalds struct nlm_host *host; 2091da177e4SLinus Torvalds struct nlm_file *file; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds dprintk("lockd: UNLOCK called\n"); 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds resp->cookie = argp->cookie; 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds /* Don't accept new lock requests during grace period */ 2165ccb0066SStanislav Kinsbursky if (locks_in_grace(SVC_NET(rqstp))) { 2171da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 2181da177e4SLinus Torvalds return rpc_success; 2191da177e4SLinus Torvalds } 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds /* Obtain client and file */ 2221da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 223d343fce1SNeilBrown return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds /* Now try to remove the lock */ 2265ccb0066SStanislav Kinsbursky resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock); 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 22989e0edfbSBenjamin Coddington nlmsvc_release_lockowner(&argp->lock); 23067216b94SChuck Lever nlmsvc_release_host(host); 2311da177e4SLinus Torvalds nlm_release_file(file); 2321da177e4SLinus Torvalds return rpc_success; 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds 235a6beb732SChristoph Hellwig static __be32 236a6beb732SChristoph Hellwig nlm4svc_proc_unlock(struct svc_rqst *rqstp) 237a6beb732SChristoph Hellwig { 238a6beb732SChristoph Hellwig return __nlm4svc_proc_unlock(rqstp, rqstp->rq_resp); 239a6beb732SChristoph Hellwig } 240a6beb732SChristoph Hellwig 2411da177e4SLinus Torvalds /* 2421da177e4SLinus Torvalds * GRANTED: A server calls us to tell that a process' lock request 2431da177e4SLinus Torvalds * was granted 2441da177e4SLinus Torvalds */ 2457111c66eSAl Viro static __be32 246a6beb732SChristoph Hellwig __nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp) 2471da177e4SLinus Torvalds { 248a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 249a6beb732SChristoph Hellwig 2501da177e4SLinus Torvalds resp->cookie = argp->cookie; 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds dprintk("lockd: GRANTED called\n"); 253dcff09f1SChuck Lever resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock); 2541da177e4SLinus Torvalds dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 2551da177e4SLinus Torvalds return rpc_success; 2561da177e4SLinus Torvalds } 2571da177e4SLinus Torvalds 258a6beb732SChristoph Hellwig static __be32 259a6beb732SChristoph Hellwig nlm4svc_proc_granted(struct svc_rqst *rqstp) 260a6beb732SChristoph Hellwig { 261a6beb732SChristoph Hellwig return __nlm4svc_proc_granted(rqstp, rqstp->rq_resp); 262a6beb732SChristoph Hellwig } 263a6beb732SChristoph Hellwig 2641da177e4SLinus Torvalds /* 265d4716624STrond Myklebust * This is the generic lockd callback for async RPC calls 266d4716624STrond Myklebust */ 267d4716624STrond Myklebust static void nlm4svc_callback_exit(struct rpc_task *task, void *data) 268d4716624STrond Myklebust { 269c041b5ffSChuck Lever dprintk("lockd: %5u callback returned %d\n", task->tk_pid, 270d4716624STrond Myklebust -task->tk_status); 271d4716624STrond Myklebust } 272d4716624STrond Myklebust 273d4716624STrond Myklebust static void nlm4svc_callback_release(void *data) 274d4716624STrond Myklebust { 2757db836d4SChuck Lever nlmsvc_release_call(data); 276d4716624STrond Myklebust } 277d4716624STrond Myklebust 278d4716624STrond Myklebust static const struct rpc_call_ops nlm4svc_callback_ops = { 279d4716624STrond Myklebust .rpc_call_done = nlm4svc_callback_exit, 280d4716624STrond Myklebust .rpc_release = nlm4svc_callback_release, 281d4716624STrond Myklebust }; 282d4716624STrond Myklebust 283d4716624STrond Myklebust /* 2841da177e4SLinus Torvalds * `Async' versions of the above service routines. They aren't really, 2851da177e4SLinus Torvalds * because we send the callback before the reply proper. I hope this 2861da177e4SLinus Torvalds * doesn't break any clients. 2871da177e4SLinus Torvalds */ 288a6beb732SChristoph Hellwig static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, 289a6beb732SChristoph Hellwig __be32 (*func)(struct svc_rqst *, struct nlm_res *)) 290d4716624STrond Myklebust { 291a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 292d4716624STrond Myklebust struct nlm_host *host; 293d4716624STrond Myklebust struct nlm_rqst *call; 2947111c66eSAl Viro __be32 stat; 295d4716624STrond Myklebust 296db4e4c9aSOlaf Kirch host = nlmsvc_lookup_host(rqstp, 297db4e4c9aSOlaf Kirch argp->lock.caller, 298db4e4c9aSOlaf Kirch argp->lock.len); 299d4716624STrond Myklebust if (host == NULL) 300d4716624STrond Myklebust return rpc_system_err; 301d4716624STrond Myklebust 302d4716624STrond Myklebust call = nlm_alloc_call(host); 303446945abSAl Viro nlmsvc_release_host(host); 304d4716624STrond Myklebust if (call == NULL) 305d4716624STrond Myklebust return rpc_system_err; 306d4716624STrond Myklebust 307a6beb732SChristoph Hellwig stat = func(rqstp, &call->a_res); 308d4716624STrond Myklebust if (stat != 0) { 3097db836d4SChuck Lever nlmsvc_release_call(call); 310d4716624STrond Myklebust return stat; 311d4716624STrond Myklebust } 312d4716624STrond Myklebust 313d4716624STrond Myklebust call->a_flags = RPC_TASK_ASYNC; 314d4716624STrond Myklebust if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0) 315d4716624STrond Myklebust return rpc_system_err; 316d4716624STrond Myklebust return rpc_success; 317d4716624STrond Myklebust } 318d4716624STrond Myklebust 319a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp) 3201da177e4SLinus Torvalds { 3211da177e4SLinus Torvalds dprintk("lockd: TEST_MSG called\n"); 322a6beb732SChristoph Hellwig return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, __nlm4svc_proc_test); 3231da177e4SLinus Torvalds } 3241da177e4SLinus Torvalds 325a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp) 3261da177e4SLinus Torvalds { 3271da177e4SLinus Torvalds dprintk("lockd: LOCK_MSG called\n"); 328a6beb732SChristoph Hellwig return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, __nlm4svc_proc_lock); 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds 331a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp) 3321da177e4SLinus Torvalds { 3331da177e4SLinus Torvalds dprintk("lockd: CANCEL_MSG called\n"); 334a6beb732SChristoph Hellwig return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, __nlm4svc_proc_cancel); 3351da177e4SLinus Torvalds } 3361da177e4SLinus Torvalds 337a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp) 3381da177e4SLinus Torvalds { 3391da177e4SLinus Torvalds dprintk("lockd: UNLOCK_MSG called\n"); 340a6beb732SChristoph Hellwig return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlm4svc_proc_unlock); 3411da177e4SLinus Torvalds } 3421da177e4SLinus Torvalds 343a6beb732SChristoph Hellwig static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp) 3441da177e4SLinus Torvalds { 3451da177e4SLinus Torvalds dprintk("lockd: GRANTED_MSG called\n"); 346a6beb732SChristoph Hellwig return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, __nlm4svc_proc_granted); 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds /* 3501da177e4SLinus Torvalds * SHARE: create a DOS share or alter existing share. 3511da177e4SLinus Torvalds */ 3527111c66eSAl Viro static __be32 353a6beb732SChristoph Hellwig nlm4svc_proc_share(struct svc_rqst *rqstp) 3541da177e4SLinus Torvalds { 355a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 356a6beb732SChristoph Hellwig struct nlm_res *resp = rqstp->rq_resp; 3571da177e4SLinus Torvalds struct nlm_host *host; 3581da177e4SLinus Torvalds struct nlm_file *file; 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds dprintk("lockd: SHARE called\n"); 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds resp->cookie = argp->cookie; 3631da177e4SLinus Torvalds 3641da177e4SLinus Torvalds /* Don't accept new lock requests during grace period */ 3655ccb0066SStanislav Kinsbursky if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { 3661da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 3671da177e4SLinus Torvalds return rpc_success; 3681da177e4SLinus Torvalds } 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds /* Obtain client and file */ 3711da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 372d343fce1SNeilBrown return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds /* Now try to create the share */ 3751da177e4SLinus Torvalds resp->status = nlmsvc_share_file(host, file, argp); 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); 37889e0edfbSBenjamin Coddington nlmsvc_release_lockowner(&argp->lock); 37967216b94SChuck Lever nlmsvc_release_host(host); 3801da177e4SLinus Torvalds nlm_release_file(file); 3811da177e4SLinus Torvalds return rpc_success; 3821da177e4SLinus Torvalds } 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds /* 3851da177e4SLinus Torvalds * UNSHARE: Release a DOS share. 3861da177e4SLinus Torvalds */ 3877111c66eSAl Viro static __be32 388a6beb732SChristoph Hellwig nlm4svc_proc_unshare(struct svc_rqst *rqstp) 3891da177e4SLinus Torvalds { 390a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 391a6beb732SChristoph Hellwig struct nlm_res *resp = rqstp->rq_resp; 3921da177e4SLinus Torvalds struct nlm_host *host; 3931da177e4SLinus Torvalds struct nlm_file *file; 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds dprintk("lockd: UNSHARE called\n"); 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds resp->cookie = argp->cookie; 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds /* Don't accept requests during grace period */ 4005ccb0066SStanislav Kinsbursky if (locks_in_grace(SVC_NET(rqstp))) { 4011da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 4021da177e4SLinus Torvalds return rpc_success; 4031da177e4SLinus Torvalds } 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds /* Obtain client and file */ 4061da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 407d343fce1SNeilBrown return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds /* Now try to lock the file */ 4101da177e4SLinus Torvalds resp->status = nlmsvc_unshare_file(host, file, argp); 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); 41389e0edfbSBenjamin Coddington nlmsvc_release_lockowner(&argp->lock); 41467216b94SChuck Lever nlmsvc_release_host(host); 4151da177e4SLinus Torvalds nlm_release_file(file); 4161da177e4SLinus Torvalds return rpc_success; 4171da177e4SLinus Torvalds } 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds /* 4201da177e4SLinus Torvalds * NM_LOCK: Create an unmonitored lock 4211da177e4SLinus Torvalds */ 4227111c66eSAl Viro static __be32 423a6beb732SChristoph Hellwig nlm4svc_proc_nm_lock(struct svc_rqst *rqstp) 4241da177e4SLinus Torvalds { 425a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 426a6beb732SChristoph Hellwig 4271da177e4SLinus Torvalds dprintk("lockd: NM_LOCK called\n"); 4281da177e4SLinus Torvalds 4291da177e4SLinus Torvalds argp->monitor = 0; /* just clean the monitor flag */ 430a6beb732SChristoph Hellwig return nlm4svc_proc_lock(rqstp); 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds /* 4341da177e4SLinus Torvalds * FREE_ALL: Release all locks and shares held by client 4351da177e4SLinus Torvalds */ 4367111c66eSAl Viro static __be32 437a6beb732SChristoph Hellwig nlm4svc_proc_free_all(struct svc_rqst *rqstp) 4381da177e4SLinus Torvalds { 439a6beb732SChristoph Hellwig struct nlm_args *argp = rqstp->rq_argp; 4401da177e4SLinus Torvalds struct nlm_host *host; 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds /* Obtain client */ 4431da177e4SLinus Torvalds if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL)) 4441da177e4SLinus Torvalds return rpc_success; 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds nlmsvc_free_host_resources(host); 44767216b94SChuck Lever nlmsvc_release_host(host); 4481da177e4SLinus Torvalds return rpc_success; 4491da177e4SLinus Torvalds } 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds /* 4521da177e4SLinus Torvalds * SM_NOTIFY: private callback from statd (not part of official NLM proto) 4531da177e4SLinus Torvalds */ 4547111c66eSAl Viro static __be32 455a6beb732SChristoph Hellwig nlm4svc_proc_sm_notify(struct svc_rqst *rqstp) 4561da177e4SLinus Torvalds { 457a6beb732SChristoph Hellwig struct nlm_reboot *argp = rqstp->rq_argp; 458a6beb732SChristoph Hellwig 4591da177e4SLinus Torvalds dprintk("lockd: SM_NOTIFY called\n"); 460b85e4676SChuck Lever 461b85e4676SChuck Lever if (!nlm_privileged_requester(rqstp)) { 462ad06e4bdSChuck Lever char buf[RPC_MAX_ADDRBUFLEN]; 463ad06e4bdSChuck Lever printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 464ad06e4bdSChuck Lever svc_print_addr(rqstp, buf, sizeof(buf))); 4651da177e4SLinus Torvalds return rpc_system_err; 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds 4680ad95472SAndrey Ryabinin nlm_host_rebooted(SVC_NET(rqstp), argp); 4691da177e4SLinus Torvalds return rpc_success; 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds /* 4731da177e4SLinus Torvalds * client sent a GRANTED_RES, let's remove the associated block 4741da177e4SLinus Torvalds */ 4757111c66eSAl Viro static __be32 476a6beb732SChristoph Hellwig nlm4svc_proc_granted_res(struct svc_rqst *rqstp) 4771da177e4SLinus Torvalds { 478a6beb732SChristoph Hellwig struct nlm_res *argp = rqstp->rq_argp; 479a6beb732SChristoph Hellwig 4801da177e4SLinus Torvalds if (!nlmsvc_ops) 4811da177e4SLinus Torvalds return rpc_success; 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds dprintk("lockd: GRANTED_RES called\n"); 4841da177e4SLinus Torvalds 48539be4502SOlaf Kirch nlmsvc_grant_reply(&argp->cookie, argp->status); 4861da177e4SLinus Torvalds return rpc_success; 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds 489*49d99608SChuck Lever static __be32 490*49d99608SChuck Lever nlm4svc_proc_unused(struct svc_rqst *rqstp) 491*49d99608SChuck Lever { 492*49d99608SChuck Lever return rpc_proc_unavail; 493*49d99608SChuck Lever } 494*49d99608SChuck Lever 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds /* 4971da177e4SLinus Torvalds * NLM Server procedures. 4981da177e4SLinus Torvalds */ 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds struct nlm_void { int dummy; }; 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ 5031da177e4SLinus Torvalds #define No (1+1024/4) /* netobj */ 5041da177e4SLinus Torvalds #define St 1 /* status */ 5051da177e4SLinus Torvalds #define Rg 4 /* range (offset + length) */ 5061da177e4SLinus Torvalds 507*49d99608SChuck Lever const struct svc_procedure nlmsvc_procedures4[24] = { 508*49d99608SChuck Lever [NLMPROC_NULL] = { 509*49d99608SChuck Lever .pc_func = nlm4svc_proc_null, 510*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 511*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 512*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_void), 513*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 514*49d99608SChuck Lever .pc_xdrressize = St, 515*49d99608SChuck Lever }, 516*49d99608SChuck Lever [NLMPROC_TEST] = { 517*49d99608SChuck Lever .pc_func = nlm4svc_proc_test, 518*49d99608SChuck Lever .pc_decode = nlm4svc_decode_testargs, 519*49d99608SChuck Lever .pc_encode = nlm4svc_encode_testres, 520*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 521*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 522*49d99608SChuck Lever .pc_xdrressize = Ck+St+2+No+Rg, 523*49d99608SChuck Lever }, 524*49d99608SChuck Lever [NLMPROC_LOCK] = { 525*49d99608SChuck Lever .pc_func = nlm4svc_proc_lock, 526*49d99608SChuck Lever .pc_decode = nlm4svc_decode_lockargs, 527*49d99608SChuck Lever .pc_encode = nlm4svc_encode_res, 528*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 529*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 530*49d99608SChuck Lever .pc_xdrressize = Ck+St, 531*49d99608SChuck Lever }, 532*49d99608SChuck Lever [NLMPROC_CANCEL] = { 533*49d99608SChuck Lever .pc_func = nlm4svc_proc_cancel, 534*49d99608SChuck Lever .pc_decode = nlm4svc_decode_cancargs, 535*49d99608SChuck Lever .pc_encode = nlm4svc_encode_res, 536*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 537*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 538*49d99608SChuck Lever .pc_xdrressize = Ck+St, 539*49d99608SChuck Lever }, 540*49d99608SChuck Lever [NLMPROC_UNLOCK] = { 541*49d99608SChuck Lever .pc_func = nlm4svc_proc_unlock, 542*49d99608SChuck Lever .pc_decode = nlm4svc_decode_unlockargs, 543*49d99608SChuck Lever .pc_encode = nlm4svc_encode_res, 544*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 545*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 546*49d99608SChuck Lever .pc_xdrressize = Ck+St, 547*49d99608SChuck Lever }, 548*49d99608SChuck Lever [NLMPROC_GRANTED] = { 549*49d99608SChuck Lever .pc_func = nlm4svc_proc_granted, 550*49d99608SChuck Lever .pc_decode = nlm4svc_decode_testargs, 551*49d99608SChuck Lever .pc_encode = nlm4svc_encode_res, 552*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 553*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 554*49d99608SChuck Lever .pc_xdrressize = Ck+St, 555*49d99608SChuck Lever }, 556*49d99608SChuck Lever [NLMPROC_TEST_MSG] = { 557*49d99608SChuck Lever .pc_func = nlm4svc_proc_test_msg, 558*49d99608SChuck Lever .pc_decode = nlm4svc_decode_testargs, 559*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 560*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 561*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 562*49d99608SChuck Lever .pc_xdrressize = St, 563*49d99608SChuck Lever }, 564*49d99608SChuck Lever [NLMPROC_LOCK_MSG] = { 565*49d99608SChuck Lever .pc_func = nlm4svc_proc_lock_msg, 566*49d99608SChuck Lever .pc_decode = nlm4svc_decode_lockargs, 567*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 568*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 569*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 570*49d99608SChuck Lever .pc_xdrressize = St, 571*49d99608SChuck Lever }, 572*49d99608SChuck Lever [NLMPROC_CANCEL_MSG] = { 573*49d99608SChuck Lever .pc_func = nlm4svc_proc_cancel_msg, 574*49d99608SChuck Lever .pc_decode = nlm4svc_decode_cancargs, 575*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 576*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 577*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 578*49d99608SChuck Lever .pc_xdrressize = St, 579*49d99608SChuck Lever }, 580*49d99608SChuck Lever [NLMPROC_UNLOCK_MSG] = { 581*49d99608SChuck Lever .pc_func = nlm4svc_proc_unlock_msg, 582*49d99608SChuck Lever .pc_decode = nlm4svc_decode_unlockargs, 583*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 584*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 585*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 586*49d99608SChuck Lever .pc_xdrressize = St, 587*49d99608SChuck Lever }, 588*49d99608SChuck Lever [NLMPROC_GRANTED_MSG] = { 589*49d99608SChuck Lever .pc_func = nlm4svc_proc_granted_msg, 590*49d99608SChuck Lever .pc_decode = nlm4svc_decode_testargs, 591*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 592*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 593*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 594*49d99608SChuck Lever .pc_xdrressize = St, 595*49d99608SChuck Lever }, 596*49d99608SChuck Lever [NLMPROC_TEST_RES] = { 597*49d99608SChuck Lever .pc_func = nlm4svc_proc_null, 598*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 599*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 600*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_res), 601*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 602*49d99608SChuck Lever .pc_xdrressize = St, 603*49d99608SChuck Lever }, 604*49d99608SChuck Lever [NLMPROC_LOCK_RES] = { 605*49d99608SChuck Lever .pc_func = nlm4svc_proc_null, 606*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 607*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 608*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_res), 609*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 610*49d99608SChuck Lever .pc_xdrressize = St, 611*49d99608SChuck Lever }, 612*49d99608SChuck Lever [NLMPROC_CANCEL_RES] = { 613*49d99608SChuck Lever .pc_func = nlm4svc_proc_null, 614*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 615*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 616*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_res), 617*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 618*49d99608SChuck Lever .pc_xdrressize = St, 619*49d99608SChuck Lever }, 620*49d99608SChuck Lever [NLMPROC_UNLOCK_RES] = { 621*49d99608SChuck Lever .pc_func = nlm4svc_proc_null, 622*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 623*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 624*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_res), 625*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 626*49d99608SChuck Lever .pc_xdrressize = St, 627*49d99608SChuck Lever }, 628*49d99608SChuck Lever [NLMPROC_GRANTED_RES] = { 629*49d99608SChuck Lever .pc_func = nlm4svc_proc_granted_res, 630*49d99608SChuck Lever .pc_decode = nlm4svc_decode_res, 631*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 632*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_res), 633*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 634*49d99608SChuck Lever .pc_xdrressize = St, 635*49d99608SChuck Lever }, 636*49d99608SChuck Lever [NLMPROC_NSM_NOTIFY] = { 637*49d99608SChuck Lever .pc_func = nlm4svc_proc_sm_notify, 638*49d99608SChuck Lever .pc_decode = nlm4svc_decode_reboot, 639*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 640*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_reboot), 641*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 642*49d99608SChuck Lever .pc_xdrressize = St, 643*49d99608SChuck Lever }, 644*49d99608SChuck Lever [17] = { 645*49d99608SChuck Lever .pc_func = nlm4svc_proc_unused, 646*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 647*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 648*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_void), 649*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 650*49d99608SChuck Lever .pc_xdrressize = 0, 651*49d99608SChuck Lever }, 652*49d99608SChuck Lever [18] = { 653*49d99608SChuck Lever .pc_func = nlm4svc_proc_unused, 654*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 655*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 656*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_void), 657*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 658*49d99608SChuck Lever .pc_xdrressize = 0, 659*49d99608SChuck Lever }, 660*49d99608SChuck Lever [19] = { 661*49d99608SChuck Lever .pc_func = nlm4svc_proc_unused, 662*49d99608SChuck Lever .pc_decode = nlm4svc_decode_void, 663*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 664*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_void), 665*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 666*49d99608SChuck Lever .pc_xdrressize = 0, 667*49d99608SChuck Lever }, 668*49d99608SChuck Lever [NLMPROC_SHARE] = { 669*49d99608SChuck Lever .pc_func = nlm4svc_proc_share, 670*49d99608SChuck Lever .pc_decode = nlm4svc_decode_shareargs, 671*49d99608SChuck Lever .pc_encode = nlm4svc_encode_shareres, 672*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 673*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 674*49d99608SChuck Lever .pc_xdrressize = Ck+St+1, 675*49d99608SChuck Lever }, 676*49d99608SChuck Lever [NLMPROC_UNSHARE] = { 677*49d99608SChuck Lever .pc_func = nlm4svc_proc_unshare, 678*49d99608SChuck Lever .pc_decode = nlm4svc_decode_shareargs, 679*49d99608SChuck Lever .pc_encode = nlm4svc_encode_shareres, 680*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 681*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 682*49d99608SChuck Lever .pc_xdrressize = Ck+St+1, 683*49d99608SChuck Lever }, 684*49d99608SChuck Lever [NLMPROC_NM_LOCK] = { 685*49d99608SChuck Lever .pc_func = nlm4svc_proc_nm_lock, 686*49d99608SChuck Lever .pc_decode = nlm4svc_decode_lockargs, 687*49d99608SChuck Lever .pc_encode = nlm4svc_encode_res, 688*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 689*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_res), 690*49d99608SChuck Lever .pc_xdrressize = Ck+St, 691*49d99608SChuck Lever }, 692*49d99608SChuck Lever [NLMPROC_FREE_ALL] = { 693*49d99608SChuck Lever .pc_func = nlm4svc_proc_free_all, 694*49d99608SChuck Lever .pc_decode = nlm4svc_decode_notify, 695*49d99608SChuck Lever .pc_encode = nlm4svc_encode_void, 696*49d99608SChuck Lever .pc_argsize = sizeof(struct nlm_args), 697*49d99608SChuck Lever .pc_ressize = sizeof(struct nlm_void), 698*49d99608SChuck Lever .pc_xdrressize = St, 699*49d99608SChuck Lever }, 7001da177e4SLinus Torvalds }; 701