On 32-bit userspace running against a 64-bit kernel
BTRFS_IOC_GET_SUBVOL_INFO returns -ENOTTY: struct
btrfs_ioctl_get_subvol_info_args embeds four btrfs_ioctl_timespec
values, and that timespec struct (__u64 sec; __u32 nsec) packs to 12
bytes on i386 but 16 on x86_64 due to differing __u64 alignment.
sizeof(struct) is part of the ioctl cmd number via _IOR(), so the cmd
emitted by 32-bit userspace doesn't match the case label compiled by
the 64-bit kernel and the switch falls through to -ENOTTY.
btrfs already handles this exact class of bug for
BTRFS_IOC_SET_RECEIVED_SUBVOL via a btrfs_ioctl_timespec_32 struct
plus a _32 cmd alias in fs/btrfs/ioctl.c, but GET_SUBVOL_INFO (added
in 2018, four years after that fix) didn't get the same treatment.
Until a kernel patch lands the test can't exercise the ioctl on
32-bit, so convert TEST(info) to TEST_RET(info) and return
EXIT_TEST_SKIP with a clear message when -ENOTTY comes back. The
other tests in the file use ioctls that already have working compat
paths and remain unaffected.
return fd;
}
-TEST(info) {
+TEST_RET(info) {
_cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
_cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
BtrfsSubvolInfo info;
BtrfsQuotaInfo quota;
int r;
- ASSERT_OK(btrfs_subvol_get_info_fd(dir_fd, 0, &info));
+ r = btrfs_subvol_get_info_fd(dir_fd, 0, &info);
+ if (r == -ENOTTY)
+ return log_tests_skipped("BTRFS_IOC_GET_SUBVOL_INFO not supported "
+ "(missing 32-bit compat handler in kernel?)");
+ ASSERT_OK(r);
log_info("otime: %s", FORMAT_TIMESTAMP(info.otime));
log_info("read-only (search): %s", yes_no(info.read_only));
r = ASSERT_OK(btrfs_subvol_get_read_only_fd(dir_fd));
log_info("read-only (ioctl): %s", yes_no(r));
+
+ return EXIT_SUCCESS;
}
TEST(subvol) {