mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
f2fs: keep POSIX_FADV_NOREUSE ranges
[ Upstream commit ef0c333cad8d1940f132a7ce15f15920216a3bd5 ] This patch records POSIX_FADV_NOREUSE ranges for users to reclaim the caches instantly off from LRU. Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
64ed96a21f
commit
1a00afcdae
@@ -100,6 +100,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
|
||||
si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
|
||||
si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
|
||||
si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
|
||||
si->ndonate_files = sbi->donate_files;
|
||||
si->nquota_files = sbi->nquota_files;
|
||||
si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
|
||||
si->aw_cnt = atomic_read(&sbi->atomic_files);
|
||||
@@ -436,6 +437,8 @@ static int stat_show(struct seq_file *s, void *v)
|
||||
si->compr_inode, si->compr_blocks);
|
||||
seq_printf(s, " - Swapfile Inode: %u\n",
|
||||
si->swapfile_inode);
|
||||
seq_printf(s, " - Donate Inode: %u\n",
|
||||
si->ndonate_files);
|
||||
seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n",
|
||||
si->orphans, si->append, si->update);
|
||||
seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
|
||||
|
||||
@@ -837,6 +837,11 @@ struct f2fs_inode_info {
|
||||
#endif
|
||||
struct list_head dirty_list; /* dirty list for dirs and files */
|
||||
struct list_head gdirty_list; /* linked in global dirty list */
|
||||
|
||||
/* linked in global inode list for cache donation */
|
||||
struct list_head gdonate_list;
|
||||
pgoff_t donate_start, donate_end; /* inclusive */
|
||||
|
||||
struct task_struct *atomic_write_task; /* store atomic write task */
|
||||
struct extent_tree *extent_tree[NR_EXTENT_CACHES];
|
||||
/* cached extent_tree entry */
|
||||
@@ -1261,6 +1266,7 @@ enum inode_type {
|
||||
DIR_INODE, /* for dirty dir inode */
|
||||
FILE_INODE, /* for dirty regular/symlink inode */
|
||||
DIRTY_META, /* for all dirtied inode metadata */
|
||||
DONATE_INODE, /* for all inode to donate pages */
|
||||
NR_INODE_TYPE,
|
||||
};
|
||||
|
||||
@@ -1613,6 +1619,9 @@ struct f2fs_sb_info {
|
||||
unsigned int warm_data_age_threshold;
|
||||
unsigned int last_age_weight;
|
||||
|
||||
/* control donate caches */
|
||||
unsigned int donate_files;
|
||||
|
||||
/* basic filesystem units */
|
||||
unsigned int log_sectors_per_block; /* log2 sectors per block */
|
||||
unsigned int log_blocksize; /* log2 block size */
|
||||
@@ -3948,7 +3957,8 @@ struct f2fs_stat_info {
|
||||
unsigned long long allocated_data_blocks;
|
||||
int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta;
|
||||
int ndirty_data, ndirty_qdata;
|
||||
unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all;
|
||||
unsigned int ndirty_dirs, ndirty_files, ndirty_all;
|
||||
unsigned int nquota_files, ndonate_files;
|
||||
int nats, dirty_nats, sits, dirty_sits;
|
||||
int free_nids, avail_nids, alloc_nids;
|
||||
int total_count, utilization;
|
||||
|
||||
@@ -2435,6 +2435,52 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void f2fs_keep_noreuse_range(struct inode *inode,
|
||||
loff_t offset, loff_t len)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||
u64 max_bytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
|
||||
u64 start, end;
|
||||
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
return;
|
||||
|
||||
if (offset >= max_bytes || len > max_bytes ||
|
||||
(offset + len) > max_bytes)
|
||||
return;
|
||||
|
||||
start = offset >> PAGE_SHIFT;
|
||||
end = DIV_ROUND_UP(offset + len, PAGE_SIZE);
|
||||
|
||||
inode_lock(inode);
|
||||
if (f2fs_is_atomic_file(inode)) {
|
||||
inode_unlock(inode);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&sbi->inode_lock[DONATE_INODE]);
|
||||
/* let's remove the range, if len = 0 */
|
||||
if (!len) {
|
||||
if (!list_empty(&F2FS_I(inode)->gdonate_list)) {
|
||||
list_del_init(&F2FS_I(inode)->gdonate_list);
|
||||
sbi->donate_files--;
|
||||
}
|
||||
} else {
|
||||
if (list_empty(&F2FS_I(inode)->gdonate_list)) {
|
||||
list_add_tail(&F2FS_I(inode)->gdonate_list,
|
||||
&sbi->inode_list[DONATE_INODE]);
|
||||
sbi->donate_files++;
|
||||
} else {
|
||||
list_move_tail(&F2FS_I(inode)->gdonate_list,
|
||||
&sbi->inode_list[DONATE_INODE]);
|
||||
}
|
||||
F2FS_I(inode)->donate_start = start;
|
||||
F2FS_I(inode)->donate_end = end - 1;
|
||||
}
|
||||
spin_unlock(&sbi->inode_lock[DONATE_INODE]);
|
||||
inode_unlock(inode);
|
||||
}
|
||||
|
||||
static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
@@ -5078,12 +5124,16 @@ static int f2fs_file_fadvise(struct file *filp, loff_t offset, loff_t len,
|
||||
}
|
||||
|
||||
err = generic_fadvise(filp, offset, len, advice);
|
||||
if (!err && advice == POSIX_FADV_DONTNEED &&
|
||||
test_opt(F2FS_I_SB(inode), COMPRESS_CACHE) &&
|
||||
f2fs_compressed_file(inode))
|
||||
f2fs_invalidate_compress_pages(F2FS_I_SB(inode), inode->i_ino);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return err;
|
||||
if (advice == POSIX_FADV_DONTNEED &&
|
||||
(test_opt(F2FS_I_SB(inode), COMPRESS_CACHE) &&
|
||||
f2fs_compressed_file(inode)))
|
||||
f2fs_invalidate_compress_pages(F2FS_I_SB(inode), inode->i_ino);
|
||||
else if (advice == POSIX_FADV_NOREUSE)
|
||||
f2fs_keep_noreuse_range(inode, offset, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
@@ -811,6 +811,19 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void f2fs_remove_donate_inode(struct inode *inode)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||
|
||||
if (list_empty(&F2FS_I(inode)->gdonate_list))
|
||||
return;
|
||||
|
||||
spin_lock(&sbi->inode_lock[DONATE_INODE]);
|
||||
list_del_init(&F2FS_I(inode)->gdonate_list);
|
||||
sbi->donate_files--;
|
||||
spin_unlock(&sbi->inode_lock[DONATE_INODE]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called at the last iput() if i_nlink is zero
|
||||
*/
|
||||
@@ -844,6 +857,7 @@ void f2fs_evict_inode(struct inode *inode)
|
||||
|
||||
f2fs_bug_on(sbi, get_dirty_pages(inode));
|
||||
f2fs_remove_dirty_inode(inode);
|
||||
f2fs_remove_donate_inode(inode);
|
||||
|
||||
f2fs_destroy_extent_tree(inode);
|
||||
|
||||
|
||||
@@ -1413,6 +1413,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
|
||||
spin_lock_init(&fi->i_size_lock);
|
||||
INIT_LIST_HEAD(&fi->dirty_list);
|
||||
INIT_LIST_HEAD(&fi->gdirty_list);
|
||||
INIT_LIST_HEAD(&fi->gdonate_list);
|
||||
init_f2fs_rwsem(&fi->i_gc_rwsem[READ]);
|
||||
init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]);
|
||||
init_f2fs_rwsem(&fi->i_xattr_sem);
|
||||
|
||||
Reference in New Issue
Block a user