1 Star 0 Fork 18

liuh/btrfs-progs

forked from src-openEuler/btrfs-progs 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0011-btrfs-progs-convert-for-ext2-fix-possible-tree-check.patch 3.37 KB
一键复制 编辑 原始数据 按行查看 历史
From 631ee666394a36ec36abf1042956cdb2e6058b86 Mon Sep 17 00:00:00 2001
From: Qu Wenruo <wqu@suse.com>
Date: Fri, 12 Jan 2024 16:13:27 +1030
Subject: [PATCH] btrfs-progs: convert: for ext2, fix possible tree-checker
error when converting a large fs
[BUG]
There is a report about failed btrfs-convert, which shows the following
error:
corrupt leaf: root=5 block=5001928998912 slot=1 ino=89911763, invalid previous key objectid, have 89911762 expect 89911763
ERROR: failed to copy ext2 inode 89911320: -5
ERROR: error during copy_inodes -5
WARNING: error during conversion, the original filesystem is not modified
[CAUSE]
Above error is triggered when checking the following items inside a
subvolume:
- inode ref
- dir item/index
- file extent
- xattr
This is to make sure these items have correct previous key.
However btrfs-convert is not following this requirement, it always
inserts those items first, then creates a btrfs_inode for it.
Thus it can lead to the error.
This can only happen for large fs, as for most cases we have all these
modified tree blocks cached, thus tree-checker won't be triggered.
But when the tree block cache is not hit, and we have to read from disk,
then such behavior can lead to above tree-checker error.
[FIX]
Make sure we insert the inode item first, then the file extents/dir
items/xattrs. And after the file extents/dir items/xattrs inserted, we
update the existing inode (to update its size and bytes).
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
---
convert/source-ext2.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/convert/source-ext2.c b/convert/source-ext2.c
index cfffc9e..ad7aeda 100644
--- a/convert/source-ext2.c
+++ b/convert/source-ext2.c
@@ -854,6 +854,8 @@ static int ext2_copy_single_inode(struct btrfs_trans_handle *trans,
int ret;
int s_inode_size;
struct btrfs_inode_item btrfs_inode;
+ struct btrfs_key inode_key;
+ struct btrfs_path path = { 0 };
if (ext2_inode->i_links_count == 0)
return 0;
@@ -875,6 +877,15 @@ static int ext2_copy_single_inode(struct btrfs_trans_handle *trans,
}
ext2_convert_inode_flags(&btrfs_inode, ext2_inode);
+ /*
+ * The inode item must be inserted before any file extents/dir items/xattrs,
+ * or we may trigger tree-checker. File extents/dir items/xattrs require
+ * the previous item has the same key objectid.
+ */
+ ret = btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
+ if (ret < 0)
+ return ret;
+
switch (ext2_inode->i_mode & S_IFMT) {
case S_IFREG:
ret = ext2_create_file_extents(trans, root, objectid,
@@ -901,7 +912,25 @@ static int ext2_copy_single_inode(struct btrfs_trans_handle *trans,
if (ret)
return ret;
}
- return btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
+
+ /*
+ * Update the inode item, as above insert never updates the inode's
+ * nbytes and size.
+ */
+ inode_key.objectid = objectid;
+ inode_key.type = BTRFS_INODE_ITEM_KEY;
+ inode_key.offset = 0;
+
+ ret = btrfs_lookup_inode(trans, root, &path, &inode_key, 1);
+ if (ret > 0)
+ ret = -ENOENT;
+ if (ret < 0)
+ return ret;
+ write_extent_buffer(path.nodes[0], &btrfs_inode,
+ btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
+ sizeof(btrfs_inode));
+ btrfs_release_path(&path);
+ return 0;
}
static bool ext2_is_special_inode(ext2_filsys ext2_fs, ext2_ino_t ino)
--
2.43.0
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/liuh0329/btrfs-progs.git
git@gitee.com:liuh0329/btrfs-progs.git
liuh0329
btrfs-progs
btrfs-progs
master

搜索帮助