January 11, 2008

Upgrade from 32-bit to 64-bit Fedora Linux without a system reinstall

Author: Ben Martin

One great thing about Linux is that you can transplant a hard disk from a machine that runs a 32-bit AMD XP processor into a new 64-bit Intel Core 2 machine, and the Linux installation will continue to work. However, if you do this, you'll be running a 32-bit kernel, a C library, and a complete system install on a processor that could happily run 64-bit code. You'll waste even more resources if your new machine has 4GB or more of system memory, and you'll be forced to either not use some of it or run a 32-bit Physical Address Extension (PAE) kernel. Cross-grading to the 64-bit variant of your Linux distribution can help you use your resources more wisely.

This happened to me with a Fedora Linux installation, and I finally decided to migrate. Over the years, I've talked to Fedora enthusiasts and Red Hat employees at Linux conferences about doing a cross-grade to 64-bit. I generally heard one solution: reinstall. However, I like to reserve this approach for when a critical number of system disks fail at once and I have absolutely no other option. I wanted to see if a cross-grade was feasible at a whole distribution level.

A disclaimer: changing the architecture of your Fedora installation from 32 to 64-bit isn't recommended or supported in any way. Perform this at your own risk after creating a suitable backup.

As a test, I installed Fedora 7 i386 in a VMware server instance, then modified the CPU architecture of the hosted virtual machine to be 64-bit. I then booted the virtual machine from the Fedora 8 x86_64 DVD image. After I selected the option to upgrade an existing Linux installation, the installer warned me that my existing install and the DVD were for different architectures. The warning was ominous, along the lines of "don't do this." I dismissed the warning; the upgrade proceeded, and I rebooted the virtual machine as normal. Everything still seemed to work in the virtual machine after the cross-grade. With that success, I then moved on to the real thing: cross-grading a real live system.

If you tackle this task, I recommend using something like Clonezilla to create a full system backup. That way, if the cross-grade doesn't go well, you can quickly revert to the way the system was before you attempted the migration.

I also recommend downloading all the RPM files you might need before you begin. If you mirror the Fedora 8 Everything directory and the updates directory, you'll download more than you strictly need, but once you're in the throes of upgrading, the last thing you want is to wait for 600MB of data to download. The DVD image, Fedora-8-x86_64-DVD.iso, is 3.7GB, the Fedora 8 Everything directory for x86_64 is 12GB, and the updates directory for x86_64 is 3.2GB, as of December 2007. Use the following script to grab the Everything directory and set up a local yum repository for it. You need to change the URL for wget to your fastest Fedora mirror. Creating yum.repo files for the new local repositories allows you to use them in preference to the default fedora.repo and fedora-updates.repo files. Note that /yum-repo-mirrors should be a large enough partition to contain all this data:

# cat f8everything.sh
#!/bin/bash
mkdir -p /yum-repo-mirrors/f8everything
cd /yum-repo-mirrors/f8everything
wget -Y off -m "ftp://mirror.../pub/fedora/linux/releases/8/Everything/x86_64/os/Packages/"

cd /yum-repo-mirrors/f8everything
nice createrepo `pwd`

/etc/yum.repos.d]# cat f8everything.repo
[f8everything]
name=Fedora $releasever - $basearch
baseurl=file:///yum-repo-mirrors/f8everything/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora

Updating a real installation

Once I downloaded all the packages and made a solid system backup in preparation, I booted the Fedora 7 i386 machine from the Fedora 8 x86_64 DVD. If you're running database servers, dump them to a text SQL file to back them up before the update. Also, anything using a native binary on disk format might be susceptible to changes from 32-bit to 64-bit.

Initially, the upgrade complained about /usr/tmp not being a correct symlink. It turned out that I was using the XFS filesystem for /usr, and in /etc/fstab I list the filesystem type as auto. The Fedora 8 DVD didn't like this and failed to mount /usr. Changing the filesystem type to xfs in /etc/fstab fixed this issue.

The upgrade warned me about the different architectures, and I proceeded just as I did in the virtual machine. For some reason, the installation didn't want to upgrade GNU GRUB for me. I chose to leave the old boot configuration in place and fix that later.

After the update finished, I rebooted. The new kernel was listed in GRUB, and I selected and booted it. I'm not sure what caused the problem with updating GRUB, but at least it presented no bar to booting.

Initially, I had issues getting audio to play. Fedora 8 has moved to PulseAudio, and it wasn't working as it should. To fix things, I added my user to the pulse-access group and made sure that the PulseAudio daemon was running by adding pulseaudio -D to my ~/.xinitrc file. Also, some of the media players didn't work properly, mainly because the system libraries updated to new versions and the media player executables were looking for a shared library that was no longer there. But this issue was not specific to the 64-bit cross-grade and would have been there if I updated to 32-bit Fedora 8.

One area in which I expected the update to cause problems was with the differing size of integers. If an application stores its state in a binary file by dumping and loading the contents of RAM directly, then such 32-bit configuration files wouldn't work under the 64-bit installation. Applications using boost::serialization in binary format suffered from the update, so I had to fix them manually.

At this point, my system had an odd mix of i386 and x86_64 RPMs on it. Most of the devel RPMs were only for i386, because the updates weren't included on the Fedora 8 DVD. Also, an RPM file will likely still report that it is running on a 32-bit machine. Here's the initial report from RPM as to what architecture it was running on before and after removing the i386 RPM packages:

# rpm --eval '%{_arch}'
i386
# rpm -e rpm.i386 rpm-python-4.4.2.2-2.fc7.i386 rpm-build-4.4.2.2-2.fc7.i386
# rpm --eval '%{_arch}'
x86_64

Once both i386 and x86_64 packages were installed, I told RPM to report which architecture each package was compiled for, so I could easily tell what still needed updating and what could be removed:

# vi /etc/rpm/macros
%_query_all_fmt %%{name}-%%{version}-%%{release}.%%{arch}
%_query_fmt %%{name}-%%{version}-%%{release}.%%{arch}

You may also have to update the rpm platform file so that rpm and yum to pick x86_64 packages by default.

# cat /etc/rpm/platform
x86_64-redhat-linux

Because I had a mix of i386 and x86_64 packages installed, I needed to use yum's exclude option. Generally, specifying the foo.x86_64 RPM explicitly tells yum to install the 64-bit dependencies as well:

# yum install --exclude="*.i386 *.586 *.686" foo

At this point, I noticed that a partition wasn't being mounted anymore. A look at /etc/fstab showed that the update had cleaned up this file and removed anything it didn't understand, including a partition I had with a filesystem type auto. This was annoying, as I had many comments in /etc/fstab and some filesystems mounts that were commented out. I had to manually merge the new /etc/fstab with the one from my backups (you made backups, right?).

The cross-grade's cleaning up fstab also broke /dev/shm, the shared memory device. I had four filesystems mounted as tmpfs types for various uses. The cleanup only kept the first tmpfs filesystem, which didn't happen to be the /dev/shm one. Without /dev/shm mounted as tmpfs, shared memory didn't work.

To make the cross-grade legitimate, I updated the i386 devel packages and also included the new updates from the Fedora 8 updates repository. Here I had to do some package tinkering by hand. A simple yum update tried to resolve dependencies and reported about 25 libraries that were broken. Most of the time, you can fix this by doing an RPM -e package.i386 followed by a yum install package.x86_64. Sometimes the Fedora 8 x86_64 distribution ships with both an i386 and an x86_64 RPM for a package. Incompatibilities can exist between the Fedora 7 i386 RPM and the newer x64 RPMs. For example, the following code shows incompatibility for CinePaint. You can resolve this either by removing the package or by moving to the local repository mirror directory and force-updating the package to the newer version:

file /usr/lib/python2.5/site-packages/gimpui.pyc
from install of cinepaint-0.22.1-5.fc8 conflicts with file from package cinepaint-0.22.1-4.fc7
...

Some of the few packages that behave this way include koffice-krita, NetworkManager, mono, gstreamer, and ruby. I fixed the Mono and GStreamer issues by updating their i386 RPMs to the Fedora 8 RPM files manually with the rpm command.

A subsequent attempt to yum update reported a total download size of 339MB, but during the transaction test, it failed again with some incompatible files. You can fix some of these clashes by removing the i386 version of the incompatible RPM from the system, leaving only the x86_64 RPM installed. In the case of i386 packages with large dependency trees, such as gnome-keyring, gphoto2, nas, and openldap, a better approach is to force-update the RPM file from the Everything or updates repository mirror. By force-updating the package, you remove the path clashes, and yum happily updates the rest of the system.

When crossgrading a second system, I used commands similar to the following to make sure
that x86_64 versions of all development packages were installed before removing the i386 packages. Once there are no i386 development packages, running the rpm query again and making sure that there are also x86_64 versions of every package installed is a good idea.

# cd /tmp
# rpm -qa --queryformat '%{name}.%{arch}\n' |grep i386 >| /tmp/i4
# yum install $( grep devel /tmp/i4|sed 's/.i386/.x86_64/g' | tr '\n' ' ' )
# yum remove $( grep devel /tmp/i4 | tr '\n' ' ' )

You will also want to add lib64 to the shared library's search path.

# cat /etc/ld.so.conf.d/usr-local.conf
/usr/local/lib
/usr/local/lib64

Conclusion

Updating from Fedora 7 i386 to Fedora 8 x86_64 isn't supported, and many folks will tell you to just reinstall in order to move to a 64-bit Linux. However, I managed to resolve the main problems when doing a yum update in a single day. Your mileage will vary depending on what third-party repositories you're using, how much software you've installed by hand, and how dependent your software is on the system libraries.

Category:

  • System Administration