]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
lockd: Use xdrgen XDR functions for the NLMv3 GRANTED procedure
authorChuck Lever <chuck.lever@oracle.com>
Tue, 12 May 2026 18:13:53 +0000 (14:13 -0400)
committerChuck Lever <cel@kernel.org>
Tue, 9 Jun 2026 20:32:59 +0000 (16:32 -0400)
The NLM GRANTED procedure allows servers to notify clients when
a previously blocked lock request has been granted, completing
the asynchronous lock request flow. This patch converts the NLMv3
GRANTED procedure to use xdrgen-generated XDR functions.

The conversion replaces the legacy decoder with the xdrgen
functions nlm_svc_decode_nlm_testargs and nlm_svc_encode_nlm_res
generated from the NLM version 3 protocol specification. The
procedure handler accesses xdrgen types through a wrapper structure
that bridges between generated code and the legacy lockd_lock
representation still used by the core lockd logic.

A new helper function nlm_lock_to_lockd_lock() converts an xdrgen
nlm_lock into the legacy lockd_lock format. The helper complements
the existing nlm3svc_lookup_host() and nlm3svc_lookup_file()
functions used throughout this series.

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
helper populates each field of the wrapper's lock member that any
downstream consumer reads: fh, oh, svid, and the file_lock byte
range. Because pc_argzero no longer scrubs the rq_argp slot, the
shared nlmclnt_lock_event tracepoint class is updated to source
its byte-range fields from lock->fl.fl_start and lock->fl.fl_end,
which both the client and server populate unconditionally; the old
lock_start and lock_len fields are no longer required by the trace.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/lockd/svcproc.c
fs/lockd/trace.h

index ccc6a633df7bac44528ecba09e13a1b954e69e6a..264212e44ec5a76506def656c795dc0713156ebe 100644 (file)
@@ -89,6 +89,20 @@ nlm_netobj_to_cookie(struct lockd_cookie *cookie, netobj *object)
        return nlm_granted;
 }
 
+static __be32
+nlm_lock_to_lockd_lock(struct lockd_lock *lock, struct nlm_lock *alock)
+{
+       if (alock->fh.len != NLM3_FHSIZE)
+               return nlm_lck_denied;
+       lock->fh.size = alock->fh.len;
+       memcpy(lock->fh.data, alock->fh.data, alock->fh.len);
+       lock->oh.len = alock->oh.len;
+       lock->oh.data = alock->oh.data;
+       lock->svid = alock->uppid;
+       lockd_set_file_lock_range3(&lock->fl, alock->l_offset, alock->l_len);
+       return nlm_granted;
+}
+
 static struct nlm_host *
 nlm3svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored)
 {
@@ -700,10 +714,41 @@ __nlmsvc_proc_granted(struct svc_rqst *rqstp, struct lockd_res *resp)
        return rpc_success;
 }
 
+/**
+ * nlmsvc_proc_granted - GRANTED: Blocked lock has been granted
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ *   %rpc_success:             RPC executed successfully.
+ *
+ * RPC synopsis:
+ *   nlm_res NLM_GRANTED(nlm_testargs) = 5;
+ *
+ * Permissible procedure status codes:
+ *   %LCK_GRANTED:             The granted lock was accepted.
+ *   %LCK_DENIED:              The procedure failed, possibly due to
+ *                             internal resource constraints.
+ *   %LCK_DENIED_GRACE_PERIOD: The client host recently restarted and
+ *                             its NLM is re-establishing existing locks,
+ *                             so it is not yet ready to accept callbacks.
+ */
 static __be32
 nlmsvc_proc_granted(struct svc_rqst *rqstp)
 {
-       return __nlmsvc_proc_granted(rqstp, rqstp->rq_resp);
+       struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
+       struct nlm_res_wrapper *resp = rqstp->rq_resp;
+
+       resp->xdrgen.cookie = argp->xdrgen.cookie;
+
+       resp->xdrgen.stat.stat = nlm_lock_to_lockd_lock(&argp->lock,
+                                                       &argp->xdrgen.alock);
+       if (resp->xdrgen.stat.stat)
+               goto out;
+
+       resp->xdrgen.stat.stat = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
+
+out:
+       return rpc_success;
 }
 
 /*
@@ -1012,15 +1057,15 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
                .pc_xdrressize  = NLM3_nlm_res_sz,
                .pc_name        = "UNLOCK",
        },
-       [NLMPROC_GRANTED] = {
-               .pc_func = nlmsvc_proc_granted,
-               .pc_decode = nlmsvc_decode_testargs,
-               .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 = "GRANTED",
+       [NLM_GRANTED] = {
+               .pc_func        = nlmsvc_proc_granted,
+               .pc_decode      = nlm_svc_decode_nlm_testargs,
+               .pc_encode      = nlm_svc_encode_nlm_res,
+               .pc_argsize     = sizeof(struct nlm_testargs_wrapper),
+               .pc_argzero     = 0,
+               .pc_ressize     = sizeof(struct nlm_res_wrapper),
+               .pc_xdrressize  = NLM3_nlm_res_sz,
+               .pc_name        = "GRANTED",
        },
        [NLMPROC_TEST_MSG] = {
                .pc_func = nlmsvc_proc_test_msg,
index aa858d9d406dde97cfbf587e149020dab932c24f..a11d04e8c835eb8bd657e3045444fd495e077efa 100644 (file)
@@ -61,8 +61,8 @@ DECLARE_EVENT_CLASS(nlmclnt_lock_event,
                        __field(u32, svid)
                        __field(u32, fh)
                        __field(unsigned long, status)
-                       __field(u64, start)
-                       __field(u64, len)
+                       __field(loff_t, start)
+                       __field(loff_t, end)
                        __sockaddr(addr, addrlen)
                ),
 
@@ -70,16 +70,16 @@ DECLARE_EVENT_CLASS(nlmclnt_lock_event,
                        __entry->oh = ~crc32_le(0xffffffff, lock->oh.data, lock->oh.len);
                        __entry->svid = lock->svid;
                        __entry->fh = nfs_fhandle_hash(&lock->fh);
-                       __entry->start = lock->lock_start;
-                       __entry->len = lock->lock_len;
+                       __entry->start = lock->fl.fl_start;
+                       __entry->end = lock->fl.fl_end;
                        __entry->status = be32_to_cpu(status);
                        __assign_sockaddr(addr, addr, addrlen);
                ),
 
                TP_printk(
-                       "addr=%pISpc oh=0x%08x svid=0x%08x fh=0x%08x start=%llu len=%llu status=%s",
+                       "addr=%pISpc oh=0x%08x svid=0x%08x fh=0x%08x start=%lld end=%lld status=%s",
                        __get_sockaddr(addr), __entry->oh, __entry->svid,
-                       __entry->fh, __entry->start, __entry->len,
+                       __entry->fh, __entry->start, __entry->end,
                        show_nlm_status(__entry->status)
                )
 );