diff options
| -rw-r--r-- | arch/x86/kvm/mmu.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 2 | ||||
| -rw-r--r-- | fs/dcache.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/glock.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/quota.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/quota.h | 2 | ||||
| -rw-r--r-- | fs/inode.c | 2 | ||||
| -rw-r--r-- | fs/mbcache.c | 5 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 2 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 3 | ||||
| -rw-r--r-- | fs/quota/dquot.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/shrinker.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 2 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 5 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 2 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 130 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.h | 2 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_trace.h | 3 | ||||
| -rw-r--r-- | fs/xfs/quota/xfs_qm.c | 7 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.h | 2 | ||||
| -rw-r--r-- | include/linux/mm.h | 2 | ||||
| -rw-r--r-- | mm/vmscan.c | 8 |
22 files changed, 111 insertions, 80 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 3699613e8830..b1ed0a1a5913 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
| @@ -2926,7 +2926,7 @@ static int kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm) | |||
| 2926 | return kvm_mmu_zap_page(kvm, page) + 1; | 2926 | return kvm_mmu_zap_page(kvm, page) + 1; |
| 2927 | } | 2927 | } |
| 2928 | 2928 | ||
| 2929 | static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) | 2929 | static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) |
| 2930 | { | 2930 | { |
| 2931 | struct kvm *kvm; | 2931 | struct kvm *kvm; |
| 2932 | struct kvm *kvm_freed = NULL; | 2932 | struct kvm *kvm_freed = NULL; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8757ecf6e96b..e7018708cc31 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -4978,7 +4978,7 @@ i915_gpu_is_active(struct drm_device *dev) | |||
| 4978 | } | 4978 | } |
| 4979 | 4979 | ||
| 4980 | static int | 4980 | static int |
| 4981 | i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) | 4981 | i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) |
| 4982 | { | 4982 | { |
| 4983 | drm_i915_private_t *dev_priv, *next_dev; | 4983 | drm_i915_private_t *dev_priv, *next_dev; |
| 4984 | struct drm_i915_gem_object *obj_priv, *next_obj; | 4984 | struct drm_i915_gem_object *obj_priv, *next_obj; |
diff --git a/fs/dcache.c b/fs/dcache.c index c8c78ba07827..86d4db15473e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -896,7 +896,7 @@ EXPORT_SYMBOL(shrink_dcache_parent); | |||
| 896 | * | 896 | * |
| 897 | * In this case we return -1 to tell the caller that we baled. | 897 | * In this case we return -1 to tell the caller that we baled. |
| 898 | */ | 898 | */ |
| 899 | static int shrink_dcache_memory(int nr, gfp_t gfp_mask) | 899 | static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
| 900 | { | 900 | { |
| 901 | if (nr) { | 901 | if (nr) { |
| 902 | if (!(gfp_mask & __GFP_FS)) | 902 | if (!(gfp_mask & __GFP_FS)) |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index dbab3fdc2582..0898f3ec8212 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -1358,7 +1358,7 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret) | |||
| 1358 | } | 1358 | } |
| 1359 | 1359 | ||
| 1360 | 1360 | ||
| 1361 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | 1361 | static int gfs2_shrink_glock_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
| 1362 | { | 1362 | { |
| 1363 | struct gfs2_glock *gl; | 1363 | struct gfs2_glock *gl; |
| 1364 | int may_demote; | 1364 | int may_demote; |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index b256d6f24288..8f02d3db8f42 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
| @@ -77,7 +77,7 @@ static LIST_HEAD(qd_lru_list); | |||
| 77 | static atomic_t qd_lru_count = ATOMIC_INIT(0); | 77 | static atomic_t qd_lru_count = ATOMIC_INIT(0); |
| 78 | static DEFINE_SPINLOCK(qd_lru_lock); | 78 | static DEFINE_SPINLOCK(qd_lru_lock); |
| 79 | 79 | ||
| 80 | int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask) | 80 | int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
| 81 | { | 81 | { |
| 82 | struct gfs2_quota_data *qd; | 82 | struct gfs2_quota_data *qd; |
| 83 | struct gfs2_sbd *sdp; | 83 | struct gfs2_sbd *sdp; |
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index 195f60c8bd14..e7d236ca48bd 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h | |||
| @@ -51,7 +51,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) | |||
| 51 | return ret; | 51 | return ret; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask); | 54 | extern int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask); |
| 55 | extern const struct quotactl_ops gfs2_quotactl_ops; | 55 | extern const struct quotactl_ops gfs2_quotactl_ops; |
| 56 | 56 | ||
| 57 | #endif /* __QUOTA_DOT_H__ */ | 57 | #endif /* __QUOTA_DOT_H__ */ |
diff --git a/fs/inode.c b/fs/inode.c index 2bee20ae3d65..722860b323a9 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -512,7 +512,7 @@ static void prune_icache(int nr_to_scan) | |||
| 512 | * This function is passed the number of inodes to scan, and it returns the | 512 | * This function is passed the number of inodes to scan, and it returns the |
| 513 | * total number of remaining possibly-reclaimable inodes. | 513 | * total number of remaining possibly-reclaimable inodes. |
| 514 | */ | 514 | */ |
| 515 | static int shrink_icache_memory(int nr, gfp_t gfp_mask) | 515 | static int shrink_icache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
| 516 | { | 516 | { |
| 517 | if (nr) { | 517 | if (nr) { |
| 518 | /* | 518 | /* |
diff --git a/fs/mbcache.c b/fs/mbcache.c index ec88ff3d04a9..e28f21b95344 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
| @@ -115,7 +115,7 @@ mb_cache_indexes(struct mb_cache *cache) | |||
| 115 | * What the mbcache registers as to get shrunk dynamically. | 115 | * What the mbcache registers as to get shrunk dynamically. |
| 116 | */ | 116 | */ |
| 117 | 117 | ||
| 118 | static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask); | 118 | static int mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask); |
| 119 | 119 | ||
| 120 | static struct shrinker mb_cache_shrinker = { | 120 | static struct shrinker mb_cache_shrinker = { |
| 121 | .shrink = mb_cache_shrink_fn, | 121 | .shrink = mb_cache_shrink_fn, |
| @@ -191,13 +191,14 @@ forget: | |||
| 191 | * This function is called by the kernel memory management when memory | 191 | * This function is called by the kernel memory management when memory |
| 192 | * gets low. | 192 | * gets low. |
| 193 | * | 193 | * |
| 194 | * @shrink: (ignored) | ||
| 194 | * @nr_to_scan: Number of objects to scan | 195 | * @nr_to_scan: Number of objects to scan |
| 195 | * @gfp_mask: (ignored) | 196 | * @gfp_mask: (ignored) |
| 196 | * | 197 | * |
| 197 | * Returns the number of objects which are present in the cache. | 198 | * Returns the number of objects which are present in the cache. |
| 198 | */ | 199 | */ |
| 199 | static int | 200 | static int |
| 200 | mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask) | 201 | mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) |
| 201 | { | 202 | { |
| 202 | LIST_HEAD(free_list); | 203 | LIST_HEAD(free_list); |
| 203 | struct list_head *l, *ltmp; | 204 | struct list_head *l, *ltmp; |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 782b431ef91c..e60416d3f818 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1710,7 +1710,7 @@ static void nfs_access_free_list(struct list_head *head) | |||
| 1710 | } | 1710 | } |
| 1711 | } | 1711 | } |
| 1712 | 1712 | ||
| 1713 | int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | 1713 | int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) |
| 1714 | { | 1714 | { |
| 1715 | LIST_HEAD(head); | 1715 | LIST_HEAD(head); |
| 1716 | struct nfs_inode *nfsi; | 1716 | struct nfs_inode *nfsi; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index d8bd619e386c..e70f44b9b3f4 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -205,7 +205,8 @@ extern struct rpc_procinfo nfs4_procedures[]; | |||
| 205 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 205 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
| 206 | 206 | ||
| 207 | /* dir.c */ | 207 | /* dir.c */ |
| 208 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | 208 | extern int nfs_access_cache_shrinker(struct shrinker *shrink, |
| 209 | int nr_to_scan, gfp_t gfp_mask); | ||
| 209 | 210 | ||
| 210 | /* inode.c */ | 211 | /* inode.c */ |
| 211 | extern struct workqueue_struct *nfsiod_workqueue; | 212 | extern struct workqueue_struct *nfsiod_workqueue; |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 12c233da1b6b..437d2ca2de97 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -676,7 +676,7 @@ static void prune_dqcache(int count) | |||
| 676 | * This is called from kswapd when we think we need some | 676 | * This is called from kswapd when we think we need some |
| 677 | * more memory | 677 | * more memory |
| 678 | */ | 678 | */ |
| 679 | static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) | 679 | static int shrink_dqcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
| 680 | { | 680 | { |
| 681 | if (nr) { | 681 | if (nr) { |
| 682 | spin_lock(&dq_list_lock); | 682 | spin_lock(&dq_list_lock); |
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index 02feb59cefca..0b201114a5ad 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c | |||
| @@ -277,7 +277,7 @@ static int kick_a_thread(void) | |||
| 277 | return 0; | 277 | return 0; |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | int ubifs_shrinker(int nr, gfp_t gfp_mask) | 280 | int ubifs_shrinker(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
| 281 | { | 281 | { |
| 282 | int freed, contention = 0; | 282 | int freed, contention = 0; |
| 283 | long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt); | 283 | long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt); |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 2eef553d50c8..04310878f449 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -1575,7 +1575,7 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot); | |||
| 1575 | int ubifs_tnc_end_commit(struct ubifs_info *c); | 1575 | int ubifs_tnc_end_commit(struct ubifs_info *c); |
| 1576 | 1576 | ||
| 1577 | /* shrinker.c */ | 1577 | /* shrinker.c */ |
| 1578 | int ubifs_shrinker(int nr_to_scan, gfp_t gfp_mask); | 1578 | int ubifs_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask); |
| 1579 | 1579 | ||
| 1580 | /* commit.c */ | 1580 | /* commit.c */ |
| 1581 | int ubifs_bg_thread(void *info); | 1581 | int ubifs_bg_thread(void *info); |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 649ade8ef598..2ee3f7a60163 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | 45 | ||
| 46 | static kmem_zone_t *xfs_buf_zone; | 46 | static kmem_zone_t *xfs_buf_zone; |
| 47 | STATIC int xfsbufd(void *); | 47 | STATIC int xfsbufd(void *); |
| 48 | STATIC int xfsbufd_wakeup(int, gfp_t); | 48 | STATIC int xfsbufd_wakeup(struct shrinker *, int, gfp_t); |
| 49 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); | 49 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); |
| 50 | static struct shrinker xfs_buf_shake = { | 50 | static struct shrinker xfs_buf_shake = { |
| 51 | .shrink = xfsbufd_wakeup, | 51 | .shrink = xfsbufd_wakeup, |
| @@ -340,7 +340,7 @@ _xfs_buf_lookup_pages( | |||
| 340 | __func__, gfp_mask); | 340 | __func__, gfp_mask); |
| 341 | 341 | ||
| 342 | XFS_STATS_INC(xb_page_retries); | 342 | XFS_STATS_INC(xb_page_retries); |
| 343 | xfsbufd_wakeup(0, gfp_mask); | 343 | xfsbufd_wakeup(NULL, 0, gfp_mask); |
| 344 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 344 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
| 345 | goto retry; | 345 | goto retry; |
| 346 | } | 346 | } |
| @@ -1762,6 +1762,7 @@ xfs_buf_runall_queues( | |||
| 1762 | 1762 | ||
| 1763 | STATIC int | 1763 | STATIC int |
| 1764 | xfsbufd_wakeup( | 1764 | xfsbufd_wakeup( |
| 1765 | struct shrinker *shrink, | ||
| 1765 | int priority, | 1766 | int priority, |
| 1766 | gfp_t mask) | 1767 | gfp_t mask) |
| 1767 | { | 1768 | { |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index f2d1718c9165..80938c736c27 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -1883,7 +1883,6 @@ init_xfs_fs(void) | |||
| 1883 | goto out_cleanup_procfs; | 1883 | goto out_cleanup_procfs; |
| 1884 | 1884 | ||
| 1885 | vfs_initquota(); | 1885 | vfs_initquota(); |
| 1886 | xfs_inode_shrinker_init(); | ||
| 1887 | 1886 | ||
| 1888 | error = register_filesystem(&xfs_fs_type); | 1887 | error = register_filesystem(&xfs_fs_type); |
| 1889 | if (error) | 1888 | if (error) |
| @@ -1911,7 +1910,6 @@ exit_xfs_fs(void) | |||
| 1911 | { | 1910 | { |
| 1912 | vfs_exitquota(); | 1911 | vfs_exitquota(); |
| 1913 | unregister_filesystem(&xfs_fs_type); | 1912 | unregister_filesystem(&xfs_fs_type); |
| 1914 | xfs_inode_shrinker_destroy(); | ||
| 1915 | xfs_sysctl_unregister(); | 1913 | xfs_sysctl_unregister(); |
| 1916 | xfs_cleanup_procfs(); | 1914 | xfs_cleanup_procfs(); |
| 1917 | xfs_buf_terminate(); | 1915 | xfs_buf_terminate(); |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index ef7f0218bccb..a51a07c3a70c 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
| @@ -144,6 +144,41 @@ restart: | |||
| 144 | return last_error; | 144 | return last_error; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | /* | ||
| 148 | * Select the next per-ag structure to iterate during the walk. The reclaim | ||
| 149 | * walk is optimised only to walk AGs with reclaimable inodes in them. | ||
| 150 | */ | ||
| 151 | static struct xfs_perag * | ||
| 152 | xfs_inode_ag_iter_next_pag( | ||
| 153 | struct xfs_mount *mp, | ||
| 154 | xfs_agnumber_t *first, | ||
| 155 | int tag) | ||
| 156 | { | ||
| 157 | struct xfs_perag *pag = NULL; | ||
| 158 | |||
| 159 | if (tag == XFS_ICI_RECLAIM_TAG) { | ||
| 160 | int found; | ||
| 161 | int ref; | ||
| 162 | |||
| 163 | spin_lock(&mp->m_perag_lock); | ||
| 164 | found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, | ||
| 165 | (void **)&pag, *first, 1, tag); | ||
| 166 | if (found <= 0) { | ||
| 167 | spin_unlock(&mp->m_perag_lock); | ||
| 168 | return NULL; | ||
| 169 | } | ||
| 170 | *first = pag->pag_agno + 1; | ||
| 171 | /* open coded pag reference increment */ | ||
| 172 | ref = atomic_inc_return(&pag->pag_ref); | ||
| 173 | spin_unlock(&mp->m_perag_lock); | ||
| 174 | trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_); | ||
| 175 | } else { | ||
| 176 | pag = xfs_perag_get(mp, *first); | ||
| 177 | (*first)++; | ||
| 178 | } | ||
| 179 | return pag; | ||
| 180 | } | ||
| 181 | |||
| 147 | int | 182 | int |
| 148 | xfs_inode_ag_iterator( | 183 | xfs_inode_ag_iterator( |
| 149 | struct xfs_mount *mp, | 184 | struct xfs_mount *mp, |
| @@ -154,16 +189,15 @@ xfs_inode_ag_iterator( | |||
| 154 | int exclusive, | 189 | int exclusive, |
| 155 | int *nr_to_scan) | 190 | int *nr_to_scan) |
| 156 | { | 191 | { |
| 192 | struct xfs_perag *pag; | ||
| 157 | int error = 0; | 193 | int error = 0; |
| 158 | int last_error = 0; | 194 | int last_error = 0; |
| 159 | xfs_agnumber_t ag; | 195 | xfs_agnumber_t ag; |
| 160 | int nr; | 196 | int nr; |
| 161 | 197 | ||
| 162 | nr = nr_to_scan ? *nr_to_scan : INT_MAX; | 198 | nr = nr_to_scan ? *nr_to_scan : INT_MAX; |
| 163 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | 199 | ag = 0; |
| 164 | struct xfs_perag *pag; | 200 | while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, tag))) { |
| 165 | |||
| 166 | pag = xfs_perag_get(mp, ag); | ||
| 167 | error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, | 201 | error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, |
| 168 | exclusive, &nr); | 202 | exclusive, &nr); |
| 169 | xfs_perag_put(pag); | 203 | xfs_perag_put(pag); |
| @@ -640,6 +674,17 @@ __xfs_inode_set_reclaim_tag( | |||
| 640 | radix_tree_tag_set(&pag->pag_ici_root, | 674 | radix_tree_tag_set(&pag->pag_ici_root, |
| 641 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), | 675 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), |
| 642 | XFS_ICI_RECLAIM_TAG); | 676 | XFS_ICI_RECLAIM_TAG); |
| 677 | |||
| 678 | if (!pag->pag_ici_reclaimable) { | ||
| 679 | /* propagate the reclaim tag up into the perag radix tree */ | ||
| 680 | spin_lock(&ip->i_mount->m_perag_lock); | ||
| 681 | radix_tree_tag_set(&ip->i_mount->m_perag_tree, | ||
| 682 | XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), | ||
| 683 | XFS_ICI_RECLAIM_TAG); | ||
| 684 | spin_unlock(&ip->i_mount->m_perag_lock); | ||
| 685 | trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno, | ||
| 686 | -1, _RET_IP_); | ||
| 687 | } | ||
| 643 | pag->pag_ici_reclaimable++; | 688 | pag->pag_ici_reclaimable++; |
| 644 | } | 689 | } |
| 645 | 690 | ||
| @@ -674,6 +719,16 @@ __xfs_inode_clear_reclaim_tag( | |||
| 674 | radix_tree_tag_clear(&pag->pag_ici_root, | 719 | radix_tree_tag_clear(&pag->pag_ici_root, |
| 675 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | 720 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); |
| 676 | pag->pag_ici_reclaimable--; | 721 | pag->pag_ici_reclaimable--; |
| 722 | if (!pag->pag_ici_reclaimable) { | ||
| 723 | /* clear the reclaim tag from the perag radix tree */ | ||
| 724 | spin_lock(&ip->i_mount->m_perag_lock); | ||
| 725 | radix_tree_tag_clear(&ip->i_mount->m_perag_tree, | ||
| 726 | XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), | ||
| 727 | XFS_ICI_RECLAIM_TAG); | ||
| 728 | spin_unlock(&ip->i_mount->m_perag_lock); | ||
| 729 | trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno, | ||
| 730 | -1, _RET_IP_); | ||
| 731 | } | ||
| 677 | } | 732 | } |
| 678 | 733 | ||
| 679 | /* | 734 | /* |
| @@ -828,83 +883,52 @@ xfs_reclaim_inodes( | |||
| 828 | 883 | ||
| 829 | /* | 884 | /* |
| 830 | * Shrinker infrastructure. | 885 | * Shrinker infrastructure. |
| 831 | * | ||
| 832 | * This is all far more complex than it needs to be. It adds a global list of | ||
| 833 | * mounts because the shrinkers can only call a global context. We need to make | ||
| 834 | * the shrinkers pass a context to avoid the need for global state. | ||
| 835 | */ | 886 | */ |
| 836 | static LIST_HEAD(xfs_mount_list); | ||
| 837 | static struct rw_semaphore xfs_mount_list_lock; | ||
| 838 | |||
| 839 | static int | 887 | static int |
| 840 | xfs_reclaim_inode_shrink( | 888 | xfs_reclaim_inode_shrink( |
| 889 | struct shrinker *shrink, | ||
| 841 | int nr_to_scan, | 890 | int nr_to_scan, |
| 842 | gfp_t gfp_mask) | 891 | gfp_t gfp_mask) |
| 843 | { | 892 | { |
| 844 | struct xfs_mount *mp; | 893 | struct xfs_mount *mp; |
| 845 | struct xfs_perag *pag; | 894 | struct xfs_perag *pag; |
| 846 | xfs_agnumber_t ag; | 895 | xfs_agnumber_t ag; |
| 847 | int reclaimable = 0; | 896 | int reclaimable; |
| 848 | 897 | ||
| 898 | mp = container_of(shrink, struct xfs_mount, m_inode_shrink); | ||
| 849 | if (nr_to_scan) { | 899 | if (nr_to_scan) { |
| 850 | if (!(gfp_mask & __GFP_FS)) | 900 | if (!(gfp_mask & __GFP_FS)) |
| 851 | return -1; | 901 | return -1; |
| 852 | 902 | ||
| 853 | down_read(&xfs_mount_list_lock); | 903 | xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, |
| 854 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | ||
| 855 | xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, | ||
| 856 | XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); | 904 | XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); |
| 857 | if (nr_to_scan <= 0) | 905 | /* if we don't exhaust the scan, don't bother coming back */ |
| 858 | break; | 906 | if (nr_to_scan > 0) |
| 859 | } | 907 | return -1; |
| 860 | up_read(&xfs_mount_list_lock); | 908 | } |
| 861 | } | ||
| 862 | 909 | ||
| 863 | down_read(&xfs_mount_list_lock); | 910 | reclaimable = 0; |
| 864 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | 911 | ag = 0; |
| 865 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | 912 | while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, |
| 866 | pag = xfs_perag_get(mp, ag); | 913 | XFS_ICI_RECLAIM_TAG))) { |
| 867 | reclaimable += pag->pag_ici_reclaimable; | 914 | reclaimable += pag->pag_ici_reclaimable; |
| 868 | xfs_perag_put(pag); | 915 | xfs_perag_put(pag); |
| 869 | } | ||
| 870 | } | 916 | } |
| 871 | up_read(&xfs_mount_list_lock); | ||
| 872 | return reclaimable; | 917 | return reclaimable; |
| 873 | } | 918 | } |
| 874 | 919 | ||
| 875 | static struct shrinker xfs_inode_shrinker = { | ||
| 876 | .shrink = xfs_reclaim_inode_shrink, | ||
| 877 | .seeks = DEFAULT_SEEKS, | ||
| 878 | }; | ||
| 879 | |||
| 880 | void __init | ||
| 881 | xfs_inode_shrinker_init(void) | ||
| 882 | { | ||
| 883 | init_rwsem(&xfs_mount_list_lock); | ||
| 884 | register_shrinker(&xfs_inode_shrinker); | ||
| 885 | } | ||
| 886 | |||
| 887 | void | ||
| 888 | xfs_inode_shrinker_destroy(void) | ||
| 889 | { | ||
| 890 | ASSERT(list_empty(&xfs_mount_list)); | ||
| 891 | unregister_shrinker(&xfs_inode_shrinker); | ||
| 892 | } | ||
| 893 | |||
| 894 | void | 920 | void |
| 895 | xfs_inode_shrinker_register( | 921 | xfs_inode_shrinker_register( |
| 896 | struct xfs_mount *mp) | 922 | struct xfs_mount *mp) |
| 897 | { | 923 | { |
| 898 | down_write(&xfs_mount_list_lock); | 924 | mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink; |
| 899 | list_add_tail(&mp->m_mplist, &xfs_mount_list); | 925 | mp->m_inode_shrink.seeks = DEFAULT_SEEKS; |
| 900 | up_write(&xfs_mount_list_lock); | 926 | register_shrinker(&mp->m_inode_shrink); |
| 901 | } | 927 | } |
| 902 | 928 | ||
| 903 | void | 929 | void |
| 904 | xfs_inode_shrinker_unregister( | 930 | xfs_inode_shrinker_unregister( |
| 905 | struct xfs_mount *mp) | 931 | struct xfs_mount *mp) |
| 906 | { | 932 | { |
| 907 | down_write(&xfs_mount_list_lock); | 933 | unregister_shrinker(&mp->m_inode_shrink); |
| 908 | list_del(&mp->m_mplist); | ||
| 909 | up_write(&xfs_mount_list_lock); | ||
| 910 | } | 934 | } |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index cdcbaaca9880..e28139aaa4aa 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
| @@ -55,8 +55,6 @@ int xfs_inode_ag_iterator(struct xfs_mount *mp, | |||
| 55 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), | 55 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), |
| 56 | int flags, int tag, int write_lock, int *nr_to_scan); | 56 | int flags, int tag, int write_lock, int *nr_to_scan); |
| 57 | 57 | ||
| 58 | void xfs_inode_shrinker_init(void); | ||
| 59 | void xfs_inode_shrinker_destroy(void); | ||
| 60 | void xfs_inode_shrinker_register(struct xfs_mount *mp); | 58 | void xfs_inode_shrinker_register(struct xfs_mount *mp); |
| 61 | void xfs_inode_shrinker_unregister(struct xfs_mount *mp); | 59 | void xfs_inode_shrinker_unregister(struct xfs_mount *mp); |
| 62 | 60 | ||
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h index 73d5aa117384..302820690904 100644 --- a/fs/xfs/linux-2.6/xfs_trace.h +++ b/fs/xfs/linux-2.6/xfs_trace.h | |||
| @@ -124,7 +124,10 @@ DEFINE_EVENT(xfs_perag_class, name, \ | |||
| 124 | unsigned long caller_ip), \ | 124 | unsigned long caller_ip), \ |
| 125 | TP_ARGS(mp, agno, refcount, caller_ip)) | 125 | TP_ARGS(mp, agno, refcount, caller_ip)) |
| 126 | DEFINE_PERAG_REF_EVENT(xfs_perag_get); | 126 | DEFINE_PERAG_REF_EVENT(xfs_perag_get); |
| 127 | DEFINE_PERAG_REF_EVENT(xfs_perag_get_reclaim); | ||
| 127 | DEFINE_PERAG_REF_EVENT(xfs_perag_put); | 128 | DEFINE_PERAG_REF_EVENT(xfs_perag_put); |
| 129 | DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim); | ||
| 130 | DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim); | ||
| 128 | 131 | ||
| 129 | TRACE_EVENT(xfs_attr_list_node_descend, | 132 | TRACE_EVENT(xfs_attr_list_node_descend, |
| 130 | TP_PROTO(struct xfs_attr_list_context *ctx, | 133 | TP_PROTO(struct xfs_attr_list_context *ctx, |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 8c117ff2e3ab..67c018392d62 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
| @@ -69,7 +69,7 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | |||
| 69 | 69 | ||
| 70 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); | 70 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
| 71 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); | 71 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
| 72 | STATIC int xfs_qm_shake(int, gfp_t); | 72 | STATIC int xfs_qm_shake(struct shrinker *, int, gfp_t); |
| 73 | 73 | ||
| 74 | static struct shrinker xfs_qm_shaker = { | 74 | static struct shrinker xfs_qm_shaker = { |
| 75 | .shrink = xfs_qm_shake, | 75 | .shrink = xfs_qm_shake, |
| @@ -2117,7 +2117,10 @@ xfs_qm_shake_freelist( | |||
| 2117 | */ | 2117 | */ |
| 2118 | /* ARGSUSED */ | 2118 | /* ARGSUSED */ |
| 2119 | STATIC int | 2119 | STATIC int |
| 2120 | xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask) | 2120 | xfs_qm_shake( |
| 2121 | struct shrinker *shrink, | ||
| 2122 | int nr_to_scan, | ||
| 2123 | gfp_t gfp_mask) | ||
| 2121 | { | 2124 | { |
| 2122 | int ndqused, nfree, n; | 2125 | int ndqused, nfree, n; |
| 2123 | 2126 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 1d2c7eed4eda..5761087ee8ea 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
| @@ -259,7 +259,7 @@ typedef struct xfs_mount { | |||
| 259 | wait_queue_head_t m_wait_single_sync_task; | 259 | wait_queue_head_t m_wait_single_sync_task; |
| 260 | __int64_t m_update_flags; /* sb flags we need to update | 260 | __int64_t m_update_flags; /* sb flags we need to update |
| 261 | on the next remount,rw */ | 261 | on the next remount,rw */ |
| 262 | struct list_head m_mplist; /* inode shrinker mount list */ | 262 | struct shrinker m_inode_shrink; /* inode reclaim shrinker */ |
| 263 | } xfs_mount_t; | 263 | } xfs_mount_t; |
| 264 | 264 | ||
| 265 | /* | 265 | /* |
diff --git a/include/linux/mm.h b/include/linux/mm.h index b969efb03787..a2b48041b910 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -999,7 +999,7 @@ static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm) | |||
| 999 | * querying the cache size, so a fastpath for that case is appropriate. | 999 | * querying the cache size, so a fastpath for that case is appropriate. |
| 1000 | */ | 1000 | */ |
| 1001 | struct shrinker { | 1001 | struct shrinker { |
| 1002 | int (*shrink)(int nr_to_scan, gfp_t gfp_mask); | 1002 | int (*shrink)(struct shrinker *, int nr_to_scan, gfp_t gfp_mask); |
| 1003 | int seeks; /* seeks to recreate an obj */ | 1003 | int seeks; /* seeks to recreate an obj */ |
| 1004 | 1004 | ||
| 1005 | /* These are for internal use */ | 1005 | /* These are for internal use */ |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 9c7e57cc63a3..199fa436c0dd 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -213,8 +213,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
| 213 | list_for_each_entry(shrinker, &shrinker_list, list) { | 213 | list_for_each_entry(shrinker, &shrinker_list, list) { |
| 214 | unsigned long long delta; | 214 | unsigned long long delta; |
| 215 | unsigned long total_scan; | 215 | unsigned long total_scan; |
| 216 | unsigned long max_pass = (*shrinker->shrink)(0, gfp_mask); | 216 | unsigned long max_pass; |
| 217 | 217 | ||
| 218 | max_pass = (*shrinker->shrink)(shrinker, 0, gfp_mask); | ||
| 218 | delta = (4 * scanned) / shrinker->seeks; | 219 | delta = (4 * scanned) / shrinker->seeks; |
| 219 | delta *= max_pass; | 220 | delta *= max_pass; |
| 220 | do_div(delta, lru_pages + 1); | 221 | do_div(delta, lru_pages + 1); |
| @@ -242,8 +243,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
| 242 | int shrink_ret; | 243 | int shrink_ret; |
| 243 | int nr_before; | 244 | int nr_before; |
| 244 | 245 | ||
| 245 | nr_before = (*shrinker->shrink)(0, gfp_mask); | 246 | nr_before = (*shrinker->shrink)(shrinker, 0, gfp_mask); |
| 246 | shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask); | 247 | shrink_ret = (*shrinker->shrink)(shrinker, this_scan, |
| 248 | gfp_mask); | ||
| 247 | if (shrink_ret == -1) | 249 | if (shrink_ret == -1) |
| 248 | break; | 250 | break; |
| 249 | if (shrink_ret < nr_before) | 251 | if (shrink_ret < nr_before) |
