]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
nfsd: prepare delegation code for handing out *_ATTRS_DELEG delegations
authorJeff Layton <jlayton@kernel.org>
Mon, 9 Dec 2024 21:13:57 +0000 (16:13 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Tue, 21 Jan 2025 20:30:01 +0000 (15:30 -0500)
Add some preparatory code to various functions that handle delegation
types to allow them to handle the OPEN_DELEGATE_*_ATTRS_DELEG constants.
Add helpers for detecting whether it's a read or write deleg, and
whether the attributes are delegated.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/state.h

index 0c73cb8fae1944e3ba044ea6365e4bc3ae71c5a2..e7b26806797acb4f34641ae07eb7126da8b2acd5 100644 (file)
@@ -2951,6 +2951,21 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st)
        return 0;
 }
 
+static char *nfs4_show_deleg_type(u32 dl_type)
+{
+       switch (dl_type) {
+       case OPEN_DELEGATE_READ:
+               return "r";
+       case OPEN_DELEGATE_WRITE:
+               return "w";
+       case OPEN_DELEGATE_READ_ATTRS_DELEG:
+               return "ra";
+       case OPEN_DELEGATE_WRITE_ATTRS_DELEG:
+               return "wa";
+       }
+       return "?";
+}
+
 static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st)
 {
        struct nfs4_delegation *ds;
@@ -2964,8 +2979,7 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st)
        nfs4_show_stateid(s, &st->sc_stateid);
        seq_puts(s, ": { type: deleg, ");
 
-       seq_printf(s, "access: %s",
-                  ds->dl_type == OPEN_DELEGATE_READ ? "r" : "w");
+       seq_printf(s, "access: %s", nfs4_show_deleg_type(ds->dl_type));
 
        /* XXX: lease time, whether it's being recalled. */
 
@@ -5581,7 +5595,7 @@ retry:
 static inline __be32
 nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
 {
-       if ((flags & WR_STATE) && (dp->dl_type == OPEN_DELEGATE_READ))
+       if ((flags & WR_STATE) && deleg_is_read(dp->dl_type))
                return nfserr_openmode;
        else
                return nfs_ok;
@@ -5813,8 +5827,7 @@ static bool nfsd4_cb_channel_good(struct nfs4_client *clp)
        return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN;
 }
 
-static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp,
-                                               int flag)
+static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp)
 {
        struct file_lease *fl;
 
@@ -5823,7 +5836,7 @@ static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp,
                return NULL;
        fl->fl_lmops = &nfsd_lease_mng_ops;
        fl->c.flc_flags = FL_DELEG;
-       fl->c.flc_type = flag == OPEN_DELEGATE_READ ? F_RDLCK : F_WRLCK;
+       fl->c.flc_type = deleg_is_read(dp->dl_type) ? F_RDLCK : F_WRLCK;
        fl->c.flc_owner = (fl_owner_t)dp;
        fl->c.flc_pid = current->tgid;
        fl->c.flc_file = dp->dl_stid.sc_file->fi_deleg_file->nf_file;
@@ -6010,7 +6023,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
        if (!dp)
                goto out_delegees;
 
-       fl = nfs4_alloc_init_lease(dp, dl_type);
+       fl = nfs4_alloc_init_lease(dp);
        if (!fl)
                goto out_clnt_odstate;
 
@@ -6210,14 +6223,14 @@ out_no_deleg:
 static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
                                        struct nfs4_delegation *dp)
 {
-       if (open->op_deleg_want == OPEN4_SHARE_ACCESS_WANT_READ_DELEG &&
-           dp->dl_type == OPEN_DELEGATE_WRITE) {
-               open->op_delegate_type = OPEN_DELEGATE_NONE_EXT;
-               open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE;
-       } else if (open->op_deleg_want == OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG &&
-                  dp->dl_type == OPEN_DELEGATE_WRITE) {
-               open->op_delegate_type = OPEN_DELEGATE_NONE_EXT;
-               open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE;
+       if (deleg_is_write(dp->dl_type)) {
+               if (open->op_deleg_want == OPEN4_SHARE_ACCESS_WANT_READ_DELEG) {
+                       open->op_delegate_type = OPEN_DELEGATE_NONE_EXT;
+                       open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE;
+               } else if (open->op_deleg_want == OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG) {
+                       open->op_delegate_type = OPEN_DELEGATE_NONE_EXT;
+                       open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE;
+               }
        }
        /* Otherwise the client must be confused wanting a delegation
         * it already has, therefore we don't return
index e3f1cb59e1181bdc95697a570955467cfc368a86..66b1e2c224ffdf039929f0be15429235fd3acae5 100644 (file)
@@ -4237,10 +4237,12 @@ nfsd4_encode_open_delegation4(struct xdr_stream *xdr, struct nfsd4_open *open)
                status = nfs_ok;
                break;
        case OPEN_DELEGATE_READ:
+       case OPEN_DELEGATE_READ_ATTRS_DELEG:
                /* read */
                status = nfsd4_encode_open_read_delegation4(xdr, open);
                break;
        case OPEN_DELEGATE_WRITE:
+       case OPEN_DELEGATE_WRITE_ATTRS_DELEG:
                /* write */
                status = nfsd4_encode_open_write_delegation4(xdr, open);
                break;
index b31a8523c8e50d291b1276c37219b272062c83a6..17e98a2521ff5f349956d92a0712d7f0e7d9c2f1 100644 (file)
@@ -207,6 +207,22 @@ struct nfs4_delegation {
        struct nfs4_cb_fattr    dl_cb_fattr;
 };
 
+static inline bool deleg_is_read(u32 dl_type)
+{
+       return (dl_type == OPEN_DELEGATE_READ || dl_type == OPEN_DELEGATE_READ_ATTRS_DELEG);
+}
+
+static inline bool deleg_is_write(u32 dl_type)
+{
+       return (dl_type == OPEN_DELEGATE_WRITE || dl_type == OPEN_DELEGATE_WRITE_ATTRS_DELEG);
+}
+
+static inline bool deleg_attrs_deleg(u32 dl_type)
+{
+       return dl_type == OPEN_DELEGATE_READ_ATTRS_DELEG ||
+              dl_type == OPEN_DELEGATE_WRITE_ATTRS_DELEG;
+}
+
 #define cb_to_delegation(cb) \
        container_of(cb, struct nfs4_delegation, dl_recall)