aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-18 18:03:27 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-19 17:19:25 -0400
commita49c3c7736a2e77931dabc5bc4a83fb4b2da013e (patch)
tree1921900be210540ee53a4011c9e8f781deb0367e /fs/nfs
parent565277f63c616e11c37309a1e98c052d18ebbb55 (diff)
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 <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfs/inode.c22
-rw-r--r--fs/nfs/nfs4_fs.h3
-rw-r--r--fs/nfs/nfs4proc.c13
-rw-r--r--fs/nfs/nfs4state.c14
5 files changed, 41 insertions, 13 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d29f90d00aa2..b3bb89f7d5d2 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -131,7 +131,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
131{ 131{
132 /* Ensure that dirty pages are flushed out with the right creds */ 132 /* Ensure that dirty pages are flushed out with the right creds */
133 if (filp->f_mode & FMODE_WRITE) 133 if (filp->f_mode & FMODE_WRITE)
134 filemap_fdatawrite(filp->f_mapping); 134 nfs_wb_all(filp->f_path.dentry->d_inode);
135 nfs_inc_stats(inode, NFSIOS_VFSRELEASE); 135 nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
136 return NFS_PROTO(inode)->file_release(inode, filp); 136 return NFS_PROTO(inode)->file_release(inode, filp);
137} 137}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 173e294dffc5..db5d96dc6107 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)
514 return ctx; 514 return ctx;
515} 515}
516 516
517void put_nfs_open_context(struct nfs_open_context *ctx) 517static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait)
518{ 518{
519 struct inode *inode = ctx->path.dentry->d_inode; 519 struct inode *inode = ctx->path.dentry->d_inode;
520 520
@@ -522,8 +522,12 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
522 return; 522 return;
523 list_del(&ctx->list); 523 list_del(&ctx->list);
524 spin_unlock(&inode->i_lock); 524 spin_unlock(&inode->i_lock);
525 if (ctx->state != NULL) 525 if (ctx->state != NULL) {
526 nfs4_close_state(&ctx->path, ctx->state, ctx->mode); 526 if (wait)
527 nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);
528 else
529 nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
530 }
527 if (ctx->cred != NULL) 531 if (ctx->cred != NULL)
528 put_rpccred(ctx->cred); 532 put_rpccred(ctx->cred);
529 dput(ctx->path.dentry); 533 dput(ctx->path.dentry);
@@ -531,6 +535,16 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
531 kfree(ctx); 535 kfree(ctx);
532} 536}
533 537
538void put_nfs_open_context(struct nfs_open_context *ctx)
539{
540 __put_nfs_open_context(ctx, 0);
541}
542
543static void put_nfs_open_context_sync(struct nfs_open_context *ctx)
544{
545 __put_nfs_open_context(ctx, 1);
546}
547
534/* 548/*
535 * Ensure that mmap has a recent RPC credential for use when writing out 549 * Ensure that mmap has a recent RPC credential for use when writing out
536 * shared pages 550 * shared pages
@@ -577,7 +591,7 @@ static void nfs_file_clear_open_context(struct file *filp)
577 spin_lock(&inode->i_lock); 591 spin_lock(&inode->i_lock);
578 list_move_tail(&ctx->list, &NFS_I(inode)->open_files); 592 list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
579 spin_unlock(&inode->i_lock); 593 spin_unlock(&inode->i_lock);
580 put_nfs_open_context(ctx); 594 put_nfs_open_context_sync(ctx);
581 } 595 }
582} 596}
583 597
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d2802b1ca3b9..a4e3b961b63b 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
178extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); 178extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
179extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); 179extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
180extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); 180extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
181extern int nfs4_do_close(struct path *path, struct nfs4_state *state); 181extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait);
182extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); 182extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
183extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 183extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
184extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); 184extern 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 *);
209extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); 209extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
210extern void nfs4_put_open_state(struct nfs4_state *); 210extern void nfs4_put_open_state(struct nfs4_state *);
211extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t); 211extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
212extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t);
212extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); 213extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
213extern void nfs4_schedule_state_recovery(struct nfs_client *); 214extern void nfs4_schedule_state_recovery(struct nfs_client *);
214extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 215extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2cb3b8b71ee7..f03d9d5f5ba4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1305,7 +1305,7 @@ static const struct rpc_call_ops nfs4_close_ops = {
1305 * 1305 *
1306 * NOTE: Caller must be holding the sp->so_owner semaphore! 1306 * NOTE: Caller must be holding the sp->so_owner semaphore!
1307 */ 1307 */
1308int nfs4_do_close(struct path *path, struct nfs4_state *state) 1308int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
1309{ 1309{
1310 struct nfs_server *server = NFS_SERVER(state->inode); 1310 struct nfs_server *server = NFS_SERVER(state->inode);
1311 struct nfs4_closedata *calldata; 1311 struct nfs4_closedata *calldata;
@@ -1333,8 +1333,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state)
1333 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); 1333 task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
1334 if (IS_ERR(task)) 1334 if (IS_ERR(task))
1335 return PTR_ERR(task); 1335 return PTR_ERR(task);
1336 status = 0;
1337 if (wait)
1338 status = rpc_wait_for_completion_task(task);
1336 rpc_put_task(task); 1339 rpc_put_task(task);
1337 return 0; 1340 return status;
1338out_free_calldata: 1341out_free_calldata:
1339 kfree(calldata); 1342 kfree(calldata);
1340out: 1343out:
@@ -1365,7 +1368,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
1365 } 1368 }
1366 ret = PTR_ERR(filp); 1369 ret = PTR_ERR(filp);
1367out_close: 1370out_close:
1368 nfs4_close_state(path, state, nd->intent.open.flags); 1371 nfs4_close_sync(path, state, nd->intent.open.flags);
1369 return ret; 1372 return ret;
1370} 1373}
1371 1374
@@ -1450,7 +1453,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
1450 nfs4_intent_set_file(nd, &path, state); 1453 nfs4_intent_set_file(nd, &path, state);
1451 return 1; 1454 return 1;
1452 } 1455 }
1453 nfs4_close_state(&path, state, openflags); 1456 nfs4_close_sync(&path, state, openflags);
1454out_drop: 1457out_drop:
1455 d_drop(dentry); 1458 d_drop(dentry);
1456 return 0; 1459 return 0;
@@ -1904,7 +1907,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1904 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) 1907 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
1905 status = nfs4_intent_set_file(nd, &path, state); 1908 status = nfs4_intent_set_file(nd, &path, state);
1906 else 1909 else
1907 nfs4_close_state(&path, state, flags); 1910 nfs4_close_sync(&path, state, flags);
1908out: 1911out:
1909 return status; 1912 return status;
1910} 1913}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index bfb36261cecb..23a9a36556bf 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -425,7 +425,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
425/* 425/*
426 * Close the current file. 426 * Close the current file.
427 */ 427 */
428void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 428static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mode, int wait)
429{ 429{
430 struct nfs4_state_owner *owner = state->owner; 430 struct nfs4_state_owner *owner = state->owner;
431 int call_close = 0; 431 int call_close = 0;
@@ -466,7 +466,17 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
466 nfs4_put_open_state(state); 466 nfs4_put_open_state(state);
467 nfs4_put_state_owner(owner); 467 nfs4_put_state_owner(owner);
468 } else 468 } else
469 nfs4_do_close(path, state); 469 nfs4_do_close(path, state, wait);
470}
471
472void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
473{
474 __nfs4_close(path, state, mode, 0);
475}
476
477void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode)
478{
479 __nfs4_close(path, state, mode, 1);
470} 480}
471 481
472/* 482/*