ext4: add a new helper to check if es must be kept
[ Upstream commit 9649eb18c6288f514cacffdd699d5cd999c2f8f6 ] 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: Jan Kara <jack@suse.cz> Signed-off-by: Baokun Li <libaokun1@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20230424033846.4732-3-libaokun1@huawei.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Stable-dep-of: 8e387c89e96b ("ext4: make sure allocate pending entry not fail") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
b9cd5c3afc
commit
c48b5fdd46
@ -439,6 +439,19 @@ static void ext4_es_list_del(struct inode *inode)
|
||||
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 *
|
||||
ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
|
||||
ext4_fsblk_t pblk)
|
||||
@ -451,10 +464,8 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
|
||||
es->es_len = len;
|
||||
es->es_pblk = pblk;
|
||||
|
||||
/*
|
||||
* We don't count delayed extent because we never try to reclaim them
|
||||
*/
|
||||
if (!ext4_es_is_delayed(es)) {
|
||||
/* We never try to reclaim a must kept extent, so we don't count it. */
|
||||
if (!ext4_es_must_keep(es)) {
|
||||
if (!EXT4_I(inode)->i_es_shk_nr++)
|
||||
ext4_es_list_add(inode);
|
||||
percpu_counter_inc(&EXT4_SB(inode->i_sb)->
|
||||
@ -472,8 +483,8 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
|
||||
EXT4_I(inode)->i_es_all_nr--;
|
||||
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 */
|
||||
if (!ext4_es_is_delayed(es)) {
|
||||
/* Decrease the shrink counter when we can reclaim the extent. */
|
||||
if (!ext4_es_must_keep(es)) {
|
||||
BUG_ON(EXT4_I(inode)->i_es_shk_nr == 0);
|
||||
if (!--EXT4_I(inode)->i_es_shk_nr)
|
||||
ext4_es_list_del(inode);
|
||||
@ -842,7 +853,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
|
||||
if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb),
|
||||
128, EXT4_I(inode)))
|
||||
goto retry;
|
||||
if (err == -ENOMEM && !ext4_es_is_delayed(&newes))
|
||||
if (err == -ENOMEM && !ext4_es_must_keep(&newes))
|
||||
err = 0;
|
||||
|
||||
if (sbi->s_cluster_ratio > 1 && test_opt(inode->i_sb, DELALLOC) &&
|
||||
@ -1683,11 +1694,8 @@ static int es_do_reclaim_extents(struct ext4_inode_info *ei, ext4_lblk_t end,
|
||||
|
||||
(*nr_to_scan)--;
|
||||
node = rb_next(&es->rb_node);
|
||||
/*
|
||||
* We can't reclaim delayed extent from status tree because
|
||||
* fiemap, bigallic, and seek_data/hole need to use it.
|
||||
*/
|
||||
if (ext4_es_is_delayed(es))
|
||||
|
||||
if (ext4_es_must_keep(es))
|
||||
goto next;
|
||||
if (ext4_es_is_referenced(es)) {
|
||||
ext4_es_clear_referenced(es);
|
||||
@ -1751,7 +1759,7 @@ void ext4_clear_inode_es(struct inode *inode)
|
||||
while (node) {
|
||||
es = rb_entry(node, struct extent_status, rb_node);
|
||||
node = rb_next(node);
|
||||
if (!ext4_es_is_delayed(es)) {
|
||||
if (!ext4_es_must_keep(es)) {
|
||||
rb_erase(&es->rb_node, &tree->root);
|
||||
ext4_es_free_extent(inode, es);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user