diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-10-05 12:27:55 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-10-07 17:41:00 -0400 |
commit | d65f557f39448c2d9e58cd564037b81e646aed2c (patch) | |
tree | 8837231b55453405e40b2b8bd22470f3314cfa11 | |
parent | a10ad17630024bf7aae8e7f18352f816ee483091 (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.c | 35 |
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 | ||
1020 | static 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 | */ |
1034 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1046 | int 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 | */ |
1060 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1067 | int 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); | 1090 | out_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 | /* |