aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-05 12:27:55 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-07 17:41:00 -0400
commitd65f557f39448c2d9e58cd564037b81e646aed2c (patch)
tree8837231b55453405e40b2b8bd22470f3314cfa11
parenta10ad17630024bf7aae8e7f18352f816ee483091 (diff)
NFS: Fix nfs_post_op_update_inode_force_wcc()
If we believe that the attributes are old (see nfs_refresh_inode()), then we shouldn't force an update. Also ensure that we hold the inode->i_lock across attribute checks and the call to nfs_refresh_inode_locked() to ensure that we don't race with other attribute updates. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/inode.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 8c514a1353c0..610d022fc7a5 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1017,6 +1017,18 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1017 return status; 1017 return status;
1018} 1018}
1019 1019
1020static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
1021{
1022 struct nfs_inode *nfsi = NFS_I(inode);
1023
1024 nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
1025 if (S_ISDIR(inode->i_mode))
1026 nfsi->cache_validity |= NFS_INO_INVALID_DATA;
1027 if ((fattr->valid & NFS_ATTR_FATTR) == 0)
1028 return 0;
1029 return nfs_refresh_inode_locked(inode, fattr);
1030}
1031
1020/** 1032/**
1021 * nfs_post_op_update_inode - try to update the inode attribute cache 1033 * nfs_post_op_update_inode - try to update the inode attribute cache
1022 * @inode - pointer to inode 1034 * @inode - pointer to inode
@@ -1033,15 +1045,10 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1033 */ 1045 */
1034int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) 1046int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1035{ 1047{
1036 struct nfs_inode *nfsi = NFS_I(inode); 1048 int status;
1037 int status = 0;
1038 1049
1039 spin_lock(&inode->i_lock); 1050 spin_lock(&inode->i_lock);
1040 nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; 1051 status = nfs_post_op_update_inode_locked(inode, fattr);
1041 if (S_ISDIR(inode->i_mode))
1042 nfsi->cache_validity |= NFS_INO_INVALID_DATA;
1043 if ((fattr->valid & NFS_ATTR_FATTR) != 0)
1044 status = nfs_refresh_inode_locked(inode, fattr);
1045 spin_unlock(&inode->i_lock); 1052 spin_unlock(&inode->i_lock);
1046 return status; 1053 return status;
1047} 1054}
@@ -1059,6 +1066,15 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1059 */ 1066 */
1060int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) 1067int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr)
1061{ 1068{
1069 int status;
1070
1071 spin_lock(&inode->i_lock);
1072 /* Don't do a WCC update if these attributes are already stale */
1073 if ((fattr->valid & NFS_ATTR_FATTR) == 0 ||
1074 !nfs_inode_attrs_need_update(inode, fattr)) {
1075 fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC);
1076 goto out_noforce;
1077 }
1062 if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && 1078 if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
1063 (fattr->valid & NFS_ATTR_WCC_V4) == 0) { 1079 (fattr->valid & NFS_ATTR_WCC_V4) == 0) {
1064 fattr->pre_change_attr = NFS_I(inode)->change_attr; 1080 fattr->pre_change_attr = NFS_I(inode)->change_attr;
@@ -1071,7 +1087,10 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
1071 fattr->pre_size = i_size_read(inode); 1087 fattr->pre_size = i_size_read(inode);
1072 fattr->valid |= NFS_ATTR_WCC; 1088 fattr->valid |= NFS_ATTR_WCC;
1073 } 1089 }
1074 return nfs_post_op_update_inode(inode, fattr); 1090out_noforce:
1091 status = nfs_post_op_update_inode_locked(inode, fattr);
1092 spin_unlock(&inode->i_lock);
1093 return status;
1075} 1094}
1076 1095
1077/* 1096/*