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 <dste...@suse.cz> --- 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 majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html