diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2018-03-20 16:53:31 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2018-04-10 16:06:22 -0400 |
commit | 16e143751727471f9a565515344196693bbc8762 (patch) | |
tree | eb6905af5fe0ad1f65b2392656f0bd218a8f5a03 | |
parent | cac88f942d5890706a8965e40a068d295ac95ae2 (diff) |
NFS: More fine grained attribute tracking
Currently, if the NFS_INO_INVALID_ATTR flag is set, for instance by
a call to nfs_post_op_update_inode_locked(), then it will not be cleared
until all the attributes have been revalidated. This means, for instance,
that NFSv4 writes will always force a full attribute revalidation.
Track the ctime, mtime, size and change attribute separately from the
other attributes so that we can have nfs_post_op_update_inode_locked()
set them correctly, and later have the cache consistency bitmask be
able to clear them.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | fs/nfs/dir.c | 4 | ||||
-rw-r--r-- | fs/nfs/inode.c | 109 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 7 | ||||
-rw-r--r-- | fs/nfs/write.c | 7 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 21 |
5 files changed, 94 insertions, 54 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8001f8c7ad0e..73f8b43d988c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1272,7 +1272,9 @@ static void nfs_drop_nlink(struct inode *inode) | |||
1272 | /* drop the inode if we're reasonably sure this is the last link */ | 1272 | /* drop the inode if we're reasonably sure this is the last link */ |
1273 | if (inode->i_nlink == 1) | 1273 | if (inode->i_nlink == 1) |
1274 | clear_nlink(inode); | 1274 | clear_nlink(inode); |
1275 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | 1275 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE |
1276 | | NFS_INO_INVALID_CTIME | ||
1277 | | NFS_INO_INVALID_OTHER; | ||
1276 | spin_unlock(&inode->i_lock); | 1278 | spin_unlock(&inode->i_lock); |
1277 | } | 1279 | } |
1278 | 1280 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6e5a96e2e9a0..23880f45c1e4 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -452,7 +452,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
452 | inode->i_mode = fattr->mode; | 452 | inode->i_mode = fattr->mode; |
453 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0 | 453 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0 |
454 | && nfs_server_capable(inode, NFS_CAP_MODE)) | 454 | && nfs_server_capable(inode, NFS_CAP_MODE)) |
455 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 455 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER); |
456 | /* Why so? Because we want revalidate for devices/FIFOs, and | 456 | /* Why so? Because we want revalidate for devices/FIFOs, and |
457 | * that's precisely what we have in nfs_file_inode_operations. | 457 | * that's precisely what we have in nfs_file_inode_operations. |
458 | */ | 458 | */ |
@@ -498,37 +498,35 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
498 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) | 498 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
499 | inode->i_atime = fattr->atime; | 499 | inode->i_atime = fattr->atime; |
500 | else if (nfs_server_capable(inode, NFS_CAP_ATIME)) | 500 | else if (nfs_server_capable(inode, NFS_CAP_ATIME)) |
501 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 501 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME); |
502 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) | 502 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) |
503 | inode->i_mtime = fattr->mtime; | 503 | inode->i_mtime = fattr->mtime; |
504 | else if (nfs_server_capable(inode, NFS_CAP_MTIME)) | 504 | else if (nfs_server_capable(inode, NFS_CAP_MTIME)) |
505 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 505 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME); |
506 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) | 506 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) |
507 | inode->i_ctime = fattr->ctime; | 507 | inode->i_ctime = fattr->ctime; |
508 | else if (nfs_server_capable(inode, NFS_CAP_CTIME)) | 508 | else if (nfs_server_capable(inode, NFS_CAP_CTIME)) |
509 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 509 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME); |
510 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | 510 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
511 | inode_set_iversion_raw(inode, fattr->change_attr); | 511 | inode_set_iversion_raw(inode, fattr->change_attr); |
512 | else | 512 | else |
513 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR | 513 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE); |
514 | | NFS_INO_REVAL_PAGECACHE); | ||
515 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) | 514 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
516 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 515 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
517 | else | 516 | else |
518 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR | 517 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_SIZE); |
519 | | NFS_INO_REVAL_PAGECACHE); | ||
520 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) | 518 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) |
521 | set_nlink(inode, fattr->nlink); | 519 | set_nlink(inode, fattr->nlink); |
522 | else if (nfs_server_capable(inode, NFS_CAP_NLINK)) | 520 | else if (nfs_server_capable(inode, NFS_CAP_NLINK)) |
523 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 521 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER); |
524 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) | 522 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) |
525 | inode->i_uid = fattr->uid; | 523 | inode->i_uid = fattr->uid; |
526 | else if (nfs_server_capable(inode, NFS_CAP_OWNER)) | 524 | else if (nfs_server_capable(inode, NFS_CAP_OWNER)) |
527 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 525 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER); |
528 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) | 526 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) |
529 | inode->i_gid = fattr->gid; | 527 | inode->i_gid = fattr->gid; |
530 | else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP)) | 528 | else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP)) |
531 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); | 529 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER); |
532 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | 530 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) |
533 | inode->i_blocks = fattr->du.nfs2.blocks; | 531 | inode->i_blocks = fattr->du.nfs2.blocks; |
534 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { | 532 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { |
@@ -657,6 +655,7 @@ out: | |||
657 | * nfs_setattr_update_inode - Update inode metadata after a setattr call. | 655 | * nfs_setattr_update_inode - Update inode metadata after a setattr call. |
658 | * @inode: pointer to struct inode | 656 | * @inode: pointer to struct inode |
659 | * @attr: pointer to struct iattr | 657 | * @attr: pointer to struct iattr |
658 | * @fattr: pointer to struct nfs_fattr | ||
660 | * | 659 | * |
661 | * Note: we do this in the *proc.c in order to ensure that | 660 | * Note: we do this in the *proc.c in order to ensure that |
662 | * it works for things like exclusive creates too. | 661 | * it works for things like exclusive creates too. |
@@ -669,6 +668,8 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, | |||
669 | 668 | ||
670 | spin_lock(&inode->i_lock); | 669 | spin_lock(&inode->i_lock); |
671 | NFS_I(inode)->attr_gencount = fattr->gencount; | 670 | NFS_I(inode)->attr_gencount = fattr->gencount; |
671 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE | ||
672 | | NFS_INO_INVALID_CTIME); | ||
672 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 673 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
673 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 674 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
674 | int mode = attr->ia_mode & S_IALLUGO; | 675 | int mode = attr->ia_mode & S_IALLUGO; |
@@ -683,13 +684,12 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, | |||
683 | | NFS_INO_INVALID_ACL); | 684 | | NFS_INO_INVALID_ACL); |
684 | } | 685 | } |
685 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 686 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
687 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME); | ||
686 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | 688 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); |
687 | nfs_vmtruncate(inode, attr->ia_size); | 689 | nfs_vmtruncate(inode, attr->ia_size); |
688 | } | 690 | } |
689 | if (fattr->valid) | 691 | if (fattr->valid) |
690 | nfs_update_inode(inode, fattr); | 692 | nfs_update_inode(inode, fattr); |
691 | else | ||
692 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | ||
693 | spin_unlock(&inode->i_lock); | 693 | spin_unlock(&inode->i_lock); |
694 | } | 694 | } |
695 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); | 695 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); |
@@ -1361,33 +1361,41 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
1361 | if (!nfs_file_has_buffered_writers(nfsi)) { | 1361 | if (!nfs_file_has_buffered_writers(nfsi)) { |
1362 | /* Verify a few of the more important attributes */ | 1362 | /* Verify a few of the more important attributes */ |
1363 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && !inode_eq_iversion_raw(inode, fattr->change_attr)) | 1363 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && !inode_eq_iversion_raw(inode, fattr->change_attr)) |
1364 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_REVAL_PAGECACHE; | 1364 | invalid |= NFS_INO_INVALID_CHANGE |
1365 | | NFS_INO_REVAL_PAGECACHE; | ||
1365 | 1366 | ||
1366 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) | 1367 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) |
1367 | invalid |= NFS_INO_INVALID_ATTR; | 1368 | invalid |= NFS_INO_INVALID_MTIME; |
1368 | 1369 | ||
1369 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1370 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime)) |
1370 | invalid |= NFS_INO_INVALID_ATTR; | 1371 | invalid |= NFS_INO_INVALID_CTIME; |
1371 | 1372 | ||
1372 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { | 1373 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1373 | cur_size = i_size_read(inode); | 1374 | cur_size = i_size_read(inode); |
1374 | new_isize = nfs_size_to_loff_t(fattr->size); | 1375 | new_isize = nfs_size_to_loff_t(fattr->size); |
1375 | if (cur_size != new_isize) | 1376 | if (cur_size != new_isize) |
1376 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 1377 | invalid |= NFS_INO_INVALID_SIZE |
1378 | | NFS_INO_REVAL_PAGECACHE; | ||
1377 | } | 1379 | } |
1378 | } | 1380 | } |
1379 | 1381 | ||
1380 | /* Have any file permissions changed? */ | 1382 | /* Have any file permissions changed? */ |
1381 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) | 1383 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) |
1382 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 1384 | invalid |= NFS_INO_INVALID_ACCESS |
1385 | | NFS_INO_INVALID_ACL | ||
1386 | | NFS_INO_INVALID_OTHER; | ||
1383 | if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid)) | 1387 | if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid)) |
1384 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 1388 | invalid |= NFS_INO_INVALID_ACCESS |
1389 | | NFS_INO_INVALID_ACL | ||
1390 | | NFS_INO_INVALID_OTHER; | ||
1385 | if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && !gid_eq(inode->i_gid, fattr->gid)) | 1391 | if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && !gid_eq(inode->i_gid, fattr->gid)) |
1386 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 1392 | invalid |= NFS_INO_INVALID_ACCESS |
1393 | | NFS_INO_INVALID_ACL | ||
1394 | | NFS_INO_INVALID_OTHER; | ||
1387 | 1395 | ||
1388 | /* Has the link count changed? */ | 1396 | /* Has the link count changed? */ |
1389 | if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink) | 1397 | if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink) |
1390 | invalid |= NFS_INO_INVALID_ATTR; | 1398 | invalid |= NFS_INO_INVALID_OTHER; |
1391 | 1399 | ||
1392 | if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime)) | 1400 | if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime)) |
1393 | invalid |= NFS_INO_INVALID_ATIME; | 1401 | invalid |= NFS_INO_INVALID_ATIME; |
@@ -1589,10 +1597,9 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1589 | } | 1597 | } |
1590 | EXPORT_SYMBOL_GPL(nfs_refresh_inode); | 1598 | EXPORT_SYMBOL_GPL(nfs_refresh_inode); |
1591 | 1599 | ||
1592 | static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | 1600 | static int nfs_post_op_update_inode_locked(struct inode *inode, |
1601 | struct nfs_fattr *fattr, unsigned int invalid) | ||
1593 | { | 1602 | { |
1594 | unsigned long invalid = NFS_INO_INVALID_ATTR; | ||
1595 | |||
1596 | if (S_ISDIR(inode->i_mode)) | 1603 | if (S_ISDIR(inode->i_mode)) |
1597 | invalid |= NFS_INO_INVALID_DATA; | 1604 | invalid |= NFS_INO_INVALID_DATA; |
1598 | nfs_set_cache_invalid(inode, invalid); | 1605 | nfs_set_cache_invalid(inode, invalid); |
@@ -1621,7 +1628,9 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1621 | 1628 | ||
1622 | spin_lock(&inode->i_lock); | 1629 | spin_lock(&inode->i_lock); |
1623 | nfs_fattr_set_barrier(fattr); | 1630 | nfs_fattr_set_barrier(fattr); |
1624 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1631 | status = nfs_post_op_update_inode_locked(inode, fattr, |
1632 | NFS_INO_INVALID_CHANGE | ||
1633 | | NFS_INO_INVALID_CTIME); | ||
1625 | spin_unlock(&inode->i_lock); | 1634 | spin_unlock(&inode->i_lock); |
1626 | 1635 | ||
1627 | return status; | 1636 | return status; |
@@ -1673,7 +1682,10 @@ int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fa | |||
1673 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE; | 1682 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE; |
1674 | } | 1683 | } |
1675 | out_noforce: | 1684 | out_noforce: |
1676 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1685 | status = nfs_post_op_update_inode_locked(inode, fattr, |
1686 | NFS_INO_INVALID_CHANGE | ||
1687 | | NFS_INO_INVALID_CTIME | ||
1688 | | NFS_INO_INVALID_MTIME); | ||
1677 | return status; | 1689 | return status; |
1678 | } | 1690 | } |
1679 | 1691 | ||
@@ -1795,12 +1807,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1795 | inode->i_sb->s_id, inode->i_ino); | 1807 | inode->i_sb->s_id, inode->i_ino); |
1796 | /* Could it be a race with writeback? */ | 1808 | /* Could it be a race with writeback? */ |
1797 | if (!have_writers) { | 1809 | if (!have_writers) { |
1798 | invalid |= NFS_INO_INVALID_ATTR | 1810 | invalid |= NFS_INO_INVALID_CHANGE |
1799 | | NFS_INO_INVALID_DATA | 1811 | | NFS_INO_INVALID_DATA |
1800 | | NFS_INO_INVALID_ACCESS | 1812 | | NFS_INO_INVALID_ACCESS |
1801 | | NFS_INO_INVALID_ACL; | 1813 | | NFS_INO_INVALID_ACL; |
1802 | /* Force revalidate of all attributes */ | 1814 | /* Force revalidate of all attributes */ |
1803 | save_cache_validity |= NFS_INO_INVALID_ATTR; | 1815 | save_cache_validity |= NFS_INO_INVALID_CTIME |
1816 | | NFS_INO_INVALID_MTIME | ||
1817 | | NFS_INO_INVALID_SIZE | ||
1818 | | NFS_INO_INVALID_OTHER; | ||
1804 | if (S_ISDIR(inode->i_mode)) | 1819 | if (S_ISDIR(inode->i_mode)) |
1805 | nfs_force_lookup_revalidate(inode); | 1820 | nfs_force_lookup_revalidate(inode); |
1806 | } | 1821 | } |
@@ -1808,7 +1823,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1808 | } | 1823 | } |
1809 | } else { | 1824 | } else { |
1810 | nfsi->cache_validity |= save_cache_validity & | 1825 | nfsi->cache_validity |= save_cache_validity & |
1811 | (NFS_INO_INVALID_ATTR | 1826 | (NFS_INO_INVALID_CHANGE |
1812 | | NFS_INO_REVAL_PAGECACHE | 1827 | | NFS_INO_REVAL_PAGECACHE |
1813 | | NFS_INO_REVAL_FORCED); | 1828 | | NFS_INO_REVAL_FORCED); |
1814 | cache_revalidated = false; | 1829 | cache_revalidated = false; |
@@ -1818,7 +1833,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1818 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1833 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
1819 | } else if (server->caps & NFS_CAP_MTIME) { | 1834 | } else if (server->caps & NFS_CAP_MTIME) { |
1820 | nfsi->cache_validity |= save_cache_validity & | 1835 | nfsi->cache_validity |= save_cache_validity & |
1821 | (NFS_INO_INVALID_ATTR | 1836 | (NFS_INO_INVALID_MTIME |
1822 | | NFS_INO_REVAL_FORCED); | 1837 | | NFS_INO_REVAL_FORCED); |
1823 | cache_revalidated = false; | 1838 | cache_revalidated = false; |
1824 | } | 1839 | } |
@@ -1827,7 +1842,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1827 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1842 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
1828 | } else if (server->caps & NFS_CAP_CTIME) { | 1843 | } else if (server->caps & NFS_CAP_CTIME) { |
1829 | nfsi->cache_validity |= save_cache_validity & | 1844 | nfsi->cache_validity |= save_cache_validity & |
1830 | (NFS_INO_INVALID_ATTR | 1845 | (NFS_INO_INVALID_CTIME |
1831 | | NFS_INO_REVAL_FORCED); | 1846 | | NFS_INO_REVAL_FORCED); |
1832 | cache_revalidated = false; | 1847 | cache_revalidated = false; |
1833 | } | 1848 | } |
@@ -1842,7 +1857,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1842 | if (!nfs_have_writebacks(inode) || new_isize > cur_isize) { | 1857 | if (!nfs_have_writebacks(inode) || new_isize > cur_isize) { |
1843 | i_size_write(inode, new_isize); | 1858 | i_size_write(inode, new_isize); |
1844 | if (!have_writers) | 1859 | if (!have_writers) |
1845 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1860 | invalid |= NFS_INO_INVALID_DATA; |
1846 | } | 1861 | } |
1847 | dprintk("NFS: isize change on server for file %s/%ld " | 1862 | dprintk("NFS: isize change on server for file %s/%ld " |
1848 | "(%Ld to %Ld)\n", | 1863 | "(%Ld to %Ld)\n", |
@@ -1853,7 +1868,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1853 | } | 1868 | } |
1854 | } else { | 1869 | } else { |
1855 | nfsi->cache_validity |= save_cache_validity & | 1870 | nfsi->cache_validity |= save_cache_validity & |
1856 | (NFS_INO_INVALID_ATTR | 1871 | (NFS_INO_INVALID_SIZE |
1857 | | NFS_INO_REVAL_PAGECACHE | 1872 | | NFS_INO_REVAL_PAGECACHE |
1858 | | NFS_INO_REVAL_FORCED); | 1873 | | NFS_INO_REVAL_FORCED); |
1859 | cache_revalidated = false; | 1874 | cache_revalidated = false; |
@@ -1874,55 +1889,61 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1874 | umode_t newmode = inode->i_mode & S_IFMT; | 1889 | umode_t newmode = inode->i_mode & S_IFMT; |
1875 | newmode |= fattr->mode & S_IALLUGO; | 1890 | newmode |= fattr->mode & S_IALLUGO; |
1876 | inode->i_mode = newmode; | 1891 | inode->i_mode = newmode; |
1877 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1892 | invalid |= NFS_INO_INVALID_ACCESS |
1893 | | NFS_INO_INVALID_ACL | ||
1894 | | NFS_INO_INVALID_OTHER; | ||
1878 | } | 1895 | } |
1879 | } else if (server->caps & NFS_CAP_MODE) { | 1896 | } else if (server->caps & NFS_CAP_MODE) { |
1880 | nfsi->cache_validity |= save_cache_validity & | 1897 | nfsi->cache_validity |= save_cache_validity & |
1881 | (NFS_INO_INVALID_ATTR | 1898 | (NFS_INO_INVALID_ACCESS |
1882 | | NFS_INO_INVALID_ACCESS | ||
1883 | | NFS_INO_INVALID_ACL | 1899 | | NFS_INO_INVALID_ACL |
1900 | | NFS_INO_INVALID_OTHER | ||
1884 | | NFS_INO_REVAL_FORCED); | 1901 | | NFS_INO_REVAL_FORCED); |
1885 | cache_revalidated = false; | 1902 | cache_revalidated = false; |
1886 | } | 1903 | } |
1887 | 1904 | ||
1888 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) { | 1905 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) { |
1889 | if (!uid_eq(inode->i_uid, fattr->uid)) { | 1906 | if (!uid_eq(inode->i_uid, fattr->uid)) { |
1890 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1907 | invalid |= NFS_INO_INVALID_ACCESS |
1908 | | NFS_INO_INVALID_ACL | ||
1909 | | NFS_INO_INVALID_OTHER; | ||
1891 | inode->i_uid = fattr->uid; | 1910 | inode->i_uid = fattr->uid; |
1892 | } | 1911 | } |
1893 | } else if (server->caps & NFS_CAP_OWNER) { | 1912 | } else if (server->caps & NFS_CAP_OWNER) { |
1894 | nfsi->cache_validity |= save_cache_validity & | 1913 | nfsi->cache_validity |= save_cache_validity & |
1895 | (NFS_INO_INVALID_ATTR | 1914 | (NFS_INO_INVALID_ACCESS |
1896 | | NFS_INO_INVALID_ACCESS | ||
1897 | | NFS_INO_INVALID_ACL | 1915 | | NFS_INO_INVALID_ACL |
1916 | | NFS_INO_INVALID_OTHER | ||
1898 | | NFS_INO_REVAL_FORCED); | 1917 | | NFS_INO_REVAL_FORCED); |
1899 | cache_revalidated = false; | 1918 | cache_revalidated = false; |
1900 | } | 1919 | } |
1901 | 1920 | ||
1902 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) { | 1921 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) { |
1903 | if (!gid_eq(inode->i_gid, fattr->gid)) { | 1922 | if (!gid_eq(inode->i_gid, fattr->gid)) { |
1904 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1923 | invalid |= NFS_INO_INVALID_ACCESS |
1924 | | NFS_INO_INVALID_ACL | ||
1925 | | NFS_INO_INVALID_OTHER; | ||
1905 | inode->i_gid = fattr->gid; | 1926 | inode->i_gid = fattr->gid; |
1906 | } | 1927 | } |
1907 | } else if (server->caps & NFS_CAP_OWNER_GROUP) { | 1928 | } else if (server->caps & NFS_CAP_OWNER_GROUP) { |
1908 | nfsi->cache_validity |= save_cache_validity & | 1929 | nfsi->cache_validity |= save_cache_validity & |
1909 | (NFS_INO_INVALID_ATTR | 1930 | (NFS_INO_INVALID_ACCESS |
1910 | | NFS_INO_INVALID_ACCESS | ||
1911 | | NFS_INO_INVALID_ACL | 1931 | | NFS_INO_INVALID_ACL |
1932 | | NFS_INO_INVALID_OTHER | ||
1912 | | NFS_INO_REVAL_FORCED); | 1933 | | NFS_INO_REVAL_FORCED); |
1913 | cache_revalidated = false; | 1934 | cache_revalidated = false; |
1914 | } | 1935 | } |
1915 | 1936 | ||
1916 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) { | 1937 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) { |
1917 | if (inode->i_nlink != fattr->nlink) { | 1938 | if (inode->i_nlink != fattr->nlink) { |
1918 | invalid |= NFS_INO_INVALID_ATTR; | 1939 | invalid |= NFS_INO_INVALID_OTHER; |
1919 | if (S_ISDIR(inode->i_mode)) | 1940 | if (S_ISDIR(inode->i_mode)) |
1920 | invalid |= NFS_INO_INVALID_DATA; | 1941 | invalid |= NFS_INO_INVALID_DATA; |
1921 | set_nlink(inode, fattr->nlink); | 1942 | set_nlink(inode, fattr->nlink); |
1922 | } | 1943 | } |
1923 | } else if (server->caps & NFS_CAP_NLINK) { | 1944 | } else if (server->caps & NFS_CAP_NLINK) { |
1924 | nfsi->cache_validity |= save_cache_validity & | 1945 | nfsi->cache_validity |= save_cache_validity & |
1925 | (NFS_INO_INVALID_ATTR | 1946 | (NFS_INO_INVALID_OTHER |
1926 | | NFS_INO_REVAL_FORCED); | 1947 | | NFS_INO_REVAL_FORCED); |
1927 | cache_revalidated = false; | 1948 | cache_revalidated = false; |
1928 | } | 1949 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 24b5c80b8128..e5ad2c186927 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1045,7 +1045,9 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo, | |||
1045 | struct nfs_inode *nfsi = NFS_I(dir); | 1045 | struct nfs_inode *nfsi = NFS_I(dir); |
1046 | 1046 | ||
1047 | spin_lock(&dir->i_lock); | 1047 | spin_lock(&dir->i_lock); |
1048 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1048 | nfsi->cache_validity |= NFS_INO_INVALID_CTIME |
1049 | | NFS_INO_INVALID_MTIME | ||
1050 | | NFS_INO_INVALID_DATA; | ||
1049 | if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(dir)) { | 1051 | if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(dir)) { |
1050 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1052 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
1051 | nfsi->attrtimeo_timestamp = jiffies; | 1053 | nfsi->attrtimeo_timestamp = jiffies; |
@@ -5364,7 +5366,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
5364 | * so mark the attribute cache invalid. | 5366 | * so mark the attribute cache invalid. |
5365 | */ | 5367 | */ |
5366 | spin_lock(&inode->i_lock); | 5368 | spin_lock(&inode->i_lock); |
5367 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | 5369 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE |
5370 | | NFS_INO_INVALID_CTIME; | ||
5368 | spin_unlock(&inode->i_lock); | 5371 | spin_unlock(&inode->i_lock); |
5369 | nfs_access_zap_cache(inode); | 5372 | nfs_access_zap_cache(inode); |
5370 | nfs_zap_acl_cache(inode); | 5373 | nfs_zap_acl_cache(inode); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 7428a669d7a7..3efce54ef1cd 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1562,8 +1562,11 @@ static int nfs_writeback_done(struct rpc_task *task, | |||
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | /* Deal with the suid/sgid bit corner case */ | 1564 | /* Deal with the suid/sgid bit corner case */ |
1565 | if (nfs_should_remove_suid(inode)) | 1565 | if (nfs_should_remove_suid(inode)) { |
1566 | nfs_mark_for_revalidate(inode); | 1566 | spin_lock(&inode->i_lock); |
1567 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER; | ||
1568 | spin_unlock(&inode->i_lock); | ||
1569 | } | ||
1567 | return 0; | 1570 | return 0; |
1568 | } | 1571 | } |
1569 | 1572 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 4afb11be73f4..2f129bbfaae8 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -198,7 +198,6 @@ struct nfs_inode { | |||
198 | /* | 198 | /* |
199 | * Cache validity bit flags | 199 | * Cache validity bit flags |
200 | */ | 200 | */ |
201 | #define NFS_INO_INVALID_ATTR BIT(0) /* cached attrs are invalid */ | ||
202 | #define NFS_INO_INVALID_DATA BIT(1) /* cached data is invalid */ | 201 | #define NFS_INO_INVALID_DATA BIT(1) /* cached data is invalid */ |
203 | #define NFS_INO_INVALID_ATIME BIT(2) /* cached atime is invalid */ | 202 | #define NFS_INO_INVALID_ATIME BIT(2) /* cached atime is invalid */ |
204 | #define NFS_INO_INVALID_ACCESS BIT(3) /* cached access cred invalid */ | 203 | #define NFS_INO_INVALID_ACCESS BIT(3) /* cached access cred invalid */ |
@@ -206,6 +205,17 @@ struct nfs_inode { | |||
206 | #define NFS_INO_REVAL_PAGECACHE BIT(5) /* must revalidate pagecache */ | 205 | #define NFS_INO_REVAL_PAGECACHE BIT(5) /* must revalidate pagecache */ |
207 | #define NFS_INO_REVAL_FORCED BIT(6) /* force revalidation ignoring a delegation */ | 206 | #define NFS_INO_REVAL_FORCED BIT(6) /* force revalidation ignoring a delegation */ |
208 | #define NFS_INO_INVALID_LABEL BIT(7) /* cached label is invalid */ | 207 | #define NFS_INO_INVALID_LABEL BIT(7) /* cached label is invalid */ |
208 | #define NFS_INO_INVALID_CHANGE BIT(8) /* cached change is invalid */ | ||
209 | #define NFS_INO_INVALID_CTIME BIT(9) /* cached ctime is invalid */ | ||
210 | #define NFS_INO_INVALID_MTIME BIT(10) /* cached mtime is invalid */ | ||
211 | #define NFS_INO_INVALID_SIZE BIT(11) /* cached size is invalid */ | ||
212 | #define NFS_INO_INVALID_OTHER BIT(12) /* other attrs are invalid */ | ||
213 | |||
214 | #define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \ | ||
215 | | NFS_INO_INVALID_CTIME \ | ||
216 | | NFS_INO_INVALID_MTIME \ | ||
217 | | NFS_INO_INVALID_SIZE \ | ||
218 | | NFS_INO_INVALID_OTHER) /* inode metadata is invalid */ | ||
209 | 219 | ||
210 | /* | 220 | /* |
211 | * Bit offsets in flags field | 221 | * Bit offsets in flags field |
@@ -292,10 +302,11 @@ static inline void nfs_mark_for_revalidate(struct inode *inode) | |||
292 | struct nfs_inode *nfsi = NFS_I(inode); | 302 | struct nfs_inode *nfsi = NFS_I(inode); |
293 | 303 | ||
294 | spin_lock(&inode->i_lock); | 304 | spin_lock(&inode->i_lock); |
295 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | | 305 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE |
296 | NFS_INO_REVAL_PAGECACHE | | 306 | | NFS_INO_INVALID_ACCESS |
297 | NFS_INO_INVALID_ACCESS | | 307 | | NFS_INO_INVALID_ACL |
298 | NFS_INO_INVALID_ACL; | 308 | | NFS_INO_INVALID_CHANGE |
309 | | NFS_INO_INVALID_CTIME; | ||
299 | if (S_ISDIR(inode->i_mode)) | 310 | if (S_ISDIR(inode->i_mode)) |
300 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 311 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
301 | spin_unlock(&inode->i_lock); | 312 | spin_unlock(&inode->i_lock); |