NFS: Fix another OPEN_DOWNGRADE bug
[pandora-kernel.git] / fs / nfs / nfs4proc.c
index 351989e..9fc7998 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;