diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 69 |
1 files changed, 18 insertions, 51 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6300e05e9463..b2d16758ced8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1148,27 +1148,6 @@ void nfs_end_data_update(struct inode *inode) | |||
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | /** | 1150 | /** |
1151 | * nfs_end_data_update_defer | ||
1152 | * @inode - pointer to inode | ||
1153 | * Declare end of the operations that will update file data | ||
1154 | * This will defer marking the inode as needing revalidation | ||
1155 | * unless there are no other pending updates. | ||
1156 | */ | ||
1157 | void nfs_end_data_update_defer(struct inode *inode) | ||
1158 | { | ||
1159 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1160 | |||
1161 | if (atomic_dec_and_test(&nfsi->data_updates)) { | ||
1162 | /* Mark the attribute cache for revalidation */ | ||
1163 | nfsi->flags |= NFS_INO_INVALID_ATTR; | ||
1164 | /* Directories and symlinks: invalidate page cache too */ | ||
1165 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | ||
1166 | nfsi->flags |= NFS_INO_INVALID_DATA; | ||
1167 | nfsi->cache_change_attribute ++; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | /** | ||
1172 | * nfs_refresh_inode - verify consistency of the inode attribute cache | 1151 | * nfs_refresh_inode - verify consistency of the inode attribute cache |
1173 | * @inode - pointer to inode | 1152 | * @inode - pointer to inode |
1174 | * @fattr - updated attributes | 1153 | * @fattr - updated attributes |
@@ -1222,8 +1201,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1222 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime) | 1201 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime) |
1223 | || cur_size != new_isize) | 1202 | || cur_size != new_isize) |
1224 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1203 | nfsi->flags |= NFS_INO_INVALID_ATTR; |
1225 | } else if (S_ISREG(inode->i_mode) && new_isize > cur_size) | 1204 | } else if (new_isize != cur_size && nfsi->npages == 0) |
1226 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1205 | nfsi->flags |= NFS_INO_INVALID_ATTR; |
1227 | 1206 | ||
1228 | /* Have any file permissions changed? */ | 1207 | /* Have any file permissions changed? */ |
1229 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 1208 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) |
@@ -1257,10 +1236,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1257 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) | 1236 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) |
1258 | { | 1237 | { |
1259 | struct nfs_inode *nfsi = NFS_I(inode); | 1238 | struct nfs_inode *nfsi = NFS_I(inode); |
1260 | __u64 new_size; | 1239 | loff_t cur_isize, new_isize; |
1261 | loff_t new_isize; | ||
1262 | unsigned int invalid = 0; | 1240 | unsigned int invalid = 0; |
1263 | loff_t cur_isize; | ||
1264 | int data_unstable; | 1241 | int data_unstable; |
1265 | 1242 | ||
1266 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 1243 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
@@ -1293,49 +1270,39 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1293 | /* Are we racing with known updates of the metadata on the server? */ | 1270 | /* Are we racing with known updates of the metadata on the server? */ |
1294 | data_unstable = ! nfs_verify_change_attribute(inode, verifier); | 1271 | data_unstable = ! nfs_verify_change_attribute(inode, verifier); |
1295 | 1272 | ||
1296 | /* Check if the file size agrees */ | 1273 | /* Check if our cached file size is stale */ |
1297 | new_size = fattr->size; | ||
1298 | new_isize = nfs_size_to_loff_t(fattr->size); | 1274 | new_isize = nfs_size_to_loff_t(fattr->size); |
1299 | cur_isize = i_size_read(inode); | 1275 | cur_isize = i_size_read(inode); |
1300 | if (cur_isize != new_size) { | 1276 | if (new_isize != cur_isize) { |
1301 | #ifdef NFS_DEBUG_VERBOSE | 1277 | /* Do we perhaps have any outstanding writes? */ |
1302 | printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); | 1278 | if (nfsi->npages == 0) { |
1303 | #endif | 1279 | /* No, but did we race with nfs_end_data_update()? */ |
1304 | /* | 1280 | if (verifier == nfsi->cache_change_attribute) { |
1305 | * If we have pending writebacks, things can get | ||
1306 | * messy. | ||
1307 | */ | ||
1308 | if (S_ISREG(inode->i_mode) && data_unstable) { | ||
1309 | if (new_isize > cur_isize) { | ||
1310 | inode->i_size = new_isize; | 1281 | inode->i_size = new_isize; |
1311 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1282 | invalid |= NFS_INO_INVALID_DATA; |
1312 | } | 1283 | } |
1313 | } else { | 1284 | invalid |= NFS_INO_INVALID_ATTR; |
1285 | } else if (new_isize > cur_isize) { | ||
1314 | inode->i_size = new_isize; | 1286 | inode->i_size = new_isize; |
1315 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1287 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1316 | } | 1288 | } |
1289 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1290 | inode->i_sb->s_id, inode->i_ino); | ||
1317 | } | 1291 | } |
1318 | 1292 | ||
1319 | /* | 1293 | /* Check if the mtime agrees */ |
1320 | * Note: we don't check inode->i_mtime since pipes etc. | ||
1321 | * can change this value in VFS without requiring a | ||
1322 | * cache revalidation. | ||
1323 | */ | ||
1324 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1294 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1325 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1295 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
1326 | #ifdef NFS_DEBUG_VERBOSE | 1296 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
1327 | printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); | 1297 | inode->i_sb->s_id, inode->i_ino); |
1328 | #endif | ||
1329 | if (!data_unstable) | 1298 | if (!data_unstable) |
1330 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1299 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1331 | } | 1300 | } |
1332 | 1301 | ||
1333 | if ((fattr->valid & NFS_ATTR_FATTR_V4) | 1302 | if ((fattr->valid & NFS_ATTR_FATTR_V4) |
1334 | && nfsi->change_attr != fattr->change_attr) { | 1303 | && nfsi->change_attr != fattr->change_attr) { |
1335 | #ifdef NFS_DEBUG_VERBOSE | 1304 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
1336 | printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n", | ||
1337 | inode->i_sb->s_id, inode->i_ino); | 1305 | inode->i_sb->s_id, inode->i_ino); |
1338 | #endif | ||
1339 | nfsi->change_attr = fattr->change_attr; | 1306 | nfsi->change_attr = fattr->change_attr; |
1340 | if (!data_unstable) | 1307 | if (!data_unstable) |
1341 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1308 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |