diff options
-rw-r--r-- | fs/nfs/dir.c | 44 | ||||
-rw-r--r-- | fs/nfs/internal.h | 3 | ||||
-rw-r--r-- | fs/nfs/super.c | 5 |
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 | ||
1654 | int 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); | ||
1661 | restart: | ||
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 { | ||
1681 | remove_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 | |||
1654 | static void __nfs_access_zap_cache(struct inode *inode) | 1698 | static 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 */ | ||
70 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | ||
71 | |||
69 | /* inode.c */ | 72 | /* inode.c */ |
70 | extern struct inode *nfs_alloc_inode(struct super_block *sb); | 73 | extern struct inode *nfs_alloc_inode(struct super_block *sb); |
71 | extern void nfs_destroy_inode(struct inode *); | 74 | extern 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 | ||
224 | static 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 | */ |
258 | void __exit unregister_nfs_fs(void) | 261 | void __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(); |