Howto: compile an Ubuntu kernel with BFQ support (example: Wily)

What is this about?

One of the things your computer has to manage is the flow of data to and from the hardware it has available (for example the hard disk or a thumb drive). As your computer is doing multiple things at the same time, some planning or “scheduling” is needed to decide what goes first. The algorithm responsible for this is called “the I/O scheduler”.

There are different strategies to decide what traffic goes first, where the simplest algorithm of all probably is “first come, first serve”. Especially for day-to-day desktop usage on slightly limited hardware, the impact of the strategy can be very noticeable.

Ubuntu comes with 3 schedulers, called noop, deadline, and cfq. This how-to will show you how to install and activate a 4th one, called bfq. This new scheduling algorithm is gaining a lot of traction, and is said by some to improve your computer experience significantly. I clearly notice a difference on my systems, but I’ll tell you right now you’ll have to try and find out for yourself.


To enable bfq on our system, we will recompile the Ubuntu kernel. We will make sure the current running kernel stays available as a fall-back option in grub. I have tested this procedure on Ubuntu Vivid and Wily with the amd64 kernel.

If any word in the previous sentence does not ring a bell at all, this how-to might not be for you.

Furthermore, beware that compiling the kernel takes a good amount of time (several hours unless you have some very beefy hardware).

What is the impact and risk when I do this?

Best case you will get a more responsive system at virtually zero risk. Before trying this how-to, make sure you know how to boot your system into an alternate boot option using the Ubuntu advanced boot options.

You should also note that we are doing all of this manually. If Canonical releases a new kernel that supersedes your custom built one, you will have to do this again. Since I did the upgrade to Wily yesterday, which came with a shiny new kernel, it is a good occasion to write up this guide.

Needless to say: I give no guarantees nor support and this is entirely at your own risk.


Credit where credit’s due, you find all information on how to recompile the kernel and more on

The bfq scheduler and patches are to be found at

Let’s go!

  1. We want to add some functionality to the standard kernel. This requires recompiling. The first thing to do, is to install the tools needed for compiling the kernel. This is a simple task to achieve:

    sudo apt-get install build-essential devscripts fakeroot libncurses5-dev ccache
    sudo apt-get install kernel-wedge makedumpfile xmlto docbook-utils gs transfig sharutils
    sudo apt-get build-dep linux
  2. Now that the required tools are installed, we need to get the actual code we want to recompile. If you want to install the source for the kernel you are actually using, you can use the following command:

    apt-get source linux-image-$(uname -r)

    If you want, you can specify the kernel package explicitly. This allos you to recompile a kernel you just upgraded before rebooting the system.

    apt-get source linux-image-4.2.0-16-generic

    This command will download the kernel source code, and unpack it in the current working directory. The folder will be named linux-4.2.0. Enter the directory.

    cd linux-4.2.0
  3. Download the patches that match your kernel version, in this particular case for kernel 4.2.0, from the website mentioned above.
  4. Before we start working, increment the version number. This is important if you want your new kernel to co-exist with the official one provided by Canonical. The newly compiled kernel will be the default one because it has the highest version number, but you will be able to boot using the stock kernel by selecing it at boot. Since only the I/O scheduler changes this carries no risk.

    debian/rules startnewrelease

    You’ll get a notification what the new release will be. In this particular case, the new version will be 4.2.0-17.20.

    As part of the build proces, some binary comparisons will be done with the previous (or current) version that you are basing the new kernel off. You can disable this check, but if you don’t you need some more files installed from the previous kernel version to make this process possible. As we are basing our build in this guide on kernel version 4.2.0-16.19, the following command retrieves the necessary files:

    bash debian/scripts/misc/getabis 4.2.0 16.19
  5. Apply the patches needed to include the bfq scheduler in the kernel.

    patch -p1 --ignore-whitespace -i 0001-block-cgroups-kconfig-build-bits-for-BFQ-v7r9-4.2.patch
    patch -p1 --ignore-whitespace -i 0002-block-introduce-the-BFQ-v7r9-I-O-sched-for-4.2.patch
    patch -p1 --ignore-whitespace -i 0003-block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r9-for-4.2.0.patch
  6. Now we are ready to start compiling. The proces consists of 3 commands, and it will the deb packages needed for a generic installation.We start by cleaning the source tree:

    fakeroot debian/rules clean

    Then we start the compilation process. The compilation scripts contain predefined targets that define what gets build. We need 3 targets called binary-headers, binary-generic, and binary-perarch:

    fakeroot debian/rules binary-headers binary-generic binary-perarch

    The system will detect the source modifications done in step 5, and ask what you want to do with them. Since the specific goal of this kernel recompilation is to include the bfq scheduler, answer “y” to the questions to include it, and select “bfq” as the default scheduler when presented with the choice.
  7. Sit back, relax, and have a coffee.
  8. When the copilation completes succesfully, you will find installable packages in the parent directory. Go there and check.

    cd ..
    ls -l *.deb

    The following packages should exist:

  9. Install the newly created packages. We need the headers, image, and tools packages.

    sudo dpkg -i linux-[hit]*4.2.0-17.20*.deb
  10. Reboot the system. If you want to check the scheduler used, use the following command (for disk /dev/sda).

    cat /sys/block/sda/queue/scheduler