Multiple filesystem signatures on a partition

I have a separate partition for /root which is mounted through /etc/fstab. Last night I’ve done a huge update to my Fedora 18 laptop and today it got stuck in the mounting step.

Use rdbreak=pre-mount boot parameter

This is a nice kernel command line parameter which tells dracut to spawn a shell before mounting the filesystems. After dropping into the shell, I looked at blkid output:

# blkid
/dev/sda1: UUID="3E1691BA1691739D" TYPE="ntfs"
/dev/sda4: LABEL="LENOVO_PART" UUID="D4F69CB3F69C9778" TYPE="ntfs"
/dev/sda6: LABEL="f18" UUID="d73af424-0839-49d8-baff-fc3021f8160d" TYPE="ext4"

Oops, blkid doesn’t show /dev/sda2. Let’s force it to do low-level superblock probing which avoids blkid caches:

# blkid -p /dev/sda2
/dev/sda2: ambivalent result (probably more filesystems on
           the device, use wipefs(8) to see more details)

So, it seems that somehow the partition got multiple filesystem signatures instead of only ext4. Let’s look at it using wipefs:

# wipefs /dev/sda2
offset               type
----------------------------------------------------------------
0x4000040            btrfs   [filesystem]
                     UUID:  7630c42b-4275-45af-b7a0-24d05bfa4e5f
 
0x438                ext4   [filesystem]
                     LABEL: ssd75g
                     UUID:  d2675c32-931a-4e6d-8b73-5d9d488f2492

Well this is interesting. As far as I remember, I used btrfs before ext4 on this partition. So it is possible that after the latest updates, the fact that the partition got multiple signatures is not handled anymore by a layer. Let’s erase the signature for btrfs giving its offset:

# wipefs -o 0x4000040 /dev/sda2
/dev/sda2: 8 bytes were erased at offset 0x04000040 (btrfs): 5f 42 48 52 66 53 5f 4d

Now let’s look at what btrfs detects now:

# blkid
/dev/sda1: UUID="3E1691BA1691739D" TYPE="ntfs"
/dev/sda4: LABEL="LENOVO_PART" UUID="D4F69CB3F69C9778" TYPE="ntfs"
/dev/sda6: LABEL="f18" UUID="d73af424-0839-49d8-baff-fc3021f8160d" TYPE="ext4"
/dev/sda2: LABEL="ssd75g" UUID="d2675c32-931a-4e6d-8b73-5d9d488f2492" TYPE="ext4"

Woot, it came back 🙂

CMake with multilib support on Linux

Multilib distributions tend to put their architecture-specific binaries in /usr/lib64 directories to provide i686 compatibility through legacy /usr/lib directory. This means that if you ever have to deal with binaries compiled against 32-bit architectures, you can install their compatibility versions through your package manager which will reside in /usr/lib. These compatibility packages have a .i686 suffix on Fedora.

Let’s say that you have a 32-bit binary which requires libXrender. After installing libXrender.i686 with yum, take a look at package contents:

$ rpm -ql libXrender.i686
/usr/lib/libXrender.so.1
/usr/lib/libXrender.so.1.3.0
/usr/share/doc/libXrender-0.9.7
/usr/share/doc/libXrender-0.9.7/AUTHORS
/usr/share/doc/libXrender-0.9.7/COPYING
/usr/share/doc/libXrender-0.9.7/ChangeLog

This makes clear that if you build a project from its source tarball or SCM tree, you don’t want to install them under /usr/lib for keeping things clean. This is also a requirement if you prepare an RPM for that application/library. On Fedora, macros.cmake in /etc/rpm checks the system and sets a CMake variable LIB_SUFFIX to 64 for further using it in CMakeLists.txt. All you have to do is to append this suffix in your project to relevant places. But this solution is limited to builds initiated by rpmbuild as it triggers the macro inclusion.

If you would like to apply a more global solution, CMake provides a module called GNUInstallDirs. You can include that and use the CMake variable CMAKE_INSTALL_LIBDIR when appropriate. The value of this variable is lib64 on multilib x86_64 installations. A quick fix for a a Python module installation looks something like this:

diff --git a/src/python.cmake b/src/python.cmake
index e1d1e20..30815e9 100644
--- a/src/python.cmake
+++ b/src/python.cmake
@@ -83,7 +83,7 @@ endif()
 
# Finally, we setup the python installation prefix centrally. This value is
# standardized by Python as defined in http://docs.python.org/install/index.html
-set(PYTHON_SITE_PACKAGES "lib/python${PYTHON_VERSION}/site-packages" CACHE
+set(PYTHON_SITE_PACKAGES "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION}/site-packages" CACHE
  PATH "Default package installation prefix for Python packages")