diff options
-rw-r--r-- | fs/nfs/file.c | 11 | ||||
-rw-r--r-- | fs/nfs/inode.c | 41 | ||||
-rw-r--r-- | fs/nfs/internal.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 10 | ||||
-rw-r--r-- | fs/nfs/proc.c | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
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 | ||
251 | static ssize_t | 244 | static 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 | */ | ||
552 | void 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 | |||
544 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) | 570 | static 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 | ||
570 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) | 596 | static 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); | |||
152 | extern struct rpc_procinfo nfs4_procedures[]; | 152 | extern struct rpc_procinfo nfs4_procedures[]; |
153 | #endif | 153 | #endif |
154 | 154 | ||
155 | /* proc.c */ | ||
156 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | ||
157 | |||
155 | /* dir.c */ | 158 | /* dir.c */ |
156 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | 159 | extern 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 | ||
1575 | void 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 | ||
1576 | static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) | 1585 | static 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 | /* |