Commit 82062051 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFSv4: Clean up open delegation return structure

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: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarLance Shelton <lance.shelton@hammerspace.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent d3318990
...@@ -1960,6 +1960,13 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state) ...@@ -1960,6 +1960,13 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
struct nfs_delegation *delegation; struct nfs_delegation *delegation;
int delegation_flags = 0; 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(); rcu_read_lock();
delegation = rcu_dereference(NFS_I(state->inode)->delegation); delegation = rcu_dereference(NFS_I(state->inode)->delegation);
if (delegation) if (delegation)
...@@ -1979,19 +1986,19 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state) ...@@ -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) if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
nfs_inode_set_delegation(state->inode, nfs_inode_set_delegation(state->inode,
data->owner->so_cred, data->owner->so_cred,
data->o_res.delegation_type, data->o_res.delegation.type,
&data->o_res.delegation, &data->o_res.delegation.stateid,
data->o_res.pagemod_limit); data->o_res.delegation.pagemod_limit);
else else
nfs_inode_reclaim_delegation(state->inode, nfs_inode_reclaim_delegation(state->inode,
data->owner->so_cred, data->owner->so_cred,
data->o_res.delegation_type, data->o_res.delegation.type,
&data->o_res.delegation, &data->o_res.delegation.stateid,
data->o_res.pagemod_limit); 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, nfs_async_inode_return_delegation(state->inode,
&data->o_res.delegation); &data->o_res.delegation.stateid);
} }
/* /*
...@@ -2015,7 +2022,6 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) ...@@ -2015,7 +2022,6 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
if (ret) if (ret)
return ERR_PTR(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, if (!update_open_stateid(state, &data->o_res.stateid,
...@@ -2083,7 +2089,7 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) ...@@ -2083,7 +2089,7 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
if (IS_ERR(state)) if (IS_ERR(state))
goto out; goto out;
if (data->o_res.delegation_type != 0) 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, if (!update_open_stateid(state, &data->o_res.stateid,
NULL, data->o_arg.fmode)) { NULL, data->o_arg.fmode)) {
...@@ -3111,7 +3117,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, ...@@ -3111,7 +3117,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
case NFS4_OPEN_CLAIM_DELEGATE_PREV: case NFS4_OPEN_CLAIM_DELEGATE_PREV:
if (!opendata->rpc_done) if (!opendata->rpc_done)
break; break;
if (opendata->o_res.delegation_type != 0) if (opendata->o_res.delegation.type != 0)
dir_verifier = nfs_save_change_attribute(dir); dir_verifier = nfs_save_change_attribute(dir);
nfs_set_verifier(dentry, dir_verifier); nfs_set_verifier(dentry, dir_verifier);
} }
......
...@@ -5148,13 +5148,12 @@ static int decode_space_limit(struct xdr_stream *xdr, ...@@ -5148,13 +5148,12 @@ static int decode_space_limit(struct xdr_stream *xdr,
} }
static int decode_rw_delegation(struct xdr_stream *xdr, static int decode_rw_delegation(struct xdr_stream *xdr,
uint32_t delegation_type, struct nfs4_open_delegation *res)
struct nfs_openres *res)
{ {
__be32 *p; __be32 *p;
int status; int status;
status = decode_delegation_stateid(xdr, &res->delegation); status = decode_delegation_stateid(xdr, &res->stateid);
if (unlikely(status)) if (unlikely(status))
return status; return status;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
...@@ -5162,52 +5161,53 @@ static int decode_rw_delegation(struct xdr_stream *xdr, ...@@ -5162,52 +5161,53 @@ static int decode_rw_delegation(struct xdr_stream *xdr,
return -EIO; return -EIO;
res->do_recall = be32_to_cpup(p); res->do_recall = be32_to_cpup(p);
switch (delegation_type) { switch (res->open_delegation_type) {
case NFS4_OPEN_DELEGATE_READ: case NFS4_OPEN_DELEGATE_READ:
res->delegation_type = FMODE_READ; res->type = FMODE_READ;
break; break;
case NFS4_OPEN_DELEGATE_WRITE: 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) if (decode_space_limit(xdr, &res->pagemod_limit) < 0)
return -EIO; return -EIO;
} }
return decode_ace(xdr, NULL); 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; __be32 *p;
uint32_t why_no_delegation;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
if (unlikely(!p)) if (unlikely(!p))
return -EIO; return -EIO;
why_no_delegation = be32_to_cpup(p); res->why_no_delegation = be32_to_cpup(p);
switch (why_no_delegation) { switch (res->why_no_delegation) {
case WND4_CONTENTION: case WND4_CONTENTION:
case WND4_RESOURCE: case WND4_RESOURCE:
xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
/* Ignore for now */ if (unlikely(!p))
return -EIO;
res->will_notify = be32_to_cpup(p);
} }
return 0; 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; __be32 *p;
uint32_t delegation_type;
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
if (unlikely(!p)) if (unlikely(!p))
return -EIO; return -EIO;
delegation_type = be32_to_cpup(p); res->open_delegation_type = be32_to_cpup(p);
res->delegation_type = 0; switch (res->open_delegation_type) {
switch (delegation_type) {
case NFS4_OPEN_DELEGATE_NONE: case NFS4_OPEN_DELEGATE_NONE:
return 0; return 0;
case NFS4_OPEN_DELEGATE_READ: case NFS4_OPEN_DELEGATE_READ:
case NFS4_OPEN_DELEGATE_WRITE: 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: case NFS4_OPEN_DELEGATE_NONE_EXT:
return decode_no_delegation(xdr, res); return decode_no_delegation(xdr, res);
} }
...@@ -5248,7 +5248,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) ...@@ -5248,7 +5248,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
for (; i < NFS4_BITMAP_SIZE; i++) for (; i < NFS4_BITMAP_SIZE; i++)
res->attrset[i] = 0; res->attrset[i] = 0;
return decode_delegation(xdr, res); return decode_delegation(xdr, &res->delegation);
xdr_error: xdr_error:
dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen); dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
return -EIO; return -EIO;
......
...@@ -449,6 +449,22 @@ struct stateowner_id { ...@@ -449,6 +449,22 @@ struct stateowner_id {
__u32 uniquifier; __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. * Arguments to the open call.
*/ */
...@@ -490,13 +506,10 @@ struct nfs_openres { ...@@ -490,13 +506,10 @@ struct nfs_openres {
struct nfs_fattr * f_attr; struct nfs_fattr * f_attr;
struct nfs_seqid * seqid; struct nfs_seqid * seqid;
const struct nfs_server *server; const struct nfs_server *server;
fmode_t delegation_type;
nfs4_stateid delegation;
unsigned long pagemod_limit;
__u32 do_recall;
__u32 attrset[NFS4_BITMAP_SIZE]; __u32 attrset[NFS4_BITMAP_SIZE];
struct nfs4_string *owner; struct nfs4_string *owner;
struct nfs4_string *group_owner; struct nfs4_string *group_owner;
struct nfs4_open_delegation delegation;
__u32 access_request; __u32 access_request;
__u32 access_supported; __u32 access_supported;
__u32 access_result; __u32 access_result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment