aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-11 14:10:23 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-11 14:10:23 -0400
commit37d9d76d8b3a2ac5817e1fa3263cfe0fdb439e51 (patch)
treeccbf57ce8f85ad8277838c50f723cbe79950eebc
parent2b57dc6cf9bf31edc0df430ea18dd1dbd3028975 (diff)
NFS: flush cached directory information slightly more readily.
If cached directory contents becomes incorrect, there is no way to flush the contents. This contrasts with files where file locking is the recommended way to ensure cache consistency between multiple applications (a read-lock always flushes the cache). Also while changes to files often change the size of the file (thus triggering a cache flush), changes to directories often do not change the apparent size (as the size is often rounded to a block size). So it is particularly important with directories to avoid the possibility of an incorrect cache wherever possible. When the link count on a directory changes it implies a change in the number of child directories, and so a change in the contents of this directory. So use that as a trigger to flush cached contents. When the ctime changes but the mtime does not, there are two possible reasons. 1/ The owner/mode information has been changed. 2/ utimes has been used to set the mtime backwards. In the first case, a data-cache flush is not required. In the second case it is. So on the basis that correctness trumps performance, flush the directory contents cache in this case also. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/inode.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index acaaa7c7efa4..268ce3a46220 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1113,8 +1113,16 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1113 nfs_force_lookup_revalidate(inode); 1113 nfs_force_lookup_revalidate(inode);
1114 } 1114 }
1115 /* If ctime has changed we should definitely clear access+acl caches */ 1115 /* If ctime has changed we should definitely clear access+acl caches */
1116 if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) 1116 if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
1117 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 1117 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1118 /* and probably clear data for a directory too as utimes can cause
1119 * havoc with our cache.
1120 */
1121 if (S_ISDIR(inode->i_mode)) {
1122 invalid |= NFS_INO_INVALID_DATA;
1123 nfs_force_lookup_revalidate(inode);
1124 }
1125 }
1118 } else if (nfsi->change_attr != fattr->change_attr) { 1126 } else if (nfsi->change_attr != fattr->change_attr) {
1119 dprintk("NFS: change_attr change on server for file %s/%ld\n", 1127 dprintk("NFS: change_attr change on server for file %s/%ld\n",
1120 inode->i_sb->s_id, inode->i_ino); 1128 inode->i_sb->s_id, inode->i_ino);
@@ -1148,8 +1156,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1148 inode->i_gid != fattr->gid) 1156 inode->i_gid != fattr->gid)
1149 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 1157 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1150 1158
1151 if (inode->i_nlink != fattr->nlink) 1159 if (inode->i_nlink != fattr->nlink) {
1152 invalid |= NFS_INO_INVALID_ATTR; 1160 invalid |= NFS_INO_INVALID_ATTR;
1161 if (S_ISDIR(inode->i_mode))
1162 invalid |= NFS_INO_INVALID_DATA;
1163 }
1153 1164
1154 inode->i_mode = fattr->mode; 1165 inode->i_mode = fattr->mode;
1155 inode->i_nlink = fattr->nlink; 1166 inode->i_nlink = fattr->nlink;