@@ -198,6 +198,8 @@ xfs_inode_set_reclaim_tag(
xfs_perag_set_reclaim_tag(pag);
__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
+ list_lru_add(&mp->m_inode_lru, &VFS_I(ip)->i_lru);
+
spin_unlock(&ip->i_flags_lock);
spin_unlock(&pag->pag_ici_lock);
xfs_perag_put(pag);
@@ -370,12 +372,10 @@ xfs_iget_cache_hit(
/*
* We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
- * from stomping over us while we recycle the inode. We can't
- * clear the radix tree reclaimable tag yet as it requires
- * pag_ici_lock to be held exclusive.
+ * from stomping over us while we recycle the inode. Remove it
+ * from the LRU straight away so we can re-init the VFS inode.
*/
ip->i_flags |= XFS_IRECLAIM;
-
spin_unlock(&ip->i_flags_lock);
rcu_read_unlock();
@@ -407,6 +407,7 @@ xfs_iget_cache_hit(
*/
ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS;
ip->i_flags |= XFS_INEW;
+ list_lru_del(&mp->m_inode_lru, &inode->i_lru);
xfs_inode_clear_reclaim_tag(pag, ip->i_ino);
inode->i_state = I_NEW;
ip->i_sick = 0;
@@ -1135,6 +1136,9 @@ xfs_reclaim_inode(
ino = ip->i_ino; /* for radix_tree_delete */
ip->i_flags = XFS_IRECLAIM;
ip->i_ino = 0;
+
+ /* XXX: temporary until lru based reclaim */
+ list_lru_del(&pag->pag_mount->m_inode_lru, &VFS_I(ip)->i_lru);
spin_unlock(&ip->i_flags_lock);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -1324,26 +1328,6 @@ xfs_reclaim_inodes_nr(
return xfs_reclaim_inodes_ag(mp, sync_mode, nr_to_scan);
}
-/*
- * Return the number of reclaimable inodes in the filesystem for
- * the shrinker to determine how much to reclaim.
- */
-int
-xfs_reclaim_inodes_count(
- struct xfs_mount *mp)
-{
- struct xfs_perag *pag;
- xfs_agnumber_t ag = 0;
- int reclaimable = 0;
-
- while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
- ag = pag->pag_agno + 1;
- reclaimable += pag->pag_ici_reclaimable;
- xfs_perag_put(pag);
- }
- return reclaimable;
-}
-
STATIC int
xfs_inode_match_id(
struct xfs_inode *ip,
@@ -50,7 +50,6 @@ struct xfs_inode * xfs_inode_alloc(struct xfs_mount *mp, xfs_ino_t ino);
void xfs_inode_free(struct xfs_inode *ip);
void xfs_reclaim_all_inodes(struct xfs_mount *mp);
-int xfs_reclaim_inodes_count(struct xfs_mount *mp);
long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
@@ -75,6 +75,7 @@ typedef struct xfs_mount {
uint8_t m_rt_sick;
struct xfs_ail *m_ail; /* fs active log item list */
+ struct list_lru m_inode_lru;
struct xfs_sb m_sb; /* copy of fs superblock */
spinlock_t m_sb_lock; /* sb counter lock */
@@ -891,28 +891,31 @@ xfs_fs_destroy_inode(
struct inode *inode)
{
struct xfs_inode *ip = XFS_I(inode);
+ struct xfs_mount *mp = ip->i_mount;
trace_xfs_destroy_inode(ip);
ASSERT(!rwsem_is_locked(&inode->i_rwsem));
- XFS_STATS_INC(ip->i_mount, vn_rele);
- XFS_STATS_INC(ip->i_mount, vn_remove);
+ XFS_STATS_INC(mp, vn_rele);
+ XFS_STATS_INC(mp, vn_remove);
xfs_inactive(ip);
- if (!XFS_FORCED_SHUTDOWN(ip->i_mount) && ip->i_delayed_blks) {
+ if (!XFS_FORCED_SHUTDOWN(mp) && ip->i_delayed_blks) {
xfs_check_delalloc(ip, XFS_DATA_FORK);
xfs_check_delalloc(ip, XFS_COW_FORK);
ASSERT(0);
}
- XFS_STATS_INC(ip->i_mount, vn_reclaim);
+ XFS_STATS_INC(mp, vn_reclaim);
/*
* We should never get here with one of the reclaim flags already set.
*/
- ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
- ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIM));
+ spin_lock(&ip->i_flags_lock);
+ ASSERT_ALWAYS(!__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
+ ASSERT_ALWAYS(!__xfs_iflags_test(ip, XFS_IRECLAIM));
+ spin_unlock(&ip->i_flags_lock);
/*
* We always use background reclaim here because even if the
@@ -1544,9 +1547,16 @@ xfs_fs_fill_super(
goto out;
sb->s_fs_info = mp;
+ /*
+ * The inode lru needs to be associated with the superblock shrinker,
+ * and like the rest of the superblock shrinker, it's memcg aware.
+ */
+ if (list_lru_init_memcg(&mp->m_inode_lru, &sb->s_shrink))
+ goto out_free_fsname;
+
error = xfs_parseargs(mp, (char *)data);
if (error)
- goto out_free_fsname;
+ goto out_free_lru;
sb_min_blocksize(sb, BBSIZE);
sb->s_xattr = xfs_xattr_handlers;
@@ -1710,6 +1720,8 @@ xfs_fs_fill_super(
xfs_destroy_mount_workqueues(mp);
out_close_devices:
xfs_close_devices(mp);
+ out_free_lru:
+ list_lru_destroy(&mp->m_inode_lru);
out_free_fsname:
sb->s_fs_info = NULL;
xfs_free_fsname(mp);
@@ -1743,6 +1755,7 @@ xfs_fs_put_super(
xfs_destroy_mount_workqueues(mp);
xfs_close_devices(mp);
+ list_lru_destroy(&mp->m_inode_lru);
sb->s_fs_info = NULL;
xfs_free_fsname(mp);
kfree(mp);
@@ -1766,7 +1779,8 @@ xfs_fs_nr_cached_objects(
/* Paranoia: catch incorrect calls during mount setup or teardown */
if (WARN_ON_ONCE(!sb->s_fs_info))
return 0;
- return xfs_reclaim_inodes_count(XFS_M(sb));
+
+ return list_lru_shrink_count(&XFS_M(sb)->m_inode_lru, sc);
}
static long