nfs4: fix missing-braces warning
[cascardo/linux.git] / fs / nfs / nfs4proc.c
index 6f0df2c..45b38ee 100644 (file)
@@ -755,6 +755,13 @@ static int nfs41_sequence_process(struct rpc_task *task,
        /* Check the SEQUENCE operation status */
        switch (res->sr_status) {
        case 0:
+               /* If previous op on slot was interrupted and we reused
+                * the seq# and got a reply from the cache, then retry
+                */
+               if (task->tk_status == -EREMOTEIO && interrupted) {
+                       ++slot->seq_nr;
+                       goto retry_nowait;
+               }
                /* Update the slot's sequence and clientid lease timer */
                slot->seq_done = 1;
                clp = session->clp;
@@ -1387,6 +1394,19 @@ static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
        nfs4_state_set_mode_locked(state, state->state | fmode);
 }
 
+#ifdef CONFIG_NFS_V4_1
+static bool nfs_open_stateid_recover_openmode(struct nfs4_state *state)
+{
+       if (state->n_rdonly && !test_bit(NFS_O_RDONLY_STATE, &state->flags))
+               return true;
+       if (state->n_wronly && !test_bit(NFS_O_WRONLY_STATE, &state->flags))
+               return true;
+       if (state->n_rdwr && !test_bit(NFS_O_RDWR_STATE, &state->flags))
+               return true;
+       return false;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
 {
        struct nfs_client *clp = state->owner->so_server->nfs_client;
@@ -1525,7 +1545,7 @@ static int update_open_stateid(struct nfs4_state *state,
        struct nfs_client *clp = server->nfs_client;
        struct nfs_inode *nfsi = NFS_I(state->inode);
        struct nfs_delegation *deleg_cur;
-       nfs4_stateid freeme = {0};
+       nfs4_stateid freeme = { };
        int ret = 0;
 
        fmode &= (FMODE_READ|FMODE_WRITE);
@@ -2560,6 +2580,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
                        if (status == -NFS4ERR_EXPIRED ||
                            status == -NFS4ERR_BAD_STATEID) {
                                clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
+                               lsp->ls_stateid.type = NFS4_INVALID_STATEID_TYPE;
                                if (!recover_lost_locks)
                                        set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
                        } else if (status != NFS_OK) {
@@ -2588,16 +2609,13 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
        int status;
 
        if (test_bit(NFS_OPEN_STATE, &state->flags) == 0) {
-               if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
-                       return NFS_OK;
+               if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)  {
+                       if (nfs4_have_delegation(state->inode, state->state))
+                               return NFS_OK;
+                       return -NFS4ERR_OPENMODE;
+               }
                return -NFS4ERR_BAD_STATEID;
        }
-       /* If a state reset has been done, test_stateid is unneeded */
-       if ((test_bit(NFS_O_RDONLY_STATE, &state->flags) == 0) &&
-           (test_bit(NFS_O_WRONLY_STATE, &state->flags) == 0) &&
-           (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0))
-               return -NFS4ERR_BAD_STATEID;
-
        status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
        trace_nfs4_test_open_stateid(state, NULL, status);
        if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) {
@@ -2605,8 +2623,13 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
                clear_bit(NFS_O_WRONLY_STATE, &state->flags);
                clear_bit(NFS_O_RDWR_STATE, &state->flags);
                clear_bit(NFS_OPEN_STATE, &state->flags);
+               stateid->type = NFS4_INVALID_STATEID_TYPE;
        }
-       return status;
+       if (status != NFS_OK)
+               return status;
+       if (nfs_open_stateid_recover_openmode(state))
+               return -NFS4ERR_OPENMODE;
+       return NFS_OK;
 }
 
 static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
@@ -4541,11 +4564,6 @@ static bool nfs4_error_stateid_expired(int err)
        return false;
 }
 
-void __nfs4_read_done_cb(struct nfs_pgio_header *hdr)
-{
-       nfs_invalidate_atime(hdr->inode);
-}
-
 static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr)
 {
        struct nfs_server *server = NFS_SERVER(hdr->inode);
@@ -4565,7 +4583,6 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr)
                }
        }
 
-       __nfs4_read_done_cb(hdr);
        if (task->tk_status > 0)
                renew_lease(server, hdr->timestamp);
        return 0;
@@ -4594,6 +4611,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
                return -EAGAIN;
        if (nfs4_read_stateid_changed(task, &hdr->args))
                return -EAGAIN;
+       if (task->tk_status > 0)
+               nfs_invalidate_atime(hdr->inode);
        return hdr->pgio_done_cb ? hdr->pgio_done_cb(task, hdr) :
                                    nfs4_read_done_cb(task, hdr);
 }
@@ -5280,12 +5299,14 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp,
        if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
                /* An impossible timestamp guarantees this value
                 * will never match a generated boot time. */
-               verf[0] = 0;
-               verf[1] = cpu_to_be32(NSEC_PER_SEC + 1);
+               verf[0] = cpu_to_be32(U32_MAX);
+               verf[1] = cpu_to_be32(U32_MAX);
        } else {
                struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
-               verf[0] = cpu_to_be32(nn->boot_time.tv_sec);
-               verf[1] = cpu_to_be32(nn->boot_time.tv_nsec);
+               u64 ns = ktime_to_ns(nn->boot_time);
+
+               verf[0] = cpu_to_be32(ns >> 32);
+               verf[1] = cpu_to_be32(ns);
        }
        memcpy(bootverf->data, verf, sizeof(bootverf->data));
 }
@@ -8927,6 +8948,7 @@ static void nfs4_handle_delay_or_session_error(struct nfs_server *server,
        exception->retry = 0;
        switch(err) {
        case -NFS4ERR_DELAY:
+       case -NFS4ERR_RETRY_UNCACHED_REP:
                nfs4_handle_exception(server, err, exception);
                break;
        case -NFS4ERR_BADSESSION:
@@ -9032,7 +9054,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
 
        msg.rpc_argp = &data->args;
        msg.rpc_resp = &data->res;
-       nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
+       nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
        if (privileged)
                nfs4_set_sequence_privileged(&data->args.seq_args);