diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 81 |
1 files changed, 33 insertions, 48 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6391d896421..afd75d0463f 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 | ||
56 | static void nfs_invalidate_inode(struct inode *); | 56 | static void nfs_invalidate_inode(struct inode *); |
57 | static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long); | 57 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); |
58 | 58 | ||
59 | static struct inode *nfs_alloc_inode(struct super_block *sb); | 59 | static struct inode *nfs_alloc_inode(struct super_block *sb); |
60 | static void nfs_destroy_inode(struct inode *); | 60 | static void nfs_destroy_inode(struct inode *); |
@@ -643,14 +643,11 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
643 | /* | 643 | /* |
644 | * Invalidate the local caches | 644 | * Invalidate the local caches |
645 | */ | 645 | */ |
646 | void | 646 | static void nfs_zap_caches_locked(struct inode *inode) |
647 | nfs_zap_caches(struct inode *inode) | ||
648 | { | 647 | { |
649 | struct nfs_inode *nfsi = NFS_I(inode); | 648 | struct nfs_inode *nfsi = NFS_I(inode); |
650 | int mode = inode->i_mode; | 649 | int mode = inode->i_mode; |
651 | 650 | ||
652 | spin_lock(&inode->i_lock); | ||
653 | |||
654 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 651 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); |
655 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 652 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; |
656 | 653 | ||
@@ -659,7 +656,12 @@ nfs_zap_caches(struct inode *inode) | |||
659 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 656 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
660 | else | 657 | else |
661 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 658 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
659 | } | ||
662 | 660 | ||
661 | void nfs_zap_caches(struct inode *inode) | ||
662 | { | ||
663 | spin_lock(&inode->i_lock); | ||
664 | nfs_zap_caches_locked(inode); | ||
663 | spin_unlock(&inode->i_lock); | 665 | spin_unlock(&inode->i_lock); |
664 | } | 666 | } |
665 | 667 | ||
@@ -676,16 +678,13 @@ static void nfs_zap_acl_cache(struct inode *inode) | |||
676 | } | 678 | } |
677 | 679 | ||
678 | /* | 680 | /* |
679 | * Invalidate, but do not unhash, the inode | 681 | * Invalidate, but do not unhash, the inode. |
682 | * NB: must be called with inode->i_lock held! | ||
680 | */ | 683 | */ |
681 | static void | 684 | static void nfs_invalidate_inode(struct inode *inode) |
682 | nfs_invalidate_inode(struct inode *inode) | ||
683 | { | 685 | { |
684 | umode_t save_mode = inode->i_mode; | 686 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
685 | 687 | nfs_zap_caches_locked(inode); | |
686 | make_bad_inode(inode); | ||
687 | inode->i_mode = save_mode; | ||
688 | nfs_zap_caches(inode); | ||
689 | } | 688 | } |
690 | 689 | ||
691 | struct nfs_find_desc { | 690 | struct nfs_find_desc { |
@@ -1081,8 +1080,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1081 | int status = -ESTALE; | 1080 | int status = -ESTALE; |
1082 | struct nfs_fattr fattr; | 1081 | struct nfs_fattr fattr; |
1083 | struct nfs_inode *nfsi = NFS_I(inode); | 1082 | struct nfs_inode *nfsi = NFS_I(inode); |
1084 | unsigned long verifier; | ||
1085 | unsigned long cache_validity; | ||
1086 | 1083 | ||
1087 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 1084 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
1088 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 1085 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
@@ -1107,8 +1104,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1107 | } | 1104 | } |
1108 | } | 1105 | } |
1109 | 1106 | ||
1110 | /* Protect against RPC races by saving the change attribute */ | ||
1111 | verifier = nfs_save_change_attribute(inode); | ||
1112 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 1107 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
1113 | if (status != 0) { | 1108 | if (status != 0) { |
1114 | 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", |
@@ -1123,7 +1118,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1123 | } | 1118 | } |
1124 | 1119 | ||
1125 | spin_lock(&inode->i_lock); | 1120 | spin_lock(&inode->i_lock); |
1126 | status = nfs_update_inode(inode, &fattr, verifier); | 1121 | status = nfs_update_inode(inode, &fattr); |
1127 | if (status) { | 1122 | if (status) { |
1128 | spin_unlock(&inode->i_lock); | 1123 | spin_unlock(&inode->i_lock); |
1129 | 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", |
@@ -1131,20 +1126,11 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1131 | (long long)NFS_FILEID(inode), status); | 1126 | (long long)NFS_FILEID(inode), status); |
1132 | goto out; | 1127 | goto out; |
1133 | } | 1128 | } |
1134 | cache_validity = nfsi->cache_validity; | ||
1135 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
1136 | |||
1137 | /* | ||
1138 | * We may need to keep the attributes marked as invalid if | ||
1139 | * we raced with nfs_end_attr_update(). | ||
1140 | */ | ||
1141 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) | ||
1142 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1143 | spin_unlock(&inode->i_lock); | 1129 | spin_unlock(&inode->i_lock); |
1144 | 1130 | ||
1145 | nfs_revalidate_mapping(inode, inode->i_mapping); | 1131 | nfs_revalidate_mapping(inode, inode->i_mapping); |
1146 | 1132 | ||
1147 | if (cache_validity & NFS_INO_INVALID_ACL) | 1133 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
1148 | nfs_zap_acl_cache(inode); | 1134 | nfs_zap_acl_cache(inode); |
1149 | 1135 | ||
1150 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1136 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
@@ -1347,10 +1333,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1347 | return 0; | 1333 | return 0; |
1348 | spin_lock(&inode->i_lock); | 1334 | spin_lock(&inode->i_lock); |
1349 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1335 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
1350 | if (nfs_verify_change_attribute(inode, fattr->time_start)) | ||
1351 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1352 | if (time_after(fattr->time_start, nfsi->last_updated)) | 1336 | if (time_after(fattr->time_start, nfsi->last_updated)) |
1353 | status = nfs_update_inode(inode, fattr, fattr->time_start); | 1337 | status = nfs_update_inode(inode, fattr); |
1354 | else | 1338 | else |
1355 | status = nfs_check_inode_attributes(inode, fattr); | 1339 | status = nfs_check_inode_attributes(inode, fattr); |
1356 | 1340 | ||
@@ -1376,10 +1360,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1376 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; | 1360 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; |
1377 | goto out; | 1361 | goto out; |
1378 | } | 1362 | } |
1379 | status = nfs_update_inode(inode, fattr, fattr->time_start); | 1363 | status = nfs_update_inode(inode, fattr); |
1380 | if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute)) | ||
1381 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
1382 | nfsi->cache_change_attribute = jiffies; | ||
1383 | out: | 1364 | out: |
1384 | spin_unlock(&inode->i_lock); | 1365 | spin_unlock(&inode->i_lock); |
1385 | return status; | 1366 | return status; |
@@ -1397,12 +1378,12 @@ out: | |||
1397 | * | 1378 | * |
1398 | * A very similar scenario holds for the dir cache. | 1379 | * A very similar scenario holds for the dir cache. |
1399 | */ | 1380 | */ |
1400 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) | 1381 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
1401 | { | 1382 | { |
1402 | struct nfs_inode *nfsi = NFS_I(inode); | 1383 | struct nfs_inode *nfsi = NFS_I(inode); |
1403 | loff_t cur_isize, new_isize; | 1384 | loff_t cur_isize, new_isize; |
1404 | unsigned int invalid = 0; | 1385 | unsigned int invalid = 0; |
1405 | int data_unstable; | 1386 | int data_stable; |
1406 | 1387 | ||
1407 | 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", |
1408 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, | 1389 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, |
@@ -1433,8 +1414,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1433 | nfsi->last_updated = jiffies; | 1414 | nfsi->last_updated = jiffies; |
1434 | 1415 | ||
1435 | /* 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? */ |
1436 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || | 1417 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
1437 | (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); | 1418 | if (data_stable) |
1419 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1438 | 1420 | ||
1439 | /* Check if our cached file size is stale */ | 1421 | /* Check if our cached file size is stale */ |
1440 | new_isize = nfs_size_to_loff_t(fattr->size); | 1422 | new_isize = nfs_size_to_loff_t(fattr->size); |
@@ -1443,7 +1425,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1443 | /* Do we perhaps have any outstanding writes? */ | 1425 | /* Do we perhaps have any outstanding writes? */ |
1444 | if (nfsi->npages == 0) { | 1426 | if (nfsi->npages == 0) { |
1445 | /* No, but did we race with nfs_end_data_update()? */ | 1427 | /* No, but did we race with nfs_end_data_update()? */ |
1446 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) { | 1428 | if (data_stable) { |
1447 | inode->i_size = new_isize; | 1429 | inode->i_size = new_isize; |
1448 | invalid |= NFS_INO_INVALID_DATA; | 1430 | invalid |= NFS_INO_INVALID_DATA; |
1449 | } | 1431 | } |
@@ -1452,6 +1434,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1452 | inode->i_size = new_isize; | 1434 | inode->i_size = new_isize; |
1453 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1435 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1454 | } | 1436 | } |
1437 | nfsi->cache_change_attribute = jiffies; | ||
1455 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1438 | dprintk("NFS: isize change on server for file %s/%ld\n", |
1456 | inode->i_sb->s_id, inode->i_ino); | 1439 | inode->i_sb->s_id, inode->i_ino); |
1457 | } | 1440 | } |
@@ -1461,8 +1444,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1461 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1444 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
1462 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1445 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
1463 | inode->i_sb->s_id, inode->i_ino); | 1446 | inode->i_sb->s_id, inode->i_ino); |
1464 | if (!data_unstable) | 1447 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1465 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1448 | nfsi->cache_change_attribute = jiffies; |
1466 | } | 1449 | } |
1467 | 1450 | ||
1468 | if ((fattr->valid & NFS_ATTR_FATTR_V4) | 1451 | if ((fattr->valid & NFS_ATTR_FATTR_V4) |
@@ -1470,15 +1453,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1470 | 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", |
1471 | inode->i_sb->s_id, inode->i_ino); | 1454 | inode->i_sb->s_id, inode->i_ino); |
1472 | nfsi->change_attr = fattr->change_attr; | 1455 | nfsi->change_attr = fattr->change_attr; |
1473 | if (!data_unstable) | 1456 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1474 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1457 | nfsi->cache_change_attribute = jiffies; |
1475 | } | 1458 | } |
1476 | 1459 | ||
1477 | /* If ctime has changed we should definitely clear access+acl caches */ | 1460 | /* If ctime has changed we should definitely clear access+acl caches */ |
1478 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1461 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1479 | if (!data_unstable) | 1462 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1480 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1481 | 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; | ||
1482 | } | 1465 | } |
1483 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1466 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1484 | 1467 | ||
@@ -1516,6 +1499,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1516 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1499 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1517 | || S_ISLNK(inode->i_mode))) | 1500 | || S_ISLNK(inode->i_mode))) |
1518 | 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); | ||
1519 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1504 | if (!nfs_have_delegation(inode, FMODE_READ)) |
1520 | nfsi->cache_validity |= invalid; | 1505 | nfsi->cache_validity |= invalid; |
1521 | 1506 | ||
@@ -1528,14 +1513,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1528 | printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", | 1513 | printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", |
1529 | __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); | 1514 | __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); |
1530 | #endif | 1515 | #endif |
1516 | out_err: | ||
1531 | /* | 1517 | /* |
1532 | * No need to worry about unhashing the dentry, as the | 1518 | * No need to worry about unhashing the dentry, as the |
1533 | * lookup validation will know that the inode is bad. | 1519 | * lookup validation will know that the inode is bad. |
1534 | * (But we fall through to invalidate the caches.) | 1520 | * (But we fall through to invalidate the caches.) |
1535 | */ | 1521 | */ |
1536 | nfs_invalidate_inode(inode); | 1522 | nfs_invalidate_inode(inode); |
1537 | out_err: | ||
1538 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | ||
1539 | return -ESTALE; | 1523 | return -ESTALE; |
1540 | } | 1524 | } |
1541 | 1525 | ||
@@ -2068,6 +2052,7 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) | |||
2068 | return NULL; | 2052 | return NULL; |
2069 | nfsi->flags = 0UL; | 2053 | nfsi->flags = 0UL; |
2070 | nfsi->cache_validity = 0UL; | 2054 | nfsi->cache_validity = 0UL; |
2055 | nfsi->cache_change_attribute = jiffies; | ||
2071 | #ifdef CONFIG_NFS_V3_ACL | 2056 | #ifdef CONFIG_NFS_V3_ACL |
2072 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 2057 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
2073 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 2058 | nfsi->acl_default = ERR_PTR(-EAGAIN); |