aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/inode.c34
-rw-r--r--fs/nfs/nfs3proc.c2
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfs/proc.c2
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--include/linux/nfs_xdr.h3
6 files changed, 40 insertions, 4 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 23feb9e3d8b0..c5f4e0567533 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -793,6 +793,12 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
793{ 793{
794 struct nfs_inode *nfsi = NFS_I(inode); 794 struct nfs_inode *nfsi = NFS_I(inode);
795 795
796 if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 &&
797 nfsi->change_attr == fattr->pre_change_attr) {
798 nfsi->change_attr = fattr->change_attr;
799 if (S_ISDIR(inode->i_mode))
800 nfsi->cache_validity |= NFS_INO_INVALID_DATA;
801 }
796 /* If we have atomic WCC data, we may update some attributes */ 802 /* If we have atomic WCC data, we may update some attributes */
797 if ((fattr->valid & NFS_ATTR_WCC) != 0) { 803 if ((fattr->valid & NFS_ATTR_WCC) != 0) {
798 if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) 804 if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime))
@@ -923,6 +929,34 @@ out:
923 return status; 929 return status;
924} 930}
925 931
932/**
933 * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache
934 * @inode - pointer to inode
935 * @fattr - updated attributes
936 *
937 * After an operation that has changed the inode metadata, mark the
938 * attribute cache as being invalid, then try to update it. Fake up
939 * weak cache consistency data, if none exist.
940 *
941 * This function is mainly designed to be used by the ->write_done() functions.
942 */
943int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr)
944{
945 if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
946 (fattr->valid & NFS_ATTR_WCC_V4) == 0) {
947 fattr->pre_change_attr = NFS_I(inode)->change_attr;
948 fattr->valid |= NFS_ATTR_WCC_V4;
949 }
950 if ((fattr->valid & NFS_ATTR_FATTR) != 0 &&
951 (fattr->valid & NFS_ATTR_WCC) == 0) {
952 memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime));
953 memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime));
954 fattr->pre_size = inode->i_size;
955 fattr->valid |= NFS_ATTR_WCC;
956 }
957 return nfs_post_op_update_inode(inode, fattr);
958}
959
926/* 960/*
927 * Many nfs protocol calls return the new file attributes after 961 * Many nfs protocol calls return the new file attributes after
928 * an operation. Here we update the inode to reflect the state 962 * an operation. Here we update the inode to reflect the state
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index fc6b1193a631..ce1fb99e67e1 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -750,7 +750,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
750 if (nfs3_async_handle_jukebox(task, data->inode)) 750 if (nfs3_async_handle_jukebox(task, data->inode))
751 return -EAGAIN; 751 return -EAGAIN;
752 if (task->tk_status >= 0) 752 if (task->tk_status >= 0)
753 nfs_post_op_update_inode(data->inode, data->res.fattr); 753 nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr);
754 return 0; 754 return 0;
755} 755}
756 756
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d311984d2c88..796bc8ea7194 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2427,7 +2427,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
2427 } 2427 }
2428 if (task->tk_status >= 0) { 2428 if (task->tk_status >= 0) {
2429 renew_lease(NFS_SERVER(inode), data->timestamp); 2429 renew_lease(NFS_SERVER(inode), data->timestamp);
2430 nfs_post_op_update_inode(inode, data->res.fattr); 2430 nfs_post_op_update_inode_force_wcc(inode, data->res.fattr);
2431 } 2431 }
2432 return 0; 2432 return 0;
2433} 2433}
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index ec3ede890bf4..97669ed05500 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -579,7 +579,7 @@ static void nfs_proc_read_setup(struct nfs_read_data *data)
579static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) 579static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
580{ 580{
581 if (task->tk_status >= 0) 581 if (task->tk_status >= 0)
582 nfs_post_op_update_inode(data->inode, data->res.fattr); 582 nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr);
583 return 0; 583 return 0;
584} 584}
585 585
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 63850a884902..9449286c5867 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -293,6 +293,7 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
293 struct nfs_fattr *); 293 struct nfs_fattr *);
294extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); 294extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
295extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); 295extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
296extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
296extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 297extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
297extern int nfs_permission(struct inode *, int, struct nameidata *); 298extern int nfs_permission(struct inode *, int, struct nameidata *);
298extern int nfs_open(struct inode *, struct file *); 299extern int nfs_open(struct inode *, struct file *);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 03032017ffaa..daab252f2e5c 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -62,7 +62,8 @@ struct nfs_fattr {
62#define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ 62#define NFS_ATTR_FATTR 0x0002 /* post-op attributes */
63#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ 63#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */
64#define NFS_ATTR_FATTR_V4 0x0008 /* NFSv4 change attribute */ 64#define NFS_ATTR_FATTR_V4 0x0008 /* NFSv4 change attribute */
65#define NFS_ATTR_FATTR_V4_REFERRAL 0x0010 /* NFSv4 referral */ 65#define NFS_ATTR_WCC_V4 0x0010 /* pre-op change attribute */
66#define NFS_ATTR_FATTR_V4_REFERRAL 0x0020 /* NFSv4 referral */
66 67
67/* 68/*
68 * Info on the file system 69 * Info on the file system