NFSv4: Fix open state recovery
Ensure that opendata->state is always initialised when we do state recovery. Ensure that we set the filehandle in the case where we're doing an "OPEN_CLAIM_PREVIOUS" call due to a server reboot. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
8cd69e1bc7
commit
6f220ed5a8
1 changed files with 24 additions and 12 deletions
|
@ -552,6 +552,18 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx, struct nfs4_state *state)
|
||||||
|
{
|
||||||
|
struct nfs4_opendata *opendata;
|
||||||
|
|
||||||
|
opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
|
||||||
|
if (opendata == NULL)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
opendata->state = state;
|
||||||
|
atomic_inc(&state->count);
|
||||||
|
return opendata;
|
||||||
|
}
|
||||||
|
|
||||||
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
|
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
|
||||||
{
|
{
|
||||||
struct nfs4_state *newstate;
|
struct nfs4_state *newstate;
|
||||||
|
@ -626,12 +638,11 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
|
||||||
int delegation_type = 0;
|
int delegation_type = 0;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
|
opendata = nfs4_open_recoverdata_alloc(ctx, state);
|
||||||
if (opendata == NULL)
|
if (IS_ERR(opendata))
|
||||||
return -ENOMEM;
|
return PTR_ERR(opendata);
|
||||||
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);
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
delegation = rcu_dereference(NFS_I(state->inode)->delegation);
|
delegation = rcu_dereference(NFS_I(state->inode)->delegation);
|
||||||
if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
|
if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
|
||||||
|
@ -672,13 +683,12 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
|
||||||
|
|
||||||
static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
|
static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
|
||||||
{
|
{
|
||||||
struct nfs4_state_owner *sp = state->owner;
|
|
||||||
struct nfs4_opendata *opendata;
|
struct nfs4_opendata *opendata;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL);
|
opendata = nfs4_open_recoverdata_alloc(ctx, state);
|
||||||
if (opendata == NULL)
|
if (IS_ERR(opendata))
|
||||||
return -ENOMEM;
|
return PTR_ERR(opendata);
|
||||||
opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
|
opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
|
||||||
memcpy(opendata->o_arg.u.delegation.data, stateid->data,
|
memcpy(opendata->o_arg.u.delegation.data, stateid->data,
|
||||||
sizeof(opendata->o_arg.u.delegation.data));
|
sizeof(opendata->o_arg.u.delegation.data));
|
||||||
|
@ -823,8 +833,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
|
||||||
/* Update sequence id. */
|
/* Update sequence id. */
|
||||||
data->o_arg.id = sp->so_owner_id.id;
|
data->o_arg.id = sp->so_owner_id.id;
|
||||||
data->o_arg.clientid = sp->so_client->cl_clientid;
|
data->o_arg.clientid = sp->so_client->cl_clientid;
|
||||||
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
|
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
|
||||||
msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
|
msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
|
||||||
|
nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
|
||||||
|
}
|
||||||
data->timestamp = jiffies;
|
data->timestamp = jiffies;
|
||||||
rpc_call_setup(task, &msg, 0);
|
rpc_call_setup(task, &msg, 0);
|
||||||
return;
|
return;
|
||||||
|
@ -989,9 +1001,9 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
|
||||||
struct nfs4_opendata *opendata;
|
struct nfs4_opendata *opendata;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
|
opendata = nfs4_open_recoverdata_alloc(ctx, state);
|
||||||
if (opendata == NULL)
|
if (IS_ERR(opendata))
|
||||||
return -ENOMEM;
|
return PTR_ERR(opendata);
|
||||||
ret = nfs4_open_recover(opendata, state);
|
ret = nfs4_open_recover(opendata, state);
|
||||||
if (ret == -ESTALE) {
|
if (ret == -ESTALE) {
|
||||||
/* Invalidate the state owner so we don't ever use it again */
|
/* Invalidate the state owner so we don't ever use it again */
|
||||||
|
|
Loading…
Reference in a new issue