Merge branch 'shrinker' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/xfsdev
* 'shrinker' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/xfsdev: xfs: track AGs with reclaimable inodes in per-ag radix tree xfs: convert inode shrinker to per-filesystem contexts mm: add context argument to shrinker callback
This commit is contained in:
Коммит
620d0be881
|
@ -2926,7 +2926,7 @@ static int kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm)
|
||||||
return kvm_mmu_zap_page(kvm, page) + 1;
|
return kvm_mmu_zap_page(kvm, page) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
|
static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
struct kvm *kvm;
|
struct kvm *kvm;
|
||||||
struct kvm *kvm_freed = NULL;
|
struct kvm *kvm_freed = NULL;
|
||||||
|
|
|
@ -4978,7 +4978,7 @@ i915_gpu_is_active(struct drm_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
|
i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
drm_i915_private_t *dev_priv, *next_dev;
|
drm_i915_private_t *dev_priv, *next_dev;
|
||||||
struct drm_i915_gem_object *obj_priv, *next_obj;
|
struct drm_i915_gem_object *obj_priv, *next_obj;
|
||||||
|
|
|
@ -896,7 +896,7 @@ EXPORT_SYMBOL(shrink_dcache_parent);
|
||||||
*
|
*
|
||||||
* In this case we return -1 to tell the caller that we baled.
|
* In this case we return -1 to tell the caller that we baled.
|
||||||
*/
|
*/
|
||||||
static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
|
static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
if (nr) {
|
if (nr) {
|
||||||
if (!(gfp_mask & __GFP_FS))
|
if (!(gfp_mask & __GFP_FS))
|
||||||
|
|
|
@ -1358,7 +1358,7 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
|
static int gfs2_shrink_glock_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
struct gfs2_glock *gl;
|
struct gfs2_glock *gl;
|
||||||
int may_demote;
|
int may_demote;
|
||||||
|
|
|
@ -77,7 +77,7 @@ static LIST_HEAD(qd_lru_list);
|
||||||
static atomic_t qd_lru_count = ATOMIC_INIT(0);
|
static atomic_t qd_lru_count = ATOMIC_INIT(0);
|
||||||
static DEFINE_SPINLOCK(qd_lru_lock);
|
static DEFINE_SPINLOCK(qd_lru_lock);
|
||||||
|
|
||||||
int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask)
|
int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
struct gfs2_quota_data *qd;
|
struct gfs2_quota_data *qd;
|
||||||
struct gfs2_sbd *sdp;
|
struct gfs2_sbd *sdp;
|
||||||
|
|
|
@ -51,7 +51,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask);
|
extern int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask);
|
||||||
extern const struct quotactl_ops gfs2_quotactl_ops;
|
extern const struct quotactl_ops gfs2_quotactl_ops;
|
||||||
|
|
||||||
#endif /* __QUOTA_DOT_H__ */
|
#endif /* __QUOTA_DOT_H__ */
|
||||||
|
|
|
@ -512,7 +512,7 @@ static void prune_icache(int nr_to_scan)
|
||||||
* This function is passed the number of inodes to scan, and it returns the
|
* This function is passed the number of inodes to scan, and it returns the
|
||||||
* total number of remaining possibly-reclaimable inodes.
|
* total number of remaining possibly-reclaimable inodes.
|
||||||
*/
|
*/
|
||||||
static int shrink_icache_memory(int nr, gfp_t gfp_mask)
|
static int shrink_icache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
if (nr) {
|
if (nr) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -115,7 +115,7 @@ mb_cache_indexes(struct mb_cache *cache)
|
||||||
* What the mbcache registers as to get shrunk dynamically.
|
* What the mbcache registers as to get shrunk dynamically.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask);
|
static int mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask);
|
||||||
|
|
||||||
static struct shrinker mb_cache_shrinker = {
|
static struct shrinker mb_cache_shrinker = {
|
||||||
.shrink = mb_cache_shrink_fn,
|
.shrink = mb_cache_shrink_fn,
|
||||||
|
@ -191,13 +191,14 @@ forget:
|
||||||
* This function is called by the kernel memory management when memory
|
* This function is called by the kernel memory management when memory
|
||||||
* gets low.
|
* gets low.
|
||||||
*
|
*
|
||||||
|
* @shrink: (ignored)
|
||||||
* @nr_to_scan: Number of objects to scan
|
* @nr_to_scan: Number of objects to scan
|
||||||
* @gfp_mask: (ignored)
|
* @gfp_mask: (ignored)
|
||||||
*
|
*
|
||||||
* Returns the number of objects which are present in the cache.
|
* Returns the number of objects which are present in the cache.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask)
|
mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
LIST_HEAD(free_list);
|
LIST_HEAD(free_list);
|
||||||
struct list_head *l, *ltmp;
|
struct list_head *l, *ltmp;
|
||||||
|
|
|
@ -1710,7 +1710,7 @@ static void nfs_access_free_list(struct list_head *head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
|
int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
LIST_HEAD(head);
|
LIST_HEAD(head);
|
||||||
struct nfs_inode *nfsi;
|
struct nfs_inode *nfsi;
|
||||||
|
|
|
@ -205,7 +205,8 @@ extern struct rpc_procinfo nfs4_procedures[];
|
||||||
void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
|
void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
|
||||||
|
|
||||||
/* dir.c */
|
/* dir.c */
|
||||||
extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
|
extern int nfs_access_cache_shrinker(struct shrinker *shrink,
|
||||||
|
int nr_to_scan, gfp_t gfp_mask);
|
||||||
|
|
||||||
/* inode.c */
|
/* inode.c */
|
||||||
extern struct workqueue_struct *nfsiod_workqueue;
|
extern struct workqueue_struct *nfsiod_workqueue;
|
||||||
|
|
|
@ -676,7 +676,7 @@ static void prune_dqcache(int count)
|
||||||
* This is called from kswapd when we think we need some
|
* This is called from kswapd when we think we need some
|
||||||
* more memory
|
* more memory
|
||||||
*/
|
*/
|
||||||
static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
|
static int shrink_dqcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
if (nr) {
|
if (nr) {
|
||||||
spin_lock(&dq_list_lock);
|
spin_lock(&dq_list_lock);
|
||||||
|
|
|
@ -277,7 +277,7 @@ static int kick_a_thread(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ubifs_shrinker(int nr, gfp_t gfp_mask)
|
int ubifs_shrinker(struct shrinker *shrink, int nr, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
int freed, contention = 0;
|
int freed, contention = 0;
|
||||||
long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
|
long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
|
||||||
|
|
|
@ -1575,7 +1575,7 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot);
|
||||||
int ubifs_tnc_end_commit(struct ubifs_info *c);
|
int ubifs_tnc_end_commit(struct ubifs_info *c);
|
||||||
|
|
||||||
/* shrinker.c */
|
/* shrinker.c */
|
||||||
int ubifs_shrinker(int nr_to_scan, gfp_t gfp_mask);
|
int ubifs_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask);
|
||||||
|
|
||||||
/* commit.c */
|
/* commit.c */
|
||||||
int ubifs_bg_thread(void *info);
|
int ubifs_bg_thread(void *info);
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
static kmem_zone_t *xfs_buf_zone;
|
static kmem_zone_t *xfs_buf_zone;
|
||||||
STATIC int xfsbufd(void *);
|
STATIC int xfsbufd(void *);
|
||||||
STATIC int xfsbufd_wakeup(int, gfp_t);
|
STATIC int xfsbufd_wakeup(struct shrinker *, int, gfp_t);
|
||||||
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
|
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
|
||||||
static struct shrinker xfs_buf_shake = {
|
static struct shrinker xfs_buf_shake = {
|
||||||
.shrink = xfsbufd_wakeup,
|
.shrink = xfsbufd_wakeup,
|
||||||
|
@ -340,7 +340,7 @@ _xfs_buf_lookup_pages(
|
||||||
__func__, gfp_mask);
|
__func__, gfp_mask);
|
||||||
|
|
||||||
XFS_STATS_INC(xb_page_retries);
|
XFS_STATS_INC(xb_page_retries);
|
||||||
xfsbufd_wakeup(0, gfp_mask);
|
xfsbufd_wakeup(NULL, 0, gfp_mask);
|
||||||
congestion_wait(BLK_RW_ASYNC, HZ/50);
|
congestion_wait(BLK_RW_ASYNC, HZ/50);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
@ -1762,6 +1762,7 @@ xfs_buf_runall_queues(
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
xfsbufd_wakeup(
|
xfsbufd_wakeup(
|
||||||
|
struct shrinker *shrink,
|
||||||
int priority,
|
int priority,
|
||||||
gfp_t mask)
|
gfp_t mask)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1883,7 +1883,6 @@ init_xfs_fs(void)
|
||||||
goto out_cleanup_procfs;
|
goto out_cleanup_procfs;
|
||||||
|
|
||||||
vfs_initquota();
|
vfs_initquota();
|
||||||
xfs_inode_shrinker_init();
|
|
||||||
|
|
||||||
error = register_filesystem(&xfs_fs_type);
|
error = register_filesystem(&xfs_fs_type);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -1911,7 +1910,6 @@ exit_xfs_fs(void)
|
||||||
{
|
{
|
||||||
vfs_exitquota();
|
vfs_exitquota();
|
||||||
unregister_filesystem(&xfs_fs_type);
|
unregister_filesystem(&xfs_fs_type);
|
||||||
xfs_inode_shrinker_destroy();
|
|
||||||
xfs_sysctl_unregister();
|
xfs_sysctl_unregister();
|
||||||
xfs_cleanup_procfs();
|
xfs_cleanup_procfs();
|
||||||
xfs_buf_terminate();
|
xfs_buf_terminate();
|
||||||
|
|
|
@ -144,6 +144,41 @@ restart:
|
||||||
return last_error;
|
return last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Select the next per-ag structure to iterate during the walk. The reclaim
|
||||||
|
* walk is optimised only to walk AGs with reclaimable inodes in them.
|
||||||
|
*/
|
||||||
|
static struct xfs_perag *
|
||||||
|
xfs_inode_ag_iter_next_pag(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
xfs_agnumber_t *first,
|
||||||
|
int tag)
|
||||||
|
{
|
||||||
|
struct xfs_perag *pag = NULL;
|
||||||
|
|
||||||
|
if (tag == XFS_ICI_RECLAIM_TAG) {
|
||||||
|
int found;
|
||||||
|
int ref;
|
||||||
|
|
||||||
|
spin_lock(&mp->m_perag_lock);
|
||||||
|
found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
|
||||||
|
(void **)&pag, *first, 1, tag);
|
||||||
|
if (found <= 0) {
|
||||||
|
spin_unlock(&mp->m_perag_lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*first = pag->pag_agno + 1;
|
||||||
|
/* open coded pag reference increment */
|
||||||
|
ref = atomic_inc_return(&pag->pag_ref);
|
||||||
|
spin_unlock(&mp->m_perag_lock);
|
||||||
|
trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_);
|
||||||
|
} else {
|
||||||
|
pag = xfs_perag_get(mp, *first);
|
||||||
|
(*first)++;
|
||||||
|
}
|
||||||
|
return pag;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_inode_ag_iterator(
|
xfs_inode_ag_iterator(
|
||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
|
@ -154,16 +189,15 @@ xfs_inode_ag_iterator(
|
||||||
int exclusive,
|
int exclusive,
|
||||||
int *nr_to_scan)
|
int *nr_to_scan)
|
||||||
{
|
{
|
||||||
|
struct xfs_perag *pag;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int last_error = 0;
|
int last_error = 0;
|
||||||
xfs_agnumber_t ag;
|
xfs_agnumber_t ag;
|
||||||
int nr;
|
int nr;
|
||||||
|
|
||||||
nr = nr_to_scan ? *nr_to_scan : INT_MAX;
|
nr = nr_to_scan ? *nr_to_scan : INT_MAX;
|
||||||
for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
|
ag = 0;
|
||||||
struct xfs_perag *pag;
|
while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, tag))) {
|
||||||
|
|
||||||
pag = xfs_perag_get(mp, ag);
|
|
||||||
error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
|
error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
|
||||||
exclusive, &nr);
|
exclusive, &nr);
|
||||||
xfs_perag_put(pag);
|
xfs_perag_put(pag);
|
||||||
|
@ -640,6 +674,17 @@ __xfs_inode_set_reclaim_tag(
|
||||||
radix_tree_tag_set(&pag->pag_ici_root,
|
radix_tree_tag_set(&pag->pag_ici_root,
|
||||||
XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
|
XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
|
||||||
XFS_ICI_RECLAIM_TAG);
|
XFS_ICI_RECLAIM_TAG);
|
||||||
|
|
||||||
|
if (!pag->pag_ici_reclaimable) {
|
||||||
|
/* propagate the reclaim tag up into the perag radix tree */
|
||||||
|
spin_lock(&ip->i_mount->m_perag_lock);
|
||||||
|
radix_tree_tag_set(&ip->i_mount->m_perag_tree,
|
||||||
|
XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
|
||||||
|
XFS_ICI_RECLAIM_TAG);
|
||||||
|
spin_unlock(&ip->i_mount->m_perag_lock);
|
||||||
|
trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno,
|
||||||
|
-1, _RET_IP_);
|
||||||
|
}
|
||||||
pag->pag_ici_reclaimable++;
|
pag->pag_ici_reclaimable++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,6 +719,16 @@ __xfs_inode_clear_reclaim_tag(
|
||||||
radix_tree_tag_clear(&pag->pag_ici_root,
|
radix_tree_tag_clear(&pag->pag_ici_root,
|
||||||
XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
|
XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
|
||||||
pag->pag_ici_reclaimable--;
|
pag->pag_ici_reclaimable--;
|
||||||
|
if (!pag->pag_ici_reclaimable) {
|
||||||
|
/* clear the reclaim tag from the perag radix tree */
|
||||||
|
spin_lock(&ip->i_mount->m_perag_lock);
|
||||||
|
radix_tree_tag_clear(&ip->i_mount->m_perag_tree,
|
||||||
|
XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
|
||||||
|
XFS_ICI_RECLAIM_TAG);
|
||||||
|
spin_unlock(&ip->i_mount->m_perag_lock);
|
||||||
|
trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno,
|
||||||
|
-1, _RET_IP_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -828,83 +883,52 @@ xfs_reclaim_inodes(
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shrinker infrastructure.
|
* Shrinker infrastructure.
|
||||||
*
|
|
||||||
* This is all far more complex than it needs to be. It adds a global list of
|
|
||||||
* mounts because the shrinkers can only call a global context. We need to make
|
|
||||||
* the shrinkers pass a context to avoid the need for global state.
|
|
||||||
*/
|
*/
|
||||||
static LIST_HEAD(xfs_mount_list);
|
|
||||||
static struct rw_semaphore xfs_mount_list_lock;
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xfs_reclaim_inode_shrink(
|
xfs_reclaim_inode_shrink(
|
||||||
|
struct shrinker *shrink,
|
||||||
int nr_to_scan,
|
int nr_to_scan,
|
||||||
gfp_t gfp_mask)
|
gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp;
|
struct xfs_mount *mp;
|
||||||
struct xfs_perag *pag;
|
struct xfs_perag *pag;
|
||||||
xfs_agnumber_t ag;
|
xfs_agnumber_t ag;
|
||||||
int reclaimable = 0;
|
int reclaimable;
|
||||||
|
|
||||||
|
mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
|
||||||
if (nr_to_scan) {
|
if (nr_to_scan) {
|
||||||
if (!(gfp_mask & __GFP_FS))
|
if (!(gfp_mask & __GFP_FS))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
down_read(&xfs_mount_list_lock);
|
xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
|
||||||
list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
|
|
||||||
xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
|
|
||||||
XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);
|
XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);
|
||||||
if (nr_to_scan <= 0)
|
/* if we don't exhaust the scan, don't bother coming back */
|
||||||
break;
|
if (nr_to_scan > 0)
|
||||||
}
|
return -1;
|
||||||
up_read(&xfs_mount_list_lock);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
down_read(&xfs_mount_list_lock);
|
reclaimable = 0;
|
||||||
list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
|
ag = 0;
|
||||||
for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
|
while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag,
|
||||||
pag = xfs_perag_get(mp, ag);
|
XFS_ICI_RECLAIM_TAG))) {
|
||||||
reclaimable += pag->pag_ici_reclaimable;
|
reclaimable += pag->pag_ici_reclaimable;
|
||||||
xfs_perag_put(pag);
|
xfs_perag_put(pag);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
up_read(&xfs_mount_list_lock);
|
|
||||||
return reclaimable;
|
return reclaimable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct shrinker xfs_inode_shrinker = {
|
|
||||||
.shrink = xfs_reclaim_inode_shrink,
|
|
||||||
.seeks = DEFAULT_SEEKS,
|
|
||||||
};
|
|
||||||
|
|
||||||
void __init
|
|
||||||
xfs_inode_shrinker_init(void)
|
|
||||||
{
|
|
||||||
init_rwsem(&xfs_mount_list_lock);
|
|
||||||
register_shrinker(&xfs_inode_shrinker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xfs_inode_shrinker_destroy(void)
|
|
||||||
{
|
|
||||||
ASSERT(list_empty(&xfs_mount_list));
|
|
||||||
unregister_shrinker(&xfs_inode_shrinker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_inode_shrinker_register(
|
xfs_inode_shrinker_register(
|
||||||
struct xfs_mount *mp)
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
down_write(&xfs_mount_list_lock);
|
mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink;
|
||||||
list_add_tail(&mp->m_mplist, &xfs_mount_list);
|
mp->m_inode_shrink.seeks = DEFAULT_SEEKS;
|
||||||
up_write(&xfs_mount_list_lock);
|
register_shrinker(&mp->m_inode_shrink);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_inode_shrinker_unregister(
|
xfs_inode_shrinker_unregister(
|
||||||
struct xfs_mount *mp)
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
down_write(&xfs_mount_list_lock);
|
unregister_shrinker(&mp->m_inode_shrink);
|
||||||
list_del(&mp->m_mplist);
|
|
||||||
up_write(&xfs_mount_list_lock);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,6 @@ int xfs_inode_ag_iterator(struct xfs_mount *mp,
|
||||||
int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
|
int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
|
||||||
int flags, int tag, int write_lock, int *nr_to_scan);
|
int flags, int tag, int write_lock, int *nr_to_scan);
|
||||||
|
|
||||||
void xfs_inode_shrinker_init(void);
|
|
||||||
void xfs_inode_shrinker_destroy(void);
|
|
||||||
void xfs_inode_shrinker_register(struct xfs_mount *mp);
|
void xfs_inode_shrinker_register(struct xfs_mount *mp);
|
||||||
void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
|
void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,10 @@ DEFINE_EVENT(xfs_perag_class, name, \
|
||||||
unsigned long caller_ip), \
|
unsigned long caller_ip), \
|
||||||
TP_ARGS(mp, agno, refcount, caller_ip))
|
TP_ARGS(mp, agno, refcount, caller_ip))
|
||||||
DEFINE_PERAG_REF_EVENT(xfs_perag_get);
|
DEFINE_PERAG_REF_EVENT(xfs_perag_get);
|
||||||
|
DEFINE_PERAG_REF_EVENT(xfs_perag_get_reclaim);
|
||||||
DEFINE_PERAG_REF_EVENT(xfs_perag_put);
|
DEFINE_PERAG_REF_EVENT(xfs_perag_put);
|
||||||
|
DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim);
|
||||||
|
DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
|
||||||
|
|
||||||
TRACE_EVENT(xfs_attr_list_node_descend,
|
TRACE_EVENT(xfs_attr_list_node_descend,
|
||||||
TP_PROTO(struct xfs_attr_list_context *ctx,
|
TP_PROTO(struct xfs_attr_list_context *ctx,
|
||||||
|
|
|
@ -69,7 +69,7 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
|
||||||
|
|
||||||
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
|
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
|
||||||
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
|
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
|
||||||
STATIC int xfs_qm_shake(int, gfp_t);
|
STATIC int xfs_qm_shake(struct shrinker *, int, gfp_t);
|
||||||
|
|
||||||
static struct shrinker xfs_qm_shaker = {
|
static struct shrinker xfs_qm_shaker = {
|
||||||
.shrink = xfs_qm_shake,
|
.shrink = xfs_qm_shake,
|
||||||
|
@ -2117,7 +2117,10 @@ xfs_qm_shake_freelist(
|
||||||
*/
|
*/
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
|
xfs_qm_shake(
|
||||||
|
struct shrinker *shrink,
|
||||||
|
int nr_to_scan,
|
||||||
|
gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
int ndqused, nfree, n;
|
int ndqused, nfree, n;
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ typedef struct xfs_mount {
|
||||||
wait_queue_head_t m_wait_single_sync_task;
|
wait_queue_head_t m_wait_single_sync_task;
|
||||||
__int64_t m_update_flags; /* sb flags we need to update
|
__int64_t m_update_flags; /* sb flags we need to update
|
||||||
on the next remount,rw */
|
on the next remount,rw */
|
||||||
struct list_head m_mplist; /* inode shrinker mount list */
|
struct shrinker m_inode_shrink; /* inode reclaim shrinker */
|
||||||
} xfs_mount_t;
|
} xfs_mount_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -999,7 +999,7 @@ static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
|
||||||
* querying the cache size, so a fastpath for that case is appropriate.
|
* querying the cache size, so a fastpath for that case is appropriate.
|
||||||
*/
|
*/
|
||||||
struct shrinker {
|
struct shrinker {
|
||||||
int (*shrink)(int nr_to_scan, gfp_t gfp_mask);
|
int (*shrink)(struct shrinker *, int nr_to_scan, gfp_t gfp_mask);
|
||||||
int seeks; /* seeks to recreate an obj */
|
int seeks; /* seeks to recreate an obj */
|
||||||
|
|
||||||
/* These are for internal use */
|
/* These are for internal use */
|
||||||
|
|
|
@ -213,8 +213,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
|
||||||
list_for_each_entry(shrinker, &shrinker_list, list) {
|
list_for_each_entry(shrinker, &shrinker_list, list) {
|
||||||
unsigned long long delta;
|
unsigned long long delta;
|
||||||
unsigned long total_scan;
|
unsigned long total_scan;
|
||||||
unsigned long max_pass = (*shrinker->shrink)(0, gfp_mask);
|
unsigned long max_pass;
|
||||||
|
|
||||||
|
max_pass = (*shrinker->shrink)(shrinker, 0, gfp_mask);
|
||||||
delta = (4 * scanned) / shrinker->seeks;
|
delta = (4 * scanned) / shrinker->seeks;
|
||||||
delta *= max_pass;
|
delta *= max_pass;
|
||||||
do_div(delta, lru_pages + 1);
|
do_div(delta, lru_pages + 1);
|
||||||
|
@ -242,8 +243,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
|
||||||
int shrink_ret;
|
int shrink_ret;
|
||||||
int nr_before;
|
int nr_before;
|
||||||
|
|
||||||
nr_before = (*shrinker->shrink)(0, gfp_mask);
|
nr_before = (*shrinker->shrink)(shrinker, 0, gfp_mask);
|
||||||
shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask);
|
shrink_ret = (*shrinker->shrink)(shrinker, this_scan,
|
||||||
|
gfp_mask);
|
||||||
if (shrink_ret == -1)
|
if (shrink_ret == -1)
|
||||||
break;
|
break;
|
||||||
if (shrink_ret < nr_before)
|
if (shrink_ret < nr_before)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче