Bug 251035 - [zfs] Allow 64 bit ZFS to support 32 bit ioctls (Wine)
Summary: [zfs] Allow 64 bit ZFS to support 32 bit ioctls (Wine)
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.2-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-fs (Nobody)
Keywords: needs-qa
Depends on:
Reported: 2020-11-11 06:35 UTC by Damjan Jovanovic
Modified: 2020-11-12 05:18 UTC (History)
0 users

See Also:
koobs: mfc-stable12?
koobs: mfc-stable11?

convert 32 bit zfs_iocparm_t to 64 bit (1.62 KB, patch)
2020-11-11 06:35 UTC, Damjan Jovanovic
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Damjan Jovanovic 2020-11-11 06:35:59 UTC
Created attachment 219540 [details]
convert 32 bit zfs_iocparm_t to 64 bit

When 32 bit applications use libzfs to access ZFS data, they always fail in zfs_open(), with 32 bit "zfs list" and "zpool list" crashing.

This is because /usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c function zfsdev_ioctl() checks for:

if (len != sizeof(zfs_iocparm_t)) {

On amd64, sizeof(zfs_iocparm_t) is 24, as in /usr/src/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h we have:

typedef struct zfs_iocparm {
        uint32_t        zfs_ioctl_version;
        uint64_t        zfs_cmd;
        uint64_t        zfs_cmd_size;
} zfs_iocparm_t;

which has its fields aligned to 8 byte boundaries. On i386, they are aligned to 4 byte boundaries, sizeof(zfs_iocparm_t) is only 20, and every ioctl fails with EINVAL.

This affects Wine as it runs many 32 bit apps. Since Windows is case-insensitive, Wine has to slowly scan the entire directory when doing file I/O on a case-sensitive filesystem, to match filenames case-insensitively. ZFS can create filesystems with casesensitivity=insensitive, allowing Wine to skip the slow scan and speeding up file I/O considerably for some apps. When developing a patch to Wine to check that casesensitivity property and use it when insensitive (https://source.winehq.org/patches/data/195726) I noticed zfs_open() always fails, which led me to this bug.

The attached patch correctly converts the 32 bit zfs_iocparm_t to 64 bit, and allows at least Wine to work correctly. I haven't yet had a chance to test whether it fixes 32 bit versions of the "zpool" and "zfs" tools (which probably use more elaborate ioctls).
Comment 1 Andriy Gapon freebsd_committer 2020-11-11 08:09:44 UTC
zfs-devel@ is disused.
Comment 2 Damjan Jovanovic 2020-11-12 05:18:42 UTC
With further tests, I see that 32 bit "zpool" and "zfs" commands go from crashing to fully working with this patch. I can successfully zpool create, zpool destroy, zpool list, zpool status, zfs list, zfs create, zfs get all, etc.