105 lines
2.3 KiB
C
105 lines
2.3 KiB
C
|
/*
|
||
|
* 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>
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 as
|
||
|
* published by the Free Software Foundation.
|
||
|
*/
|
||
|
#include <linux/fs.h>
|
||
|
#include <linux/f2fs_fs.h>
|
||
|
|
||
|
#include "f2fs.h"
|
||
|
|
||
|
static LIST_HEAD(f2fs_list);
|
||
|
static DEFINE_SPINLOCK(f2fs_list_lock);
|
||
|
static unsigned int shrinker_run_no;
|
||
|
|
||
|
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);
|
||
|
|
||
|
/* TODO: count # of objects */
|
||
|
|
||
|
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;
|
||
|
|
||
|
/* TODO: shrink caches */
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
spin_lock(&f2fs_list_lock);
|
||
|
list_del(&sbi->s_list);
|
||
|
spin_unlock(&f2fs_list_lock);
|
||
|
}
|