diff options
| -rw-r--r-- | fs/nfs/dir.c | 2 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 97 | ||||
| -rw-r--r-- | fs/nfs/symlink.c | 4 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 1 |
4 files changed, 72 insertions, 32 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index dee3d6c0f194..d9ba8cb0ee75 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -532,7 +532,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 532 | 532 | ||
| 533 | lock_kernel(); | 533 | lock_kernel(); |
| 534 | 534 | ||
| 535 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 535 | res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); |
| 536 | if (res < 0) { | 536 | if (res < 0) { |
| 537 | unlock_kernel(); | 537 | unlock_kernel(); |
| 538 | return res; | 538 | return res; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 63e470279309..d83498282837 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -665,49 +665,86 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 665 | return __nfs_revalidate_inode(server, inode); | 665 | return __nfs_revalidate_inode(server, inode); |
| 666 | } | 666 | } |
| 667 | 667 | ||
| 668 | static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_space *mapping) | ||
| 669 | { | ||
| 670 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 671 | |||
| 672 | if (mapping->nrpages != 0) { | ||
| 673 | int ret = invalidate_inode_pages2(mapping); | ||
| 674 | if (ret < 0) | ||
| 675 | return ret; | ||
| 676 | } | ||
| 677 | spin_lock(&inode->i_lock); | ||
| 678 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | ||
| 679 | if (S_ISDIR(inode->i_mode)) { | ||
| 680 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
| 681 | /* This ensures we revalidate child dentries */ | ||
| 682 | nfsi->cache_change_attribute = jiffies; | ||
| 683 | } | ||
| 684 | spin_unlock(&inode->i_lock); | ||
| 685 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | ||
| 686 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | ||
| 687 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | ||
| 688 | return 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) | ||
| 692 | { | ||
| 693 | int ret = 0; | ||
| 694 | |||
| 695 | mutex_lock(&inode->i_mutex); | ||
| 696 | if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_DATA) { | ||
| 697 | ret = nfs_sync_mapping(mapping); | ||
| 698 | if (ret == 0) | ||
| 699 | ret = nfs_invalidate_mapping_nolock(inode, mapping); | ||
| 700 | } | ||
| 701 | mutex_unlock(&inode->i_mutex); | ||
| 702 | return ret; | ||
| 703 | } | ||
| 704 | |||
| 668 | /** | 705 | /** |
| 669 | * nfs_revalidate_mapping - Revalidate the pagecache | 706 | * nfs_revalidate_mapping_nolock - Revalidate the pagecache |
| 670 | * @inode - pointer to host inode | 707 | * @inode - pointer to host inode |
| 671 | * @mapping - pointer to mapping | 708 | * @mapping - pointer to mapping |
| 672 | */ | 709 | */ |
| 673 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | 710 | int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping) |
| 674 | { | 711 | { |
| 675 | struct nfs_inode *nfsi = NFS_I(inode); | 712 | struct nfs_inode *nfsi = NFS_I(inode); |
| 676 | int ret = 0; | 713 | int ret = 0; |
| 677 | 714 | ||
| 678 | if (NFS_STALE(inode)) | ||
| 679 | ret = -ESTALE; | ||
| 680 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) | 715 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
| 681 | || nfs_attribute_timeout(inode)) | 716 | || nfs_attribute_timeout(inode) || NFS_STALE(inode)) { |
| 682 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 717 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 683 | if (ret < 0) | 718 | if (ret < 0) |
| 684 | goto out; | 719 | goto out; |
| 720 | } | ||
| 721 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) | ||
| 722 | ret = nfs_invalidate_mapping_nolock(inode, mapping); | ||
| 723 | out: | ||
| 724 | return ret; | ||
| 725 | } | ||
| 685 | 726 | ||
| 686 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { | 727 | /** |
| 687 | if (mapping->nrpages != 0) { | 728 | * nfs_revalidate_mapping - Revalidate the pagecache |
| 688 | if (S_ISREG(inode->i_mode)) { | 729 | * @inode - pointer to host inode |
| 689 | ret = nfs_sync_mapping(mapping); | 730 | * @mapping - pointer to mapping |
| 690 | if (ret < 0) | 731 | * |
| 691 | goto out; | 732 | * This version of the function will take the inode->i_mutex and attempt to |
| 692 | } | 733 | * flush out all dirty data if it needs to invalidate the page cache. |
| 693 | ret = invalidate_inode_pages2(mapping); | 734 | */ |
| 694 | if (ret < 0) | 735 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) |
| 695 | goto out; | 736 | { |
| 696 | } | 737 | struct nfs_inode *nfsi = NFS_I(inode); |
| 697 | spin_lock(&inode->i_lock); | 738 | int ret = 0; |
| 698 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | ||
| 699 | if (S_ISDIR(inode->i_mode)) { | ||
| 700 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
| 701 | /* This ensures we revalidate child dentries */ | ||
| 702 | nfsi->cache_change_attribute = jiffies; | ||
| 703 | } | ||
| 704 | spin_unlock(&inode->i_lock); | ||
| 705 | 739 | ||
| 706 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 740 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
| 707 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 741 | || nfs_attribute_timeout(inode) || NFS_STALE(inode)) { |
| 708 | inode->i_sb->s_id, | 742 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 709 | (long long)NFS_FILEID(inode)); | 743 | if (ret < 0) |
| 744 | goto out; | ||
| 710 | } | 745 | } |
| 746 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) | ||
| 747 | ret = nfs_invalidate_mapping(inode, mapping); | ||
| 711 | out: | 748 | out: |
| 712 | return ret; | 749 | return ret; |
| 713 | } | 750 | } |
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 6c686112cc03..525c136c7d8c 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c | |||
| @@ -50,7 +50,9 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 50 | { | 50 | { |
| 51 | struct inode *inode = dentry->d_inode; | 51 | struct inode *inode = dentry->d_inode; |
| 52 | struct page *page; | 52 | struct page *page; |
| 53 | void *err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); | 53 | void *err; |
| 54 | |||
| 55 | err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping)); | ||
| 54 | if (err) | 56 | if (err) |
| 55 | goto read_failed; | 57 | goto read_failed; |
| 56 | page = read_cache_page(&inode->i_data, 0, | 58 | page = read_cache_page(&inode->i_data, 0, |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 04963063e620..c5d4084773e8 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -308,6 +308,7 @@ extern int nfs_attribute_timeout(struct inode *inode); | |||
| 308 | extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); | 308 | extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); |
| 309 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | 309 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); |
| 310 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | 310 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |
| 311 | extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping); | ||
| 311 | extern int nfs_setattr(struct dentry *, struct iattr *); | 312 | extern int nfs_setattr(struct dentry *, struct iattr *); |
| 312 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); | 313 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); |
| 313 | extern void nfs_begin_attr_update(struct inode *); | 314 | extern void nfs_begin_attr_update(struct inode *); |
