aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/dir.c44
-rw-r--r--fs/nfs/internal.h3
-rw-r--r--fs/nfs/super.c5
3 files changed, 52 insertions, 0 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index bf4f5ffda703..067d144d141b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1651,6 +1651,50 @@ static void nfs_access_free_entry(struct nfs_access_entry *entry)
1651 smp_mb__after_atomic_dec(); 1651 smp_mb__after_atomic_dec();
1652} 1652}
1653 1653
1654int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
1655{
1656 LIST_HEAD(head);
1657 struct nfs_inode *nfsi;
1658 struct nfs_access_entry *cache;
1659
1660 spin_lock(&nfs_access_lru_lock);
1661restart:
1662 list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
1663 struct inode *inode;
1664
1665 if (nr_to_scan-- == 0)
1666 break;
1667 inode = igrab(&nfsi->vfs_inode);
1668 if (inode == NULL)
1669 continue;
1670 spin_lock(&inode->i_lock);
1671 if (list_empty(&nfsi->access_cache_entry_lru))
1672 goto remove_lru_entry;
1673 cache = list_entry(nfsi->access_cache_entry_lru.next,
1674 struct nfs_access_entry, lru);
1675 list_move(&cache->lru, &head);
1676 rb_erase(&cache->rb_node, &nfsi->access_cache);
1677 if (!list_empty(&nfsi->access_cache_entry_lru))
1678 list_move_tail(&nfsi->access_cache_inode_lru,
1679 &nfs_access_lru_list);
1680 else {
1681remove_lru_entry:
1682 list_del_init(&nfsi->access_cache_inode_lru);
1683 clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
1684 }
1685 spin_unlock(&inode->i_lock);
1686 iput(inode);
1687 goto restart;
1688 }
1689 spin_unlock(&nfs_access_lru_lock);
1690 while (!list_empty(&head)) {
1691 cache = list_entry(head.next, struct nfs_access_entry, lru);
1692 list_del(&cache->lru);
1693 nfs_access_free_entry(cache);
1694 }
1695 return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure;
1696}
1697
1654static void __nfs_access_zap_cache(struct inode *inode) 1698static void __nfs_access_zap_cache(struct inode *inode)
1655{ 1699{
1656 struct nfs_inode *nfsi = NFS_I(inode); 1700 struct nfs_inode *nfsi = NFS_I(inode);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index e4f4e5def0fc..660e9ff5341c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -66,6 +66,9 @@ extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
66 struct page *page); 66 struct page *page);
67#endif 67#endif
68 68
69/* dir.c */
70extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
71
69/* inode.c */ 72/* inode.c */
70extern struct inode *nfs_alloc_inode(struct super_block *sb); 73extern struct inode *nfs_alloc_inode(struct super_block *sb);
71extern void nfs_destroy_inode(struct inode *); 74extern void nfs_destroy_inode(struct inode *);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index e8a9bee74d9d..06c321beacfe 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -221,6 +221,8 @@ module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
221 &nfs_idmap_cache_timeout, 0644); 221 &nfs_idmap_cache_timeout, 0644);
222#endif 222#endif
223 223
224static struct shrinker *acl_shrinker;
225
224/* 226/*
225 * Register the NFS filesystems 227 * Register the NFS filesystems
226 */ 228 */
@@ -240,6 +242,7 @@ int __init register_nfs_fs(void)
240 if (ret < 0) 242 if (ret < 0)
241 goto error_2; 243 goto error_2;
242#endif 244#endif
245 acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
243 return 0; 246 return 0;
244 247
245#ifdef CONFIG_NFS_V4 248#ifdef CONFIG_NFS_V4
@@ -257,6 +260,8 @@ error_0:
257 */ 260 */
258void __exit unregister_nfs_fs(void) 261void __exit unregister_nfs_fs(void)
259{ 262{
263 if (acl_shrinker != NULL)
264 remove_shrinker(acl_shrinker);
260#ifdef CONFIG_NFS_V4 265#ifdef CONFIG_NFS_V4
261 unregister_filesystem(&nfs4_fs_type); 266 unregister_filesystem(&nfs4_fs_type);
262 nfs_unregister_sysctl(); 267 nfs_unregister_sysctl();