diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
commit | 482368b1a8e45430672c58c9a42e7d2004367126 (patch) | |
tree | ce2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /fs/lockd | |
parent | e4d0251c6f56ab2e191afb70f80f382793e23f74 (diff) |
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/Makefile | 5 | ||||
-rw-r--r-- | fs/lockd/clntproc.c | 2 | ||||
-rw-r--r-- | fs/lockd/lockd_syms.c | 11 | ||||
-rw-r--r-- | fs/lockd/svc.c | 4 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 561 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 20 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 45 | ||||
-rw-r--r-- | fs/lockd/svcsubs.c | 6 | ||||
-rw-r--r-- | fs/lockd/xdr.c | 19 | ||||
-rw-r--r-- | fs/lockd/xdr4.c | 601 |
10 files changed, 1257 insertions, 17 deletions
diff --git a/fs/lockd/Makefile b/fs/lockd/Makefile index 7c319ffc3..ceab1f466 100644 --- a/fs/lockd/Makefile +++ b/fs/lockd/Makefile @@ -10,6 +10,11 @@ O_TARGET := lockd.o O_OBJS := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \ svcproc.o svcsubs.o mon.o xdr.o + +ifdef CONFIG_LOCKD_V4 + O_OBJS += xdr4.o svc4proc.o +endif + OX_OBJS := lockd_syms.o M_OBJS := $(O_TARGET) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 4160bf2e3..517456326 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -69,7 +69,7 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) call->a_args.lock = *lock; call->a_args.lock.caller = system_utsname.nodename; - init_waitqueue_head(&lock->fl.fl_wait); + init_waitqueue_head(&call->a_args.lock.fl.fl_wait); /* set default data area */ call->a_args.lock.oh.data = call->a_owner; diff --git a/fs/lockd/lockd_syms.c b/fs/lockd/lockd_syms.c index b3990ed98..db36300ba 100644 --- a/fs/lockd/lockd_syms.c +++ b/fs/lockd/lockd_syms.c @@ -39,4 +39,15 @@ EXPORT_SYMBOL(nlmsvc_ops); EXPORT_SYMBOL(nlmsvc_grace_period); EXPORT_SYMBOL(nlmsvc_timeout); +#ifdef CONFIG_LOCKD_V4 + +/* NLM4 exported symbols */ +EXPORT_SYMBOL(nlm4_rofs); +EXPORT_SYMBOL(nlm4_stale_fh); +EXPORT_SYMBOL(nlm4_deadlock); +EXPORT_SYMBOL(nlm4_failed); +EXPORT_SYMBOL(nlm4_fbig); + +#endif + #endif /* CONFIG_MODULES */ diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index e22007445..62401adbd 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -343,7 +343,7 @@ static struct svc_version nlmsvc_version1 = { static struct svc_version nlmsvc_version3 = { 3, 24, nlmsvc_procedures, NULL }; -#ifdef CONFIG_NFSD_NFS3 +#ifdef CONFIG_LOCKD_V4 static struct svc_version nlmsvc_version4 = { 4, 24, nlmsvc_procedures4, NULL }; @@ -353,7 +353,7 @@ static struct svc_version * nlmsvc_version[] = { &nlmsvc_version1, NULL, &nlmsvc_version3, -#ifdef CONFIG_NFSD_NFS3 +#ifdef CONFIG_LOCKD_V4 &nlmsvc_version4, #endif }; diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c new file mode 100644 index 000000000..b690eb97e --- /dev/null +++ b/fs/lockd/svc4proc.c @@ -0,0 +1,561 @@ +/* + * linux/fs/lockd/svc4proc.c + * + * Lockd server procedures. We don't implement the NLM_*_RES + * procedures because we don't use the async procedures. + * + * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> + */ + +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/malloc.h> +#include <linux/in.h> +#include <linux/sunrpc/svc.h> +#include <linux/sunrpc/clnt.h> +#include <linux/nfsd/nfsd.h> +#include <linux/lockd/lockd.h> +#include <linux/lockd/share.h> +#include <linux/lockd/sm_inter.h> + + +#define NLMDBG_FACILITY NLMDBG_CLIENT + +static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); +static void nlm4svc_callback_exit(struct rpc_task *); + +/* + * Obtain client and file from arguments + */ +static u32 +nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_host **hostp, struct nlm_file **filp) +{ + struct nlm_host *host = NULL; + struct nlm_file *file = NULL; + struct nlm_lock *lock = &argp->lock; + u32 error = 0; + + /* nfsd callbacks must have been installed for this procedure */ + if (!nlmsvc_ops) + return nlm_lck_denied_nolocks; + + /* Obtain handle for client host */ + if (rqstp->rq_client == NULL) { + printk(KERN_NOTICE + "lockd: unauthenticated request from (%08x:%d)\n", + ntohl(rqstp->rq_addr.sin_addr.s_addr), + ntohs(rqstp->rq_addr.sin_port)); + return nlm_lck_denied_nolocks; + } + + /* Obtain host handle */ + if (!(host = nlmsvc_lookup_host(rqstp)) + || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) + goto no_locks; + *hostp = host; + + /* Obtain file pointer. Not used by FREE_ALL call. */ + if (filp != NULL) { + if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) + goto no_locks; + *filp = file; + + /* Set up the missing parts of the file_lock structure */ + lock->fl.fl_file = &file->f_file; + lock->fl.fl_owner = (fl_owner_t) host; + } + + return 0; + +no_locks: + if (host) + nlm_release_host(host); + if (error) + return error; + return nlm_lck_denied_nolocks; +} + +/* + * NULL: Test for presence of service + */ +static int +nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) +{ + dprintk("lockd: NULL called\n"); + return rpc_success; +} + +/* + * TEST: Check for conflicting lock + */ +static int +nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_file *file; + + dprintk("lockd: TEST4 called\n"); + resp->cookie = argp->cookie; + + /* Don't accept test requests during grace period */ + if (nlmsvc_grace_period) { + resp->status = nlm_lck_denied_grace_period; + return rpc_success; + } + + /* Obtain client and file */ + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return rpc_success; + + /* Now check for conflicting locks */ + resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); + + dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); + nlm_release_host(host); + nlm_release_file(file); + return rpc_success; +} + +static int +nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_file *file; + + dprintk("lockd: LOCK called\n"); + + resp->cookie = argp->cookie; + + /* Don't accept new lock requests during grace period */ + if (nlmsvc_grace_period && !argp->reclaim) { + resp->status = nlm_lck_denied_grace_period; + return rpc_success; + } + + /* Obtain client and file */ + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return rpc_success; + +#if 0 + /* If supplied state doesn't match current state, we assume it's + * an old request that time-warped somehow. Any error return would + * do in this case because it's irrelevant anyway. + * + * NB: We don't retrieve the remote host's state yet. + */ + if (host->h_nsmstate && host->h_nsmstate != argp->state) { + resp->status = nlm_lck_denied_nolocks; + } else +#endif + + /* Now try to lock the file */ + resp->status = nlmsvc_lock(rqstp, file, &argp->lock, + argp->block, &argp->cookie); + + dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); + nlm_release_host(host); + nlm_release_file(file); + return rpc_success; +} + +static int +nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_file *file; + + dprintk("lockd: CANCEL called\n"); + + resp->cookie = argp->cookie; + + /* Don't accept requests during grace period */ + if (nlmsvc_grace_period) { + resp->status = nlm_lck_denied_grace_period; + return rpc_success; + } + + /* Obtain client and file */ + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return rpc_success; + + /* Try to cancel request. */ + resp->status = nlmsvc_cancel_blocked(file, &argp->lock); + + dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); + nlm_release_host(host); + nlm_release_file(file); + return rpc_success; +} + +/* + * UNLOCK: release a lock + */ +static int +nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_file *file; + + dprintk("lockd: UNLOCK called\n"); + + resp->cookie = argp->cookie; + + /* Don't accept new lock requests during grace period */ + if (nlmsvc_grace_period) { + resp->status = nlm_lck_denied_grace_period; + return rpc_success; + } + + /* Obtain client and file */ + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return rpc_success; + + /* Now try to remove the lock */ + resp->status = nlmsvc_unlock(file, &argp->lock); + + dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); + nlm_release_host(host); + nlm_release_file(file); + return rpc_success; +} + +/* + * GRANTED: A server calls us to tell that a process' lock request + * was granted + */ +static int +nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + resp->cookie = argp->cookie; + + dprintk("lockd: GRANTED called\n"); + resp->status = nlmclnt_grant(&argp->lock); + dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); + return rpc_success; +} + +/* + * `Async' versions of the above service routines. They aren't really, + * because we send the callback before the reply proper. I hope this + * doesn't break any clients. + */ +static int +nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ + struct nlm_res res; + u32 stat; + + dprintk("lockd: TEST_MSG called\n"); + + if ((stat = nlm4svc_proc_test(rqstp, argp, &res)) == 0) + stat = nlm4svc_callback(rqstp, NLMPROC_TEST_RES, &res); + return stat; +} + +static int +nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ + struct nlm_res res; + u32 stat; + + dprintk("lockd: LOCK_MSG called\n"); + + if ((stat = nlm4svc_proc_lock(rqstp, argp, &res)) == 0) + stat = nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, &res); + return stat; +} + +static int +nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ + struct nlm_res res; + u32 stat; + + dprintk("lockd: CANCEL_MSG called\n"); + + if ((stat = nlm4svc_proc_cancel(rqstp, argp, &res)) == 0) + stat = nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, &res); + return stat; +} + +static int +nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ + struct nlm_res res; + u32 stat; + + dprintk("lockd: UNLOCK_MSG called\n"); + + if ((stat = nlm4svc_proc_unlock(rqstp, argp, &res)) == 0) + stat = nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, &res); + return stat; +} + +static int +nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ + struct nlm_res res; + u32 stat; + + dprintk("lockd: GRANTED_MSG called\n"); + + if ((stat = nlm4svc_proc_granted(rqstp, argp, &res)) == 0) + stat = nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, &res); + return stat; +} + +/* + * SHARE: create a DOS share or alter existing share. + */ +static int +nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_file *file; + + dprintk("lockd: SHARE called\n"); + + resp->cookie = argp->cookie; + + /* Don't accept new lock requests during grace period */ + if (nlmsvc_grace_period && !argp->reclaim) { + resp->status = nlm_lck_denied_grace_period; + return rpc_success; + } + + /* Obtain client and file */ + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return rpc_success; + + /* Now try to create the share */ + resp->status = nlmsvc_share_file(host, file, argp); + + dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); + nlm_release_host(host); + nlm_release_file(file); + return rpc_success; +} + +/* + * UNSHARE: Release a DOS share. + */ +static int +nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_file *file; + + dprintk("lockd: UNSHARE called\n"); + + resp->cookie = argp->cookie; + + /* Don't accept requests during grace period */ + if (nlmsvc_grace_period) { + resp->status = nlm_lck_denied_grace_period; + return rpc_success; + } + + /* Obtain client and file */ + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return rpc_success; + + /* Now try to lock the file */ + resp->status = nlmsvc_unshare_file(host, file, argp); + + dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); + nlm_release_host(host); + nlm_release_file(file); + return rpc_success; +} + +/* + * NM_LOCK: Create an unmonitored lock + */ +static int +nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, + struct nlm_res *resp) +{ + dprintk("lockd: NM_LOCK called\n"); + + argp->monitor = 0; /* just clean the monitor flag */ + return nlm4svc_proc_lock(rqstp, argp, resp); +} + +/* + * FREE_ALL: Release all locks and shares held by client + */ +static int +nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ + struct nlm_host *host; + + /* Obtain client */ + if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL)) + return rpc_success; + + nlmsvc_free_host_resources(host); + nlm_release_host(host); + return rpc_success; +} + +/* + * SM_NOTIFY: private callback from statd (not part of official NLM proto) + */ +static int +nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, + void *resp) +{ + struct sockaddr_in saddr = rqstp->rq_addr; + struct nlm_host *host; + + dprintk("lockd: SM_NOTIFY called\n"); + if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) + || ntohs(saddr.sin_port) >= 1024) { + printk(KERN_WARNING + "lockd: rejected NSM callback from %08x:%d\n", + ntohl(rqstp->rq_addr.sin_addr.s_addr), + ntohs(rqstp->rq_addr.sin_port)); + return rpc_system_err; + } + + /* Obtain the host pointer for this NFS server and try to + * reclaim all locks we hold on this server. + */ + saddr.sin_addr.s_addr = argp->addr; + if ((host = nlm_lookup_host(NULL, &saddr, IPPROTO_UDP, 1)) != NULL) { + nlmclnt_recovery(host, argp->state); + nlm_release_host(host); + } + + /* If we run on an NFS server, delete all locks held by the client */ + if (nlmsvc_ops != NULL) { + struct svc_client *clnt; + saddr.sin_addr.s_addr = argp->addr; + if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL + && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) { + nlmsvc_free_host_resources(host); + } + nlm_release_host(host); + } + + return rpc_success; +} + +/* + * This is the generic lockd callback for async RPC calls + */ +static u32 +nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) +{ + struct nlm_host *host; + struct nlm_rqst *call; + + if (!(call = nlmclnt_alloc_call())) + return rpc_system_err; + + host = nlmclnt_lookup_host(&rqstp->rq_addr, + rqstp->rq_prot, rqstp->rq_vers); + if (!host) { + rpc_free(call); + return rpc_system_err; + } + + call->a_flags = RPC_TASK_ASYNC; + call->a_host = host; + memcpy(&call->a_args, resp, sizeof(*resp)); + +/* FIXME this should become nlmSVC_async_call when that code gets + merged in XXX */ + if (nlmclnt_async_call(call, proc, nlm4svc_callback_exit) < 0) + return rpc_system_err; + + return rpc_success; +} + +static void +nlm4svc_callback_exit(struct rpc_task *task) +{ + struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; + + if (task->tk_status < 0) { + dprintk("lockd: %4d callback failed (errno = %d)\n", + task->tk_pid, -task->tk_status); + } + nlm_release_host(call->a_host); + rpc_free(call); +} + +/* + * NLM Server procedures. + */ + +#define nlm4svc_encode_norep nlm4svc_encode_void +#define nlm4svc_decode_norep nlm4svc_decode_void +#define nlm4svc_decode_testres nlm4svc_decode_void +#define nlm4svc_decode_lockres nlm4svc_decode_void +#define nlm4svc_decode_unlockres nlm4svc_decode_void +#define nlm4svc_decode_cancelres nlm4svc_decode_void +#define nlm4svc_decode_grantedres nlm4svc_decode_void + +#define nlm4svc_proc_none nlm4svc_proc_null +#define nlm4svc_proc_test_res nlm4svc_proc_null +#define nlm4svc_proc_lock_res nlm4svc_proc_null +#define nlm4svc_proc_cancel_res nlm4svc_proc_null +#define nlm4svc_proc_unlock_res nlm4svc_proc_null +#define nlm4svc_proc_granted_res nlm4svc_proc_null + +struct nlm_void { int dummy; }; + +#define PROC(name, xargt, xrest, argt, rest) \ + { (svc_procfunc) nlm4svc_proc_##name, \ + (kxdrproc_t) nlm4svc_decode_##xargt, \ + (kxdrproc_t) nlm4svc_encode_##xrest, \ + NULL, \ + sizeof(struct nlm_##argt), \ + sizeof(struct nlm_##rest), \ + 0, \ + 0 \ + } +struct svc_procedure nlmsvc_procedures4[] = { + PROC(null, void, void, void, void), + PROC(test, testargs, testres, args, res), + PROC(lock, lockargs, res, args, res), + PROC(cancel, cancargs, res, args, res), + PROC(unlock, unlockargs, res, args, res), + PROC(granted, testargs, res, args, res), + PROC(test_msg, testargs, norep, args, void), + PROC(lock_msg, lockargs, norep, args, void), + PROC(cancel_msg, cancargs, norep, args, void), + PROC(unlock_msg, unlockargs, norep, args, void), + PROC(granted_msg, testargs, norep, args, void), + PROC(test_res, testres, norep, res, void), + PROC(lock_res, lockres, norep, res, void), + PROC(cancel_res, cancelres, norep, res, void), + PROC(unlock_res, unlockres, norep, res, void), + PROC(granted_res, grantedres, norep, res, void), + PROC(none, void, void, void, void), + PROC(none, void, void, void, void), + PROC(none, void, void, void, void), + PROC(none, void, void, void, void), + PROC(share, shareargs, shareres, args, res), + PROC(unshare, shareargs, shareres, args, res), + PROC(nm_lock, lockargs, res, args, res), + PROC(free_all, notify, void, args, void), + + /* statd callback */ + PROC(sm_notify, reboot, void, reboot, void), +}; diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 73caf6349..1bed616cb 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -20,6 +20,7 @@ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> */ +#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> @@ -98,9 +99,10 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) lock->fl.fl_end, lock->fl.fl_type); for (head = &nlm_blocked; (block = *head); head = &block->b_next) { fl = &block->b_call.a_args.lock.fl; - dprintk(" check f=%p pd=%d %ld-%ld ty=%d\n", + dprintk("lockd: check f=%p pd=%d %ld-%ld ty=%d cookie=%x\n", block->b_file, fl->fl_pid, fl->fl_start, - fl->fl_end, fl->fl_type); + fl->fl_end, fl->fl_type, + *(unsigned int*)(block->b_call.a_args.cookie.data)); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { if (remove) *head = block->b_next; @@ -129,6 +131,8 @@ nlmsvc_find_block(struct nlm_cookie *cookie) struct nlm_block *block; for (block = nlm_blocked; block; block = block->b_next) { + dprintk("cookie: head of blocked queue %p, block %p\n", + nlm_blocked, block); if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie)) break; } @@ -310,7 +314,13 @@ again: switch(-error) { case 0: return nlm_granted; - case EDEADLK: /* no applicable NLM status */ + case EDEADLK: +#ifdef CONFIG_LOCKD_V4 + return nlm4_deadlock; /* will be downgraded to lck_deined if this + * is a NLMv1,3 request */ +#else + /* no applicable NLM status */ +#endif case EAGAIN: return nlm_lck_denied; default: /* includes ENOLCK */ @@ -541,6 +551,8 @@ nlmsvc_grant_callback(struct rpc_task *task) unsigned long timeout; dprintk("lockd: GRANT_MSG RPC callback\n"); + dprintk("callback: looking for cookie %x \n", + *(unsigned int *)(call->a_args.cookie.data)); if (!(block = nlmsvc_find_block(&call->a_args.cookie))) { dprintk("lockd: no block for cookie %x\n", *(u32 *)(call->a_args.cookie.data)); return; @@ -617,7 +629,7 @@ nlmsvc_retry_blocked(void) dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", nlm_blocked, nlm_blocked? nlm_blocked->b_when : 0); - while ((block = nlm_blocked) && block->b_when < jiffies) { + while ((block = nlm_blocked) && block->b_when <= jiffies) { dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", block, block->b_when, block->b_done); if (block->b_done) diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 142d593b2..c92358dec 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -7,6 +7,7 @@ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> */ +#include <linux/config.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/malloc.h> @@ -24,6 +25,31 @@ static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *); static void nlmsvc_callback_exit(struct rpc_task *); +#ifdef CONFIG_LOCKD_V4 +static u32 +cast_to_nlm(u32 status, u32 vers) +{ + + if (vers != 4){ + switch(ntohl(status)){ + case NLM_LCK_GRANTED: + case NLM_LCK_DENIED: + case NLM_LCK_DENIED_NOLOCKS: + case NLM_LCK_BLOCKED: + case NLM_LCK_DENIED_GRACE_PERIOD: + break; + default: + status = NLM_LCK_DENIED_NOLOCKS; + } + } + + return (status); +} +#define cast_status(status) (cast_to_nlm(status, rqstp->rq_vers)) +#else +#define cast_status(status) (status) +#endif + /* * Obtain client and file from arguments */ @@ -108,9 +134,10 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; /* Now check for conflicting locks */ - resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); + resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock)); - dprintk("lockd: TEST status %d\n", ntohl(resp->status)); + dprintk("lockd: TEST status %d vers %d\n", + ntohl(resp->status), rqstp->rq_vers); nlm_release_host(host); nlm_release_file(file); return rpc_success; @@ -150,8 +177,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, #endif /* Now try to lock the file */ - resp->status = nlmsvc_lock(rqstp, file, &argp->lock, - argp->block, &argp->cookie); + resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, + argp->block, &argp->cookie)); dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); nlm_release_host(host); @@ -181,7 +208,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; /* Try to cancel request. */ - resp->status = nlmsvc_cancel_blocked(file, &argp->lock); + resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock)); dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); nlm_release_host(host); @@ -214,7 +241,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; /* Now try to remove the lock */ - resp->status = nlmsvc_unlock(file, &argp->lock); + resp->status = cast_status(nlmsvc_unlock(file, &argp->lock)); dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); nlm_release_host(host); @@ -338,7 +365,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; /* Now try to create the share */ - resp->status = nlmsvc_share_file(host, file, argp); + resp->status = cast_status(nlmsvc_share_file(host, file, argp)); dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); nlm_release_host(host); @@ -370,8 +397,8 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) return rpc_success; - /* Now try to lock the file */ - resp->status = nlmsvc_unshare_file(host, file, argp); + /* Now try to unshare the file */ + resp->status = cast_status(nlmsvc_unshare_file(host, file, argp)); dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); nlm_release_host(host); diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 8d15cba9a..b3489a88d 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -6,6 +6,7 @@ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> */ +#include <linux/config.h> #include <linux/types.h> #include <linux/string.h> #include <linux/sched.h> @@ -105,6 +106,11 @@ out_unlock: out_free: kfree(file); +#ifdef CONFIG_LOCKD_V4 + if (nfserr == 1) + nfserr = nlm4_stale_fh; + else +#endif nfserr = nlm_lck_denied; goto out_unlock; } diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 0902eaa0d..c0797a16f 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -6,6 +6,7 @@ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ +#include <linux/config.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/utsname.h> @@ -47,6 +48,14 @@ nlmxdr_init(void) nlm_lck_blocked = htonl(NLM_LCK_BLOCKED); nlm_lck_denied_grace_period = htonl(NLM_LCK_DENIED_GRACE_PERIOD); +#ifdef CONFIG_LOCKD_V4 + nlm4_deadlock = htonl(NLM_DEADLCK); + nlm4_rofs = htonl(NLM_ROFS); + nlm4_stale_fh = htonl(NLM_STALE_FH); + nlm4_fbig = htonl(NLM_FBIG); + nlm4_failed = htonl(NLM_FAILED); +#endif + inited = 1; } @@ -541,7 +550,8 @@ nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) { "nlm_" #proc, \ (kxdrproc_t) nlmclt_encode_##argtype, \ (kxdrproc_t) nlmclt_decode_##restype, \ - MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2 \ + MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2, \ + 0 \ } static struct rpc_procinfo nlm_procedures[] = { @@ -586,11 +596,18 @@ static struct rpc_version nlm_version3 = { 3, 24, nlm_procedures, }; +#ifdef CONFIG_LOCKD_V4 +extern struct rpc_version nlm_version4; +#endif + static struct rpc_version * nlm_versions[] = { NULL, &nlm_version1, NULL, &nlm_version3, +#ifdef CONFIG_LOCKD_V4 + &nlm_version4, +#endif }; static struct rpc_stat nlm_stats; diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c new file mode 100644 index 000000000..7cedcd849 --- /dev/null +++ b/fs/lockd/xdr4.c @@ -0,0 +1,601 @@ +/* + * linux/fs/lockd/xdr4.c + * + * XDR support for lockd and the lock client. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no> + */ + +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/utsname.h> +#include <linux/nfs.h> + +#include <linux/sunrpc/xdr.h> +#include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/svc.h> +#include <linux/sunrpc/stats.h> +#include <linux/lockd/lockd.h> +#include <linux/lockd/sm_inter.h> + +#define NLMDBG_FACILITY NLMDBG_XDR +#define NLM_MAXSTRLEN 1024 +#define OFFSET_MAX ((off_t)LONG_MAX) + +#define QUADLEN(len) (((len) + 3) >> 2) + +u32 nlm4_deadlock, nlm4_rofs, nlm4_stale_fh, nlm4_fbig, + nlm4_failed; + + +typedef struct nlm_args nlm_args; + +static inline off_t +size_to_off_t(__s64 size) +{ + size = (size > (__s64)LONG_MAX) ? (off_t)LONG_MAX : (off_t) size; + return (size < (__s64)-LONG_MAX) ? (off_t)-LONG_MAX : (off_t) size; +} + +/* + * XDR functions for basic NLM types + */ +static u32 * +nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) +{ + unsigned int len; + + len = ntohl(*p++); + + if(len==0) + { + c->len=4; + memset(c->data, 0, 4); /* hockeypux brain damage */ + } + else if(len<=8) + { + c->len=len; + memcpy(c->data, p, len); + p+=(len+3)>>2; + } + else + { + printk(KERN_NOTICE + "lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len); + return NULL; + } + return p; +} + +static u32 * +nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) +{ + *p++ = htonl(c->len); + memcpy(p, c->data, c->len); + p+=(c->len+3)>>2; + return p; +} + +static u32 * +nlm4_decode_fh(u32 *p, struct nfs_fh *f) +{ + memset(f->data, 0, sizeof(f->data)); +#ifdef NFS_MAXFHSIZE + f->size = ntohl(*p++); + if (f->size > NFS_MAXFHSIZE) { + printk(KERN_NOTICE + "lockd: bad fhandle size %x (should be %d)\n", + f->size, NFS_MAXFHSIZE); + return NULL; + } + memcpy(f->data, p, f->size); + return p + XDR_QUADLEN(f->size); +#else + if (ntohl(*p++) != NFS_FHSIZE) + return NULL; /* for now, all filehandles are 32 bytes */ + memcpy(f->data, p, NFS_FHSIZE); + return p + XDR_QUADLEN(NFS_FHSIZE); +#endif +} + +static u32 * +nlm4_encode_fh(u32 *p, struct nfs_fh *f) +{ +#ifdef NFS_MAXFHSIZE + *p++ = htonl(f->size); + memcpy(p, f->data, f->size); + return p + XDR_QUADLEN(f->size); +#else + *p++ = htonl(NFS_FHSIZE); + memcpy(p, f->data, NFS_FHSIZE); + return p + XDR_QUADLEN(NFS_FHSIZE); +#endif +} + +/* + * Encode and decode owner handle + */ +static u32 * +nlm4_decode_oh(u32 *p, struct xdr_netobj *oh) +{ + return xdr_decode_netobj(p, oh); +} + +static u32 * +nlm4_encode_oh(u32 *p, struct xdr_netobj *oh) +{ + return xdr_encode_netobj(p, oh); +} + +static u32 * +nlm4_decode_lock(u32 *p, struct nlm_lock *lock) +{ + struct file_lock *fl = &lock->fl; + __s64 len, start, end; + int tmp; + + if (!(p = xdr_decode_string(p, &lock->caller, &tmp, NLM_MAXSTRLEN)) + || !(p = nlm4_decode_fh(p, &lock->fh)) + || !(p = nlm4_decode_oh(p, &lock->oh))) + return NULL; + + memset(fl, 0, sizeof(*fl)); + fl->fl_owner = current->files; + fl->fl_pid = ntohl(*p++); + fl->fl_flags = FL_POSIX; + fl->fl_type = F_RDLCK; /* as good as anything else */ + p = xdr_decode_hyper(p, &start); + p = xdr_decode_hyper(p, &len); + end = start + len - 1; + + fl->fl_start = size_to_off_t(start); + fl->fl_end = size_to_off_t(end); + + if (len == 0 || fl->fl_end < 0) + fl->fl_end = OFFSET_MAX; + return p; +} + +/* + * Encode a lock as part of an NLM call + */ +static u32 * +nlm4_encode_lock(u32 *p, struct nlm_lock *lock) +{ + struct file_lock *fl = &lock->fl; + + if (!(p = xdr_encode_string(p, lock->caller)) + || !(p = nlm4_encode_fh(p, &lock->fh)) + || !(p = nlm4_encode_oh(p, &lock->oh))) + return NULL; + + *p++ = htonl(fl->fl_pid); + p = xdr_encode_hyper(p, fl->fl_start); + if (fl->fl_end == OFFSET_MAX) + p = xdr_encode_hyper(p, 0); + else + p = xdr_encode_hyper(p, fl->fl_end - fl->fl_start + 1); + + return p; +} + +/* + * Encode result of a TEST/TEST_MSG call + */ +static u32 * +nlm4_encode_testres(u32 *p, struct nlm_res *resp) +{ + dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); + if (!(p = nlm4_encode_cookie(p, &resp->cookie))) + return 0; + *p++ = resp->status; + + if (resp->status == nlm_lck_denied) { + struct file_lock *fl = &resp->lock.fl; + + *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; + *p++ = htonl(fl->fl_pid); + + /* Encode owner handle. */ + if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) + return 0; + + p = xdr_encode_hyper(p, fl->fl_start); + if (fl->fl_end == OFFSET_MAX) + p = xdr_encode_hyper(p, 0); + else + p = xdr_encode_hyper(p, fl->fl_end - fl->fl_start + 1); + dprintk("xdr: encode_testres (status %d pid %d type %d start %ld end %ld)\n", resp->status, fl->fl_pid, fl->fl_type, fl->fl_start, fl->fl_end); + } + + dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); + return p; +} + + +/* + * Check buffer bounds after decoding arguments + */ +static int +xdr_argsize_check(struct svc_rqst *rqstp, u32 *p) +{ + struct svc_buf *buf = &rqstp->rq_argbuf; + + return p - buf->base <= buf->buflen; +} + +static int +xdr_ressize_check(struct svc_rqst *rqstp, u32 *p) +{ + struct svc_buf *buf = &rqstp->rq_resbuf; + + buf->len = p - buf->base; + return (buf->len <= buf->buflen); +} + +/* + * First, the server side XDR functions + */ +int +nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +{ + u32 exclusive; + + if (!(p = nlm4_decode_cookie(p, &argp->cookie))) + return 0; + + exclusive = ntohl(*p++); + if (!(p = nlm4_decode_lock(p, &argp->lock))) + return 0; + if (exclusive) + argp->lock.fl.fl_type = F_WRLCK; + + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_encode_testres(p, resp))) + return 0; + return xdr_ressize_check(rqstp, p); +} + +int +nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +{ + u32 exclusive; + + if (!(p = nlm4_decode_cookie(p, &argp->cookie))) + return 0; + argp->block = ntohl(*p++); + exclusive = ntohl(*p++); + if (!(p = nlm4_decode_lock(p, &argp->lock))) + return 0; + if (exclusive) + argp->lock.fl.fl_type = F_WRLCK; + argp->reclaim = ntohl(*p++); + argp->state = ntohl(*p++); + argp->monitor = 1; /* monitor client by default */ + + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +{ + u32 exclusive; + + if (!(p = nlm4_decode_cookie(p, &argp->cookie))) + return 0; + argp->block = ntohl(*p++); + exclusive = ntohl(*p++); + if (!(p = nlm4_decode_lock(p, &argp->lock))) + return 0; + if (exclusive) + argp->lock.fl.fl_type = F_WRLCK; + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +{ + if (!(p = nlm4_decode_cookie(p, &argp->cookie)) + || !(p = nlm4_decode_lock(p, &argp->lock))) + return 0; + argp->lock.fl.fl_type = F_UNLCK; + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +{ + struct nlm_lock *lock = &argp->lock; + int len; + + memset(lock, 0, sizeof(*lock)); + lock->fl.fl_pid = ~(u32) 0; + + if (!(p = nlm4_decode_cookie(p, &argp->cookie)) + || !(p = xdr_decode_string(p, &lock->caller, &len, NLM_MAXSTRLEN)) + || !(p = nlm4_decode_fh(p, &lock->fh)) + || !(p = nlm4_decode_oh(p, &lock->oh))) + return 0; + argp->fsm_mode = ntohl(*p++); + argp->fsm_access = ntohl(*p++); + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_encode_cookie(p, &resp->cookie))) + return 0; + *p++ = resp->status; + *p++ = xdr_zero; /* sequence argument */ + return xdr_ressize_check(rqstp, p); +} + +int +nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_encode_cookie(p, &resp->cookie))) + return 0; + *p++ = resp->status; + return xdr_ressize_check(rqstp, p); +} + +int +nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) +{ + struct nlm_lock *lock = &argp->lock; + int len; + + if (!(p = xdr_decode_string(p, &lock->caller, &len, NLM_MAXSTRLEN))) + return 0; + argp->state = ntohl(*p++); + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) +{ + if (!(p = xdr_decode_string(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) + return 0; + argp->state = ntohl(*p++); + argp->addr = ntohl(*p++); + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_decode_cookie(p, &resp->cookie))) + return 0; + resp->status = ntohl(*p++); + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +{ + return xdr_argsize_check(rqstp, p); +} + +int +nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +{ + return xdr_ressize_check(rqstp, p); +} + +/* + * Now, the client side XDR functions + */ +static int +nlm4clt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr) +{ + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) +{ + return 0; +} + +static int +nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +{ + struct nlm_lock *lock = &argp->lock; + + if (!(p = nlm4_encode_cookie(p, &argp->cookie))) + return -EIO; + *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; + if (!(p = nlm4_encode_lock(p, lock))) + return -EIO; + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_decode_cookie(p, &resp->cookie))) + return -EIO; + resp->status = ntohl(*p++); + if (resp->status == NLM_LCK_DENIED) { + struct file_lock *fl = &resp->lock.fl; + u32 excl; + s64 start, end, len; + + memset(&resp->lock, 0, sizeof(resp->lock)); + excl = ntohl(*p++); + fl->fl_pid = ntohl(*p++); + if (!(p = nlm4_decode_oh(p, &resp->lock.oh))) + return -EIO; + + fl->fl_flags = FL_POSIX; + fl->fl_type = excl? F_WRLCK : F_RDLCK; + p = xdr_decode_hyper(p, &start); + p = xdr_decode_hyper(p, &len); + end = start + len - 1; + + fl->fl_start = size_to_off_t(start); + fl->fl_end = size_to_off_t(end); + if (len == 0 || fl->fl_end < 0) + fl->fl_end = OFFSET_MAX; + } + return 0; +} + + +static int +nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +{ + struct nlm_lock *lock = &argp->lock; + + if (!(p = nlm4_encode_cookie(p, &argp->cookie))) + return -EIO; + *p++ = argp->block? xdr_one : xdr_zero; + *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; + if (!(p = nlm4_encode_lock(p, lock))) + return -EIO; + *p++ = argp->reclaim? xdr_one : xdr_zero; + *p++ = htonl(argp->state); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +{ + struct nlm_lock *lock = &argp->lock; + + if (!(p = nlm4_encode_cookie(p, &argp->cookie))) + return -EIO; + *p++ = argp->block? xdr_one : xdr_zero; + *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; + if (!(p = nlm4_encode_lock(p, lock))) + return -EIO; + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +{ + struct nlm_lock *lock = &argp->lock; + + if (!(p = nlm4_encode_cookie(p, &argp->cookie))) + return -EIO; + if (!(p = nlm4_encode_lock(p, lock))) + return -EIO; + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_encode_cookie(p, &resp->cookie))) + return -EIO; + *p++ = resp->status; + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_encode_testres(p, resp))) + return -EIO; + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +static int +nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +{ + if (!(p = nlm4_decode_cookie(p, &resp->cookie))) + return -EIO; + resp->status = ntohl(*p++); + return 0; +} + +/* + * Buffer requirements for NLM + */ +#define NLM4_void_sz 0 +#define NLM4_cookie_sz 3 /* 1 len , 2 data */ +#define NLM4_caller_sz 1+XDR_QUADLEN(NLM_MAXSTRLEN) +#define NLM4_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) +/* #define NLM4_owner_sz 1+XDR_QUADLEN(NLM4_MAXOWNER) */ +#define NLM4_fhandle_sz 1+XDR_QUADLEN(NFS3_FHSIZE) +#define NLM4_lock_sz 5+NLM4_caller_sz+NLM4_netobj_sz+NLM4_fhandle_sz +#define NLM4_holder_sz 6+NLM4_netobj_sz + +#define NLM4_testargs_sz NLM4_cookie_sz+1+NLM4_lock_sz +#define NLM4_lockargs_sz NLM4_cookie_sz+4+NLM4_lock_sz +#define NLM4_cancargs_sz NLM4_cookie_sz+2+NLM4_lock_sz +#define NLM4_unlockargs_sz NLM4_cookie_sz+NLM4_lock_sz + +#define NLM4_testres_sz NLM4_cookie_sz+1+NLM4_holder_sz +#define NLM4_res_sz NLM4_cookie_sz+1 +#define NLM4_norep_sz 0 + +#ifndef MAX +# define MAX(a,b) (((a) > (b))? (a) : (b)) +#endif + +/* + * For NLM, a void procedure really returns nothing + */ +#define nlm4clt_decode_norep NULL + +#define PROC(proc, argtype, restype) \ + { "nlm4_" #proc, \ + (kxdrproc_t) nlm4clt_encode_##argtype, \ + (kxdrproc_t) nlm4clt_decode_##restype, \ + MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2, \ + 0 \ + } + +static struct rpc_procinfo nlm4_procedures[] = { + PROC(null, void, void), + PROC(test, testargs, testres), + PROC(lock, lockargs, res), + PROC(canc, cancargs, res), + PROC(unlock, unlockargs, res), + PROC(granted, testargs, res), + PROC(test_msg, testargs, norep), + PROC(lock_msg, lockargs, norep), + PROC(canc_msg, cancargs, norep), + PROC(unlock_msg, unlockargs, norep), + PROC(granted_msg, testargs, norep), + PROC(test_res, testres, norep), + PROC(lock_res, res, norep), + PROC(canc_res, res, norep), + PROC(unlock_res, res, norep), + PROC(granted_res, res, norep), + PROC(undef, void, void), + PROC(undef, void, void), + PROC(undef, void, void), + PROC(undef, void, void), +#ifdef NLMCLNT_SUPPORT_SHARES + PROC(share, shareargs, shareres), + PROC(unshare, shareargs, shareres), + PROC(nm_lock, lockargs, res), + PROC(free_all, notify, void), +#else + PROC(undef, void, void), + PROC(undef, void, void), + PROC(undef, void, void), + PROC(undef, void, void), +#endif +}; + +struct rpc_version nlm_version4 = { + 4, 24, nlm4_procedures, +}; |