Superblock is always 4k, but metadata blocks may be larger. We have to
use the appropriate block size when doing checksums, otherwise they're
wrong.
Signed-off-by: David Sterba <dsterba@xxxxxxx>
---
btrfs-image.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/btrfs-image.c b/btrfs-image.c
index 188291c..dca7a28 100644
--- a/btrfs-image.c
+++ b/btrfs-image.c
@@ -469,6 +469,16 @@ static int read_data_extent(struct metadump_struct *md,
return 0;
}
+static int is_sb_offset(u64 offset) {
+ switch (offset) {
+ case 65536:
+ case 67108864:
+ case 274877906944:
+ return 1;
+ }
+ return 0;
+}
+
static int flush_pending(struct metadump_struct *md, int done)
{
struct async_work *async = NULL;
@@ -506,7 +516,16 @@ static int flush_pending(struct metadump_struct *md, int done)
}
while (!md->data && size > 0) {
- eb = read_tree_block(md->root, start, blocksize, 0);
+ /*
+ * We must differentiate between superblock and
+ * metadata on filesystems with blocksize > 4k,
+ * otherwise the checksum fails for superblock
+ */
+ int bs = blocksize;
+
+ if (is_sb_offset(start))
+ bs = BTRFS_SUPER_INFO_SIZE;
+ eb = read_tree_block(md->root, start, bs, 0);
if (!eb) {
free(async->buffer);
free(async);
@@ -516,9 +535,9 @@ static int flush_pending(struct metadump_struct *md, int done)
}
copy_buffer(async->buffer + offset, eb);
free_extent_buffer(eb);
- start += blocksize;
- offset += blocksize;
- size -= blocksize;
+ start += bs;
+ offset += bs;
+ size -= bs;
}
md->pending_start = (u64)-1;
--
1.8.2
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html