Porting Fio to OpenWRT

OpenWRT is a favorite flavor of Linux intended for embedded devices such as firewalls, routers and so forth. Increasingly those devices based on various ARM SoCs are appearing with integrated SATA controllers. That, in turn, pushes use cases of such devices more and more into fileservers, backups, media server, etc.

If you’re going to use an ARM SoC as a file server, it would be nice to know the performance of your storage backend. There is a good storage performance testing Linux program called Fio. Unfortunately, fio is not a part of the OpenWRT Linux flavor but luckily porting an application over to OpenWRT can be quite simple.

1. Clone OpenWRT git repository


ds@codeminutia:~/src$ git clone https://git.openwrt.org/openwrt/openwrt.git

2. Decide on a good place where to add the application, package/utils seems like a reasonable place:


ds@codeminutia:~/src/openwrt$ mkdir package/utils/fio

3. Create a Makefile under package/utils/fio


ds@codeminutia:~/src/openwrt$ vi package/utils/fio/Makefile

4. The makefile can be copied from another package in OpenWRT, you will need to adjust some variables. Package name and release versions, PKG_VERSION is fio version; the PKG_RELEASE is OpenWRT release number.

PKG_NAME:=fio
PKG_VERSION:=3.6
PKG_RELEASE:=1

5. Variables below tell the build system where to get this software. We use git to fetch the exact revision of fio 3.6. The PKG_MIRROR_HASH is the hash of source file when it is pulled from git and compressed into fio-3.6.tar.xz.

PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/axboe/fio.git
PKG_SOURCE_VERSION:=c5477c6a3b3e0042b1f74414071429ca66d94c2f
PKG_SOURCE_DATE:=2018-04-16
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MIRROR_HASH:=""

6. The tricky part is PKG_MIRROR_HASH variable; you can put an empty string in there and then run make. This will download the source from git and create io-3.6.tar.xz:


ds@codeminutia:~/src/openwrt$ make package/utils/fio/download V=s

7. Now we need to fix up the HASH so we run:


ds@codeminutia:~/src/openwrt$ make package/utils/fio/check V=s FIXUP=1

8. That updated PKG_MIRROR_HASH variable in your makefile.

PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/axboe/fio.git
PKG_SOURCE_VERSION:=c5477c6a3b3e0042b1f74414071429ca66d94c2f
PKG_SOURCE_DATE:=2018-04-16
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MIRROR_HASH:=eecd190a100ccf803575a7f0027c111fb3ff322b05b98b83f01ad88039b33741

9. Section below tells the build system where to place the menu option when you use “make menuconfig”. We are placing fio under “Utilities” menu.

define Package/fio
  SECTION:=utils
  CATEGORY:=Utilities
  TITLE:=Flexible I/O Tester
  URL:=https://github.com/axboe/fio/
  DEPENDS:= +zlib
endef

10. This is not needed in all cases, but in our case, we make sure that configure script in fio gets the right parameters by exporting proper CONFIGURE_ARGS

# Remove quotes from CONFIG_CPU_TYPE
CONFIG_CPU_TYPE_NQ:= $(patsubst "%",%,$(CONFIG_CPU_TYPE))
# get CPU type so we can pass it to fio configure script
CONF_CPU:=$(firstword $(subst +, ,$(CONFIG_CPU_TYPE_NQ)))

CONFIGURE_ARGS = --prefix="$(PKG_INSTALL_DIR)" --cpu="$(CONF_CPU)" --cc="$(TARGET_CC)" --extra-cflags="$(TARGET_CFLAGS)"

You can see the full Makefile below:

#
# Copyright (C) 2018 - Dragan Stancevic <ds@codeminutia.com>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=fio
PKG_VERSION:=3.6
PKG_RELEASE:=1

PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/axboe/fio.git
PKG_SOURCE_VERSION:=c5477c6a3b3e0042b1f74414071429ca66d94c2f
PKG_SOURCE_DATE:=2018-04-16
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MIRROR_HASH:=eecd190a100ccf803575a7f0027c111fb3ff322b05b98b83f01ad88039b33741

PKG_MAINTAINER:=Dragan Stancevic <ds@codeminutia.com>
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING

PKG_BUILD_DEPENDS:= +zlib

HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)

include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/package.mk

define Package/fio
  SECTION:=utils
  CATEGORY:=Utilities
  TITLE:=Flexible I/O Tester
  URL:=https://github.com/axboe/fio/
  DEPENDS:= +zlib
endef

define Package/fio/description
 Flexible I/O Tester

 Fio was originally written to save me the hassle of writing special test case
 programs when I wanted to test a specific workload, either for performance
 reasons or to find/reproduce a bug. The process of writing such a test app can
 be tiresome, especially if you have to do it often.  Hence I needed a tool that
 would be able to simulate a given I/O workload without resorting to writing a
 tailored test case again and again.

 A test work load is difficult to define, though. There can be any number of
 processes or threads involved, and they can each be using their own way of
 generating I/O. You could have someone dirtying large amounts of memory in an
 memory mapped file, or maybe several threads issuing reads using asynchronous
 I/O. fio needed to be flexible enough to simulate both of these cases, and many
 more.

 Fio spawns a number of threads or processes doing a particular type of I/O
 action as specified by the user. fio takes a number of global parameters, each
 inherited by the thread unless otherwise parameters given to them overriding
 that setting is given.  The typical use of fio is to write a job file matching
 the I/O load one wants to simulate.

 Author: Jens Axboe <axboe@kernel.dk>
 Package Maintainer: <ds@codeminutia.com> http://codeminutia.com/

endef

# Remove quotes from CONFIG_CPU_TYPE
CONFIG_CPU_TYPE_NQ:= $(patsubst "%",%,$(CONFIG_CPU_TYPE))
# get CPU type so we can pass it to fio configure script
CONF_CPU:=$(firstword $(subst +, ,$(CONFIG_CPU_TYPE_NQ)))

CONFIGURE_ARGS = --prefix="$(PKG_INSTALL_DIR)" --cpu="$(CONF_CPU)" --cc="$(TARGET_CC)" --extra-cflags="$(TARGET_CFLAGS)"

define Build/Compile
        $(MAKE) -C $(PKG_BUILD_DIR)
        $(MAKE) -C $(PKG_BUILD_DIR) INSTALL_PREFIX="$(PKG_INSTALL_DIR)" install
endef

define Package/fio/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin/
endef

$(eval $(call BuildPackage,fio, +zlib))