From: Chuck Lever Date: Tue, 12 May 2026 18:13:52 +0000 (-0400) Subject: lockd: Use xdrgen XDR functions for the NLMv3 UNLOCK procedure X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1b0490e6a0849f2f9e9bd901a8a151368f57030f;p=thirdparty%2Fkernel%2Flinux.git lockd: Use xdrgen XDR functions for the NLMv3 UNLOCK procedure The NLM UNLOCK procedure allows clients to release held locks, completing the basic lock lifecycle alongside TEST, LOCK, and CANCEL procedures already converted in this series. Convert UNLOCK to use the xdrgen functions nlm_svc_decode_nlm_unlockargs and nlm_svc_encode_nlm_res generated from the NLM version 3 protocol specification, reusing the nlm3svc_lookup_host() and nlm3svc_lookup_file() helpers introduced earlier in the series. The procedure handler uses xdrgen types through a wrapper structure that bridges between generated code and the legacy lockd_lock representation still used by the core lockd logic. Setting pc_argzero to zero is safe because the generated decoder fills the argp->xdrgen subfields before the procedure runs, so the zeroing memset performed by the dispatch layer is not needed. The lock member of the wrapper is populated explicitly in nlm3svc_lookup_file() rather than relying on zero-initialization. Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index a5e40ca3f1094..ccc6a633df7ba 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -72,6 +72,13 @@ struct nlm_cancargs_wrapper { static_assert(offsetof(struct nlm_cancargs_wrapper, xdrgen) == 0); +struct nlm_unlockargs_wrapper { + struct nlm_unlockargs xdrgen; + struct lockd_lock lock; +}; + +static_assert(offsetof(struct nlm_unlockargs_wrapper, xdrgen) == 0); + static __be32 nlm_netobj_to_cookie(struct lockd_cookie *cookie, netobj *object) { @@ -619,10 +626,61 @@ __nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct lockd_res *resp) return rpc_success; } +/** + * nlmsvc_proc_unlock - UNLOCK: Remove a lock + * @rqstp: RPC transaction context + * + * Returns: + * %rpc_success: RPC executed successfully. + * %rpc_drop_reply: Do not send an RPC reply. + * + * RPC synopsis: + * nlm_res NLM_UNLOCK(nlm_unlockargs) = 4; + * + * Permissible procedure status codes: + * %LCK_GRANTED: The requested lock was released. + * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is + * re-establishing existing locks, and is not + * yet ready to accept normal service requests. + * + * The Linux NLM server implementation also returns: + * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. + */ static __be32 nlmsvc_proc_unlock(struct svc_rqst *rqstp) { - return __nlmsvc_proc_unlock(rqstp, rqstp->rq_resp); + struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp; + struct nlm_res_wrapper *resp = rqstp->rq_resp; + struct net *net = SVC_NET(rqstp); + struct nlm_host *host = NULL; + struct nlm_file *file = NULL; + + resp->xdrgen.cookie = argp->xdrgen.cookie; + + resp->xdrgen.stat.stat = nlm_lck_denied_grace_period; + if (locks_in_grace(net)) + goto out; + + resp->xdrgen.stat.stat = nlm_lck_denied_nolocks; + host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); + if (!host) + goto out; + + resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock, + &file, &argp->xdrgen.alock, + F_UNLCK); + if (resp->xdrgen.stat.stat) + goto out; + + resp->xdrgen.stat.stat = nlmsvc_unlock(net, file, &argp->lock); + nlmsvc_release_lockowner(&argp->lock); + +out: + if (file) + nlm_release_file(file); + nlmsvc_release_host(host); + return resp->xdrgen.stat.stat == nlm__int__drop_reply ? + rpc_drop_reply : rpc_success; } /* @@ -944,15 +1002,15 @@ static const struct svc_procedure nlmsvc_procedures[24] = { .pc_xdrressize = NLM3_nlm_res_sz, .pc_name = "CANCEL", }, - [NLMPROC_UNLOCK] = { - .pc_func = nlmsvc_proc_unlock, - .pc_decode = nlmsvc_decode_unlockargs, - .pc_encode = nlmsvc_encode_res, - .pc_argsize = sizeof(struct lockd_args), - .pc_argzero = sizeof(struct lockd_args), - .pc_ressize = sizeof(struct lockd_res), - .pc_xdrressize = Ck+St, - .pc_name = "UNLOCK", + [NLM_UNLOCK] = { + .pc_func = nlmsvc_proc_unlock, + .pc_decode = nlm_svc_decode_nlm_unlockargs, + .pc_encode = nlm_svc_encode_nlm_res, + .pc_argsize = sizeof(struct nlm_unlockargs_wrapper), + .pc_argzero = 0, + .pc_ressize = sizeof(struct nlm_res_wrapper), + .pc_xdrressize = NLM3_nlm_res_sz, + .pc_name = "UNLOCK", }, [NLMPROC_GRANTED] = { .pc_func = nlmsvc_proc_granted, @@ -1153,6 +1211,7 @@ union nlmsvc_xdrstore { struct nlm_testargs_wrapper testargs; struct nlm_lockargs_wrapper lockargs; struct nlm_cancargs_wrapper cancargs; + struct nlm_unlockargs_wrapper unlockargs; struct nlm_testres_wrapper testres; struct nlm_res_wrapper res; struct lockd_args args;