|
Jan Kara |
449ab7 |
From 6fed83957f21eff11c8496e9f24253b03d2bc1dc Mon Sep 17 00:00:00 2001
|
|
Jan Kara |
449ab7 |
From: Jeffle Xu <jefflexu@linux.alibaba.com>
|
|
Jan Kara |
449ab7 |
Date: Mon, 23 Aug 2021 14:13:58 +0800
|
|
Jan Kara |
449ab7 |
Subject: [PATCH] ext4: fix reserved space counter leakage
|
|
Jan Kara |
449ab7 |
Git-commit: 6fed83957f21eff11c8496e9f24253b03d2bc1dc
|
|
Jan Kara |
449ab7 |
Patch-mainline: v5.15-rc4
|
|
Jan Kara |
449ab7 |
References: bsc#1191450
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
When ext4_insert_delayed block receives and recovers from an error from
|
|
Jan Kara |
449ab7 |
ext4_es_insert_delayed_block(), e.g., ENOMEM, it does not release the
|
|
Jan Kara |
449ab7 |
space it has reserved for that block insertion as it should. One effect
|
|
Jan Kara |
449ab7 |
of this bug is that s_dirtyclusters_counter is not decremented and
|
|
Jan Kara |
449ab7 |
remains incorrectly elevated until the file system has been unmounted.
|
|
Jan Kara |
449ab7 |
This can result in premature ENOSPC returns and apparent loss of free
|
|
Jan Kara |
449ab7 |
space.
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
Another effect of this bug is that
|
|
Jan Kara |
449ab7 |
/sys/fs/ext4/<dev>/delayed_allocation_blocks can remain non-zero even
|
|
Jan Kara |
449ab7 |
after syncfs has been executed on the filesystem.
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
Besides, add check for s_dirtyclusters_counter when inode is going to be
|
|
Jan Kara |
449ab7 |
evicted and freed. s_dirtyclusters_counter can still keep non-zero until
|
|
Jan Kara |
449ab7 |
inode is written back in .evict_inode(), and thus the check is delayed
|
|
Jan Kara |
449ab7 |
to .destroy_inode().
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
Fixes: 51865fda28e5 ("ext4: let ext4 maintain extent status tree")
|
|
Jan Kara |
449ab7 |
Cc: stable@kernel.org
|
|
Jan Kara |
449ab7 |
Suggested-by: Gao Xiang <hsiangkao@linux.alibaba.com>
|
|
Jan Kara |
449ab7 |
Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
|
|
Jan Kara |
449ab7 |
Reviewed-by: Eric Whitney <enwlinux@gmail.com>
|
|
Jan Kara |
449ab7 |
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
|
Jan Kara |
449ab7 |
Link: https://lore.kernel.org/r/20210823061358.84473-1-jefflexu@linux.alibaba.com
|
|
Jan Kara |
449ab7 |
Acked-by: Jan Kara <jack@suse.cz>
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
---
|
|
Jan Kara |
449ab7 |
fs/ext4/inode.c | 5 +++++
|
|
Jan Kara |
449ab7 |
fs/ext4/super.c | 6 ++++++
|
|
Jan Kara |
449ab7 |
2 files changed, 11 insertions(+)
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
Jan Kara |
449ab7 |
index 2a076d236ba1..9df1ab070fa5 100644
|
|
Jan Kara |
449ab7 |
--- a/fs/ext4/inode.c
|
|
Jan Kara |
449ab7 |
+++ b/fs/ext4/inode.c
|
|
Jan Kara |
449ab7 |
@@ -1628,6 +1628,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
Jan Kara |
449ab7 |
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
|
Jan Kara |
449ab7 |
int ret;
|
|
Jan Kara |
449ab7 |
bool allocated = false;
|
|
Jan Kara |
449ab7 |
+ bool reserved = false;
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
/*
|
|
Jan Kara |
449ab7 |
* If the cluster containing lblk is shared with a delayed,
|
|
Jan Kara |
449ab7 |
@@ -1644,6 +1645,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
Jan Kara |
449ab7 |
ret = ext4_da_reserve_space(inode);
|
|
Jan Kara |
449ab7 |
if (ret != 0) /* ENOSPC */
|
|
Jan Kara |
449ab7 |
goto errout;
|
|
Jan Kara |
449ab7 |
+ reserved = true;
|
|
Jan Kara |
449ab7 |
} else { /* bigalloc */
|
|
Jan Kara |
449ab7 |
if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) {
|
|
Jan Kara |
449ab7 |
if (!ext4_es_scan_clu(inode,
|
|
Jan Kara |
449ab7 |
@@ -1656,6 +1658,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
Jan Kara |
449ab7 |
ret = ext4_da_reserve_space(inode);
|
|
Jan Kara |
449ab7 |
if (ret != 0) /* ENOSPC */
|
|
Jan Kara |
449ab7 |
goto errout;
|
|
Jan Kara |
449ab7 |
+ reserved = true;
|
|
Jan Kara |
449ab7 |
} else {
|
|
Jan Kara |
449ab7 |
allocated = true;
|
|
Jan Kara |
449ab7 |
}
|
|
Jan Kara |
449ab7 |
@@ -1666,6 +1669,8 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
Jan Kara |
449ab7 |
}
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
ret = ext4_es_insert_delayed_block(inode, lblk, allocated);
|
|
Jan Kara |
449ab7 |
+ if (ret && reserved)
|
|
Jan Kara |
449ab7 |
+ ext4_da_release_space(inode, 1);
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
errout:
|
|
Jan Kara |
449ab7 |
return ret;
|
|
Jan Kara |
449ab7 |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
Jan Kara |
449ab7 |
index feca816b6bf3..a52f1572daa5 100644
|
|
Jan Kara |
449ab7 |
--- a/fs/ext4/super.c
|
|
Jan Kara |
449ab7 |
+++ b/fs/ext4/super.c
|
|
Jan Kara |
449ab7 |
@@ -1352,6 +1352,12 @@ static void ext4_destroy_inode(struct inode *inode)
|
|
Jan Kara |
449ab7 |
true);
|
|
Jan Kara |
449ab7 |
dump_stack();
|
|
Jan Kara |
449ab7 |
}
|
|
Jan Kara |
449ab7 |
+
|
|
Jan Kara |
449ab7 |
+ if (EXT4_I(inode)->i_reserved_data_blocks)
|
|
Jan Kara |
449ab7 |
+ ext4_msg(inode->i_sb, KERN_ERR,
|
|
Jan Kara |
449ab7 |
+ "Inode %lu (%p): i_reserved_data_blocks (%u) not cleared!",
|
|
Jan Kara |
449ab7 |
+ inode->i_ino, EXT4_I(inode),
|
|
Jan Kara |
449ab7 |
+ EXT4_I(inode)->i_reserved_data_blocks);
|
|
Jan Kara |
449ab7 |
}
|
|
Jan Kara |
449ab7 |
|
|
Jan Kara |
449ab7 |
static void init_once(void *foo)
|
|
Jan Kara |
449ab7 |
--
|
|
Jan Kara |
449ab7 |
2.26.2
|
|
Jan Kara |
449ab7 |
|