Commit 1ac7e2fd authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Clean up the callers of nfs4_open_recover_helper()

Rely on nfs4_try_open_cached() when appropriate.

Also fix an RCU violation in _nfs4_do_open_reclaim()
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 6ee41268
...@@ -602,6 +602,19 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * ...@@ -602,6 +602,19 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
if (newstate != state) if (newstate != state)
return -ESTALE; return -ESTALE;
} }
/*
* We may have performed cached opens for all three recoveries.
* Check if we need to update the current stateid.
*/
if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) {
spin_lock(&state->owner->so_lock);
spin_lock(&state->inode->i_lock);
if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data));
spin_unlock(&state->inode->i_lock);
spin_unlock(&state->owner->so_lock);
}
return 0; return 0;
} }
...@@ -611,26 +624,22 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * ...@@ -611,26 +624,22 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
*/ */
static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state) static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
{ {
struct nfs_delegation *delegation = NFS_I(state->inode)->delegation; struct nfs_delegation *delegation;
struct nfs4_opendata *opendata; struct nfs4_opendata *opendata;
int delegation_type = 0; int delegation_type = 0;
int status; int status;
if (delegation != NULL) {
if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
memcpy(&state->stateid, &delegation->stateid,
sizeof(state->stateid));
set_bit(NFS_DELEGATED_STATE, &state->flags);
return 0;
}
delegation_type = delegation->type;
}
opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
if (opendata == NULL) if (opendata == NULL)
return -ENOMEM; return -ENOMEM;
opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
opendata->o_arg.fh = NFS_FH(state->inode); opendata->o_arg.fh = NFS_FH(state->inode);
nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
rcu_read_lock();
delegation = rcu_dereference(NFS_I(state->inode)->delegation);
if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
delegation_type = delegation->flags;
rcu_read_unlock();
opendata->o_arg.u.delegation_type = delegation_type; opendata->o_arg.u.delegation_type = delegation_type;
status = nfs4_open_recover(opendata, state); status = nfs4_open_recover(opendata, state);
nfs4_opendata_put(opendata); nfs4_opendata_put(opendata);
...@@ -980,21 +989,10 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) ...@@ -980,21 +989,10 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
*/ */
static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
{ {
struct inode *inode = state->inode;
struct nfs_delegation *delegation = NFS_I(inode)->delegation;
struct nfs4_opendata *opendata; struct nfs4_opendata *opendata;
int openflags = state->state & (FMODE_READ|FMODE_WRITE);
int ret; int ret;
if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) { opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
ret = _nfs4_do_access(inode, ctx->cred, openflags);
if (ret < 0)
return ret;
memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
set_bit(NFS_DELEGATED_STATE, &state->flags);
return 0;
}
opendata = nfs4_opendata_alloc(&ctx->path, state->owner, openflags, NULL);
if (opendata == NULL) if (opendata == NULL)
return -ENOMEM; return -ENOMEM;
ret = nfs4_open_recover(opendata, state); ret = nfs4_open_recover(opendata, state);
......
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