From: Chuck Lever Date: Tue, 12 May 2026 18:13:50 +0000 (-0400) Subject: lockd: Use xdrgen XDR functions for the NLMv3 LOCK procedure X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a77fec7b732905f143e1977ac8614f1845579e72;p=thirdparty%2Flinux.git lockd: Use xdrgen XDR functions for the NLMv3 LOCK procedure The NLM LOCK procedure requires the same host and file lookup operations established in the TEST procedure conversion. This patch extends the xdrgen migration to the LOCK procedure, leveraging the shared nlm3svc_lookup_host() and nlm3svc_lookup_file() helpers to establish consistent patterns across the series. This patch converts the LOCK procedure to use xdrgen functions nlm_svc_decode_nlm_lockargs and nlm_svc_encode_nlm_res generated from the NLM version 3 protocol specification. The procedure handler uses xdrgen types through wrapper structures that bridge 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 cookie and lock members of the wrapper are populated explicitly in nlm_netobj_to_cookie() and nlm3svc_lookup_file() rather than relying on zero-initialization. The hand-rolled svcxdr_decode_cookie() previously substituted a four-byte zero cookie when a zero-length cookie arrived on the wire, a compatibility shim for HP-UX clients that had been carried in fs/lockd/ since the original import. The xdrgen decoder reproduces the cookie verbatim, and nlm_netobj_to_cookie() copies whatever length the peer sent. As subsequent patches replace the remaining call sites of svcxdr_decode_cookie(), this series retires that HP-UX compat behavior on the server side. Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 7794e6f88a711..66bc9a2efddb8 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -51,6 +51,30 @@ struct nlm_testres_wrapper { static_assert(offsetof(struct nlm_testres_wrapper, xdrgen) == 0); +struct nlm_lockargs_wrapper { + struct nlm_lockargs xdrgen; + struct lockd_cookie cookie; + struct lockd_lock lock; +}; + +static_assert(offsetof(struct nlm_lockargs_wrapper, xdrgen) == 0); + +struct nlm_res_wrapper { + struct nlm_res xdrgen; +}; + +static_assert(offsetof(struct nlm_res_wrapper, xdrgen) == 0); + +static __be32 +nlm_netobj_to_cookie(struct lockd_cookie *cookie, netobj *object) +{ + if (object->len > NLM_MAXCOOKIELEN) + return nlm_lck_denied_nolocks; + cookie->len = object->len; + memcpy(cookie->data, object->data, object->len); + return nlm_granted; +} + static struct nlm_host * nlm3svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored) { @@ -385,10 +409,79 @@ __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct lockd_res *resp) return rc; } +static __be32 +nlmsvc_do_lock(struct svc_rqst *rqstp, bool monitored) +{ + struct nlm_lockargs_wrapper *argp = rqstp->rq_argp; + unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; + struct nlm_res_wrapper *resp = rqstp->rq_resp; + struct nlm_file *file = NULL; + struct nlm_host *host = NULL; + + resp->xdrgen.cookie = argp->xdrgen.cookie; + + resp->xdrgen.stat.stat = nlm_netobj_to_cookie(&argp->cookie, + &argp->xdrgen.cookie); + if (resp->xdrgen.stat.stat) + goto out; + + resp->xdrgen.stat.stat = nlm_lck_denied_nolocks; + host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, + monitored); + if (!host) + goto out; + + resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock, + &file, &argp->xdrgen.alock, + type); + if (resp->xdrgen.stat.stat) + goto out; + + resp->xdrgen.stat.stat = cast_status(nlmsvc_lock(rqstp, file, host, + &argp->lock, + argp->xdrgen.block, + &argp->cookie, + argp->xdrgen.reclaim)); + + 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; +} + +/** + * nlmsvc_proc_lock - LOCK: Establish a monitored 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_LOCK(nlm_lockargs) = 2; + * + * Permissible procedure status codes: + * %LCK_GRANTED: The requested lock was granted. + * %LCK_DENIED: The requested lock conflicted with existing + * lock reservations for the file. + * %LCK_DENIED_NOLOCKS: The server could not allocate the resources + * needed to process the request. + * %LCK_BLOCKED: The blocking request cannot be granted + * immediately. The server will send an + * NLM_GRANTED callback to the client when + * the lock can be granted. + * %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. + */ static __be32 nlmsvc_proc_lock(struct svc_rqst *rqstp) { - return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp); + return nlmsvc_do_lock(rqstp, true); } static __be32 @@ -674,7 +767,7 @@ nlmsvc_proc_nm_lock(struct svc_rqst *rqstp) dprintk("lockd: NM_LOCK called\n"); argp->monitor = 0; /* just clean the monitor flag */ - return nlmsvc_proc_lock(rqstp); + return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp); } /* @@ -771,15 +864,15 @@ static const struct svc_procedure nlmsvc_procedures[24] = { .pc_xdrressize = NLM3_nlm_testres_sz, .pc_name = "TEST", }, - [NLMPROC_LOCK] = { - .pc_func = nlmsvc_proc_lock, - .pc_decode = nlmsvc_decode_lockargs, - .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 = "LOCK", + [NLM_LOCK] = { + .pc_func = nlmsvc_proc_lock, + .pc_decode = nlm_svc_decode_nlm_lockargs, + .pc_encode = nlm_svc_encode_nlm_res, + .pc_argsize = sizeof(struct nlm_lockargs_wrapper), + .pc_argzero = 0, + .pc_ressize = sizeof(struct nlm_res_wrapper), + .pc_xdrressize = NLM3_nlm_res_sz, + .pc_name = "LOCK", }, [NLMPROC_CANCEL] = { .pc_func = nlmsvc_proc_cancel, @@ -998,9 +1091,10 @@ static const struct svc_procedure nlmsvc_procedures[24] = { */ union nlmsvc_xdrstore { struct nlm_testargs_wrapper testargs; + struct nlm_lockargs_wrapper lockargs; struct nlm_testres_wrapper testres; + struct nlm_res_wrapper res; struct lockd_args args; - struct lockd_res res; struct lockd_reboot reboot; };