]> err.no Git - linux-2.6/blobdiff - fs/nfs/nfs4proc.c
Merge branch 'for-2.6.24' of master.kernel.org:/pub/scm/linux/kernel/git/jwboyer...
[linux-2.6] / fs / nfs / nfs4proc.c
index 9c27a6ed1a62a8f061825379d8f4d9689e8973d0..f03d9d5f5ba40d9d3db91a1dbb4ef43d74ab64bc 100644 (file)
@@ -208,12 +208,10 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
        struct nfs_inode *nfsi = NFS_I(dir);
 
        spin_lock(&dir->i_lock);
-       if (cinfo->after != nfsi->change_attr) {
-               nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
-               if (!cinfo->atomic || cinfo->before != nfsi->change_attr)
-                       nfsi->cache_change_attribute = jiffies;
-               nfsi->change_attr = cinfo->after;
-       }
+       nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
+       if (!cinfo->atomic || cinfo->before != nfsi->change_attr)
+               nfsi->cache_change_attribute = jiffies;
+       nfsi->change_attr = cinfo->after;
        spin_unlock(&dir->i_lock);
 }
 
@@ -1307,7 +1305,7 @@ static const struct rpc_call_ops nfs4_close_ops = {
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct path *path, struct nfs4_state *state)
+int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_closedata *calldata;
@@ -1335,8 +1333,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state)
        task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
        if (IS_ERR(task))
                return PTR_ERR(task);
+       status = 0;
+       if (wait)
+               status = rpc_wait_for_completion_task(task);
        rpc_put_task(task);
-       return 0;
+       return status;
 out_free_calldata:
        kfree(calldata);
 out:
@@ -1367,13 +1368,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
        }
        ret = PTR_ERR(filp);
 out_close:
-       nfs4_close_state(path, state, nd->intent.open.flags);
+       nfs4_close_sync(path, state, nd->intent.open.flags);
        return ret;
 }
 
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+       struct dentry *parent;
        struct path path = {
                .mnt = nd->mnt,
                .dentry = dentry,
@@ -1396,16 +1398,24 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
        if (IS_ERR(cred))
                return (struct dentry *)cred;
+       parent = dentry->d_parent;
+       /* Protect against concurrent sillydeletes */
+       nfs_block_sillyrename(parent);
        state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
        put_rpccred(cred);
        if (IS_ERR(state)) {
-               if (PTR_ERR(state) == -ENOENT)
+               if (PTR_ERR(state) == -ENOENT) {
                        d_add(dentry, NULL);
+                       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+               }
+               nfs_unblock_sillyrename(parent);
                return (struct dentry *)state;
        }
        res = d_add_unique(dentry, igrab(state->inode));
        if (res != NULL)
                path.dentry = res;
+       nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
+       nfs_unblock_sillyrename(parent);
        nfs4_intent_set_file(nd, &path, state);
        return res;
 }
@@ -1439,10 +1449,11 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
                }
        }
        if (state->inode == dentry->d_inode) {
+               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
                nfs4_intent_set_file(nd, &path, state);
                return 1;
        }
-       nfs4_close_state(&path, state, openflags);
+       nfs4_close_sync(&path, state, openflags);
 out_drop:
        d_drop(dentry);
        return 0;
@@ -1879,11 +1890,13 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        }
        state = nfs4_do_open(dir, &path, flags, sattr, cred);
        put_rpccred(cred);
+       d_drop(dentry);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
                goto out;
        }
-       d_instantiate(dentry, igrab(state->inode));
+       d_add(dentry, igrab(state->inode));
+       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        if (flags & O_EXCL) {
                struct nfs_fattr fattr;
                status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
@@ -1894,7 +1907,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
                status = nfs4_intent_set_file(nd, &path, state);
        else
-               nfs4_close_state(&path, state, flags);
+               nfs4_close_sync(&path, state, flags);
 out:
        return status;
 }
@@ -2396,6 +2409,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
                rpc_restart_call(task);
                return -EAGAIN;
        }
+
+       nfs_invalidate_atime(data->inode);
        if (task->tk_status > 0)
                renew_lease(server, data->timestamp);
        return 0;
@@ -2425,7 +2440,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
        }
        if (task->tk_status >= 0) {
                renew_lease(NFS_SERVER(inode), data->timestamp);
-               nfs_post_op_update_inode(inode, data->res.fattr);
+               nfs_post_op_update_inode_force_wcc(inode, data->res.fattr);
        }
        return 0;
 }
@@ -2467,8 +2482,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
                rpc_restart_call(task);
                return -EAGAIN;
        }
-       if (task->tk_status >= 0)
-               nfs_post_op_update_inode(inode, data->res.fattr);
+       nfs_refresh_inode(inode, data->res.fattr);
        return 0;
 }
 
@@ -3038,7 +3052,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
        if (status == 0) {
                status = data->rpc_status;
                if (status == 0)
-                       nfs_post_op_update_inode(inode, &data->fattr);
+                       nfs_refresh_inode(inode, &data->fattr);
        }
        rpc_put_task(task);
        return status;