btrfs-progs: dump-super: fix read beyond device size

On aarch64 systems with glibc 2.28, several btrfs-progs test cases are
failing because the command 'btrfs inspect dump-super -a <dev>' reports
an error when it attempts to read beyond the disk/file-image size.

  $ btrfs inspect dump-super -a /dev/vdb12
  <snap>
  ERROR: Failed to read the superblock on /dev/vdb12 at 274877906944

And btrfs/184 also fails, as it uses -s 2 option to dump the last super
block.

	$ ./check btrfs/184
	FSTYP         -- btrfs
	PLATFORM      -- Linux/aarch64 a4k 6.4.0-rc7+ #7 SMP PREEMPT Sat Jun 24 02:47:24 EDT 2023
	MKFS_OPTIONS  -- /dev/vdb2
	MOUNT_OPTIONS -- /dev/vdb2 /mnt/scratch

	btrfs/184 1s ... [failed, exit status 1]- output mismatch (see /Volumes/ws/xfstests-dev/results//btrfs/184.out.bad)
	    --- tests/btrfs/184.out    2020-03-03 00:26:40.172081468 -0500
	    +++ /Volumes/ws/xfstests-dev/results//btrfs/184.out.bad    2023-06-24 05:54:40.868210737 -0400
	    @@ -1,2 +1,3 @@
	     QA output created by 184
	    -Silence is golden
	    +Deleted dev superblocks not scratched
	    +(see /Volumes/ws/xfstests-dev/results//btrfs/184.full for details)
	    ...
	    (Run 'diff -u /Volumes/ws/xfstests-dev/tests/btrfs/184.out /Volumes/ws/xfstests-dev/results//btrfs/184.out.bad'  to see the entire diff)
	Ran: btrfs/184
	Failures: btrfs/184
	Failed 1 of 1 tests

This is because `pread()` behaves differently on aarch64 and sets
`errno = 2` instead of the usual `errno = 0`.

To fix check if the sb offset is beyond the device size or regular file
size and skip the corresponding sbread().

Also, move putchar('\n') after a successful call to load_and_dump_sb() to
the load_and_dump_sb() itself.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Anand Jain 2023-06-27 16:53:15 +08:00 committed by David Sterba
parent 8da82cde9c
commit 82a9870d48
1 changed files with 21 additions and 3 deletions

View File

@ -20,6 +20,7 @@
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include <sys/stat.h>
#include "kernel-shared/ctree.h"
#include "kernel-shared/disk-io.h"
#include "kernel-shared/print-tree.h"
@ -33,8 +34,27 @@ static int load_and_dump_sb(char *filename, int fd, u64 sb_bytenr, int full,
int force)
{
struct btrfs_super_block sb;
struct stat st;
u64 ret;
if (fstat(fd, &st) < 0) {
error("unable to stat %s to when loading superblock: %m", filename);
return 1;
}
if (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode)) {
off_t last_byte;
last_byte = lseek(fd, 0, SEEK_END);
if (last_byte == -1) {
error("cannot read end of file %s: %m", filename);
return 1;
}
if (sb_bytenr > last_byte)
return 0;
}
ret = sbread(fd, &sb, sb_bytenr);
if (ret != BTRFS_SUPER_INFO_SIZE) {
/* check if the disk if too short for further superblock */
@ -54,6 +74,7 @@ static int load_and_dump_sb(char *filename, int fd, u64 sb_bytenr, int full,
return 1;
}
btrfs_print_superblock(&sb, full);
putchar('\n');
return 0;
}
@ -168,15 +189,12 @@ static int cmd_inspect_dump_super(const struct cmd_struct *cmd,
close(fd);
return 1;
}
putchar('\n');
}
} else {
if (load_and_dump_sb(filename, fd, sb_bytenr, full, force)) {
close(fd);
return 1;
}
putchar('\n');
}
close(fd);
}