aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-12-03 15:20:07 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-12-03 15:20:07 -0500
commit24aa1fe6779eaddb3e0b1b802585dcf6faf9cc44 (patch)
treedc851edc67202f459262985db0cd451b1d523462 /fs/nfs
parent223db122bfccd463751d8b0c09a638abee03681d (diff)
NFS: Fix a few further cache consistency regressions
Steve Dickson writes: Doing the following: 1. On server: $ mkdir ~/t $ echo Hello > ~/t/tmp 2. On client, wait for a string to appear in this file: $ until grep -q foo t/tmp ; do echo -n . ; sleep 1 ; done 3. On server, create a *new* file with the same name containing that string: $ mv ~/t/tmp ~/t/tmp.old; echo foo > ~/t/tmp will show how the client will never (and I mean never ;-) ) see the updated file. The problem is that we do not update nfsi->cache_change_attribute when the file changes on the server (we only update it when our client makes the changes). This again means that functions like nfs_check_verifier() will fail to register when the parent directory has changed and should trigger a dentry lookup revalidation. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/inode.c54
1 files changed, 20 insertions, 34 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index b551b19aa6e7..afd75d0463fd 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -54,7 +54,7 @@
54#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) 54#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1)
55 55
56static void nfs_invalidate_inode(struct inode *); 56static void nfs_invalidate_inode(struct inode *);
57static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long); 57static int nfs_update_inode(struct inode *, struct nfs_fattr *);
58 58
59static struct inode *nfs_alloc_inode(struct super_block *sb); 59static struct inode *nfs_alloc_inode(struct super_block *sb);
60static void nfs_destroy_inode(struct inode *); 60static void nfs_destroy_inode(struct inode *);
@@ -1080,8 +1080,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1080 int status = -ESTALE; 1080 int status = -ESTALE;
1081 struct nfs_fattr fattr; 1081 struct nfs_fattr fattr;
1082 struct nfs_inode *nfsi = NFS_I(inode); 1082 struct nfs_inode *nfsi = NFS_I(inode);
1083 unsigned long verifier;
1084 unsigned long cache_validity;
1085 1083
1086 dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", 1084 dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
1087 inode->i_sb->s_id, (long long)NFS_FILEID(inode)); 1085 inode->i_sb->s_id, (long long)NFS_FILEID(inode));
@@ -1106,8 +1104,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1106 } 1104 }
1107 } 1105 }
1108 1106
1109 /* Protect against RPC races by saving the change attribute */
1110 verifier = nfs_save_change_attribute(inode);
1111 status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); 1107 status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
1112 if (status != 0) { 1108 if (status != 0) {
1113 dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", 1109 dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
@@ -1122,7 +1118,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1122 } 1118 }
1123 1119
1124 spin_lock(&inode->i_lock); 1120 spin_lock(&inode->i_lock);
1125 status = nfs_update_inode(inode, &fattr, verifier); 1121 status = nfs_update_inode(inode, &fattr);
1126 if (status) { 1122 if (status) {
1127 spin_unlock(&inode->i_lock); 1123 spin_unlock(&inode->i_lock);
1128 dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", 1124 dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
@@ -1130,20 +1126,11 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1130 (long long)NFS_FILEID(inode), status); 1126 (long long)NFS_FILEID(inode), status);
1131 goto out; 1127 goto out;
1132 } 1128 }
1133 cache_validity = nfsi->cache_validity;
1134 nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
1135
1136 /*
1137 * We may need to keep the attributes marked as invalid if
1138 * we raced with nfs_end_attr_update().
1139 */
1140 if (time_after_eq(verifier, nfsi->cache_change_attribute))
1141 nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
1142 spin_unlock(&inode->i_lock); 1129 spin_unlock(&inode->i_lock);
1143 1130
1144 nfs_revalidate_mapping(inode, inode->i_mapping); 1131 nfs_revalidate_mapping(inode, inode->i_mapping);
1145 1132
1146 if (cache_validity & NFS_INO_INVALID_ACL) 1133 if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
1147 nfs_zap_acl_cache(inode); 1134 nfs_zap_acl_cache(inode);
1148 1135
1149 dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", 1136 dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
@@ -1346,10 +1333,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1346 return 0; 1333 return 0;
1347 spin_lock(&inode->i_lock); 1334 spin_lock(&inode->i_lock);
1348 nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; 1335 nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
1349 if (nfs_verify_change_attribute(inode, fattr->time_start))
1350 nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
1351 if (time_after(fattr->time_start, nfsi->last_updated)) 1336 if (time_after(fattr->time_start, nfsi->last_updated))
1352 status = nfs_update_inode(inode, fattr, fattr->time_start); 1337 status = nfs_update_inode(inode, fattr);
1353 else 1338 else
1354 status = nfs_check_inode_attributes(inode, fattr); 1339 status = nfs_check_inode_attributes(inode, fattr);
1355 1340
@@ -1375,10 +1360,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1375 nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; 1360 nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
1376 goto out; 1361 goto out;
1377 } 1362 }
1378 status = nfs_update_inode(inode, fattr, fattr->time_start); 1363 status = nfs_update_inode(inode, fattr);
1379 if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute))
1380 nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
1381 nfsi->cache_change_attribute = jiffies;
1382out: 1364out:
1383 spin_unlock(&inode->i_lock); 1365 spin_unlock(&inode->i_lock);
1384 return status; 1366 return status;
@@ -1396,12 +1378,12 @@ out:
1396 * 1378 *
1397 * A very similar scenario holds for the dir cache. 1379 * A very similar scenario holds for the dir cache.
1398 */ 1380 */
1399static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) 1381static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1400{ 1382{
1401 struct nfs_inode *nfsi = NFS_I(inode); 1383 struct nfs_inode *nfsi = NFS_I(inode);
1402 loff_t cur_isize, new_isize; 1384 loff_t cur_isize, new_isize;
1403 unsigned int invalid = 0; 1385 unsigned int invalid = 0;
1404 int data_unstable; 1386 int data_stable;
1405 1387
1406 dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", 1388 dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
1407 __FUNCTION__, inode->i_sb->s_id, inode->i_ino, 1389 __FUNCTION__, inode->i_sb->s_id, inode->i_ino,
@@ -1432,8 +1414,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1432 nfsi->last_updated = jiffies; 1414 nfsi->last_updated = jiffies;
1433 1415
1434 /* Are we racing with known updates of the metadata on the server? */ 1416 /* Are we racing with known updates of the metadata on the server? */
1435 data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || 1417 data_stable = nfs_verify_change_attribute(inode, fattr->time_start);
1436 (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); 1418 if (data_stable)
1419 nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
1437 1420
1438 /* Check if our cached file size is stale */ 1421 /* Check if our cached file size is stale */
1439 new_isize = nfs_size_to_loff_t(fattr->size); 1422 new_isize = nfs_size_to_loff_t(fattr->size);
@@ -1442,7 +1425,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1442 /* Do we perhaps have any outstanding writes? */ 1425 /* Do we perhaps have any outstanding writes? */
1443 if (nfsi->npages == 0) { 1426 if (nfsi->npages == 0) {
1444 /* No, but did we race with nfs_end_data_update()? */ 1427 /* No, but did we race with nfs_end_data_update()? */
1445 if (time_after_eq(verifier, nfsi->cache_change_attribute)) { 1428 if (data_stable) {
1446 inode->i_size = new_isize; 1429 inode->i_size = new_isize;
1447 invalid |= NFS_INO_INVALID_DATA; 1430 invalid |= NFS_INO_INVALID_DATA;
1448 } 1431 }
@@ -1451,6 +1434,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1451 inode->i_size = new_isize; 1434 inode->i_size = new_isize;
1452 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1435 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1453 } 1436 }
1437 nfsi->cache_change_attribute = jiffies;
1454 dprintk("NFS: isize change on server for file %s/%ld\n", 1438 dprintk("NFS: isize change on server for file %s/%ld\n",
1455 inode->i_sb->s_id, inode->i_ino); 1439 inode->i_sb->s_id, inode->i_ino);
1456 } 1440 }
@@ -1460,8 +1444,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1460 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); 1444 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
1461 dprintk("NFS: mtime change on server for file %s/%ld\n", 1445 dprintk("NFS: mtime change on server for file %s/%ld\n",
1462 inode->i_sb->s_id, inode->i_ino); 1446 inode->i_sb->s_id, inode->i_ino);
1463 if (!data_unstable) 1447 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1464 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1448 nfsi->cache_change_attribute = jiffies;
1465 } 1449 }
1466 1450
1467 if ((fattr->valid & NFS_ATTR_FATTR_V4) 1451 if ((fattr->valid & NFS_ATTR_FATTR_V4)
@@ -1469,15 +1453,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1469 dprintk("NFS: change_attr change on server for file %s/%ld\n", 1453 dprintk("NFS: change_attr change on server for file %s/%ld\n",
1470 inode->i_sb->s_id, inode->i_ino); 1454 inode->i_sb->s_id, inode->i_ino);
1471 nfsi->change_attr = fattr->change_attr; 1455 nfsi->change_attr = fattr->change_attr;
1472 if (!data_unstable) 1456 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1473 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 1457 nfsi->cache_change_attribute = jiffies;
1474 } 1458 }
1475 1459
1476 /* If ctime has changed we should definitely clear access+acl caches */ 1460 /* If ctime has changed we should definitely clear access+acl caches */
1477 if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { 1461 if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
1478 if (!data_unstable) 1462 invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1479 invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1480 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); 1463 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
1464 nfsi->cache_change_attribute = jiffies;
1481 } 1465 }
1482 memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); 1466 memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
1483 1467
@@ -1515,6 +1499,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1515 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) 1499 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
1516 || S_ISLNK(inode->i_mode))) 1500 || S_ISLNK(inode->i_mode)))
1517 invalid &= ~NFS_INO_INVALID_DATA; 1501 invalid &= ~NFS_INO_INVALID_DATA;
1502 if (data_stable)
1503 invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
1518 if (!nfs_have_delegation(inode, FMODE_READ)) 1504 if (!nfs_have_delegation(inode, FMODE_READ))
1519 nfsi->cache_validity |= invalid; 1505 nfsi->cache_validity |= invalid;
1520 1506