aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/file.c11
-rw-r--r--fs/nfs/inode.c41
-rw-r--r--fs/nfs/internal.h3
-rw-r--r--fs/nfs/nfs3proc.c1
-rw-r--r--fs/nfs/nfs4proc.c10
-rw-r--r--fs/nfs/proc.c1
-rw-r--r--include/linux/nfs_xdr.h1
7 files changed, 47 insertions, 21 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 1eab9c9ad242..d451073c4947 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -137,9 +137,6 @@ nfs_file_release(struct inode *inode, struct file *filp)
137 dentry->d_parent->d_name.name, 137 dentry->d_parent->d_name.name,
138 dentry->d_name.name); 138 dentry->d_name.name);
139 139
140 /* Ensure that dirty pages are flushed out with the right creds */
141 if (filp->f_mode & FMODE_WRITE)
142 nfs_wb_all(dentry->d_inode);
143 nfs_inc_stats(inode, NFSIOS_VFSRELEASE); 140 nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
144 return nfs_release(inode, filp); 141 return nfs_release(inode, filp);
145} 142}
@@ -231,7 +228,6 @@ nfs_file_flush(struct file *file, fl_owner_t id)
231 struct nfs_open_context *ctx = nfs_file_open_context(file); 228 struct nfs_open_context *ctx = nfs_file_open_context(file);
232 struct dentry *dentry = file->f_path.dentry; 229 struct dentry *dentry = file->f_path.dentry;
233 struct inode *inode = dentry->d_inode; 230 struct inode *inode = dentry->d_inode;
234 int status;
235 231
236 dprintk("NFS: flush(%s/%s)\n", 232 dprintk("NFS: flush(%s/%s)\n",
237 dentry->d_parent->d_name.name, 233 dentry->d_parent->d_name.name,
@@ -241,11 +237,8 @@ nfs_file_flush(struct file *file, fl_owner_t id)
241 return 0; 237 return 0;
242 nfs_inc_stats(inode, NFSIOS_VFSFLUSH); 238 nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
243 239
244 /* Ensure that data+attribute caches are up to date after close() */ 240 /* Flush writes to the server and return any errors */
245 status = nfs_do_fsync(ctx, inode); 241 return nfs_do_fsync(ctx, inode);
246 if (!status)
247 nfs_revalidate_inode(NFS_SERVER(inode), inode);
248 return status;
249} 242}
250 243
251static ssize_t 244static ssize_t
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index c40adc5dd609..a834d1d850b7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -541,6 +541,32 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
541 return err; 541 return err;
542} 542}
543 543
544/**
545 * nfs_close_context - Common close_context() routine NFSv2/v3
546 * @ctx: pointer to context
547 * @is_sync: is this a synchronous close
548 *
549 * always ensure that the attributes are up to date if we're mounted
550 * with close-to-open semantics
551 */
552void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
553{
554 struct inode *inode;
555 struct nfs_server *server;
556
557 if (!(ctx->mode & FMODE_WRITE))
558 return;
559 if (!is_sync)
560 return;
561 inode = ctx->path.dentry->d_inode;
562 if (!list_empty(&NFS_I(inode)->open_files))
563 return;
564 server = NFS_SERVER(inode);
565 if (server->flags & NFS_MOUNT_NOCTO)
566 return;
567 nfs_revalidate_inode(server, inode);
568}
569
544static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) 570static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred)
545{ 571{
546 struct nfs_open_context *ctx; 572 struct nfs_open_context *ctx;
@@ -567,24 +593,15 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
567 return ctx; 593 return ctx;
568} 594}
569 595
570static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) 596static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
571{ 597{
572 struct inode *inode; 598 struct inode *inode = ctx->path.dentry->d_inode;
573 599
574 if (ctx == NULL)
575 return;
576
577 inode = ctx->path.dentry->d_inode;
578 if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) 600 if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
579 return; 601 return;
580 list_del(&ctx->list); 602 list_del(&ctx->list);
581 spin_unlock(&inode->i_lock); 603 spin_unlock(&inode->i_lock);
582 if (ctx->state != NULL) { 604 NFS_PROTO(inode)->close_context(ctx, is_sync);
583 if (wait)
584 nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);
585 else
586 nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
587 }
588 if (ctx->cred != NULL) 605 if (ctx->cred != NULL)
589 put_rpccred(ctx->cred); 606 put_rpccred(ctx->cred);
590 path_put(&ctx->path); 607 path_put(&ctx->path);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index a55e69aa52e5..2041f68ff1cc 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -152,6 +152,9 @@ extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
152extern struct rpc_procinfo nfs4_procedures[]; 152extern struct rpc_procinfo nfs4_procedures[];
153#endif 153#endif
154 154
155/* proc.c */
156void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
157
155/* dir.c */ 158/* dir.c */
156extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); 159extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
157 160
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index c55be7a7679e..b82fe6847f14 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -834,4 +834,5 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
834 .commit_done = nfs3_commit_done, 834 .commit_done = nfs3_commit_done,
835 .lock = nfs3_proc_lock, 835 .lock = nfs3_proc_lock,
836 .clear_acl_cache = nfs3_forget_cached_acls, 836 .clear_acl_cache = nfs3_forget_cached_acls,
837 .close_context = nfs_close_context,
837}; 838};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 95f171e7e05a..97bacccff579 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1572,6 +1572,15 @@ out_drop:
1572 return 0; 1572 return 0;
1573} 1573}
1574 1574
1575void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
1576{
1577 if (ctx->state == NULL)
1578 return;
1579 if (is_sync)
1580 nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);
1581 else
1582 nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
1583}
1575 1584
1576static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) 1585static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
1577{ 1586{
@@ -3776,6 +3785,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
3776 .commit_done = nfs4_commit_done, 3785 .commit_done = nfs4_commit_done,
3777 .lock = nfs4_proc_lock, 3786 .lock = nfs4_proc_lock,
3778 .clear_acl_cache = nfs4_zap_acl_attr, 3787 .clear_acl_cache = nfs4_zap_acl_attr,
3788 .close_context = nfs4_close_context,
3779}; 3789};
3780 3790
3781/* 3791/*
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 193465210d7c..7be72d90d49d 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -663,4 +663,5 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
663 .commit_setup = nfs_proc_commit_setup, 663 .commit_setup = nfs_proc_commit_setup,
664 .lock = nfs_proc_lock, 664 .lock = nfs_proc_lock,
665 .lock_check_bounds = nfs_lock_check_bounds, 665 .lock_check_bounds = nfs_lock_check_bounds,
666 .close_context = nfs_close_context,
666}; 667};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 0691b9c188d9..9708e78a4d49 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -868,6 +868,7 @@ struct nfs_rpc_ops {
868 int (*lock)(struct file *, int, struct file_lock *); 868 int (*lock)(struct file *, int, struct file_lock *);
869 int (*lock_check_bounds)(const struct file_lock *); 869 int (*lock_check_bounds)(const struct file_lock *);
870 void (*clear_acl_cache)(struct inode *); 870 void (*clear_acl_cache)(struct inode *);
871 void (*close_context)(struct nfs_open_context *ctx, int);
871}; 872};
872 873
873/* 874/*