代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/btrfs-progs 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。