Commit 6f220ed5a84d87645a84ae22105dc565f3f248b5
1 parent
8cd69e1bc7
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 24 additions and 12 deletions Side-by-side Diff
fs/nfs/nfs4proc.c
... | ... | @@ -552,6 +552,18 @@ |
552 | 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 | 567 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) |
556 | 568 | { |
557 | 569 | struct nfs4_state *newstate; |
558 | 570 | |
... | ... | @@ -626,12 +638,11 @@ |
626 | 638 | int delegation_type = 0; |
627 | 639 | int status; |
628 | 640 | |
629 | - opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | |
630 | - if (opendata == NULL) | |
631 | - return -ENOMEM; | |
641 | + opendata = nfs4_open_recoverdata_alloc(ctx, state); | |
642 | + if (IS_ERR(opendata)) | |
643 | + return PTR_ERR(opendata); | |
632 | 644 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; |
633 | 645 | opendata->o_arg.fh = NFS_FH(state->inode); |
634 | - nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); | |
635 | 646 | rcu_read_lock(); |
636 | 647 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); |
637 | 648 | if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0) |
638 | 649 | |
... | ... | @@ -672,13 +683,12 @@ |
672 | 683 | |
673 | 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 | 686 | struct nfs4_opendata *opendata; |
677 | 687 | int ret; |
678 | 688 | |
679 | - opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL); | |
680 | - if (opendata == NULL) | |
681 | - return -ENOMEM; | |
689 | + opendata = nfs4_open_recoverdata_alloc(ctx, state); | |
690 | + if (IS_ERR(opendata)) | |
691 | + return PTR_ERR(opendata); | |
682 | 692 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; |
683 | 693 | memcpy(opendata->o_arg.u.delegation.data, stateid->data, |
684 | 694 | sizeof(opendata->o_arg.u.delegation.data)); |
685 | 695 | |
... | ... | @@ -823,8 +833,10 @@ |
823 | 833 | /* Update sequence id. */ |
824 | 834 | data->o_arg.id = sp->so_owner_id.id; |
825 | 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 | 837 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
838 | + nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | |
839 | + } | |
828 | 840 | data->timestamp = jiffies; |
829 | 841 | rpc_call_setup(task, &msg, 0); |
830 | 842 | return; |
... | ... | @@ -989,9 +1001,9 @@ |
989 | 1001 | struct nfs4_opendata *opendata; |
990 | 1002 | int ret; |
991 | 1003 | |
992 | - opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | |
993 | - if (opendata == NULL) | |
994 | - return -ENOMEM; | |
1004 | + opendata = nfs4_open_recoverdata_alloc(ctx, state); | |
1005 | + if (IS_ERR(opendata)) | |
1006 | + return PTR_ERR(opendata); | |
995 | 1007 | ret = nfs4_open_recover(opendata, state); |
996 | 1008 | if (ret == -ESTALE) { |
997 | 1009 | /* Invalidate the state owner so we don't ever use it again */ |