diff options
-rw-r--r-- | fs/nfs/inode.c | 34 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/proc.c | 2 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 3 |
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 | */ | ||
943 | int 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) | |||
579 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 579 | static 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 *); |
294 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); | 294 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); |
295 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); | 295 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); |
296 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); | ||
296 | extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 297 | extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
297 | extern int nfs_permission(struct inode *, int, struct nameidata *); | 298 | extern int nfs_permission(struct inode *, int, struct nameidata *); |
298 | extern int nfs_open(struct inode *, struct file *); | 299 | extern 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 |