Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a49c3c7736a2e77931dabc5bc4a83fb4b2da013e
Commit:     a49c3c7736a2e77931dabc5bc4a83fb4b2da013e
Parent:     565277f63c616e11c37309a1e98c052d18ebbb55
Author:     Trond Myklebust <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 18 18:03:27 2007 -0400
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Fri Oct 19 17:19:25 2007 -0400

    NFSv4: Ensure that we wait for the CLOSE request to complete
    
    Otherwise, we do end up breaking close-to-open semantics. We also end up
    breaking some of the silly-rename tests in Connectathon on some setups.
    
    Please refer to the bug-report at
        http://bugzilla.linux-nfs.org/show_bug.cgi?id=150
    
    Signed-off-by: Trond Myklebust <[EMAIL PROTECTED]>
---
 fs/nfs/file.c      |    2 +-
 fs/nfs/inode.c     |   22 ++++++++++++++++++----
 fs/nfs/nfs4_fs.h   |    3 ++-
 fs/nfs/nfs4proc.c  |   13 ++++++++-----
 fs/nfs/nfs4state.c |   14 ++++++++++++--
 5 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d29f90d..b3bb89f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -131,7 +131,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
 {
        /* Ensure that dirty pages are flushed out with the right creds */
        if (filp->f_mode & FMODE_WRITE)
-               filemap_fdatawrite(filp->f_mapping);
+               nfs_wb_all(filp->f_path.dentry->d_inode);
        nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
        return NFS_PROTO(inode)->file_release(inode, filp);
 }
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 173e294..db5d96d 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -514,7 +514,7 @@ struct nfs_open_context *get_nfs_open_context(struct 
nfs_open_context *ctx)
        return ctx;
 }
 
-void put_nfs_open_context(struct nfs_open_context *ctx)
+static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait)
 {
        struct inode *inode = ctx->path.dentry->d_inode;
 
@@ -522,8 +522,12 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
                return;
        list_del(&ctx->list);
        spin_unlock(&inode->i_lock);
-       if (ctx->state != NULL)
-               nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+       if (ctx->state != NULL) {
+               if (wait)
+                       nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);
+               else
+                       nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+       }
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        dput(ctx->path.dentry);
@@ -531,6 +535,16 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
        kfree(ctx);
 }
 
+void put_nfs_open_context(struct nfs_open_context *ctx)
+{
+       __put_nfs_open_context(ctx, 0);
+}
+
+static void put_nfs_open_context_sync(struct nfs_open_context *ctx)
+{
+       __put_nfs_open_context(ctx, 1);
+}
+
 /*
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
@@ -577,7 +591,7 @@ static void nfs_file_clear_open_context(struct file *filp)
                spin_lock(&inode->i_lock);
                list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
                spin_unlock(&inode->i_lock);
-               put_nfs_open_context(ctx);
+               put_nfs_open_context_sync(ctx);
        }
 }
 
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d2802b1..a4e3b96 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -178,7 +178,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, 
unsigned short, struc
 extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred 
*);
 extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
+extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int 
wait);
 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct 
nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct 
nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh 
*fhandle);
@@ -209,6 +209,7 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner 
*);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct 
nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
+extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
 extern void nfs4_schedule_state_recovery(struct nfs_client *);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2cb3b8b..f03d9d5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1305,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;
@@ -1333,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:
@@ -1365,7 +1368,7 @@ 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;
 }
 
@@ -1450,7 +1453,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry 
*dentry, int openflags, st
                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;
@@ -1904,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;
 }
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index bfb3626..23a9a36 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -425,7 +425,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
 /*
  * Close the current file.
  */
-void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
+static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t 
mode, int wait)
 {
        struct nfs4_state_owner *owner = state->owner;
        int call_close = 0;
@@ -466,7 +466,17 @@ void nfs4_close_state(struct path *path, struct nfs4_state 
*state, mode_t mode)
                nfs4_put_open_state(state);
                nfs4_put_state_owner(owner);
        } else
-               nfs4_do_close(path, state);
+               nfs4_do_close(path, state, wait);
+}
+
+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
+{
+       __nfs4_close(path, state, mode, 0);
+}
+
+void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode)
+{
+       __nfs4_close(path, state, mode, 1);
 }
 
 /*
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to