These changes are a raw update to a vanilla kernel 4.1.10, with the
[kvmfornfv.git] / kernel / fs / nfs / nfs4proc.c
index d3f2051..c245874 100644 (file)
@@ -1152,6 +1152,8 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode)
                return 0;
        if ((delegation->type & fmode) != fmode)
                return 0;
+       if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
+               return 0;
        if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
                return 0;
        nfs_mark_delegation_referenced(delegation);
@@ -1216,6 +1218,7 @@ static void nfs_resync_open_stateid_locked(struct nfs4_state *state)
 }
 
 static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
+               nfs4_stateid *arg_stateid,
                nfs4_stateid *stateid, fmode_t fmode)
 {
        clear_bit(NFS_O_RDWR_STATE, &state->flags);
@@ -1234,8 +1237,9 @@ static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
        if (stateid == NULL)
                return;
        /* Handle races with OPEN */
-       if (!nfs4_stateid_match_other(stateid, &state->open_stateid) ||
-           !nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
+       if (!nfs4_stateid_match_other(arg_stateid, &state->open_stateid) ||
+           (nfs4_stateid_match_other(stateid, &state->open_stateid) &&
+           !nfs4_stateid_is_newer(stateid, &state->open_stateid))) {
                nfs_resync_open_stateid_locked(state);
                return;
        }
@@ -1244,10 +1248,12 @@ static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
        nfs4_stateid_copy(&state->open_stateid, stateid);
 }
 
-static void nfs_clear_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
+static void nfs_clear_open_stateid(struct nfs4_state *state,
+       nfs4_stateid *arg_stateid,
+       nfs4_stateid *stateid, fmode_t fmode)
 {
        write_seqlock(&state->seqlock);
-       nfs_clear_open_stateid_locked(state, stateid, fmode);
+       nfs_clear_open_stateid_locked(state, arg_stateid, stateid, fmode);
        write_sequnlock(&state->seqlock);
        if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
                nfs4_schedule_state_manager(state->owner->so_server->nfs_client);
@@ -2413,7 +2419,7 @@ static int _nfs4_do_open(struct inode *dir,
                goto err_free_label;
        state = ctx->state;
 
-       if ((opendata->o_arg.open_flags & O_EXCL) &&
+       if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) &&
            (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
                nfs4_exclusive_attrset(opendata, sattr);
 
@@ -2672,7 +2678,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                                goto out_release;
                        }
        }
-       nfs_clear_open_stateid(state, res_stateid, calldata->arg.fmode);
+       nfs_clear_open_stateid(state, &calldata->arg.stateid,
+                       res_stateid, calldata->arg.fmode);
 out_release:
        nfs_release_seqid(calldata->arg.seqid);
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
@@ -8571,6 +8578,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
        .reboot_recovery_ops = &nfs41_reboot_recovery_ops,
        .nograce_recovery_ops = &nfs41_nograce_recovery_ops,
        .state_renewal_ops = &nfs41_state_renewal_ops,
+       .mig_recovery_ops = &nfs41_mig_recovery_ops,
 };
 #endif