defined by `ioengine`. If no `ioengine` is given, list all
available ioengines.
-.. option:: --showcmd=jobfile
+.. option:: --showcmd
- Convert `jobfile` to a set of command-line options.
+ Convert given job files to a set of command-line options.
.. option:: --readonly
.. option:: max_open_zones=int
- When running a random write test across an entire drive many more
- zones will be open than in a typical application workload. Hence this
- command line option that allows to limit the number of open zones. The
- number of open zones is defined as the number of zones to which write
- commands are issued.
+ A zone of a zoned block device is in the open state when it is partially
+ written (i.e. not all sectors of the zone have been written). Zoned
+ block devices may have a limit on the total number of zones that can
+ be simultaneously in the open state, that is, the number of zones that
+ can be written to simultaneously. The :option:`max_open_zones` parameter
+ limits the number of zones to which write commands are issued by all fio
+ jobs, that is, limits the number of zones that will be in the open
+ state. This parameter is relevant only if the :option:`zonemode` =zbd is
+ used. The default value is always equal to maximum number of open zones
+ of the target zoned block device and a value higher than this limit
+ cannot be specified by users unless the option
+ :option:`ignore_zone_limits` is specified. When
+ :option:`ignore_zone_limits` is specified or the target device has no
+ limit on the number of zones that can be in an open state,
+ :option:`max_open_zones` can specify 0 to disable any limit on the
+ number of zones that can be simultaneously written to by all jobs.
.. option:: job_max_open_zones=int
- Limit on the number of simultaneously opened zones per single
- thread/process.
+ In the same manner as :option:`max_open_zones`, limit the number of open
+ zones per fio job, that is, the number of zones that a single job can
+ simultaneously write to. A value of zero indicates no limit.
+ Default: zero.
.. option:: ignore_zone_limits=bool
+
If this option is used, fio will ignore the maximum number of open
zones limit of the zoned block device in use, thus allowing the
option :option:`max_open_zones` value to be larger than the device
Random mixed reads and writes.
**trimwrite**
Sequential trim+write sequences. Blocks will be trimmed first,
- then the same blocks will be written to.
+ then the same blocks will be written to. So if ``io_size=64K``
+ is specified, Fio will trim a total of 64K bytes and also
+ write 64K bytes on the same trimmed blocks. This behaviour
+ will be consistent with ``number_ios`` or other Fio options
+ limiting the total bytes or number of I/O's.
+ **randtrimwrite**
+ Like trimwrite, but uses random offsets rather
+ than sequential writes.
Fio defaults to read if the option is not specified. For the mixed I/O
types, the default is to split them 50/50. For certain types of I/O the
Generate the same offset.
``sequential`` is only useful for random I/O, where fio would normally
- generate a new random offset for every I/O. If you append e.g. 8 to randread,
- you would get a new random offset for every 8 I/Os. The result would be a
- seek for only every 8 I/Os, instead of for every I/O. Use ``rw=randread:8``
- to specify that. As sequential I/O is already sequential, setting
- ``sequential`` for that would not result in any differences. ``identical``
- behaves in a similar fashion, except it sends the same offset 8 number of
- times before generating a new offset.
+ generate a new random offset for every I/O. If you append e.g. 8 to
+ randread, i.e. ``rw=randread:8`` you would get a new random offset for
+ every 8 I/Os. The result would be a sequence of 8 sequential offsets
+ with a random starting point. However this behavior may change if a
+ sequential I/O reaches end of the file. As sequential I/O is already
+ sequential, setting ``sequential`` for that would not result in any
+ difference. ``identical`` behaves in a similar fashion, except it sends
+ the same offset 8 number of times before generating a new offset.
+
+ Example #1::
+
+ rw=randread:8
+ rw_sequencer=sequential
+ bs=4k
+
+ The generated sequence of offsets will look like this:
+ 4k, 8k, 12k, 16k, 20k, 24k, 28k, 32k, 92k, 96k, 100k, 104k, 108k,
+ 112k, 116k, 120k, 48k, 52k ...
+
+ Example #2::
+
+ rw=randread:8
+ rw_sequencer=identical
+ bs=4k
+
+ The generated sequence of offsets will look like this:
+ 4k, 4k, 4k, 4k, 4k, 4k, 4k, 4k, 92k, 92k, 92k, 92k, 92k, 92k, 92k, 92k,
+ 48k, 48k, 48k ...
.. option:: unified_rw_reporting=str
effectively caps the file size at `real_size - offset`. Can be combined with
:option:`size` to constrain the start and end range of the I/O workload.
A percentage can be specified by a number between 1 and 100 followed by '%',
- for example, ``offset=20%`` to specify 20%. In ZBD mode, value can be set as
+ for example, ``offset=20%`` to specify 20%. In ZBD mode, value can be set as
number of zones using 'z'.
.. option:: offset_align=int
supplied as a value between 0 and 100.
The second, optional float is allowed for **pareto**, **zipf** and **normal** distributions.
- It allows to set base of distribution in non-default place, giving more control
+ It allows one to set base of distribution in non-default place, giving more control
over most probable outcome. This value is in range [0-1] which maps linearly to
range of possible random values.
Defaults are: random for **pareto** and **zipf**, and 0.5 for **normal**.
**mmaphuge** to work, the system must have free huge pages allocated. This
can normally be checked and set by reading/writing
:file:`/proc/sys/vm/nr_hugepages` on a Linux system. Fio assumes a huge page
- is 4MiB in size. So to calculate the number of huge pages you need for a
- given job file, add up the I/O depth of all jobs (normally one unless
- :option:`iodepth` is used) and multiply by the maximum bs set. Then divide
- that number by the huge page size. You can see the size of the huge pages in
- :file:`/proc/meminfo`. If no huge pages are allocated by having a non-zero
- number in `nr_hugepages`, using **mmaphuge** or **shmhuge** will fail. Also
- see :option:`hugepage-size`.
+ is 2 or 4MiB in size depending on the platform. So to calculate the
+ number of huge pages you need for a given job file, add up the I/O
+ depth of all jobs (normally one unless :option:`iodepth` is used) and
+ multiply by the maximum bs set. Then divide that number by the huge
+ page size. You can see the size of the huge pages in
+ :file:`/proc/meminfo`. If no huge pages are allocated by having a
+ non-zero number in `nr_hugepages`, using **mmaphuge** or **shmhuge**
+ will fail. Also see :option:`hugepage-size`.
**mmaphuge** also needs to have hugetlbfs mounted and the file location
should point there. So if it's mounted in :file:`/huge`, you would use
.. option:: hugepage-size=int
- Defines the size of a huge page. Must at least be equal to the system
- setting, see :file:`/proc/meminfo`. Defaults to 4MiB. Should probably
- always be a multiple of megabytes, so using ``hugepage-size=Xm`` is the
- preferred way to set this to avoid setting a non-pow-2 bad value.
+ Defines the size of a huge page. Must at least be equal to the system
+ setting, see :file:`/proc/meminfo` and
+ :file:`/sys/kernel/mm/hugepages/`. Defaults to 2 or 4MiB depending on
+ the platform. Should probably always be a multiple of megabytes, so
+ using ``hugepage-size=Xm`` is the preferred way to set this to avoid
+ setting a non-pow-2 bad value.
.. option:: lockmem=int
.. option:: size=int
The total size of file I/O for each thread of this job. Fio will run until
- this many bytes has been transferred, unless runtime is limited by other options
- (such as :option:`runtime`, for instance, or increased/decreased by :option:`io_size`).
+ this many bytes has been transferred, unless runtime is altered by other means
+ such as (1) :option:`runtime`, (2) :option:`io_size` (3) :option:`number_ios`,
+ (4) gaps/holes while doing I/O's such as ``rw=read:16K``, or (5) sequential
+ I/O reaching end of the file which is possible when :option:`percentage_random`
+ is less than 100.
Fio will divide this size between the available files determined by options
such as :option:`nrfiles`, :option:`filename`, unless :option:`filesize` is
specified by the job. If the result of division happens to be 0, the size is
If this option is not specified, fio will use the full size of the given
files or devices. If the files do not exist, size must be given. It is also
possible to give size as a percentage between 1 and 100. If ``size=20%`` is
- given, fio will use 20% of the full size of the given files or devices.
+ given, fio will use 20% of the full size of the given files or devices.
In ZBD mode, value can also be set as number of zones using 'z'.
Can be combined with :option:`offset` to constrain the start and end range
that I/O will be done within.
for both direct and buffered IO.
This engine defines engine specific options.
+ **io_uring_cmd**
+ Fast Linux native asynchronous I/O for pass through commands.
+ This engine defines engine specific options.
+
**libaio**
Linux native asynchronous I/O. Note that Linux may only support
queued behavior with non-buffered I/O (set ``direct=1`` or
the SPDK NVMe driver, or your own custom NVMe driver. The xnvme engine includes
engine specific options. (See https://xnvme.io).
+ **libblkio**
+ Use the libblkio library
+ (https://gitlab.com/libblkio/libblkio). The specific
+ *driver* to use must be set using
+ :option:`libblkio_driver`. If
+ :option:`mem`/:option:`iomem` is not specified, memory
+ allocation is delegated to libblkio (and so is
+ guaranteed to work with the selected *driver*). One
+ libblkio instance is used per process, so all jobs
+ setting option :option:`thread` will share a single
+ instance (with one queue per thread) and must specify
+ compatible options. Note that some drivers don't allow
+ several instances to access the same device or file
+ simultaneously, but allow it for threads.
+
I/O engine specific parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
values for trim IOs are ignored. This option is mutually exclusive with
the :option:`cmdprio_percentage` option.
-.. option:: fixedbufs : [io_uring]
+.. option:: fixedbufs : [io_uring] [io_uring_cmd]
+
+ If fio is asked to do direct IO, then Linux will map pages for each
+ IO call, and release them when IO is done. If this option is set, the
+ pages are pre-mapped before IO is started. This eliminates the need to
+ map and release for each IO. This is more efficient, and reduces the
+ IO latency as well.
+
+.. option:: nonvectored=int : [io_uring] [io_uring_cmd]
+
+ With this option, fio will use non-vectored read/write commands, where
+ address must contain the address directly. Default is -1.
- If fio is asked to do direct IO, then Linux will map pages for each
- IO call, and release them when IO is done. If this option is set, the
- pages are pre-mapped before IO is started. This eliminates the need to
- map and release for each IO. This is more efficient, and reduces the
- IO latency as well.
+.. option:: force_async=int : [io_uring] [io_uring_cmd]
-.. option:: registerfiles : [io_uring]
+ Normal operation for io_uring is to try and issue an sqe as
+ non-blocking first, and if that fails, execute it in an async manner.
+ With this option set to N, then every N request fio will ask sqe to
+ be issued in an async manner. Default is 0.
+
+.. option:: registerfiles : [io_uring] [io_uring_cmd]
With this option, fio registers the set of files being used with the
kernel. This avoids the overhead of managing file counts in the kernel,
making the submission and completion part more lightweight. Required
for the below :option:`sqthread_poll` option.
-.. option:: sqthread_poll : [io_uring] [xnvme]
+.. option:: sqthread_poll : [io_uring] [io_uring_cmd] [xnvme]
Normally fio will submit IO by issuing a system call to notify the
kernel of available items in the SQ ring. If this option is set, the
act of submitting IO will be done by a polling thread in the kernel.
This frees up cycles for fio, at the cost of using more CPU in the
- system.
+ system. As submission is just the time it takes to fill in the sqe
+ entries and any syscall required to wake up the idle kernel thread,
+ fio will not report submission latencies.
-.. option:: sqthread_poll_cpu : [io_uring]
+.. option:: sqthread_poll_cpu=int : [io_uring] [io_uring_cmd]
When :option:`sqthread_poll` is set, this option provides a way to
define which CPU should be used for the polling thread.
+.. option:: cmd_type=str : [io_uring_cmd]
+
+ Specifies the type of uring passthrough command to be used. Supported
+ value is nvme. Default is nvme.
+
.. option:: hipri
- [io_uring], [xnvme]
+ [io_uring] [io_uring_cmd] [xnvme]
If this option is set, fio will attempt to use polled IO completions.
Normal IO completions generate interrupts to signal the completion of
by the application. The benefits are more efficient IO for high IOPS
scenarios, and lower latencies for low queue depth IO.
+ [libblkio]
+
+ Use poll queues. This is incompatible with
+ :option:`libblkio_wait_mode=eventfd <libblkio_wait_mode>` and
+ :option:`libblkio_force_enable_completion_eventfd`.
+
[pvsync2]
Set RWF_HIPRI on I/O, indicating to the kernel that it's of higher priority
When hipri is set this determines the probability of a pvsync2 I/O being high
priority. The default is 100%.
-.. option:: nowait : [pvsync2] [libaio] [io_uring]
+.. option:: nowait=bool : [pvsync2] [libaio] [io_uring] [io_uring_cmd]
By default if a request cannot be executed immediately (e.g. resource starvation,
waiting on locks) it is queued and the initiating process will be blocked until
the full *type.id* string. If no type. prefix is given, fio will add
'client.' by default.
+.. option:: conf=str : [rados]
+
+ Specifies the configuration path of ceph cluster, so conf file does not
+ have to be /etc/ceph/ceph.conf.
+
.. option:: busy_poll=bool : [rbd,rados]
Poll store instead of waiting for completion. Usually this provides better
[dfs]
- Specificy a different chunk size (in bytes) for the dfs file.
+ Specify a different chunk size (in bytes) for the dfs file.
Use DAOS container's chunk size by default.
[libhdfs]
.. option:: object_class=str : [dfs]
- Specificy a different object class for the dfs file.
+ Specify a different object class for the dfs file.
Use DAOS container's object class by default.
.. option:: skip_bad=bool : [mtd]
The S3 key/access id.
+.. option:: http_s3_sse_customer_key=str : [http]
+
+ The encryption customer key in SSE server side.
+
+.. option:: http_s3_sse_customer_algorithm=str : [http]
+
+ The encryption customer algorithm in SSE server side.
+ Default is **AES256**
+
+.. option:: http_s3_storage_class=str : [http]
+
+ Which storage class to access. User-customizable settings.
+ Default is **STANDARD**
+
.. option:: http_swift_auth_token=str : [http]
The Swift auth token. See the example configuration file on how
Select the xnvme async command interface. This can take these values.
**emu**
- This is default and used to emulate asynchronous I/O.
+ This is default and use to emulate asynchronous I/O by using a
+ single thread to create a queue pair on top of a synchronous
+ I/O interface using the NVMe driver IOCTL.
**thrpool**
- Use thread pool for Asynchronous I/O.
+ Emulate an asynchronous I/O interface with a pool of userspace
+ threads on top of a synchronous I/O interface using the NVMe
+ driver IOCTL. By default four threads are used.
**io_uring**
- Use Linux io_uring/liburing for Asynchronous I/O.
+ Linux native asynchronous I/O interface which supports both
+ direct and buffered I/O.
+ **io_uring_cmd**
+ Fast Linux native asynchronous I/O interface for NVMe pass
+ through commands. This only works with NVMe character device
+ (/dev/ngXnY).
**libaio**
Use Linux aio for Asynchronous I/O.
**posix**
- Use POSIX aio for Asynchronous I/O.
+ Use the posix asynchronous I/O interface to perform one or
+ more I/O operations asynchronously.
+ **vfio**
+ Use the user-space VFIO-based backend, implemented using
+ libvfn instead of SPDK.
**nil**
- Use nil-io; For introspective perf. evaluation
+ Do not transfer any data; just pretend to. This is mainly used
+ for introspective performance evaluation.
.. option:: xnvme_sync=str : [xnvme]
Select the xnvme synchronous command interface. This can take these values.
**nvme**
- This is default and uses Linux NVMe Driver ioctl() for synchronous I/O.
+ This is default and uses Linux NVMe Driver ioctl() for
+ synchronous I/O.
**psync**
- Use pread()/write() for synchronous I/O.
+ This supports regular as well as vectored pread() and pwrite()
+ commands.
+ **block**
+ This is the same as psync except that it also supports zone
+ management commands using Linux block layer IOCTLs.
.. option:: xnvme_admin=str : [xnvme]
Select the xnvme admin command interface. This can take these values.
**nvme**
- This is default and uses linux NVMe Driver ioctl() for admin commands.
+ This is default and uses linux NVMe Driver ioctl() for admin
+ commands.
**block**
Use Linux Block Layer ioctl() and sysfs for admin commands.
- **file_as_ns**
- Use file-stat to construct NVMe idfy responses.
.. option:: xnvme_dev_nsid=int : [xnvme]
- xnvme namespace identifier, for userspace NVMe driver.
+ xnvme namespace identifier for userspace NVMe driver, SPDK or vfio.
+
+.. option:: xnvme_dev_subnqn=str : [xnvme]
+
+ Sets the subsystem NQN for fabrics. This is for xNVMe to utilize a
+ fabrics target with multiple systems.
+
+.. option:: xnvme_mem=str : [xnvme]
+
+ Select the xnvme memory backend. This can take these values.
+
+ **posix**
+ This is the default posix memory backend for linux NVMe driver.
+ **hugepage**
+ Use hugepages, instead of existing posix memory backend. The
+ memory backend uses hugetlbfs. This require users to allocate
+ hugepages, mount hugetlbfs and set an enviornment variable for
+ XNVME_HUGETLB_PATH.
+ **spdk**
+ Uses SPDK's memory allocator.
+ **vfio**
+ Uses libvfn's memory allocator. This also specifies the use
+ of libvfn backend instead of SPDK.
.. option:: xnvme_iovec=int : [xnvme]
If this option is set. xnvme will use vectored read/write commands.
+.. option:: libblkio_driver=str : [libblkio]
+
+ The libblkio *driver* to use. Different drivers access devices through
+ different underlying interfaces. Available drivers depend on the
+ libblkio version in use and are listed at
+ https://libblkio.gitlab.io/libblkio/blkio.html#drivers
+
+.. option:: libblkio_path=str : [libblkio]
+
+ Sets the value of the driver-specific "path" property before connecting
+ the libblkio instance, which identifies the target device or file on
+ which to perform I/O. Its exact semantics are driver-dependent and not
+ all drivers may support it; see
+ https://libblkio.gitlab.io/libblkio/blkio.html#drivers
+
+.. option:: libblkio_pre_connect_props=str : [libblkio]
+
+ A colon-separated list of additional libblkio properties to be set after
+ creating but before connecting the libblkio instance. Each property must
+ have the format ``<name>=<value>``. Colons can be escaped as ``\:``.
+ These are set after the engine sets any other properties, so those can
+ be overriden. Available properties depend on the libblkio version in use
+ and are listed at
+ https://libblkio.gitlab.io/libblkio/blkio.html#properties
+
+.. option:: libblkio_num_entries=int : [libblkio]
+
+ Sets the value of the driver-specific "num-entries" property before
+ starting the libblkio instance. Its exact semantics are driver-dependent
+ and not all drivers may support it; see
+ https://libblkio.gitlab.io/libblkio/blkio.html#drivers
+
+.. option:: libblkio_queue_size=int : [libblkio]
+
+ Sets the value of the driver-specific "queue-size" property before
+ starting the libblkio instance. Its exact semantics are driver-dependent
+ and not all drivers may support it; see
+ https://libblkio.gitlab.io/libblkio/blkio.html#drivers
+
+.. option:: libblkio_pre_start_props=str : [libblkio]
+
+ A colon-separated list of additional libblkio properties to be set after
+ connecting but before starting the libblkio instance. Each property must
+ have the format ``<name>=<value>``. Colons can be escaped as ``\:``.
+ These are set after the engine sets any other properties, so those can
+ be overriden. Available properties depend on the libblkio version in use
+ and are listed at
+ https://libblkio.gitlab.io/libblkio/blkio.html#properties
+
+.. option:: libblkio_vectored : [libblkio]
+
+ Submit vectored read and write requests.
+
+.. option:: libblkio_write_zeroes_on_trim : [libblkio]
+
+ Submit trims as "write zeroes" requests instead of discard requests.
+
+.. option:: libblkio_wait_mode=str : [libblkio]
+
+ How to wait for completions:
+
+ **block** (default)
+ Use a blocking call to ``blkioq_do_io()``.
+ **eventfd**
+ Use a blocking call to ``read()`` on the completion eventfd.
+ **loop**
+ Use a busy loop with a non-blocking call to ``blkioq_do_io()``.
+
+.. option:: libblkio_force_enable_completion_eventfd : [libblkio]
+
+ Enable the queue's completion eventfd even when unused. This may impact
+ performance. The default is to enable it only if
+ :option:`libblkio_wait_mode=eventfd <libblkio_wait_mode>`.
+
I/O depth
~~~~~~~~~
Write the issued I/O patterns to the specified file. See
:option:`read_iolog`. Specify a separate file for each job, otherwise the
- iologs will be interspersed and the file may be corrupt.
+ iologs will be interspersed and the file may be corrupt. This file will
+ be opened in append mode.
.. option:: read_iolog=str
.. option:: flow=int
- Weight in token-based flow control. If this value is used, then there is a
- 'flow counter' which is used to regulate the proportion of activity between
- two or more jobs. Fio attempts to keep this flow counter near zero. The
- ``flow`` parameter stands for how much should be added or subtracted to the
- flow counter on each iteration of the main I/O loop. That is, if one job has
- ``flow=8`` and another job has ``flow=-1``, then there will be a roughly 1:8
- ratio in how much one runs vs the other.
+ Weight in token-based flow control. If this value is used, then fio
+ regulates the activity between two or more jobs sharing the same
+ flow_id. Fio attempts to keep each job activity proportional to other
+ jobs' activities in the same flow_id group, with respect to requested
+ weight per job. That is, if one job has `flow=3', another job has
+ `flow=2' and another with `flow=1`, then there will be a roughly 3:2:1
+ ratio in how much one runs vs the others.
.. option:: flow_sleep=int
make fio terminate all jobs in the same group, as soon as one job of that
group finishes.
-.. option:: exit_what
+.. option:: exit_what=str
By default, fio will continue running all other jobs when one job finishes.
- Sometimes this is not the desired action. Setting ``exit_all`` will
+ Sometimes this is not the desired action. Setting ``exitall`` will
instead make fio terminate all jobs in the same group. The option
``exit_what`` allows to control which jobs get terminated when ``exitall`` is
enabled. The default is ``group`` and does not change the behaviour of
.. option:: experimental_verify=bool
- Enable experimental verification.
+ Enable experimental verification. Standard verify records I/O metadata
+ for later use during the verification phase. Experimental verify
+ instead resets the file after the write phase and then replays I/Os for
+ the verification phase.
Steady state
~~~~~~~~~~~~
appended, the total error count and the first error. The error field given
in the stats is the first error that was hit during the run.
+ Note: a write error from the device may go unnoticed by fio when using
+ buffered IO, as the write() (or similar) system call merely dirties the
+ kernel pages, unless :option:`sync` or :option:`direct` is used. Device IO
+ errors occur when the dirty data is actually written out to disk. If fully
+ sync writes aren't desirable, :option:`fsync` or :option:`fdatasync` can be
+ used as well. This is specific to writes, as reads are always synchronous.
+
The allowed values are:
**none**
**slat**
Submission latency (**min** being the minimum, **max** being the
maximum, **avg** being the average, **stdev** being the standard
- deviation). This is the time it took to submit the I/O. For
- sync I/O this row is not displayed as the slat is really the
- completion latency (since queue/complete is one operation there).
- This value can be in nanoseconds, microseconds or milliseconds ---
- fio will choose the most appropriate base and print that (in the
- example above nanoseconds was the best scale). Note: in :option:`--minimal` mode
- latencies are always expressed in microseconds.
+ deviation). This is the time from when fio initialized the I/O
+ to submission. For synchronous ioengines this includes the time
+ up until just before the ioengine's queue function is called.
+ For asynchronous ioengines this includes the time up through the
+ completion of the ioengine's queue function (and commit function
+ if it is defined). For sync I/O this row is not displayed as the
+ slat is negligible. This value can be in nanoseconds,
+ microseconds or milliseconds --- fio will choose the most
+ appropriate base and print that (in the example above
+ nanoseconds was the best scale). Note: in :option:`--minimal`
+ mode latencies are always expressed in microseconds.
**clat**
Completion latency. Same names as slat, this denotes the time from
- submission to completion of the I/O pieces. For sync I/O, clat will
- usually be equal (or very close) to 0, as the time from submit to
- complete is basically just CPU time (I/O has already been done, see slat
- explanation).
+ submission to completion of the I/O pieces. For sync I/O, this
+ represents the time from when the I/O was submitted to the
+ operating system to when it was completed. For asynchronous
+ ioengines this is the time from when the ioengine's queue (and
+ commit if available) functions were completed to when the I/O's
+ completion was reaped by fio.
**lat**
Total latency. Same names as slat and clat, this denotes the time from
when fio created the I/O unit to completion of the I/O operation.
+ It is the sum of submission and completion latency.
**bw**
Bandwidth statistics based on samples. Same names as the xlat stats,
~~~~~~~~~~~~~~~~~~~~
The second version of the trace file format was added in fio version 1.17. It
-allows to access more then one file per trace and has a bigger set of possible
+allows one to access more than one file per trace and has a bigger set of possible
file actions.
The first line of the trace file has to be::