util/linux: fix BLK_IOC_FLSBUF on ppc64le

ioctl contants are platform dependent. It should be the same on
x86, aarch64 and s390x but it is indeed different on ppc64le.
This lead to the call to `ioctl_blockdev_flushbuf` actually
raising an exception of `OSError: [Errno 22] Invalid argument`.

The constant was calculated with a little python snippet that
in theory could also go directly into the code, but for now
the simpler condition in this patch is enough.

The snippet is a port of the defines from the Linux kernel,
specifically /usr/include/asm-generic/ioctl.h.

    class IOConstants:
        """IO Commands for Linux"""
        if platform.machine() == "ppc64le":
            NRBITS = 8
            TYPEBITS = 8
            SIZEBITS = 13

            DIR_NONE = 1
        else:
            NRBITS = 8
            TYPEBITS = 8
            SIZEBITS = 14

            DIR_NONE = 0

        NRSHIFT = 0
        TYPESHIFT = NRSHIFT+NRBITS
        SIZESHIFT = TYPESHIFT+TYPEBITS
        DIRSHIFT = SIZESHIFT+SIZEBITS

        @classmethod
        def make(cls, directory, iotype, nr, size):
            return ((directory << cls.DIRSHIFT) |
                    (iotype << cls.TYPESHIFT) |
                    (nr << cls.NRSHIFT) |
                    (size << cls.SIZESHIFT))

        @classmethod
        def make_dir_none(cls, iotype, nr):
            return cls.make(cls.DIR_NONE, iotype, nr, 0)

This is used to get the value for `BLKFLSBUF` taken from the
include `/usr/include/linux/fs.h`:

    #define BLKFLSBUF  _IO(0x12,97)	/* flush buffer cache */

The value is then obtained via:

    print("0x%x" % IOConstants.make_dir_none(0x12,97))
    0x20001261
This commit is contained in:
Christian Kellner 2022-01-28 17:01:55 +00:00 committed by Achilleas Koutsou
parent 087b403042
commit 0f670829a3

View file

@ -14,6 +14,7 @@ reasonable manner.
import array
import fcntl
import platform
__all__ = [
@ -32,7 +33,11 @@ FS_IOC_SETFLAGS = 0x40086602
FS_IMMUTABLE_FL = 0x00000010
BLK_IOC_FLSBUF = 0x00001261
if platform.machine() == "ppc64le":
BLK_IOC_FLSBUF = 0x20001261
else:
BLK_IOC_FLSBUF = 0x00001261
def ioctl_get_immutable(fd: int):