NFSv4.1: Fix the CREATE_SESSION slot number accounting
[pandora-kernel.git] / fs / nfs / nfs4proc.c
index 61a1303..0ba9bf7 100644 (file)
@@ -267,7 +267,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                case 0:
                        return 0;
                case -NFS4ERR_OPENMODE:
-                       if (nfs_have_delegation(inode, FMODE_READ)) {
+                       if (inode && nfs_have_delegation(inode, FMODE_READ)) {
                                nfs_inode_return_delegation(inode);
                                exception->retry = 1;
                                return 0;
@@ -279,10 +279,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_BAD_STATEID:
-                       if (state != NULL)
-                               nfs_remove_bad_delegation(state->inode);
                        if (state == NULL)
                                break;
+                       nfs_remove_bad_delegation(state->inode);
                        nfs4_schedule_stateid_recovery(server, state);
                        goto wait_on_recovery;
                case -NFS4ERR_EXPIRED:
@@ -1794,7 +1793,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode
        if (server->caps & NFS_CAP_POSIX_LOCK)
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
-       if (opendata->o_arg.open_flags & O_EXCL) {
+       if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
                nfs4_exclusive_attrset(opendata, sattr);
 
                nfs_fattr_init(opendata->o_res.f_attr);
@@ -2026,12 +2025,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
                        call_close |= is_wronly;
                else if (is_wronly)
                        calldata->arg.fmode |= FMODE_WRITE;
+               if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
+                       call_close |= is_rdwr;
        } else if (is_rdwr)
                calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
 
-       if (calldata->arg.fmode == 0)
-               call_close |= is_rdwr;
-
        spin_unlock(&state->owner->so_lock);
 
        if (!call_close) {
@@ -3746,8 +3744,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_BAD_STATEID:
-                       if (state != NULL)
-                               nfs_remove_bad_delegation(state->inode);
+                       if (state == NULL)
+                               break;
+                       nfs_remove_bad_delegation(state->inode);
                case -NFS4ERR_OPENMODE:
                        if (state == NULL)
                                break;
@@ -5361,14 +5360,21 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
 
        status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
+       switch (status) {
+       case -NFS4ERR_STALE_CLIENTID:
+       case -NFS4ERR_DELAY:
+       case -ETIMEDOUT:
+       case -EACCES:
+       case -EAGAIN:
+               goto out;
+       };
+
+       clp->cl_seqid++;
        if (!status)
                /* Verify the session's negotiated channel_attrs values */
                status = nfs4_verify_channel_attrs(&args, session);
-       if (!status) {
-               /* Increment the clientid slot sequence id */
-               clp->cl_seqid++;
-       }
 
+out:
        return status;
 }
 
@@ -5612,7 +5618,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr
        int ret = 0;
 
        if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
-               return 0;
+               return -EAGAIN;
        task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_ops);
        if (IS_ERR(task))
                ret = PTR_ERR(task);