Skip to main content

Flexible I/O Tester (FIO)

The Software-Enabled Flash™️ (SEF) patch for fio adds SEF as an I/O engine. The SEF I/O engine uses the SEF Block Module to issue block I/O against a defined QoS Domain. In other words, the QoS Domain which is used should be defined before the job is executed. If the QoS Domain is not configured, the engine will configure it using default values.

The SEF FIO Engine Options Table enumerates the options accepted by the SEF I/O engine. qos_domain_id or qos_domain_label option should be provided to identify the target QoS Domain. If both options are provided, qos_domain_id is used as default. The qos_domain_label should be unique across the SEF Unit or the job will fail.

SEF FIO Engine Options

OptionTypeRequiredDescription
sef_unit_indexint (16 bit)YesThe index of the SEF Unit, the index is zero based
qos_domain_idint (16 bit)Yes*The Id of the QoS Domain
qos_domain_labeluint (Two 64 bits)Yes*The label of the QoS Domain
sef_zero_copyboolNoUse zero copy buffers
read_queueint (16 bit)NokSEFRead queue override when valid
read_weightint (16 bit)NoRead weight to override when non-zero
write_weightint (16 bit)NoWrite weight to override when non-zero
placement_idint (16 bit)NoPlacement ID for writes

Listing 1 is an example job file that runs for 10 minutes. It contains two jobs, both operating on SEF Unit 0. The first randomly writes to QoS Domain 2, and the second reads and writes to a QoS Domain labeled as 61300673829223,888776657572036.

It’s important to note the thread option. It’s required because the SEF Block Module and SEF libraries do not currently support forked processes.

Listing 1: Example SEF Engine FIO Job

[global]
ioengine=sef
sef_unit_index=0
bs=4k
time_based=1
runtime=600
verify=md5
iodepth=16
thread


[sef-write]
qos_domain_id=2
rw=randwrite
size=100%


[sef-read-write]
qos_domain_label=61300673829223,888776657572036
rw=randrw
size=100%

Buddy Allocator

The sef_zero_copy option of the SEF FIO Engine uses the Buddy Allocator to write the data.

The Buddy Allocator works by associating fragmented memory with the incoming I/O requests and freeing them as I/O get completed. The buddy allocator allocates blocks of memory in multiples of a fixed size—in this case, the ADU size. A pool of memory is pre-allocated by the buddy allocator in a power-of-2 of the fixed size. Free lists are maintained for each power-of-2 from the fixed size to the size of the whole pool. The buddy allocator begins searching for free blocks at the smallest power-of-2 which is larger than the requested allocation. If space can’t be found there, the next largest level is checked until space is found. The block there will be split, and the unallocated portion of the block will be assigned to the lower power-of-2 free list. When blocks are freed, a "buddy" is looked for in the matching power-of-2 list, and if found, the blocks are combined and moved to the higher power-of-2 list.

Unlike a regular heap, it is possible to use blocks from within a previous allocation.

For the SEF FIO engine, we allocate a pool that is larger than the size of the outstanding I/O, and the blocks are returned to the buddy allocator when the nameless write completes.