aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c42
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 */
612static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state) 625static 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 */
981static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) 990static 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);