// SPDX-License-Identifier: GPL-2.0
/*
 * f2fs shrinker support
 *   the basic infra was copied from fs/ubifs/shrinker.c
 *
 * Copyright (c) 2015 Motorola Mobility
 * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
 */
#include <linux/fs.h>
#include <linux/f2fs_fs.h>

#include "f2fs.h"
#include "node.h"

static LIST_HEAD(f2fs_list);
static DEFINE_SPINLOCK(f2fs_list_lock);
static unsigned int shrinker_run_no;

static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)
{
	return NM_I(sbi)->nat_cnt[RECLAIMABLE_NAT];
}

static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
{
	long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS;

	return count > 0 ? count : 0;
}

static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi,
					enum extent_type type)
{
	struct extent_tree_info *eti = &sbi->extent_tree[type];

	return atomic_read(&eti->total_zombie_tree) +
				atomic_read(&eti->total_ext_node);
}

unsigned long f2fs_shrink_count(struct shrinker *shrink,
				struct shrink_control *sc)
{
	struct f2fs_sb_info *sbi;
	struct list_head *p;
	unsigned long count = 0;

	spin_lock(&f2fs_list_lock);
	p = f2fs_list.next;
	while (p != &f2fs_list) {
		sbi = list_entry(p, struct f2fs_sb_info, s_list);

		/* stop f2fs_put_super */
		if (!mutex_trylock(&sbi->umount_mutex)) {
			p = p->next;
			continue;
		}
		spin_unlock(&f2fs_list_lock);

		/* count read extent cache entries */
		count += __count_extent_cache(sbi, EX_READ);

		/* count block age extent cache entries */
		count += __count_extent_cache(sbi, EX_BLOCK_AGE);

		/* count clean nat cache entries */
		count += __count_nat_entries(sbi);

		/* count free nids cache entries */
		count += __count_free_nids(sbi);

		spin_lock(&f2fs_list_lock);
		p = p->next;
		mutex_unlock(&sbi->umount_mutex);
	}
	spin_unlock(&f2fs_list_lock);
	return count ?: SHRINK_EMPTY;
}

unsigned long f2fs_shrink_scan(struct shrinker *shrink,
				struct shrink_control *sc)
{
	unsigned long nr = sc->nr_to_scan;
	struct f2fs_sb_info *sbi;
	struct list_head *p;
	unsigned int run_no;
	unsigned long freed = 0;

	spin_lock(&f2fs_list_lock);
	do {
		run_no = ++shrinker_run_no;
	} while (run_no == 0);
	p = f2fs_list.next;
	while (p != &f2fs_list) {
		sbi = list_entry(p, struct f2fs_sb_info, s_list);

		if (sbi->shrinker_run_no == run_no)
			break;

		/* stop f2fs_put_super */
		if (!mutex_trylock(&sbi->umount_mutex)) {
			p = p->next;
			continue;
		}
		spin_unlock(&f2fs_list_lock);

		sbi->shrinker_run_no = run_no;

		/* shrink extent cache entries */
		freed += f2fs_shrink_age_extent_tree(sbi, nr >> 2);

		/* shrink read extent cache entries */
		freed += f2fs_shrink_read_extent_tree(sbi, nr >> 2);

		/* shrink clean nat cache entries */
		if (freed < nr)
			freed += f2fs_try_to_free_nats(sbi, nr - freed);

		/* shrink free nids cache entries */
		if (freed < nr)
			freed += f2fs_try_to_free_nids(sbi, nr - freed);

		spin_lock(&f2fs_list_lock);
		p = p->next;
		list_move_tail(&sbi->s_list, &f2fs_list);
		mutex_unlock(&sbi->umount_mutex);
		if (freed >= nr)
			break;
	}
	spin_unlock(&f2fs_list_lock);
	return freed;
}

unsigned int f2fs_donate_files(void)
{
	struct f2fs_sb_info *sbi;
	struct list_head *p;
	unsigned int donate_files = 0;

	spin_lock(&f2fs_list_lock);
	p = f2fs_list.next;
	while (p != &f2fs_list) {
		sbi = list_entry(p, struct f2fs_sb_info, s_list);

		/* stop f2fs_put_super */
		if (!mutex_trylock(&sbi->umount_mutex)) {
			p = p->next;
			continue;
		}
		spin_unlock(&f2fs_list_lock);

		donate_files += sbi->donate_files;

		spin_lock(&f2fs_list_lock);
		p = p->next;
		mutex_unlock(&sbi->umount_mutex);
	}
	spin_unlock(&f2fs_list_lock);

	return donate_files;
}

static unsigned int do_reclaim_caches(struct f2fs_sb_info *sbi,
				unsigned int reclaim_caches_kb)
{
	struct inode *inode;
	struct f2fs_inode_info *fi;
	unsigned int nfiles = sbi->donate_files;
	pgoff_t npages = reclaim_caches_kb >> (PAGE_SHIFT - 10);

	while (npages && nfiles--) {
		pgoff_t len;

		spin_lock(&sbi->inode_lock[DONATE_INODE]);
		if (list_empty(&sbi->inode_list[DONATE_INODE])) {
			spin_unlock(&sbi->inode_lock[DONATE_INODE]);
			break;
		}
		fi = list_first_entry(&sbi->inode_list[DONATE_INODE],
					struct f2fs_inode_info, gdonate_list);
		list_move_tail(&fi->gdonate_list, &sbi->inode_list[DONATE_INODE]);
		inode = igrab(&fi->vfs_inode);
		spin_unlock(&sbi->inode_lock[DONATE_INODE]);

		if (!inode)
			continue;

		inode_lock(inode);
		if (!is_inode_flag_set(inode, FI_DONATE_FINISHED)) {
			len = fi->donate_end - fi->donate_start + 1;
			npages = npages < len ? 0 : npages - len;

			invalidate_inode_pages2_range(inode->i_mapping,
					fi->donate_start, fi->donate_end);
			set_inode_flag(inode, FI_DONATE_FINISHED);
		}
		inode_unlock(inode);

		iput(inode);
		cond_resched();
	}
	return npages << (PAGE_SHIFT - 10);
}

void f2fs_reclaim_caches(unsigned int reclaim_caches_kb)
{
	struct f2fs_sb_info *sbi;
	struct list_head *p;

	spin_lock(&f2fs_list_lock);
	p = f2fs_list.next;
	while (p != &f2fs_list && reclaim_caches_kb) {
		sbi = list_entry(p, struct f2fs_sb_info, s_list);

		/* stop f2fs_put_super */
		if (!mutex_trylock(&sbi->umount_mutex)) {
			p = p->next;
			continue;
		}
		spin_unlock(&f2fs_list_lock);

		reclaim_caches_kb = do_reclaim_caches(sbi, reclaim_caches_kb);

		spin_lock(&f2fs_list_lock);
		p = p->next;
		mutex_unlock(&sbi->umount_mutex);
	}
	spin_unlock(&f2fs_list_lock);
}

void f2fs_join_shrinker(struct f2fs_sb_info *sbi)
{
	spin_lock(&f2fs_list_lock);
	list_add_tail(&sbi->s_list, &f2fs_list);
	spin_unlock(&f2fs_list_lock);
}

void f2fs_leave_shrinker(struct f2fs_sb_info *sbi)
{
	f2fs_shrink_read_extent_tree(sbi, __count_extent_cache(sbi, EX_READ));
	f2fs_shrink_age_extent_tree(sbi,
				__count_extent_cache(sbi, EX_BLOCK_AGE));

	spin_lock(&f2fs_list_lock);
	list_del_init(&sbi->s_list);
	spin_unlock(&f2fs_list_lock);
}
