If the client requests a directory delegation with notifications
enabled, set the appropriate return mask in gddr_notification[0]. This
will ensure the lease acquisition sets the appropriate ignore mask.

If the client doesn't set NOTIFY4_GFLAG_EXTEND, then don't offer any
notifications, as nfsd won't provide directory offset information, and
"classic" notifications require them.

Signed-off-by: Jeff Layton <[email protected]>
---
 fs/nfsd/nfs4proc.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 
277022d437cec18e527c836f108f0e97c6844b23..220fc873db8f08a90ac74e51ac9d931fe7edb9e4
 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -2335,12 +2335,18 @@ nfsd4_verify(struct svc_rqst *rqstp, struct 
nfsd4_compound_state *cstate,
        return status == nfserr_same ? nfs_ok : status;
 }
 
+#define SUPPORTED_NOTIFY_MASK  (BIT(NOTIFY4_REMOVE_ENTRY) |    \
+                                BIT(NOTIFY4_ADD_ENTRY) |       \
+                                BIT(NOTIFY4_RENAME_ENTRY) |    \
+                                BIT(NOTIFY4_GFLAG_EXTEND))
+
 static __be32
 nfsd4_get_dir_delegation(struct svc_rqst *rqstp,
                         struct nfsd4_compound_state *cstate,
                         union nfsd4_op_u *u)
 {
        struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation;
+       u32 requested = gdd->gdda_notification_types[0];
        struct nfs4_delegation *dd;
        struct nfsd_file *nf;
        __be32 status;
@@ -2349,6 +2355,12 @@ nfsd4_get_dir_delegation(struct svc_rqst *rqstp,
        if (status != nfs_ok)
                return status;
 
+       /* No notifications if you don't set NOTIFY4_GFLAG_EXTEND! */
+       if (!(requested & BIT(NOTIFY4_GFLAG_EXTEND)))
+               requested = 0;
+
+       gdd->gddr_notification[0] = requested & SUPPORTED_NOTIFY_MASK;
+
        /*
         * RFC 8881, section 18.39.3 says:
         *

-- 
2.51.0


Reply via email to