NFSv4: Clean up open delegation return structure
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 17 Jun 2024 01:21:19 +0000 (21:21 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 8 Jul 2024 17:47:25 +0000 (13:47 -0400)
Instead of having the fields open coded in the struct nfs_openres,
add a separate structure for them so that we can reuse that code
for the WANT_DELEGATION case.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Lance Shelton <lance.shelton@hammerspace.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_xdr.h

index a691fa10b3e95f63ce810ea149410bb41dfd840e..7a74dc1bcfbd806a5143fba524e675d42311dfc0 100644 (file)
@@ -1960,6 +1960,13 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
        struct nfs_delegation *delegation;
        int delegation_flags = 0;
 
+       switch (data->o_res.delegation.open_delegation_type) {
+       case NFS4_OPEN_DELEGATE_READ:
+       case NFS4_OPEN_DELEGATE_WRITE:
+               break;
+       default:
+               return;
+       };
        rcu_read_lock();
        delegation = rcu_dereference(NFS_I(state->inode)->delegation);
        if (delegation)
@@ -1979,19 +1986,19 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
        if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
                nfs_inode_set_delegation(state->inode,
                                data->owner->so_cred,
-                               data->o_res.delegation_type,
-                               &data->o_res.delegation,
-                               data->o_res.pagemod_limit);
+                               data->o_res.delegation.type,
+                               &data->o_res.delegation.stateid,
+                               data->o_res.delegation.pagemod_limit);
        else
                nfs_inode_reclaim_delegation(state->inode,
                                data->owner->so_cred,
-                               data->o_res.delegation_type,
-                               &data->o_res.delegation,
-                               data->o_res.pagemod_limit);
+                               data->o_res.delegation.type,
+                               &data->o_res.delegation.stateid,
+                               data->o_res.delegation.pagemod_limit);
 
-       if (data->o_res.do_recall)
+       if (data->o_res.delegation.do_recall)
                nfs_async_inode_return_delegation(state->inode,
-                                                 &data->o_res.delegation);
+                                                 &data->o_res.delegation.stateid);
 }
 
 /*
@@ -2015,8 +2022,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
        if (ret)
                return ERR_PTR(ret);
 
-       if (data->o_res.delegation_type != 0)
-               nfs4_opendata_check_deleg(data, state);
+       nfs4_opendata_check_deleg(data, state);
 
        if (!update_open_stateid(state, &data->o_res.stateid,
                                NULL, data->o_arg.fmode))
@@ -2083,7 +2089,7 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
        if (IS_ERR(state))
                goto out;
 
-       if (data->o_res.delegation_type != 0)
+       if (data->o_res.delegation.type != 0)
                nfs4_opendata_check_deleg(data, state);
        if (!update_open_stateid(state, &data->o_res.stateid,
                                NULL, data->o_arg.fmode)) {
@@ -3111,7 +3117,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
        case NFS4_OPEN_CLAIM_DELEGATE_PREV:
                if (!opendata->rpc_done)
                        break;
-               if (opendata->o_res.delegation_type != 0)
+               if (opendata->o_res.delegation.type != 0)
                        dir_verifier = nfs_save_change_attribute(dir);
                nfs_set_verifier(dentry, dir_verifier);
        }
index 1416099dfcd159a9cb4a0ffb21dbd826ad940a07..119061da52989d20d16dc6c52fa29439913defc9 100644 (file)
@@ -5148,13 +5148,12 @@ static int decode_space_limit(struct xdr_stream *xdr,
 }
 
 static int decode_rw_delegation(struct xdr_stream *xdr,
-               uint32_t delegation_type,
-               struct nfs_openres *res)
+               struct nfs4_open_delegation *res)
 {
        __be32 *p;
        int status;
 
-       status = decode_delegation_stateid(xdr, &res->delegation);
+       status = decode_delegation_stateid(xdr, &res->stateid);
        if (unlikely(status))
                return status;
        p = xdr_inline_decode(xdr, 4);
@@ -5162,52 +5161,53 @@ static int decode_rw_delegation(struct xdr_stream *xdr,
                return -EIO;
        res->do_recall = be32_to_cpup(p);
 
-       switch (delegation_type) {
+       switch (res->open_delegation_type) {
        case NFS4_OPEN_DELEGATE_READ:
-               res->delegation_type = FMODE_READ;
+               res->type = FMODE_READ;
                break;
        case NFS4_OPEN_DELEGATE_WRITE:
-               res->delegation_type = FMODE_WRITE|FMODE_READ;
+               res->type = FMODE_WRITE|FMODE_READ;
                if (decode_space_limit(xdr, &res->pagemod_limit) < 0)
                                return -EIO;
        }
        return decode_ace(xdr, NULL);
 }
 
-static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+static int decode_no_delegation(struct xdr_stream *xdr,
+               struct nfs4_open_delegation *res)
 {
        __be32 *p;
-       uint32_t why_no_delegation;
 
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                return -EIO;
-       why_no_delegation = be32_to_cpup(p);
-       switch (why_no_delegation) {
+       res->why_no_delegation = be32_to_cpup(p);
+       switch (res->why_no_delegation) {
                case WND4_CONTENTION:
                case WND4_RESOURCE:
-                       xdr_inline_decode(xdr, 4);
-                       /* Ignore for now */
+                       p = xdr_inline_decode(xdr, 4);
+                       if (unlikely(!p))
+                               return -EIO;
+                       res->will_notify = be32_to_cpup(p);
        }
        return 0;
 }
 
-static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+static int decode_delegation(struct xdr_stream *xdr,
+               struct nfs4_open_delegation *res)
 {
        __be32 *p;
-       uint32_t delegation_type;
 
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                return -EIO;
-       delegation_type = be32_to_cpup(p);
-       res->delegation_type = 0;
-       switch (delegation_type) {
+       res->open_delegation_type = be32_to_cpup(p);
+       switch (res->open_delegation_type) {
        case NFS4_OPEN_DELEGATE_NONE:
                return 0;
        case NFS4_OPEN_DELEGATE_READ:
        case NFS4_OPEN_DELEGATE_WRITE:
-               return decode_rw_delegation(xdr, delegation_type, res);
+               return decode_rw_delegation(xdr, res);
        case NFS4_OPEN_DELEGATE_NONE_EXT:
                return decode_no_delegation(xdr, res);
        }
@@ -5248,7 +5248,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
        for (; i < NFS4_BITMAP_SIZE; i++)
                res->attrset[i] = 0;
 
-       return decode_delegation(xdr, res);
+       return decode_delegation(xdr, &res->delegation);
 xdr_error:
        dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
        return -EIO;
index d09b9773b20c8251f5a2e9232bbed6b22f6bd708..682559e19d9d0c76e8a445c4437d3c5a59b2b357 100644 (file)
@@ -449,6 +449,22 @@ struct stateowner_id {
        __u32   uniquifier;
 };
 
+struct nfs4_open_delegation {
+       __u32 open_delegation_type;
+       union {
+               struct {
+                       fmode_t                 type;
+                       __u32                   do_recall;
+                       nfs4_stateid            stateid;
+                       unsigned long           pagemod_limit;
+               };
+               struct {
+                       __u32                   why_no_delegation;
+                       __u32                   will_notify;
+               };
+       };
+};
+
 /*
  * Arguments to the open call.
  */
@@ -490,13 +506,10 @@ struct nfs_openres {
        struct nfs_fattr *      f_attr;
        struct nfs_seqid *      seqid;
        const struct nfs_server *server;
-       fmode_t                 delegation_type;
-       nfs4_stateid            delegation;
-       unsigned long           pagemod_limit;
-       __u32                   do_recall;
        __u32                   attrset[NFS4_BITMAP_SIZE];
        struct nfs4_string      *owner;
        struct nfs4_string      *group_owner;
+       struct nfs4_open_delegation     delegation;
        __u32                   access_request;
        __u32                   access_supported;
        __u32                   access_result;