diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-17 21:50:45 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-19 15:09:03 -0400 |
commit | 6f220ed5a84d87645a84ae22105dc565f3f248b5 (patch) | |
tree | f7a9cc2a178da84c656f794248e1a55c6f5e09d3 | |
parent | 8cd69e1bc7970bfb032b425043cc0d4e4345c74c (diff) |
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>
-rw-r--r-- | fs/nfs/nfs4proc.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index fee2da856c9..8799b1d54a0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -552,6 +552,18 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state * | |||
552 | return ERR_PTR(-ENOENT); | 552 | return ERR_PTR(-ENOENT); |
553 | } | 553 | } |
554 | 554 | ||
555 | static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx, struct nfs4_state *state) | ||
556 | { | ||
557 | struct nfs4_opendata *opendata; | ||
558 | |||
559 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | ||
560 | if (opendata == NULL) | ||
561 | return ERR_PTR(-ENOMEM); | ||
562 | opendata->state = state; | ||
563 | atomic_inc(&state->count); | ||
564 | return opendata; | ||
565 | } | ||
566 | |||
555 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) | 567 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) |
556 | { | 568 | { |
557 | struct nfs4_state *newstate; | 569 | struct nfs4_state *newstate; |
@@ -626,12 +638,11 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state | |||
626 | int delegation_type = 0; | 638 | int delegation_type = 0; |
627 | int status; | 639 | int status; |
628 | 640 | ||
629 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | 641 | opendata = nfs4_open_recoverdata_alloc(ctx, state); |
630 | if (opendata == NULL) | 642 | if (IS_ERR(opendata)) |
631 | return -ENOMEM; | 643 | return PTR_ERR(opendata); |
632 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; | 644 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; |
633 | opendata->o_arg.fh = NFS_FH(state->inode); | 645 | opendata->o_arg.fh = NFS_FH(state->inode); |
634 | nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); | ||
635 | rcu_read_lock(); | 646 | rcu_read_lock(); |
636 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | 647 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); |
637 | if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0) | 648 | 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 | |||
672 | 683 | ||
673 | static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) | 684 | static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) |
674 | { | 685 | { |
675 | struct nfs4_state_owner *sp = state->owner; | ||
676 | struct nfs4_opendata *opendata; | 686 | struct nfs4_opendata *opendata; |
677 | int ret; | 687 | int ret; |
678 | 688 | ||
679 | opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL); | 689 | opendata = nfs4_open_recoverdata_alloc(ctx, state); |
680 | if (opendata == NULL) | 690 | if (IS_ERR(opendata)) |
681 | return -ENOMEM; | 691 | return PTR_ERR(opendata); |
682 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; | 692 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; |
683 | memcpy(opendata->o_arg.u.delegation.data, stateid->data, | 693 | memcpy(opendata->o_arg.u.delegation.data, stateid->data, |
684 | sizeof(opendata->o_arg.u.delegation.data)); | 694 | sizeof(opendata->o_arg.u.delegation.data)); |
@@ -823,8 +833,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
823 | /* Update sequence id. */ | 833 | /* Update sequence id. */ |
824 | data->o_arg.id = sp->so_owner_id.id; | 834 | data->o_arg.id = sp->so_owner_id.id; |
825 | data->o_arg.clientid = sp->so_client->cl_clientid; | 835 | data->o_arg.clientid = sp->so_client->cl_clientid; |
826 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) | 836 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
827 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 837 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
838 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | ||
839 | } | ||
828 | data->timestamp = jiffies; | 840 | data->timestamp = jiffies; |
829 | rpc_call_setup(task, &msg, 0); | 841 | rpc_call_setup(task, &msg, 0); |
830 | return; | 842 | return; |
@@ -989,9 +1001,9 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s | |||
989 | struct nfs4_opendata *opendata; | 1001 | struct nfs4_opendata *opendata; |
990 | int ret; | 1002 | int ret; |
991 | 1003 | ||
992 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | 1004 | opendata = nfs4_open_recoverdata_alloc(ctx, state); |
993 | if (opendata == NULL) | 1005 | if (IS_ERR(opendata)) |
994 | return -ENOMEM; | 1006 | return PTR_ERR(opendata); |
995 | ret = nfs4_open_recover(opendata, state); | 1007 | ret = nfs4_open_recover(opendata, state); |
996 | if (ret == -ESTALE) { | 1008 | if (ret == -ESTALE) { |
997 | /* Invalidate the state owner so we don't ever use it again */ | 1009 | /* Invalidate the state owner so we don't ever use it again */ |