-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAl/1wNYACgkQONu9yGCS aT64cxAAwwt2H911zFagJCVDfLKXJ4da062n0YcJe3saGSg+mdEkSGYEDxjV6jjM jTzK1W5C49sQ9kzIF43YnYgdULwcXJ76G/uqFjFOlmbRzAKAYgs/3KXesa7S4cp+ LT0fiR7uyViOw1zn4yBIeSnax8uRwT4vR1vV++ILC/7vL6hcnOBOPLxGzUKYlvJQ TD8ZQjeTXe5E7IhE+ztuhJQT+hZr1VERTjoktcfmlUps94uITeKdKYoCCZQ/zYIL IS7OgnAw5RNERHa1JUZruaGFvJORTu8wAfVtgD1VgRUZAe2ziWH6aCeDPaWaLzS5 3U7Rc3Fyf0CRYrhe7mI1J864GIEUAe9V34sGQzaU/ap4SWpLvHbu12ePlb+nLNKF MZmGEd0eZuKKDSx9dlcx8hbfVg99YpI5oOeDvfCJpYx/uxNzzJhO5wkkZxweiN9s XTMUhhkTNkhgYdzn4Y8G9++LLAZpwOImSh3NkntoH+mSVlC+jVBbskz6PdywDjQR ROVpW26t5Ee6uDTrjci5cffbfje2y0r9km5/sbRWUz2YGsqYfAI3FtbH5isNUPOm Q6ucTd+xvmApfp9bn+XYLnbTQEGAD6mAgSmO11CIDsUJUvOTD/2cv861kATJqhXm 01rHgohIG604vERppYC3WWFjh0cdevBvwSOpDi1LIdlgbEF6QY0= =q0Fm -----END PGP SIGNATURE----- Merge 5.4.87 into android11-5.4-lts Changes in 5.4.87 net/sched: sch_taprio: reset child qdiscs before freeing them md/raid10: initialize r10_bio->read_slot before use. thermal/drivers/cpufreq_cooling: Update cpufreq_state only if state has changed ext4: prevent creating duplicate encrypted filenames ubifs: prevent creating duplicate encrypted filenames f2fs: prevent creating duplicate encrypted filenames fscrypt: add fscrypt_is_nokey_name() fscrypt: remove kernel-internal constants from UAPI header vfio/pci: Move dummy_resources_list init in vfio_pci_probe() btrfs: fix race when defragmenting leads to unnecessary IO ext4: don't remount read-only with errors=continue on reboot KVM: x86: avoid incorrect writes to host MSR_IA32_SPEC_CTRL KVM: SVM: relax conditions for allowing MSR_IA32_SPEC_CTRL accesses KVM: x86: reinstate vendor-agnostic check on SPEC_CTRL cpuid bits powerpc/bitops: Fix possible undefined behaviour with fls() and fls64() jffs2: Allow setting rp_size to zero during remounting jffs2: Fix NULL pointer dereference in rp_size fs option parsing scsi: block: Fix a race in the runtime power management code uapi: move constants from <linux/kernel.h> to <linux/const.h> tools headers UAPI: Sync linux/const.h with the kernel headers null_blk: Fix zone size initialization of: fix linker-section match-table corruption cgroup: Fix memory leak when parsing multiple source parameters scsi: cxgb4i: Fix TLS dependency Bluetooth: hci_h5: close serdev device and free hu in h5_close reiserfs: add check for an invalid ih_entry_count misc: vmw_vmci: fix kernel info-leak by initializing dbells in vmci_ctx_get_chkpt_doorbells() media: gp8psk: initialize stats at power control logic f2fs: fix shift-out-of-bounds in sanity_check_raw_super() ALSA: seq: Use bool for snd_seq_queue internal flags ALSA: rawmidi: Access runtime->avail always in spinlock bfs: don't use WARNING: string when it's just info. fcntl: Fix potential deadlock in send_sig{io, urg}() rtc: sun6i: Fix memleak in sun6i_rtc_clk_init module: set MODULE_STATE_GOING state when a module fails to load quota: Don't overflow quota file offsets rtc: pl031: fix resource leak in pl031_probe powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe() i3c master: fix missing destroy_workqueue() on error in i3c_master_register NFSv4: Fix a pNFS layout related use-after-free race when freeing the inode f2fs: avoid race condition for shrinker count module: delay kobject uevent until after module init call fs/namespace.c: WARN if mnt_count has become negative um: ubd: Submit all data segments atomically tick/sched: Remove bogus boot "safety" check ALSA: pcm: Clear the full allocated memory at hw_params dm verity: skip verity work if I/O error when system is shutting down Linux 5.4.87 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> [EB: fixed fs/crypto/ merge resolution] Signed-off-by: Eric Biggers <ebiggers@google.com> Change-Id: I383fa03a6d3c025d167ab57faebf0d3a59919a00
139 lines
3.1 KiB
C
139 lines
3.1 KiB
C
// 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)
|
|
{
|
|
return atomic_read(&sbi->total_zombie_tree) +
|
|
atomic_read(&sbi->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 extent cache entries */
|
|
count += __count_extent_cache(sbi);
|
|
|
|
/* 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;
|
|
}
|
|
|
|
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_extent_tree(sbi, nr >> 1);
|
|
|
|
/* 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;
|
|
}
|
|
|
|
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_extent_tree(sbi, __count_extent_cache(sbi));
|
|
|
|
spin_lock(&f2fs_list_lock);
|
|
list_del_init(&sbi->s_list);
|
|
spin_unlock(&f2fs_list_lock);
|
|
}
|