diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1de076619253..3a2af8053767 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -602,6 +602,19 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
602 | if (newstate != state) | 602 | if (newstate != state) |
603 | return -ESTALE; | 603 | return -ESTALE; |
604 | } | 604 | } |
605 | /* | ||
606 | * We may have performed cached opens for all three recoveries. | ||
607 | * Check if we need to update the current stateid. | ||
608 | */ | ||
609 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 && | ||
610 | memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) { | ||
611 | spin_lock(&state->owner->so_lock); | ||
612 | spin_lock(&state->inode->i_lock); | ||
613 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | ||
614 | memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)); | ||
615 | spin_unlock(&state->inode->i_lock); | ||
616 | spin_unlock(&state->owner->so_lock); | ||
617 | } | ||
605 | return 0; | 618 | return 0; |
606 | } | 619 | } |
607 | 620 | ||
@@ -611,26 +624,22 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
611 | */ | 624 | */ |
612 | static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state) | 625 | static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state) |
613 | { | 626 | { |
614 | struct nfs_delegation *delegation = NFS_I(state->inode)->delegation; | 627 | struct nfs_delegation *delegation; |
615 | struct nfs4_opendata *opendata; | 628 | struct nfs4_opendata *opendata; |
616 | int delegation_type = 0; | 629 | int delegation_type = 0; |
617 | int status; | 630 | int status; |
618 | 631 | ||
619 | if (delegation != NULL) { | ||
620 | if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) { | ||
621 | memcpy(&state->stateid, &delegation->stateid, | ||
622 | sizeof(state->stateid)); | ||
623 | set_bit(NFS_DELEGATED_STATE, &state->flags); | ||
624 | return 0; | ||
625 | } | ||
626 | delegation_type = delegation->type; | ||
627 | } | ||
628 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); | 632 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); |
629 | if (opendata == NULL) | 633 | if (opendata == NULL) |
630 | return -ENOMEM; | 634 | return -ENOMEM; |
631 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; | 635 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; |
632 | opendata->o_arg.fh = NFS_FH(state->inode); | 636 | opendata->o_arg.fh = NFS_FH(state->inode); |
633 | nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); | 637 | nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); |
638 | rcu_read_lock(); | ||
639 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | ||
640 | if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0) | ||
641 | delegation_type = delegation->flags; | ||
642 | rcu_read_unlock(); | ||
634 | opendata->o_arg.u.delegation_type = delegation_type; | 643 | opendata->o_arg.u.delegation_type = delegation_type; |
635 | status = nfs4_open_recover(opendata, state); | 644 | status = nfs4_open_recover(opendata, state); |
636 | nfs4_opendata_put(opendata); | 645 | nfs4_opendata_put(opendata); |
@@ -980,21 +989,10 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) | |||
980 | */ | 989 | */ |
981 | static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) | 990 | static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) |
982 | { | 991 | { |
983 | struct inode *inode = state->inode; | ||
984 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | ||
985 | struct nfs4_opendata *opendata; | 992 | struct nfs4_opendata *opendata; |
986 | int openflags = state->state & (FMODE_READ|FMODE_WRITE); | ||
987 | int ret; | 993 | int ret; |
988 | 994 | ||
989 | if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) { | 995 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); |
990 | ret = _nfs4_do_access(inode, ctx->cred, openflags); | ||
991 | if (ret < 0) | ||
992 | return ret; | ||
993 | memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid)); | ||
994 | set_bit(NFS_DELEGATED_STATE, &state->flags); | ||
995 | return 0; | ||
996 | } | ||
997 | opendata = nfs4_opendata_alloc(&ctx->path, state->owner, openflags, NULL); | ||
998 | if (opendata == NULL) | 996 | if (opendata == NULL) |
999 | return -ENOMEM; | 997 | return -ENOMEM; |
1000 | ret = nfs4_open_recover(opendata, state); | 998 | ret = nfs4_open_recover(opendata, state); |