Commit 9649eb18 authored by Baokun Li's avatar Baokun Li Committed by Theodore Ts'o

ext4: add a new helper to check if es must be kept

In the extent status tree, we have extents which we can just drop without
issues and extents we must not drop - this depends on the extent's status
- currently ext4_es_is_delayed() extents must stay, others may be dropped.

A helper function is added to help determine if the current extent can
be dropped, although only ext4_es_is_delayed() extents cannot be dropped
currently.
Suggested-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20230424033846.4732-3-libaokun1@huawei.comSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent de25d6e9
...@@ -446,6 +446,19 @@ static void ext4_es_list_del(struct inode *inode) ...@@ -446,6 +446,19 @@ static void ext4_es_list_del(struct inode *inode)
spin_unlock(&sbi->s_es_lock); spin_unlock(&sbi->s_es_lock);
} }
/*
* Returns true if we cannot fail to allocate memory for this extent_status
* entry and cannot reclaim it until its status changes.
*/
static inline bool ext4_es_must_keep(struct extent_status *es)
{
/* fiemap, bigalloc, and seek_data/hole need to use it. */
if (ext4_es_is_delayed(es))
return true;
return false;
}
static struct extent_status * static struct extent_status *
ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len, ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
ext4_fsblk_t pblk) ext4_fsblk_t pblk)
...@@ -458,10 +471,8 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len, ...@@ -458,10 +471,8 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
es->es_len = len; es->es_len = len;
es->es_pblk = pblk; es->es_pblk = pblk;
/* /* We never try to reclaim a must kept extent, so we don't count it. */
* We don't count delayed extent because we never try to reclaim them if (!ext4_es_must_keep(es)) {
*/
if (!ext4_es_is_delayed(es)) {
if (!EXT4_I(inode)->i_es_shk_nr++) if (!EXT4_I(inode)->i_es_shk_nr++)
ext4_es_list_add(inode); ext4_es_list_add(inode);
percpu_counter_inc(&EXT4_SB(inode->i_sb)-> percpu_counter_inc(&EXT4_SB(inode->i_sb)->
...@@ -479,8 +490,8 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es) ...@@ -479,8 +490,8 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
EXT4_I(inode)->i_es_all_nr--; EXT4_I(inode)->i_es_all_nr--;
percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt); percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt);
/* Decrease the shrink counter when this es is not delayed */ /* Decrease the shrink counter when we can reclaim the extent. */
if (!ext4_es_is_delayed(es)) { if (!ext4_es_must_keep(es)) {
BUG_ON(EXT4_I(inode)->i_es_shk_nr == 0); BUG_ON(EXT4_I(inode)->i_es_shk_nr == 0);
if (!--EXT4_I(inode)->i_es_shk_nr) if (!--EXT4_I(inode)->i_es_shk_nr)
ext4_es_list_del(inode); ext4_es_list_del(inode);
...@@ -851,7 +862,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, ...@@ -851,7 +862,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb), if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb),
128, EXT4_I(inode))) 128, EXT4_I(inode)))
goto retry; goto retry;
if (err == -ENOMEM && !ext4_es_is_delayed(&newes)) if (err == -ENOMEM && !ext4_es_must_keep(&newes))
err = 0; err = 0;
if (sbi->s_cluster_ratio > 1 && test_opt(inode->i_sb, DELALLOC) && if (sbi->s_cluster_ratio > 1 && test_opt(inode->i_sb, DELALLOC) &&
...@@ -1702,11 +1713,8 @@ static int es_do_reclaim_extents(struct ext4_inode_info *ei, ext4_lblk_t end, ...@@ -1702,11 +1713,8 @@ static int es_do_reclaim_extents(struct ext4_inode_info *ei, ext4_lblk_t end,
(*nr_to_scan)--; (*nr_to_scan)--;
node = rb_next(&es->rb_node); node = rb_next(&es->rb_node);
/*
* We can't reclaim delayed extent from status tree because if (ext4_es_must_keep(es))
* fiemap, bigallic, and seek_data/hole need to use it.
*/
if (ext4_es_is_delayed(es))
goto next; goto next;
if (ext4_es_is_referenced(es)) { if (ext4_es_is_referenced(es)) {
ext4_es_clear_referenced(es); ext4_es_clear_referenced(es);
...@@ -1770,7 +1778,7 @@ void ext4_clear_inode_es(struct inode *inode) ...@@ -1770,7 +1778,7 @@ void ext4_clear_inode_es(struct inode *inode)
while (node) { while (node) {
es = rb_entry(node, struct extent_status, rb_node); es = rb_entry(node, struct extent_status, rb_node);
node = rb_next(node); node = rb_next(node);
if (!ext4_es_is_delayed(es)) { if (!ext4_es_must_keep(es)) {
rb_erase(&es->rb_node, &tree->root); rb_erase(&es->rb_node, &tree->root);
ext4_es_free_extent(inode, es); ext4_es_free_extent(inode, es);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment