Fix incorrect definition of major(3)/minor(3) macros

Review Request #130090 - Created April 17, 2017 and submitted

KJ Tsanaktsidis
Previously, udesksblock.cpp was attempting to find a definition for
major/minor on Linux in <sys/kdev_t.h> by checking Q_OS_LINUX before
importing the header. Q_OS_LINUX is however only set when
qsystemdetection.h is included, and the macro was being checked first.

Even had this check worked, it would still be wrong. On a modern version
of the userspace linux-headers, <sys/kdev_t.h> includes definitions for
major and minor that assume each is limited to 8 bits and that dev_t is
16 bits. This is no longer true anymore; on Linux, major numbers can be
up to 12 bits at present and minor numbers up to 20. Calling these
macros with dev_t values > 2^16 would give incorrect results.

Because the Q_OS_LINUX check failed, a fallback version of the macros
were defined for use on all platforms. The code is allegedly copied from
kdev_t.h, except it is copied from the *kernel* version of the header,
not the userspace version. Linux internally uses a different
representation of dev_t than it exposes to userspace - the kernelspace
version is 20 bits of minor/12 bits of major contiguously, but the
userspace version packs the bits in a different order to maintain
compatability with old 16-bit device numbers. Thus, this code also does
not work for dev_t values > 2^16.

To fix this, we add CMake rules to search for a system-provided
definition of the major/minor macros - on various systems, these can be
in a few different places. As a fallback, we assume old-style 16-bit
dev_t (although I suspect that is only used for Windows, where
major/minor numbers are pretty meaningless anyway).

I've written a little snippet to iterate through block devices, print their major/minor number, and their device properties. It was previously incorrectly labeling all my disks with major 0 and minor == device_number (since it was using the first 20 bits for the minor). It now correctly identifies their major/minor number.


  • 0
  • 13
  • 0
  • 13
Description From Last Updated
Lamarque Souza
KJ Tsanaktsidis
KJ Tsanaktsidis
Lamarque Souza
KJ Tsanaktsidis
Lamarque Souza
KJ Tsanaktsidis
Lamarque Souza
KJ Tsanaktsidis
Lamarque Souza
KJ Tsanaktsidis
Review request changed

Status: Closed (submitted)

Change Summary:

Submitted with commit 3c1e1648a94c474c9270e203e9462285cd5d0619 by Lamarque V. Souza on behalf of Konstantinos Tsanaktsidis to branch master.
Albert Astals Cid

Lamarque, you broke the build.

  1. Fixed. Thanks for the quick report about the broken build and sorry for not adding all files to the commit.

  2. This patch broke the MSVC build and will be reverted shortly.
    Please see for the build log.

  3. Well, the simpler solution is removing all those #if, #include and #error clauses (lines 31 oto 39 of autotests/solidudisks2test.cpp), they are not required. I do not have a MSVC machine with frameworks installed to test that now. I will test that after next frameworks release.

  4. They're needed to actually find the right header file to include for these macros on the various BSD's I think. Actually I think we should just disable this test for windows, this feature is totally meaningless on windows. Another hacky option is to code in the fallback macros (including makedev) in solidudisks2test.cpp in the same way they are defined in udisksblock.cpp, which will probably make that test compile and "work". It wouldn't really be testing anything on windows though.

    The original reason I put the #error case in that test was to make sure we found out if there was some platform that was supposed to be supported that didn't have these macros in any of the places I looked for them. I guess we found out.

  5. If you post a revised patch i'm happy to test it on the Windows CI setup.