├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── config.yml │ └── enhancement.md ├── PULL_REQUEST_TEMPLATE.md ├── SUPPORT.md ├── actions │ ├── build-qemu │ │ └── action.yml │ ├── create-guest-image │ │ └── action.yml │ └── start-vm │ │ └── action.yml └── workflows │ ├── ci.yml │ ├── cifuzz.yml │ └── qemu.yml ├── .gitignore ├── .readthedocs.yaml ├── CITATION.cff ├── COPYING ├── DEDUPE-TODO ├── FIO-VERSION-GEN ├── GFIO-TODO ├── HOWTO.rst ├── MORAL-LICENSE ├── Makefile ├── README.rst ├── REPORTING-BUGS ├── SERVER-TODO ├── STEADYSTATE-TODO ├── arch ├── arch-aarch64.h ├── arch-alpha.h ├── arch-arm.h ├── arch-generic.h ├── arch-hppa.h ├── arch-ia64.h ├── arch-loongarch64.h ├── arch-mips.h ├── arch-ppc.h ├── arch-riscv64.h ├── arch-s390.h ├── arch-sh.h ├── arch-sparc.h ├── arch-sparc64.h ├── arch-x86-common.h ├── arch-x86.h ├── arch-x86_64.h └── arch.h ├── backend.c ├── blktrace.c ├── blktrace.h ├── blktrace_api.h ├── cairo_text_helpers.c ├── cairo_text_helpers.h ├── cconv.c ├── cgroup.c ├── cgroup.h ├── ci ├── actions-build.sh ├── actions-full-test.sh ├── actions-install.sh ├── actions-smoke-test.sh └── common.sh ├── client.c ├── client.h ├── compiler └── compiler.h ├── configure ├── crc ├── crc-t10dif.h ├── crc16.c ├── crc16.h ├── crc32.c ├── crc32.h ├── crc32c-arm64.c ├── crc32c-intel.c ├── crc32c.c ├── crc32c.h ├── crc64.c ├── crc64.h ├── crc64table.h ├── crc7.c ├── crc7.h ├── crct10dif_common.c ├── fnv.c ├── fnv.h ├── md5.c ├── md5.h ├── murmur3.c ├── murmur3.h ├── sha1.c ├── sha1.h ├── sha256.c ├── sha256.h ├── sha3.c ├── sha3.h ├── sha512.c ├── sha512.h ├── test.c ├── test.h ├── xxhash.c └── xxhash.h ├── dataplacement.c ├── dataplacement.h ├── debug.c ├── debug.h ├── dedupe.c ├── dedupe.h ├── diskutil.c ├── diskutil.h ├── doc ├── Makefile ├── conf.py ├── fio-histo-log-pctiles.pdf ├── fio_doc.rst ├── fio_examples.rst ├── index.rst └── make.bat ├── engines ├── cmdprio.c ├── cmdprio.h ├── cpu.c ├── dev-dax.c ├── dfs.c ├── e4defrag.c ├── exec.c ├── falloc.c ├── fileoperations.c ├── ftruncate.c ├── gfapi.h ├── glusterfs.c ├── glusterfs_async.c ├── glusterfs_sync.c ├── http.c ├── ime.c ├── io_uring.c ├── libaio.c ├── libblkio.c ├── libcufile.c ├── libhdfs.c ├── libiscsi.c ├── libpmem.c ├── libzbc.c ├── mmap.c ├── mtd.c ├── nbd.c ├── net.c ├── nfs.c ├── null.c ├── nvme.c ├── nvme.h ├── posixaio.c ├── rados.c ├── rbd.c ├── rdma.c ├── sg.c ├── skeleton_external.c ├── solarisaio.c ├── splice.c ├── sync.c ├── windowsaio.c └── xnvme.c ├── err.h ├── eta.c ├── examples ├── 1mbs_clients.fio ├── 1mbs_clients.png ├── aio-read.fio ├── aio-read.png ├── atomic-verify.fio ├── backwards-read.fio ├── backwards-read.png ├── basic-verify.fio ├── basic-verify.png ├── butterfly.fio ├── butterfly.png ├── cmdprio-bssplit.fio ├── cmdprio-bssplit.png ├── cmdprio-percentage.fio ├── cmdprio-percentage.png ├── cpp_null.fio ├── cpp_null.png ├── cpuio.fio ├── cpuio.png ├── cross-stripe-verify.fio ├── cross-stripe-verify.png ├── dedupe-global.fio ├── dedupe-global.png ├── dev-dax.fio ├── dev-dax.png ├── dfs.fio ├── dfs.png ├── dircreate-ioengine.fio ├── dircreate-ioengine.png ├── dirdelete-ioengine.fio ├── dirdelete-ioengine.png ├── dirstat-ioengine.fio ├── dirstat-ioengine.png ├── disk-zone-profile.fio ├── disk-zone-profile.png ├── e4defrag.fio ├── e4defrag.png ├── e4defrag2.fio ├── e4defrag2.png ├── enospc-pressure.fio ├── enospc-pressure.png ├── exec.fio ├── exec.png ├── exitwhat.fio ├── exitwhat.png ├── falloc.fio ├── falloc.png ├── filecreate-ioengine.fio ├── filecreate-ioengine.png ├── filedelete-ioengine.fio ├── filedelete-ioengine.png ├── filestat-ioengine.fio ├── filestat-ioengine.png ├── fio-rand-RW.fio ├── fio-rand-RW.png ├── fio-rand-read.fio ├── fio-rand-read.png ├── fio-rand-write.fio ├── fio-rand-write.png ├── fio-seq-RW.fio ├── fio-seq-RW.png ├── fio-seq-read.fio ├── fio-seq-read.png ├── fio-seq-write.fio ├── fio-seq-write.png ├── fixed-rate-submission.fio ├── fixed-rate-submission.png ├── flow.fio ├── flow.png ├── fsx.fio ├── fsx.png ├── ftruncate.fio ├── ftruncate.png ├── gfapi.fio ├── gfapi.png ├── gpudirect-rdmaio-client.fio ├── gpudirect-rdmaio-client.png ├── gpudirect-rdmaio-server.fio ├── gpudirect-rdmaio-server.png ├── http-s3-crypto.fio ├── http-s3-crypto.png ├── http-s3-storage-class.fio ├── http-s3-storage-class.png ├── http-s3.fio ├── http-s3.png ├── http-swift.fio ├── http-swift.png ├── http-webdav.fio ├── http-webdav.png ├── ime.fio ├── ime.png ├── iometer-file-access-server.fio ├── iometer-file-access-server.png ├── jesd219.fio ├── jesd219.png ├── latency-profile.fio ├── latency-profile.png ├── libblkio-io_uring.fio ├── libblkio-io_uring.png ├── libblkio-virtio-blk-vfio-pci.fio ├── libblkio-virtio-blk-vfio-pci.png ├── libcufile-cufile.fio ├── libcufile-cufile.png ├── libcufile-posix.fio ├── libcufile-posix.png ├── libhdfs.fio ├── libhdfs.png ├── libiscsi.fio ├── libiscsi.png ├── libpmem.fio ├── libpmem.png ├── libzbc-rand-write.fio ├── libzbc-rand-write.png ├── libzbc-seq-read.fio ├── libzbc-seq-read.png ├── mtd.fio ├── mtd.png ├── nbd.fio ├── nbd.png ├── netio.fio ├── netio.png ├── netio_multicast.fio ├── netio_multicast.png ├── netio_vsock.fio ├── netio_vsock.png ├── netio_vsock_receiver.fio ├── netio_vsock_receiver.png ├── netio_vsock_sender.fio ├── netio_vsock_sender.png ├── nfs.fio ├── nfs.png ├── null.fio ├── null.png ├── numa.fio ├── numa.png ├── poisson-rate-submission.fio ├── poisson-rate-submission.png ├── rados.fio ├── rados.png ├── rand-zones.fio ├── rand-zones.png ├── rbd.fio ├── rbd.png ├── rdmaio-client.fio ├── rdmaio-client.png ├── rdmaio-server.fio ├── rdmaio-server.png ├── sg_verify-fail.fio ├── sg_verify-fail.png ├── sg_verify.fio ├── sg_verify.png ├── sg_write_same_ndob.fio ├── sg_write_same_ndob.png ├── ssd-steadystate.fio ├── ssd-steadystate.png ├── ssd-test.fio ├── ssd-test.png ├── steadystate.fio ├── steadystate.png ├── surface-scan.fio ├── surface-scan.png ├── tiobench-example.fio ├── tiobench-example.png ├── uring-cmd-fdp.fio ├── uring-cmd-fdp.png ├── uring-cmd-ng.fio ├── uring-cmd-ng.png ├── uring-cmd-pi-ext.fio ├── uring-cmd-pi-ext.png ├── uring-cmd-pi-sb.fio ├── uring-cmd-pi-sb.png ├── uring-cmd-trim-multi-range.fio ├── uring-cmd-trim-multi-range.png ├── uring-cmd-zoned.fio ├── uring-cmd-zoned.png ├── waitfor.fio ├── waitfor.png ├── xnvme-compare.fio ├── xnvme-compare.png ├── xnvme-fdp.fio ├── xnvme-fdp.png ├── xnvme-pi.fio ├── xnvme-pi.png ├── xnvme-zoned.fio ├── xnvme-zoned.png ├── zbd-rand-write-trim-gc.fio ├── zbd-rand-write-trim-gc.png ├── zbd-rand-write-zone-reset-gc.fio ├── zbd-rand-write-zone-reset-gc.png ├── zbd-rand-write.fio ├── zbd-rand-write.png ├── zbd-seq-read.fio ├── zbd-seq-read.png ├── zipf.fio └── zipf.png ├── exp ├── expression-parser.l ├── expression-parser.y └── test-expression-parser.c ├── fifo.c ├── fifo.h ├── file.h ├── filehash.c ├── filehash.h ├── filelock.c ├── filelock.h ├── filesetup.c ├── fio.1 ├── fio.c ├── fio.h ├── fio_sem.c ├── fio_sem.h ├── fio_shared_sem.c ├── fio_time.h ├── flist.h ├── flow.c ├── flow.h ├── gclient.c ├── gclient.h ├── gcompat.c ├── gcompat.h ├── gerror.c ├── gerror.h ├── gettime-thread.c ├── gettime.c ├── gettime.h ├── gfio.c ├── gfio.h ├── ghelpers.c ├── ghelpers.h ├── goptions.c ├── goptions.h ├── graph.c ├── graph.h ├── hash.h ├── helper_thread.c ├── helper_thread.h ├── helpers.c ├── helpers.h ├── idletime.c ├── idletime.h ├── init.c ├── io_ddir.h ├── io_u.c ├── io_u.h ├── io_u_queue.c ├── io_u_queue.h ├── ioengines.c ├── ioengines.h ├── iolog.c ├── iolog.h ├── json.c ├── json.h ├── lib ├── axmap.c ├── axmap.h ├── bloom.c ├── bloom.h ├── bswap.h ├── ffz.h ├── flist_sort.c ├── fls.h ├── gauss.c ├── gauss.h ├── getrusage.c ├── getrusage.h ├── hweight.c ├── hweight.h ├── ieee754.c ├── ieee754.h ├── lfsr.c ├── lfsr.h ├── memalign.c ├── memalign.h ├── memcpy.c ├── memcpy.h ├── mountcheck.c ├── mountcheck.h ├── nowarn_snprintf.h ├── num2str.c ├── num2str.h ├── output_buffer.c ├── output_buffer.h ├── pattern.c ├── pattern.h ├── pow2.h ├── prio_tree.c ├── prio_tree.h ├── rand.c ├── rand.h ├── rbtree.c ├── rbtree.h ├── roundup.h ├── seqlock.h ├── strntol.c ├── strntol.h ├── types.h ├── zipf.c └── zipf.h ├── libfio.c ├── log.c ├── log.h ├── memory.c ├── minmax.h ├── optgroup.c ├── optgroup.h ├── options.c ├── options.h ├── os ├── kcompat.h ├── linux │ └── io_uring.h ├── os-aix.h ├── os-ashmem.h ├── os-dragonfly.h ├── os-freebsd.h ├── os-hpux.h ├── os-linux-syscall.h ├── os-linux.h ├── os-mac.h ├── os-netbsd.h ├── os-openbsd.h ├── os-qnx.h ├── os-solaris.h ├── os-windows-7.h ├── os-windows.h ├── os.h └── windows │ ├── WixUI_Minimal_NoEULA.wxs │ ├── WixUI_fio.wxl │ ├── cpu-affinity.c │ ├── dlls.c │ ├── dobuild.cmd │ ├── examples.wxs │ ├── install.wxs │ ├── posix.c │ ├── posix.h │ └── posix │ └── include │ ├── arpa │ └── inet.h │ ├── asm │ └── types.h │ ├── dirent.h │ ├── dlfcn.h │ ├── libgen.h │ ├── netdb.h │ ├── netinet │ ├── in.h │ └── tcp.h │ ├── poll.h │ ├── semaphore.h │ ├── sys │ ├── ioctl.h │ ├── ipc.h │ ├── mman.h │ ├── resource.h │ ├── shm.h │ ├── socket.h │ ├── uio.h │ ├── un.h │ └── wait.h │ └── syslog.h ├── oslib ├── asprintf.c ├── asprintf.h ├── blkzoned.h ├── getopt.h ├── getopt_long.c ├── inet_aton.c ├── inet_aton.h ├── libmtd.c ├── libmtd.h ├── libmtd_common.h ├── libmtd_int.h ├── libmtd_legacy.c ├── libmtd_xalloc.h ├── linux-blkzoned.c ├── linux-dev-lookup.c ├── linux-dev-lookup.h ├── statx.c ├── statx.h ├── strcasestr.c ├── strcasestr.h ├── strlcat.c ├── strlcat.h ├── strndup.c ├── strndup.h ├── strsep.c └── strsep.h ├── parse.c ├── parse.h ├── printing.c ├── printing.h ├── profile.c ├── profile.h ├── profiles ├── act.c └── tiobench.c ├── pshared.c ├── pshared.h ├── rate-submit.c ├── rate-submit.h ├── rwlock.c ├── rwlock.h ├── server.c ├── server.h ├── smalloc.c ├── smalloc.h ├── stat.c ├── stat.h ├── steadystate.c ├── steadystate.h ├── t ├── arch.c ├── axmap.c ├── btrace2fio.c ├── client_server.py ├── client_server │ ├── test01.fio │ ├── test04-noglobal.fio │ ├── test07-slat.fio │ ├── test08-clat.fio │ ├── test09-lat.fio │ ├── test10-noclat.fio │ └── test11-alllat.fio ├── debug.c ├── debug.h ├── dedupe.c ├── fiotestcommon.py ├── fiotestlib.py ├── fuzz │ ├── fuzz_parseini.c │ └── onefile.c ├── gen-rand.c ├── genzipf.c ├── ieee754.c ├── io_uring.c ├── jobs │ ├── t0001-52c58027.fio │ ├── t0002-13af05ae-post.fio │ ├── t0002-13af05ae-pre.fio │ ├── t0003-0ae2c6e1-post.fio │ ├── t0003-0ae2c6e1-pre.fio │ ├── t0004-8a99fdf6.fio │ ├── t0005-f7078f7b.fio │ ├── t0006-82af2a7c.fio │ ├── t0007-37cf9e3c.fio │ ├── t0008-ae2fafc8.fio │ ├── t0009-f8b0bd10.fio │ ├── t0010-b7aae4ba.fio │ ├── t0011-5d2788d5.fio │ ├── t0012.fio │ ├── t0013.fio │ ├── t0014.fio │ ├── t0015-4e7e7898.fio │ ├── t0016-d54ae22.fio │ ├── t0017.fio │ ├── t0018.fio │ ├── t0019.fio │ ├── t0020.fio │ ├── t0021.fio │ ├── t0022.fio │ ├── t0023.fio │ ├── t0024.fio │ ├── t0025.fio │ ├── t0026.fio │ ├── t0027.fio │ ├── t0028-c6cade16.fio │ ├── t0029.fio │ ├── t0030.fio │ ├── t0031-pre.fio │ ├── t0031.fio │ ├── t0032-43063a1c.fio │ ├── t0033.fio │ ├── t0034.fio │ ├── t0035.fio │ ├── t0036-post.fio │ ├── t0036-pre.fio │ ├── t0037-post.fio │ └── t0037-pre.fio ├── jsonplus2csv_test.py ├── latency_percentiles.py ├── lfsr-test.c ├── log.c ├── log_compression.py ├── memlock.c ├── nvmept.py ├── nvmept_fdp.py ├── nvmept_pi.py ├── nvmept_streams.py ├── nvmept_trim.py ├── one-core-peak.sh ├── random_seed.py ├── read-to-pipe-async.c ├── readonly.py ├── run-fio-tests.py ├── sgunmap-perf.py ├── sgunmap-test.py ├── steadystate_tests.py ├── stest.c ├── strided.py ├── time-test.c ├── verify-state.c ├── verify-trim.py ├── verify.py └── zbd │ ├── functions │ ├── run-tests-against-nullb │ ├── run-tests-against-scsi_debug │ └── test-zbd-support ├── td_error.c ├── td_error.h ├── thread_options.h ├── tickmarks.c ├── tickmarks.h ├── time.c ├── tools ├── .gitignore ├── fio.service ├── fio_generate_plots ├── fio_generate_plots.1 ├── fio_jsonplus_clat2csv ├── fiograph │ ├── fiograph.conf │ └── fiograph.py ├── fiologparser.py ├── genfio ├── hist │ ├── .gitignore │ ├── fio-histo-log-pctiles.py │ ├── fiologparser_hist.py │ ├── fiologparser_hist.py.1 │ └── half-bins.py └── plot │ ├── fio2gnuplot │ ├── fio2gnuplot.1 │ ├── fio2gnuplot.manpage │ ├── graph2D.gpm │ ├── graph3D.gpm │ ├── math.gpm │ └── samples │ ├── Makefile │ └── fio-logs.tar.gz ├── trim.c ├── trim.h ├── unittests ├── lib │ ├── memalign.c │ ├── num2str.c │ └── strntol.c ├── oslib │ ├── strcasestr.c │ ├── strlcat.c │ ├── strndup.c │ └── strsep.c ├── unittest.c └── unittest.h ├── verify-state.h ├── verify.c ├── verify.h ├── workqueue.c ├── workqueue.h ├── zbd.c ├── zbd.h ├── zbd_types.h ├── zone-dist.c └── zone-dist.h /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Please acknowledge you have done the following before creating a ticket** 2 | 3 | - [ ] I have read the GitHub issues section of [REPORTING-BUGS](../blob/master/REPORTING-BUGS). 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a bug 3 | about: For bugs that are reproducible with the latest fio releases 4 | 5 | --- 6 | 7 | **Please acknowledge the following before creating a ticket** 8 | 9 | - [ ] I have read the GitHub issues section of [REPORTING-BUGS](../blob/master/REPORTING-BUGS). 10 | 11 | **Description of the bug:** 12 | 13 | 14 | **Environment**: 15 | 16 | **fio version**: 17 | 18 | **Reproduction steps** 19 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | 3 | contact_links: 4 | - name: General questions (e.g. "How do I...", "Why is...") that are related to fio 5 | url: http://vger.kernel.org/vger-lists.html#fio 6 | about: Please send questions to the fio mailing list (plain-text emails ONLY) 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature enhancement request 3 | about: Suggest a new fio feature 4 | labels: enhancement 5 | 6 | --- 7 | 8 | **Description of the new feature** 9 | 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please confirm that your commit message(s) follow these guidelines: 2 | 3 | 1. First line is a commit title, a descriptive one-liner for the change 4 | 2. Empty second line 5 | 3. Commit message body that explains why the change is useful. Break lines that 6 | aren't something like a URL at 72-74 chars. 7 | 4. Empty line 8 | 5. Signed-off-by: Real Name 9 | 10 | Reminders: 11 | 12 | 1. If you modify struct thread_options, also make corresponding changes in 13 | cconv.c and bump FIO_SERVER_VER in server.h 14 | 2. If you change the ioengine interface (hooks, flags, etc), remember to bump 15 | FIO_IOOPS_VERSION in ioengines.h. 16 | -------------------------------------------------------------------------------- /.github/actions/build-qemu/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Build and Install QEMU on Ubuntu' 2 | desription: 'Build QEMU and Install on Ubuntu' 3 | 4 | inputs: 5 | version: # What QEMU version to build/install 6 | description: 'QEMU version to build and install' 7 | required: false 8 | default: '9.1.0' 9 | 10 | 11 | runs: 12 | using: "composite" 13 | steps: 14 | - name: Install QEMU build dependencies 15 | run: sudo apt update && sudo apt-get -qq install libglib2.0-dev libfdt-dev libpixman-1-dev ninja-build flex bison libsdl2-dev libaio-dev python3-tomli libslirp-dev 16 | shell: bash 17 | 18 | - name: Build and install QEMU 19 | run: | 20 | wget -nv https://download.qemu.org/qemu-$INPUT_VER.tar.xz 21 | tar xJf qemu-$INPUT_VER.tar.xz 22 | rm qemu-$INPUT_VER.tar.xz 23 | cd qemu-$INPUT_VER 24 | ./configure --enable-kvm --target-list=x86_64-softmmu 25 | make -j $(nproc) 26 | sudo make install 27 | cd .. 28 | rm -rf qemu-$INPUT_VER 29 | shell: bash 30 | env: 31 | INPUT_VER: ${{ inputs.version }} 32 | -------------------------------------------------------------------------------- /.github/workflows/cifuzz.yml: -------------------------------------------------------------------------------- 1 | name: CIFuzz 2 | on: [pull_request, workflow_dispatch] 3 | jobs: 4 | Fuzzing: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Build Fuzzers 8 | id: build 9 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master 10 | with: 11 | oss-fuzz-project-name: 'fio' 12 | dry-run: false 13 | - name: Run Fuzzers 14 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master 15 | with: 16 | oss-fuzz-project-name: 'fio' 17 | fuzz-seconds: 600 18 | dry-run: false 19 | - name: Upload Crash 20 | uses: actions/upload-artifact@v4 21 | if: failure() && steps.build.outcome == 'success' 22 | with: 23 | name: artifacts 24 | path: ./out/artifacts 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.o 3 | *.so 4 | *.exe 5 | /.depend 6 | /FIO-VERSION-FILE 7 | /config-host.h 8 | /config-host.mak 9 | /config.log 10 | /cscope.out 11 | /fio 12 | /gfio 13 | /t/axmap 14 | /t/fio-btrace2fio 15 | /t/fio-dedupe 16 | /t/fio-genzipf 17 | /t/fio-verify-state 18 | /t/gen-rand 19 | /t/ieee754 20 | t/io_uring 21 | /t/lfsr-test 22 | t/memlock 23 | t/read-to-pipe-async 24 | /t/stest 25 | /unittests/unittest 26 | y.tab.* 27 | lex.yy.c 28 | *.un~ 29 | doc/output 30 | /tags 31 | /TAGS 32 | /t/zbd/test-zbd-support.log.* 33 | /t/fuzz/fuzz_parseini 34 | tsc-rate 35 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3" 12 | 13 | # Build documentation in the docs/ directory with Sphinx 14 | sphinx: 15 | configuration: doc/conf.py 16 | 17 | # Optionally build your docs in additional formats such as PDF 18 | formats: 19 | - epub 20 | - pdf 21 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | preferred-citation: 3 | type: software 4 | authors: 5 | - family-names: "Axboe" 6 | given-names: "Jens" 7 | email: axboe@kernel.dk 8 | title: "Flexible I/O Tester" 9 | year: 2022 10 | url: "https://github.com/axboe/fio" 11 | licence: GNU GPL v2.0 12 | -------------------------------------------------------------------------------- /DEDUPE-TODO: -------------------------------------------------------------------------------- 1 | - Shifted dedup-able data. 2 | Allow for dedup buffer generation to shift contents by random number 3 | of sectors (fill the gaps with uncompressible data). Some storage 4 | subsystems modernized the deduplication detection algorithms to look 5 | for shifted data as well. For example, some databases push a timestamp 6 | on the prefix of written blocks, which makes the underlying data 7 | dedup-able in different alignment. FIO should be able to simulate such 8 | workload. 9 | 10 | - Generation of similar data (but not exact). 11 | A rising trend in enterprise storage systems. 12 | Generation of "similar" data means random uncompressible buffers 13 | that differ by few(configurable number of) bits from each other. 14 | The storage subsystem usually identifies the similar buffers using 15 | locality-sensitive hashing or other methods. 16 | 17 | -------------------------------------------------------------------------------- /FIO-VERSION-GEN: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | GVF=FIO-VERSION-FILE 4 | DEF_VER=fio-3.40 5 | 6 | LF=' 7 | ' 8 | 9 | # First see if there is a version file (included in release tarballs), 10 | # then try git-describe, then default. 11 | if test -f version 12 | then 13 | VN=`cat version` || VN="$DEF_VER" 14 | elif test -d .git -o -f .git && 15 | VN=`git describe --match "fio-[0-9]*" --abbrev=4 HEAD 2>/dev/null` && 16 | case "$VN" in 17 | *$LF*) (exit 1) ;; 18 | fio-[0-9]*) 19 | git update-index -q --refresh 20 | test -z "`git diff-index --name-only HEAD --`" || 21 | VN="$VN-dirty" ;; 22 | esac 23 | then 24 | VN=$VN 25 | else 26 | VN="$DEF_VER" 27 | fi 28 | 29 | VN=`expr "$VN" : v*'\(.*\)'` 30 | 31 | if test -r $GVF 32 | then 33 | VC=`sed -e 's/^FIO_VERSION = //' <$GVF` 34 | else 35 | VC=unset 36 | fi 37 | test "$VN" = "$VC" || { 38 | echo >&2 "FIO_VERSION = $VN" 39 | echo "FIO_VERSION = $VN" >$GVF 40 | } 41 | -------------------------------------------------------------------------------- /MORAL-LICENSE: -------------------------------------------------------------------------------- 1 | As specified by the COPYING file, fio is free software published under version 2 | 2 of the GPL license. That covers the copying part of the license. When using 3 | fio, you are encouraged to uphold the following moral obligations: 4 | 5 | - If you publish results that are done using fio, it should be clearly stated 6 | that fio was used. The specific version should also be listed. 7 | 8 | - If you develop features or bug fixes for fio, they should be sent upstream 9 | for inclusion into the main repository. This isn't specific to fio, that 10 | is a general rule for any open source project. It's just the Right Thing 11 | to do. Plus it means that you don't have to maintain the feature or change 12 | internally. In the long run, this is saving you a lot of time. 13 | 14 | I would consider the above to fall under "common courtesy", but since 15 | people tend to have differing opinions of that, it doesn't hurt to spell out 16 | my expectations clearly. 17 | 18 | -------------------------------------------------------------------------------- /SERVER-TODO: -------------------------------------------------------------------------------- 1 | - Collate ETA output from multiple connections into 1 2 | - If group_reporting is set, collate final output from multiple connections 3 | -------------------------------------------------------------------------------- /STEADYSTATE-TODO: -------------------------------------------------------------------------------- 1 | Known issues/TODO (for steady-state) 2 | 3 | - Replace the test script with a better one 4 | - Add test cases for the new check_interval option 5 | - Parse debug=steadystate output to check calculations 6 | 7 | - Instead of calculating `intervals` every time, calculate it once and stash it 8 | somewhere 9 | 10 | - Add the time unit to the ss_dur and check_interval variable names to reduce 11 | possible confusion 12 | 13 | - Better documentation for output 14 | 15 | - Report read, write, trim IOPS/BW separately 16 | 17 | - Semantics for the ring buffer ss->head are confusing. ss->head points 18 | to the beginning of the buffer up through the point where the buffer 19 | is filled for the first time. afterwards, when a new element is added, 20 | ss->head is advanced to point to the second element in the buffer. if 21 | steady state is attained upon adding a new element, ss->head is not 22 | advanced so it actually does point to the head of the buffer. 23 | -------------------------------------------------------------------------------- /arch/arch-alpha.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ALPHA_H 2 | #define ARCH_ALPHA_H 3 | 4 | #define FIO_ARCH (arch_alpha) 5 | 6 | #define nop do { } while (0) 7 | #define read_barrier() __asm__ __volatile__("mb": : :"memory") 8 | #define write_barrier() __asm__ __volatile__("wmb": : :"memory") 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /arch/arch-arm.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM_H 2 | #define ARCH_ARM_H 3 | 4 | #define FIO_ARCH (arch_arm) 5 | 6 | #if defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) \ 7 | || defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5T__) || defined (__ARM_ARCH_5E__)\ 8 | || defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5TEJ__) \ 9 | || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ 10 | || defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_6K__) 11 | #define nop __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t") 12 | #define read_barrier() __asm__ __volatile__ ("" : : : "memory") 13 | #define write_barrier() __asm__ __volatile__ ("" : : : "memory") 14 | #elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7VE__) || defined(__ARM_ARCH_8A__) 15 | #define nop __asm__ __volatile__ ("nop") 16 | #define read_barrier() __sync_synchronize() 17 | #define write_barrier() __sync_synchronize() 18 | #else 19 | #error "unsupported ARM architecture" 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /arch/arch-generic.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_GENERIC_H 2 | #define ARCH_GENERIC_H 3 | 4 | #define FIO_ARCH (arch_generic) 5 | 6 | #define nop do { } while (0) 7 | #define read_barrier() __asm__ __volatile__("": : :"memory") 8 | #define write_barrier() __asm__ __volatile__("": : :"memory") 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /arch/arch-hppa.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_HPPA_H 2 | #define ARCH_HPPA_H 3 | 4 | #define FIO_ARCH (arch_hppa) 5 | 6 | #define nop do { } while (0) 7 | 8 | #define read_barrier() __asm__ __volatile__ ("" : : : "memory") 9 | #define write_barrier() __asm__ __volatile__ ("" : : : "memory") 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /arch/arch-ia64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_IA64_H 2 | #define ARCH_IA64_H 3 | 4 | #define FIO_ARCH (arch_ia64) 5 | 6 | #define nop asm volatile ("hint @pause" ::: "memory"); 7 | #define read_barrier() asm volatile ("mf" ::: "memory") 8 | #define write_barrier() asm volatile ("mf" ::: "memory") 9 | 10 | #define ia64_popcnt(x) \ 11 | ({ \ 12 | unsigned long ia64_intri_res; \ 13 | asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \ 14 | ia64_intri_res; \ 15 | }) 16 | 17 | static inline unsigned long arch_ffz(unsigned long bitmask) 18 | { 19 | return ia64_popcnt(bitmask & (~bitmask - 1)); 20 | } 21 | 22 | static inline unsigned long long get_cpu_clock(void) 23 | { 24 | unsigned long long ret; 25 | 26 | __asm__ __volatile__("mov %0=ar.itc" : "=r" (ret) : : "memory"); 27 | return ret; 28 | } 29 | 30 | #define ARCH_HAVE_INIT 31 | extern bool tsc_reliable; 32 | static inline int arch_init(char *envp[]) 33 | { 34 | tsc_reliable = true; 35 | return 0; 36 | } 37 | 38 | #define ARCH_HAVE_FFZ 39 | #define ARCH_HAVE_CPU_CLOCK 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /arch/arch-loongarch64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_LOONGARCH64_H 2 | #define ARCH_LOONGARCH64_H 3 | 4 | #define FIO_ARCH (arch_loongarch64) 5 | 6 | #define read_barrier() __asm__ __volatile__("dbar 0": : :"memory") 7 | #define write_barrier() __asm__ __volatile__("dbar 0": : :"memory") 8 | #define nop __asm__ __volatile__("dbar 0": : :"memory") 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /arch/arch-mips.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_MIPS64_H 2 | #define ARCH_MIPS64_H 3 | 4 | #define FIO_ARCH (arch_mips) 5 | 6 | #define read_barrier() __asm__ __volatile__("": : :"memory") 7 | #define write_barrier() __asm__ __volatile__("": : :"memory") 8 | #define nop __asm__ __volatile__("": : :"memory") 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /arch/arch-s390.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_S390_H 2 | #define ARCH_S390_H 3 | 4 | #define FIO_ARCH (arch_s390) 5 | 6 | #define nop asm volatile("nop" : : : "memory") 7 | #define read_barrier() asm volatile("bcr 15,0" : : : "memory") 8 | #define write_barrier() asm volatile("bcr 15,0" : : : "memory") 9 | 10 | static inline unsigned long long get_cpu_clock(void) 11 | { 12 | unsigned long long clk; 13 | 14 | #ifdef CONFIG_S390_Z196_FACILITIES 15 | /* 16 | * Fio needs monotonic (never lower), but not strict monotonic (never 17 | * the same) so store clock fast is enough. 18 | */ 19 | __asm__ __volatile__("stckf %0" : "=Q" (clk) : : "cc"); 20 | #else 21 | __asm__ __volatile__("stck %0" : "=Q" (clk) : : "cc"); 22 | #endif 23 | return clk>>12; 24 | } 25 | 26 | #define ARCH_CPU_CLOCK_CYCLES_PER_USEC 1 27 | #define ARCH_HAVE_CPU_CLOCK 28 | #undef ARCH_CPU_CLOCK_WRAPS 29 | 30 | #define ARCH_HAVE_INIT 31 | extern bool tsc_reliable; 32 | static inline int arch_init(char *envp[]) 33 | { 34 | tsc_reliable = true; 35 | return 0; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /arch/arch-sh.h: -------------------------------------------------------------------------------- 1 | /* Renesas SH (32bit) only */ 2 | 3 | #ifndef ARCH_SH_H 4 | #define ARCH_SH_H 5 | 6 | #define FIO_ARCH (arch_sh) 7 | 8 | #define nop __asm__ __volatile__ ("nop": : :"memory") 9 | 10 | #define mb() \ 11 | do { \ 12 | if (arch_flags & ARCH_FLAG_1) \ 13 | __asm__ __volatile__ ("synco": : :"memory"); \ 14 | else \ 15 | __asm__ __volatile__ (" " : : : "memory"); \ 16 | } while (0) 17 | 18 | #define read_barrier() mb() 19 | #define write_barrier() mb() 20 | 21 | #include 22 | #include 23 | 24 | extern unsigned long arch_flags; 25 | 26 | #define CPU_HAS_LLSC 0x0040 27 | 28 | static inline int arch_init(char *envp[]) 29 | { 30 | Elf32_auxv_t *auxv; 31 | 32 | while (*envp++ != NULL) 33 | ; 34 | 35 | for (auxv = (Elf32_auxv_t *) envp; auxv->a_type != AT_NULL; auxv++) { 36 | if (auxv->a_type == AT_HWCAP) { 37 | if (auxv->a_un.a_val & CPU_HAS_LLSC) { 38 | arch_flags |= ARCH_FLAG_1; 39 | break; 40 | } 41 | } 42 | } 43 | 44 | return 0; 45 | } 46 | 47 | #define ARCH_HAVE_INIT 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /arch/arch-sparc.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_SPARC_H 2 | #define ARCH_SPARC_H 3 | 4 | #define FIO_ARCH (arch_sparc) 5 | 6 | #define nop do { } while (0) 7 | 8 | #define read_barrier() __asm__ __volatile__ ("" : : : "memory") 9 | #define write_barrier() __asm__ __volatile__ ("" : : : "memory") 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /arch/arch-sparc64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_SPARC64_H 2 | #define ARCH_SPARC64_H 3 | 4 | #define FIO_ARCH (arch_sparc64) 5 | 6 | #define nop do { } while (0) 7 | 8 | #define membar_safe(type) \ 9 | do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ 10 | " membar " type "\n" \ 11 | "1:\n" \ 12 | : : : "memory"); \ 13 | } while (0) 14 | 15 | #define read_barrier() membar_safe("#LoadLoad") 16 | #define write_barrier() membar_safe("#StoreStore") 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /arch/arch-x86.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_X86_H 2 | #define ARCH_X86_H 3 | 4 | static inline void do_cpuid(unsigned int *eax, unsigned int *ebx, 5 | unsigned int *ecx, unsigned int *edx) 6 | { 7 | asm volatile("xchgl %%ebx, %1\ncpuid\nxchgl %%ebx, %1" 8 | : "=a" (*eax), "=r" (*ebx), "=c" (*ecx), "=d" (*edx) 9 | : "0" (*eax) 10 | : "memory"); 11 | } 12 | 13 | #include "arch-x86-common.h" /* IWYU pragma: export */ 14 | 15 | #define FIO_ARCH (arch_x86) 16 | 17 | #define FIO_HUGE_PAGE 4194304 18 | 19 | #define nop __asm__ __volatile__("rep;nop": : :"memory") 20 | #define read_barrier() __asm__ __volatile__("": : :"memory") 21 | #define write_barrier() __asm__ __volatile__("": : :"memory") 22 | 23 | static inline unsigned long arch_ffz(unsigned long bitmask) 24 | { 25 | __asm__("bsfl %1,%0" :"=r" (bitmask) :"r" (~bitmask)); 26 | return bitmask; 27 | } 28 | 29 | static inline unsigned long long get_cpu_clock(void) 30 | { 31 | unsigned long long ret; 32 | 33 | __asm__ __volatile__("rdtsc" : "=A" (ret)); 34 | return ret; 35 | } 36 | 37 | #define ARCH_HAVE_FFZ 38 | #define ARCH_HAVE_CPU_CLOCK 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /blktrace.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_BLKTRACE_H 2 | #define FIO_BLKTRACE_H 3 | 4 | 5 | #ifdef FIO_HAVE_BLKTRACE 6 | 7 | #include 8 | 9 | #include "blktrace_api.h" 10 | 11 | struct blktrace_cursor { 12 | struct fifo *fifo; // fifo queue for reading 13 | FILE *f; // blktrace file 14 | __u64 length; // length of trace 15 | struct blk_io_trace t; // current io trace 16 | int swap; // bitwise reverse required 17 | int scalar; // scale percentage 18 | int iter; // current iteration 19 | int nr_iter; // number of iterations to run 20 | }; 21 | 22 | bool is_blktrace(const char *, int *); 23 | bool init_blktrace_read(struct thread_data *, const char *, int); 24 | bool read_blktrace(struct thread_data* td); 25 | 26 | int merge_blktrace_iologs(struct thread_data *td); 27 | 28 | #else 29 | 30 | static inline bool is_blktrace(const char *fname, int *need_swap) 31 | { 32 | return false; 33 | } 34 | 35 | static inline bool init_blktrace_read(struct thread_data *td, const char *fname, 36 | int need_swap) 37 | { 38 | return false; 39 | } 40 | 41 | static inline bool read_blktrace(struct thread_data* td) 42 | { 43 | return false; 44 | } 45 | 46 | 47 | static inline int merge_blktrace_iologs(struct thread_data *td) 48 | { 49 | return false; 50 | } 51 | 52 | #endif 53 | #endif 54 | -------------------------------------------------------------------------------- /cairo_text_helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef CAIRO_TEXT_HELPERS_H 2 | #define CAIRO_TEXT_HELPERS_H 3 | 4 | #include 5 | 6 | void draw_centered_text(cairo_t *cr, const char *font, double x, double y, 7 | double fontsize, const char *text); 8 | 9 | void draw_right_justified_text(cairo_t *cr, const char *font, 10 | double x, double y, 11 | double fontsize, const char *text); 12 | 13 | void draw_left_justified_text(cairo_t *cr, const char *font, 14 | double x, double y, 15 | double fontsize, const char *text); 16 | 17 | void draw_vertical_centered_text(cairo_t *cr, const char *font, double x, 18 | double y, double fontsize, 19 | const char *text); 20 | #endif 21 | -------------------------------------------------------------------------------- /cgroup.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_CGROUP_H 2 | #define FIO_CGROUP_H 3 | 4 | #ifdef FIO_HAVE_CGROUPS 5 | 6 | struct cgroup_mnt { 7 | char *path; 8 | bool cgroup2; 9 | }; 10 | 11 | int cgroup_setup(struct thread_data *, struct flist_head *, struct cgroup_mnt **); 12 | void cgroup_shutdown(struct thread_data *, struct cgroup_mnt *); 13 | 14 | void cgroup_kill(struct flist_head *list); 15 | 16 | #else 17 | 18 | struct cgroup_mnt; 19 | 20 | static inline int cgroup_setup(struct thread_data *td, struct flist_head *list, 21 | struct cgroup_mnt **mnt) 22 | { 23 | td_verror(td, EINVAL, "cgroup_setup"); 24 | return 1; 25 | } 26 | 27 | static inline void cgroup_shutdown(struct thread_data *td, struct cgroup_mnt *mnt) 28 | { 29 | } 30 | 31 | static inline void cgroup_kill(struct flist_head *list) 32 | { 33 | } 34 | 35 | #endif 36 | #endif 37 | -------------------------------------------------------------------------------- /ci/actions-smoke-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script expects to be invoked from the base fio directory. 3 | set -eu 4 | 5 | main() { 6 | case "${CI_TARGET_BUILD}" in 7 | android*) 8 | return 0;; 9 | esac 10 | 11 | echo "Running smoke tests..." 12 | make test 13 | } 14 | 15 | main 16 | -------------------------------------------------------------------------------- /ci/common.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | 3 | function set_ci_target_os { 4 | # Function that exports CI_TARGET_OS to the current OS if it is not already 5 | # set. 6 | 7 | # Don't override CI_TARGET_OS if already set 8 | CI_TARGET_OS=${CI_TARGET_OS:-} 9 | if [[ -z ${CI_TARGET_OS} ]]; then 10 | # Detect operating system 11 | case "${OSTYPE}" in 12 | linux*) 13 | CI_TARGET_OS="linux" 14 | ;; 15 | darwin*) 16 | CI_TARGET_OS="macos" 17 | ;; 18 | cygwin|msys*) 19 | CI_TARGET_OS="windows" 20 | ;; 21 | bsd*) 22 | CI_TARGET_OS="bsd" 23 | ;; 24 | *) 25 | CI_TARGET_OS="" 26 | esac 27 | fi 28 | 29 | # Don't override CI_TARGET_ARCH if already set 30 | CI_TARGET_ARCH=${CI_TARGET_ARCH:-} 31 | if [[ -z ${CI_TARGET_ARCH} ]]; then 32 | CI_TARGET_ARCH="$(uname -m)" 33 | fi 34 | } 35 | -------------------------------------------------------------------------------- /crc/crc-t10dif.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef __CRC_T10DIF_H 3 | #define __CRC_T10DIF_H 4 | 5 | extern unsigned short fio_crc_t10dif(unsigned short crc, 6 | const unsigned char *buffer, 7 | unsigned int len); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /crc/crc16.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crc16.h - CRC-16 routine 3 | * 4 | * Implements the standard CRC-16: 5 | * Width 16 6 | * Poly 0x8005 (x^16 + x^15 + x^2 + 1) 7 | * Init 0 8 | * 9 | * Copyright (c) 2005 Ben Gardner 10 | * 11 | * This source code is licensed under the GNU General Public License, 12 | * Version 2. See the file COPYING for more details. 13 | */ 14 | 15 | #ifndef __CRC16_H 16 | #define __CRC16_H 17 | 18 | extern unsigned short const crc16_table[256]; 19 | 20 | extern unsigned short fio_crc16(const void *buffer, unsigned int len); 21 | 22 | static inline unsigned short crc16_byte(unsigned short crc, 23 | const unsigned char data) 24 | { 25 | return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; 26 | } 27 | 28 | #endif /* __CRC16_H */ 29 | -------------------------------------------------------------------------------- /crc/crc32.h: -------------------------------------------------------------------------------- 1 | /* crc32 -- calculate and POSIX.2 checksum 2 | Copyright (C) 92, 1995-1999 Free Software Foundation, Inc. 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2, or (at your option) 7 | any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software Foundation, 16 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 17 | 18 | #ifndef CRC32_H 19 | #define CRC32_H 20 | 21 | #include 22 | 23 | extern uint32_t fio_crc32(const void * const, unsigned long); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /crc/crc64.h: -------------------------------------------------------------------------------- 1 | #ifndef CRC64_H 2 | #define CRC64_H 3 | 4 | unsigned long long fio_crc64(const unsigned char *, unsigned long); 5 | 6 | unsigned long long fio_crc64_nvme(unsigned long long crc, const void *p, 7 | unsigned int len); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /crc/crc7.h: -------------------------------------------------------------------------------- 1 | #ifndef CRC7_H 2 | #define CRC7_H 3 | 4 | extern const unsigned char crc7_syndrome_table[256]; 5 | 6 | static inline unsigned char crc7_byte(unsigned char crc, unsigned char data) 7 | { 8 | return crc7_syndrome_table[(crc << 1) ^ data]; 9 | } 10 | 11 | extern unsigned char fio_crc7(const unsigned char *buffer, unsigned int len); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /crc/fnv.c: -------------------------------------------------------------------------------- 1 | #include "fnv.h" 2 | 3 | #define FNV_PRIME 0x100000001b3ULL 4 | 5 | /* 6 | * 64-bit fnv, but don't require 64-bit multiples of data. Use bytes 7 | * for the last unaligned chunk. 8 | */ 9 | uint64_t fnv(const void *buf, uint32_t len, uint64_t hval) 10 | { 11 | const uint64_t *ptr = buf; 12 | 13 | while (len) { 14 | hval *= FNV_PRIME; 15 | if (len >= sizeof(uint64_t)) { 16 | hval ^= (uint64_t) *ptr++; 17 | len -= sizeof(uint64_t); 18 | continue; 19 | } else { 20 | const uint8_t *ptr8 = (const uint8_t *) ptr; 21 | uint64_t val = 0; 22 | int i; 23 | 24 | for (i = 0; i < len; i++) { 25 | val <<= 8; 26 | val |= (uint8_t) *ptr8++; 27 | } 28 | hval ^= val; 29 | break; 30 | } 31 | } 32 | 33 | return hval; 34 | } 35 | -------------------------------------------------------------------------------- /crc/fnv.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_FNV_H 2 | #define FIO_FNV_H 3 | 4 | #include 5 | 6 | uint64_t fnv(const void *, uint32_t, uint64_t); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /crc/md5.h: -------------------------------------------------------------------------------- 1 | #ifndef MD5_H 2 | #define MD5_H 3 | 4 | #include 5 | 6 | #define MD5_DIGEST_SIZE 16 7 | #define MD5_HMAC_BLOCK_SIZE 64 8 | #define MD5_BLOCK_WORDS 16 9 | #define MD5_HASH_WORDS 4 10 | 11 | #define F1(x, y, z) (z ^ (x & (y ^ z))) 12 | #define F2(x, y, z) F1(z, x, y) 13 | #define F3(x, y, z) (x ^ y ^ z) 14 | #define F4(x, y, z) (y ^ (x | ~z)) 15 | 16 | #define MD5STEP(f, w, x, y, z, in, s) \ 17 | (w += f(x, y, z) + in, w = (w<>(32-s)) + x) 18 | 19 | struct fio_md5_ctx { 20 | uint32_t *hash; 21 | uint32_t block[MD5_BLOCK_WORDS]; 22 | uint64_t byte_count; 23 | }; 24 | 25 | extern void fio_md5_update(struct fio_md5_ctx *, const uint8_t *, unsigned int); 26 | extern void fio_md5_final(struct fio_md5_ctx *); 27 | extern void fio_md5_init(struct fio_md5_ctx *); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /crc/murmur3.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_MURMUR3_H 2 | #define FIO_MURMUR3_H 3 | 4 | #include 5 | 6 | uint32_t murmurhash3(const void *key, uint32_t len, uint32_t seed); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /crc/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_SHA1 2 | #define FIO_SHA1 3 | 4 | #include 5 | 6 | /* 7 | * Based on the Mozilla SHA1 (see mozilla-sha1/sha1.h), 8 | * optimized to do word accesses rather than byte accesses, 9 | * and to avoid unnecessary copies into the context array. 10 | */ 11 | 12 | struct fio_sha1_ctx { 13 | uint32_t *H; 14 | unsigned int W[16]; 15 | unsigned long long size; 16 | }; 17 | 18 | void fio_sha1_init(struct fio_sha1_ctx *); 19 | void fio_sha1_update(struct fio_sha1_ctx *, const void *dataIn, unsigned long len); 20 | void fio_sha1_final(struct fio_sha1_ctx *); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /crc/sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_SHA256_H 2 | #define FIO_SHA256_H 3 | 4 | #include 5 | 6 | #define SHA256_DIGEST_SIZE 32 7 | #define SHA256_BLOCK_SIZE 64 8 | 9 | struct fio_sha256_ctx { 10 | uint32_t count; 11 | uint32_t state[SHA256_DIGEST_SIZE / 4]; 12 | uint8_t *buf; 13 | }; 14 | 15 | void fio_sha256_init(struct fio_sha256_ctx *); 16 | void fio_sha256_update(struct fio_sha256_ctx *, const uint8_t *, unsigned int); 17 | void fio_sha256_final(struct fio_sha256_ctx *); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /crc/sha3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Common values for SHA-3 algorithms 3 | */ 4 | #ifndef __CRYPTO_SHA3_H__ 5 | #define __CRYPTO_SHA3_H__ 6 | 7 | #include 8 | 9 | #define SHA3_224_DIGEST_SIZE (224 / 8) 10 | #define SHA3_224_BLOCK_SIZE (200 - 2 * SHA3_224_DIGEST_SIZE) 11 | 12 | #define SHA3_256_DIGEST_SIZE (256 / 8) 13 | #define SHA3_256_BLOCK_SIZE (200 - 2 * SHA3_256_DIGEST_SIZE) 14 | 15 | #define SHA3_384_DIGEST_SIZE (384 / 8) 16 | #define SHA3_384_BLOCK_SIZE (200 - 2 * SHA3_384_DIGEST_SIZE) 17 | 18 | #define SHA3_512_DIGEST_SIZE (512 / 8) 19 | #define SHA3_512_BLOCK_SIZE (200 - 2 * SHA3_512_DIGEST_SIZE) 20 | 21 | struct fio_sha3_ctx { 22 | uint64_t st[25]; 23 | unsigned int md_len; 24 | unsigned int rsiz; 25 | unsigned int rsizw; 26 | 27 | unsigned int partial; 28 | uint8_t buf[SHA3_224_BLOCK_SIZE]; 29 | 30 | uint8_t *sha; 31 | }; 32 | 33 | void fio_sha3_224_init(struct fio_sha3_ctx *sctx); 34 | void fio_sha3_256_init(struct fio_sha3_ctx *sctx); 35 | void fio_sha3_384_init(struct fio_sha3_ctx *sctx); 36 | void fio_sha3_512_init(struct fio_sha3_ctx *sctx); 37 | 38 | int fio_sha3_update(struct fio_sha3_ctx *sctx, const uint8_t *data, 39 | unsigned int len); 40 | void fio_sha3_final(struct fio_sha3_ctx *sctx); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /crc/sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_SHA512_H 2 | #define FIO_SHA512_H 3 | 4 | #include 5 | 6 | struct fio_sha512_ctx { 7 | uint64_t state[8]; 8 | uint32_t count[4]; 9 | uint8_t *buf; 10 | uint64_t W[80]; 11 | }; 12 | 13 | void fio_sha512_init(struct fio_sha512_ctx *); 14 | void fio_sha512_update(struct fio_sha512_ctx *, const uint8_t *, unsigned int); 15 | void fio_sha512_final(struct fio_sha512_ctx *sctx); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /crc/test.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_CRC_TEST_H 2 | #define FIO_CRC_TEST_H 3 | 4 | int fio_crctest(const char *type); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /dataplacement.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_DATAPLACEMENT_H 2 | #define FIO_DATAPLACEMENT_H 3 | 4 | #include "io_u.h" 5 | 6 | #define STREAMS_DIR_DTYPE 1 7 | #define FDP_DIR_DTYPE 2 8 | #define FIO_MAX_DP_IDS 128 9 | #define DP_MAX_SCHEME_ENTRIES 32 10 | 11 | /* 12 | * How fio chooses what placement identifier to use next. Choice of 13 | * uniformly random, or roundrobin. 14 | */ 15 | enum { 16 | FIO_DP_RANDOM = 0x1, 17 | FIO_DP_RR = 0x2, 18 | FIO_DP_SCHEME = 0x3, 19 | }; 20 | 21 | enum { 22 | FIO_DP_NONE = 0x0, 23 | FIO_DP_FDP = 0x1, 24 | FIO_DP_STREAMS = 0x2, 25 | }; 26 | 27 | struct fio_ruhs_info { 28 | uint32_t nr_ruhs; 29 | uint32_t pli_loc; 30 | uint16_t plis[]; 31 | }; 32 | 33 | struct fio_ruhs_scheme_entry { 34 | unsigned long long start_offset; 35 | unsigned long long end_offset; 36 | uint16_t pli; 37 | }; 38 | 39 | struct fio_ruhs_scheme { 40 | uint16_t nr_schemes; 41 | struct fio_ruhs_scheme_entry scheme_entries[DP_MAX_SCHEME_ENTRIES]; 42 | }; 43 | 44 | int dp_init(struct thread_data *td); 45 | void fdp_free_ruhs_info(struct fio_file *f); 46 | void dp_fill_dspec_data(struct thread_data *td, struct io_u *io_u); 47 | 48 | #endif /* FIO_DATAPLACEMENT_H */ 49 | -------------------------------------------------------------------------------- /debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "debug.h" 5 | #include "log.h" 6 | 7 | #ifdef FIO_INC_DEBUG 8 | void __dprint(int type, const char *str, ...) 9 | { 10 | va_list args; 11 | 12 | assert(type < FD_DEBUG_MAX); 13 | 14 | va_start(args, str); 15 | log_prevalist(type, str, args); 16 | va_end(args); 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /dedupe.h: -------------------------------------------------------------------------------- 1 | #ifndef DEDUPE_H 2 | #define DEDUPE_H 3 | 4 | int init_dedupe_working_set_seeds(struct thread_data *td, bool global_dedupe); 5 | int init_global_dedupe_working_set_seeds(void); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /doc/fio-histo-log-pctiles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/doc/fio-histo-log-pctiles.pdf -------------------------------------------------------------------------------- /doc/fio_doc.rst: -------------------------------------------------------------------------------- 1 | fio - Flexible I/O tester rev. |version| 2 | ======================================== 3 | 4 | 5 | .. include:: ../README.rst 6 | 7 | 8 | .. include:: ../HOWTO.rst 9 | 10 | .. only:: not man 11 | 12 | Examples 13 | ======== 14 | 15 | .. include:: fio_examples.rst 16 | 17 | 18 | 19 | TODO 20 | ==== 21 | 22 | 23 | GFIO TODO 24 | --------- 25 | 26 | .. include:: ../GFIO-TODO 27 | 28 | 29 | Server TODO 30 | ----------- 31 | 32 | .. include:: ../SERVER-TODO 33 | 34 | 35 | Steady State TODO 36 | ----------------- 37 | 38 | .. include:: ../STEADYSTATE-TODO 39 | 40 | 41 | 42 | Moral License 43 | ============= 44 | 45 | .. include:: ../MORAL-LICENSE 46 | 47 | 48 | License 49 | ======= 50 | 51 | .. literalinclude:: ../COPYING 52 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. FIO documentation master file, created by 2 | sphinx-quickstart on Thu Mar 20 16:24:25 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to FIO's documentation! 7 | =============================== 8 | 9 | **Version:** |release| 10 | 11 | Contents: 12 | 13 | .. toctree:: 14 | :maxdepth: 3 15 | :numbered: 16 | 17 | fio - Flexible I/O tester |version| 18 | 19 | 20 | Indices and tables 21 | ================== 22 | 23 | * :ref:`genindex` 24 | * :ref:`search` 25 | 26 | -------------------------------------------------------------------------------- /engines/ftruncate.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ftruncate: ioengine for git://git.kernel.dk/fio.git 3 | * 4 | * IO engine that does regular truncates to simulate data transfer 5 | * as fio ioengine. 6 | * DDIR_WRITE does ftruncate 7 | * 8 | */ 9 | #include 10 | #include 11 | 12 | #include "../fio.h" 13 | 14 | static enum fio_q_status fio_ftruncate_queue(struct thread_data *td, 15 | struct io_u *io_u) 16 | { 17 | struct fio_file *f = io_u->file; 18 | int ret; 19 | 20 | fio_ro_check(td, io_u); 21 | 22 | if (io_u->ddir != DDIR_WRITE) { 23 | io_u->error = EINVAL; 24 | return FIO_Q_COMPLETED; 25 | } 26 | 27 | ret = ftruncate(f->fd, io_u->offset); 28 | if (ret) 29 | io_u->error = errno; 30 | 31 | return FIO_Q_COMPLETED; 32 | } 33 | 34 | static struct ioengine_ops ioengine = { 35 | .name = "ftruncate", 36 | .version = FIO_IOOPS_VERSION, 37 | .queue = fio_ftruncate_queue, 38 | .open_file = generic_open_file, 39 | .close_file = generic_close_file, 40 | .get_file_size = generic_get_file_size, 41 | .flags = FIO_SYNCIO | FIO_FAKEIO 42 | }; 43 | 44 | static void fio_init fio_syncio_register(void) 45 | { 46 | register_ioengine(&ioengine); 47 | } 48 | 49 | static void fio_exit fio_syncio_unregister(void) 50 | { 51 | unregister_ioengine(&ioengine); 52 | } 53 | -------------------------------------------------------------------------------- /engines/gfapi.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../fio.h" 3 | 4 | struct gf_options { 5 | void *pad; 6 | char *gf_vol; 7 | char *gf_brick; 8 | int gf_single_instance; 9 | }; 10 | 11 | struct gf_data { 12 | glfs_t *fs; 13 | glfs_fd_t *fd; 14 | struct io_u **aio_events; 15 | }; 16 | 17 | extern struct fio_option gfapi_options[]; 18 | extern int fio_gf_setup(struct thread_data *td); 19 | extern void fio_gf_cleanup(struct thread_data *td); 20 | extern int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f); 21 | extern int fio_gf_open_file(struct thread_data *td, struct fio_file *f); 22 | extern int fio_gf_close_file(struct thread_data *td, struct fio_file *f); 23 | extern int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f); 24 | -------------------------------------------------------------------------------- /err.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_ERR_H 2 | #define FIO_ERR_H 3 | 4 | /* 5 | * Kernel pointers have redundant information, so we can use a 6 | * scheme where we can return either an error code or a dentry 7 | * pointer with the same return value. 8 | * 9 | * This should be a per-architecture thing, to allow different 10 | * error and pointer decisions. 11 | */ 12 | #define MAX_ERRNO 4095 13 | 14 | #define IS_ERR_VALUE(x) ((x) >= (uintptr_t)-MAX_ERRNO) 15 | 16 | static inline void *ERR_PTR(uintptr_t error) 17 | { 18 | return (void *) error; 19 | } 20 | 21 | static inline uintptr_t PTR_ERR(const void *ptr) 22 | { 23 | return (uintptr_t) ptr; 24 | } 25 | 26 | static inline uintptr_t IS_ERR(const void *ptr) 27 | { 28 | return IS_ERR_VALUE((uintptr_t)ptr); 29 | } 30 | 31 | static inline uintptr_t IS_ERR_OR_NULL(const void *ptr) 32 | { 33 | return !ptr || IS_ERR_VALUE((uintptr_t)ptr); 34 | } 35 | 36 | static inline int PTR_ERR_OR_ZERO(const void *ptr) 37 | { 38 | if (IS_ERR(ptr)) 39 | return PTR_ERR(ptr); 40 | else 41 | return 0; 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /examples/1mbs_clients.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/1mbs_clients.png -------------------------------------------------------------------------------- /examples/aio-read.fio: -------------------------------------------------------------------------------- 1 | ; Read 4 files with aio at different depths 2 | [global] 3 | ioengine=libaio 4 | buffered=0 5 | rw=randread 6 | bs=128k 7 | size=512m 8 | directory=/data1 9 | 10 | [file1] 11 | iodepth=4 12 | 13 | [file2] 14 | iodepth=32 15 | 16 | [file3] 17 | iodepth=8 18 | 19 | [file4] 20 | iodepth=16 21 | -------------------------------------------------------------------------------- /examples/aio-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/aio-read.png -------------------------------------------------------------------------------- /examples/backwards-read.fio: -------------------------------------------------------------------------------- 1 | # Demonstrates how to read backwards in a file. 2 | 3 | [backwards-read] 4 | bs=4k 5 | # seek -8k back for every IO 6 | rw=read:-8k 7 | filename=128m 8 | size=128m 9 | -------------------------------------------------------------------------------- /examples/backwards-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/backwards-read.png -------------------------------------------------------------------------------- /examples/basic-verify.fio: -------------------------------------------------------------------------------- 1 | # The most basic form of data verification. Write the device randomly 2 | # in 4K chunks, then read it back and verify the contents. 3 | [write-and-verify] 4 | rw=randwrite 5 | bs=4k 6 | direct=1 7 | ioengine=libaio 8 | iodepth=16 9 | verify=crc32c 10 | # Use /dev/XXX. For running this on a file instead, remove the filename 11 | # option and add a size=32G (or whatever file size you want) instead. 12 | filename=/dev/XXX 13 | -------------------------------------------------------------------------------- /examples/basic-verify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/basic-verify.png -------------------------------------------------------------------------------- /examples/butterfly.fio: -------------------------------------------------------------------------------- 1 | # Perform a butterfly/funnel seek pattern. This won't always alternate ends on 2 | # every I/O but it will get close. 3 | 4 | [global] 5 | filename=/tmp/testfile 6 | bs=4k 7 | direct=1 8 | 9 | [forward] 10 | rw=read 11 | flow=2 12 | # Uncomment the size= and offset= lines to prevent each direction going past 13 | # the middle of the file 14 | #size=50% 15 | 16 | [backward] 17 | rw=read:-8k 18 | flow=2 19 | #offset=50% 20 | -------------------------------------------------------------------------------- /examples/butterfly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/butterfly.png -------------------------------------------------------------------------------- /examples/cmdprio-bssplit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/cmdprio-bssplit.png -------------------------------------------------------------------------------- /examples/cmdprio-percentage.fio: -------------------------------------------------------------------------------- 1 | ; Read a block device file at queue depth 8 2 | ; with 20 % of the IOs using the high priority RT class 3 | ; and the remaining IOs using the idle priority class 4 | [global] 5 | filename=/dev/sda 6 | direct=1 7 | write_lat_log=prio-run.log 8 | log_prio=1 9 | 10 | [randread] 11 | rw=randread 12 | bs=128k 13 | ioengine=libaio 14 | iodepth=8 15 | prioclass=3 16 | cmdprio_percentage=20 17 | cmdprio_class=1 18 | -------------------------------------------------------------------------------- /examples/cmdprio-percentage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/cmdprio-percentage.png -------------------------------------------------------------------------------- /examples/cpp_null.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | bs=4k 3 | gtod_reduce=1 4 | 5 | [null] 6 | ioengine=cpp_null 7 | size=100g 8 | rw=randread 9 | norandommap 10 | time_based 11 | -------------------------------------------------------------------------------- /examples/cpp_null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/cpp_null.png -------------------------------------------------------------------------------- /examples/cpuio.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=cpuio 3 | time_based 4 | runtime=15 5 | 6 | # The following example load 2 cores at 50% with the noop (default) mode 7 | [burn_2x50_noop] 8 | cpuload=50 9 | numjobs=2 10 | cpumode=noop 11 | 12 | # Once burn_2x50_noop is over, 13 | # fio load 2 cores at 50% with the qsort mode which drains much more power 14 | [burn_2x50%_qsort] 15 | stonewall 16 | cpuload=50 17 | numjobs=2 18 | cpumode=qsort 19 | -------------------------------------------------------------------------------- /examples/cpuio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/cpuio.png -------------------------------------------------------------------------------- /examples/cross-stripe-verify.fio: -------------------------------------------------------------------------------- 1 | # Example of how to split a drive up into sections, manually, and perform 2 | # verify from a bunch of jobs. This example is special in that it assumes 3 | # the drive is at around 30 * 124G in size, so with the below settings, we'll 4 | # cover most of the drive. It's also special in that it doesn't write 5 | # everything, it just writes 16k at a specific boundary, for every 128k. 6 | # This is done to exercise the split path for Intel NVMe devices, most of 7 | # which have a 128k stripe size and require IOs to be split if the cross 8 | # the stripe boundary. 9 | # 10 | [global] 11 | bs=16k 12 | direct=1 13 | rw=write:112k 14 | verify=crc32c 15 | filename=/dev/nvme0n1 16 | verify_backlog=1 17 | offset_increment=124g 18 | io_size=120g 19 | offset=120k 20 | group_reporting 21 | verify_dump=1 22 | loops=2 23 | 24 | [write-verify] 25 | numjobs=30 26 | -------------------------------------------------------------------------------- /examples/cross-stripe-verify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/cross-stripe-verify.png -------------------------------------------------------------------------------- /examples/dedupe-global.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/dedupe-global.png -------------------------------------------------------------------------------- /examples/dev-dax.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | bs=2m 3 | ioengine=dev-dax 4 | norandommap 5 | time_based 6 | runtime=30 7 | group_reporting 8 | disable_lat=1 9 | disable_slat=1 10 | disable_clat=1 11 | clat_percentiles=0 12 | cpus_allowed_policy=split 13 | 14 | # For the dev-dax engine: 15 | # 16 | # IOs always complete immediately 17 | # IOs are always direct 18 | # 19 | iodepth=1 20 | direct=0 21 | thread 22 | numjobs=16 23 | # 24 | # The dev-dax engine does IO to DAX device that are special character 25 | # devices exported by the kernel (e.g. /dev/dax0.0). The device is 26 | # opened normally and then the region is accessible via mmap. We do 27 | # not use the O_DIRECT flag because the device is naturally direct 28 | # access. The O_DIRECT flags will result in failure. The engine 29 | # access the underlying NVDIMM directly once the mmapping is setup. 30 | # 31 | # Check the alignment requirement of your DAX device. Currently the default 32 | # should be 2M. Blocksize (bs) should meet alignment requirement. 33 | # 34 | # An example of creating a dev dax device node from pmem: 35 | # ndctl create-namespace --reconfig=namespace0.0 --mode=dax --force 36 | # 37 | filename=/dev/dax0.0 38 | 39 | [dev-dax-write] 40 | rw=randwrite 41 | stonewall 42 | 43 | [dev-dax-read] 44 | rw=randread 45 | stonewall 46 | -------------------------------------------------------------------------------- /examples/dev-dax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/dev-dax.png -------------------------------------------------------------------------------- /examples/dfs.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=dfs 3 | pool=${POOL} 4 | cont=${CONT} 5 | filename_format=fio-test.$jobnum 6 | 7 | cpus_allowed_policy=split 8 | group_reporting=1 9 | time_based=0 10 | percentile_list=99.0:99.9:99.99:99.999:99.9999:100 11 | disable_slat=1 12 | disable_clat=1 13 | 14 | bs=1M 15 | size=100G 16 | iodepth=16 17 | numjobs=16 18 | 19 | [daos-seqwrite] 20 | rw=write 21 | stonewall 22 | 23 | [daos-seqread] 24 | rw=read 25 | stonewall 26 | 27 | [daos-randwrite] 28 | rw=randwrite 29 | stonewall 30 | 31 | [daos-randread] 32 | rw=randread 33 | stonewall 34 | -------------------------------------------------------------------------------- /examples/dfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/dfs.png -------------------------------------------------------------------------------- /examples/dircreate-ioengine.fio: -------------------------------------------------------------------------------- 1 | # Example dircreate job 2 | # 3 | # create_on_open is needed so that the open happens during the run and not the 4 | # setup. 5 | # 6 | # openfiles needs to be set so that you do not exceed the maximum allowed open 7 | # files. 8 | # 9 | # filesize needs to be set to a non zero value so fio will actually run, but the 10 | # IO will not really be done and the write latency numbers will only reflect the 11 | # open times. 12 | [global] 13 | create_on_open=1 14 | nrfiles=30 15 | ioengine=dircreate 16 | fallocate=none 17 | filesize=4k 18 | openfiles=1 19 | 20 | [t0] 21 | [t1] 22 | [t2] 23 | [t3] 24 | [t4] 25 | [t5] 26 | -------------------------------------------------------------------------------- /examples/dircreate-ioengine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/dircreate-ioengine.png -------------------------------------------------------------------------------- /examples/dirdelete-ioengine.fio: -------------------------------------------------------------------------------- 1 | # Example dirdelete job 2 | 3 | # 'filedelete' engine only do 'rmdir(dirname)'. 4 | # 'filesize' must be set, then directories will be created at setup stage. 5 | # 'unlink' is better set to 0, since the directory is deleted in measurement. 6 | # the options disabled completion latency output such as 'disable_clat' and 'gtod_reduce' must not set. 7 | [global] 8 | ioengine=dirdelete 9 | filesize=4k 10 | nrfiles=200 11 | unlink=0 12 | 13 | [t0] 14 | [t1] 15 | [t2] 16 | [t3] 17 | [t4] 18 | [t5] 19 | -------------------------------------------------------------------------------- /examples/dirdelete-ioengine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/dirdelete-ioengine.png -------------------------------------------------------------------------------- /examples/dirstat-ioengine.fio: -------------------------------------------------------------------------------- 1 | # Example dirstat job 2 | 3 | # 'dirstat' engine only do 'stat(dirname)', file will not be open(). 4 | # 'filesize' must be set, then files will be created at setup stage. 5 | 6 | [global] 7 | ioengine=dirstat 8 | numjobs=10 9 | filesize=4k 10 | nrfiles=5 11 | thread 12 | 13 | [t0] 14 | [t1] 15 | [t2] 16 | [t3] 17 | [t4] 18 | [t5] 19 | -------------------------------------------------------------------------------- /examples/dirstat-ioengine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/dirstat-ioengine.png -------------------------------------------------------------------------------- /examples/disk-zone-profile.fio: -------------------------------------------------------------------------------- 1 | ; Read disk in zones of 256m/2g. Generating a plot of that afterwards 2 | ; should give a nice picture of the zoning of this drive 3 | 4 | [global] 5 | bs=64k 6 | direct=1 7 | rw=read 8 | ioengine=libaio 9 | iodepth=2 10 | zonemode=strided 11 | zonesize=256m 12 | zoneskip=2g 13 | 14 | [disk-zone-profile] 15 | filename=/dev/sdb 16 | write_bw_log 17 | log_offset=1 18 | -------------------------------------------------------------------------------- /examples/disk-zone-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/disk-zone-profile.png -------------------------------------------------------------------------------- /examples/e4defrag.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=e4defrag 3 | directory=/scratch 4 | nrfiles=1 5 | filesize=100M 6 | size=100M 7 | bs=32k 8 | #group_reporting 9 | 10 | [isolated-e4defrag] 11 | # It is important to disable buffered io 12 | buffered=0 13 | donorname=file.def 14 | filename=file1 15 | inplace=0 16 | rw=write 17 | 18 | # Run e4defrag and aio-dio workers in parallel 19 | [e4defrag] 20 | stonewall 21 | time_based 22 | runtime=30 23 | ioengine=e4defrag 24 | buffered=0 25 | donorname=file.def 26 | filename=file1 27 | inplace=0 28 | rw=write 29 | 30 | [random-aio-32k] 31 | ioengine=libaio 32 | runtime=30 33 | verify=md5 34 | direct=1 35 | bs=64k 36 | iodepth=128 37 | filename=file1 38 | rw=randrw 39 | numjobs=4 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/e4defrag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/e4defrag.png -------------------------------------------------------------------------------- /examples/e4defrag2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/e4defrag2.png -------------------------------------------------------------------------------- /examples/enospc-pressure.fio: -------------------------------------------------------------------------------- 1 | # 2 | # Test for race-condition DIO-write vs punch_hole 3 | # If race exist dio may rewrite punched block after 4 | # it was allocated to another file, we will catch that 5 | # by verifying blocks content 6 | # 7 | [global] 8 | ioengine=libaio 9 | directory=/scratch 10 | # File size is reasonably huge to provoke ENOSPC 11 | filesize=128G 12 | size=999G 13 | iodepth=128 14 | 15 | # Expect write failure due to ENOSPC, skip error dump 16 | continue_on_error=write 17 | ignore_error=,ENOSPC 18 | error_dump=0 19 | fallocate=none 20 | exitall 21 | 22 | # Two threads (dio and punch_hole) operate on single file:'raicer', 23 | # We do not care about data content here 24 | [dio-raicer] 25 | bs=128k 26 | direct=1 27 | buffered=0 28 | rw=randwrite 29 | runtime=100 30 | filename=raicer 31 | time_based 32 | 33 | [punch_hole-raicer] 34 | bs=4k 35 | rw=randtrim 36 | filename=raicer 37 | 38 | # Verifier thread continuously writes to newly allcated blocks 39 | # and verifies written content 40 | [aio-dio-verifier] 41 | create_on_open=1 42 | verify=crc32c-intel 43 | verify_fatal=1 44 | verify_dump=1 45 | verify_backlog=1024 46 | verify_async=4 47 | direct=1 48 | # block size should be equals to fs block size to prevent short writes 49 | bs=4k 50 | rw=randrw 51 | filename=aio-dio-verifier 52 | -------------------------------------------------------------------------------- /examples/enospc-pressure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/enospc-pressure.png -------------------------------------------------------------------------------- /examples/exec.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | time_based 3 | runtime=30 4 | 5 | [monitoring_noop] 6 | ioengine=exec 7 | program=/usr/sbin/turbostat 8 | arguments=-c package -qS --interval 5 -s Busy%,Bzy_MHz,Avg_MHz,CorWatt,PkgWatt,RAMWatt,PkgTmp 9 | 10 | [cpuload_noop] 11 | ioengine=cpuio 12 | cpuload=100 13 | numjobs=12 14 | cpumode=noop 15 | 16 | [sleep] 17 | # Let the processor cooling down for a few seconds 18 | stonewall 19 | ioengine=exec 20 | runtime=10 21 | program=/bin/sleep 22 | arguments=%r 23 | grace_time=0 24 | std_redirect=0 25 | 26 | [monitoring_qsort] 27 | stonewall 28 | ioengine=exec 29 | program=/usr/sbin/turbostat 30 | arguments=-c package -qS --interval 5 -s Busy%,Bzy_MHz,Avg_MHz,CorWatt,PkgWatt,RAMWatt,PkgTmp 31 | 32 | [cpuload_qsort] 33 | ioengine=cpuio 34 | cpuload=100 35 | numjobs=12 36 | cpumode=qsort 37 | -------------------------------------------------------------------------------- /examples/exec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/exec.png -------------------------------------------------------------------------------- /examples/exitwhat.fio: -------------------------------------------------------------------------------- 1 | # We want to run fast1 as long as slow1 is running, but also have a cumulative 2 | # report of fast1 (group_reporting=1/new_group=1). exitall=1 would not cause 3 | # fast1 to stop after slow1 is done. Setting exit_what=stonewall will cause 4 | # alls jobs up until the next stonewall setting to be stopped, when job slow1 5 | # finishes. 6 | # In this example skipping forward to slow2/fast2. slow2 has exit_what=all set, 7 | # which means all jobs will be cancelled when slow2 finishes. In particular, 8 | # runsnever will never run. 9 | 10 | [global] 11 | filename=/tmp/test 12 | filesize=1G 13 | blocksize=4096 14 | group_reporting 15 | exitall=1 16 | 17 | [slow1] 18 | rw=read 19 | numjobs=1 20 | ioengine=sync 21 | new_group=1 22 | thinktime=2000 23 | number_ios=1000 24 | exit_what=stonewall 25 | 26 | [fast1] 27 | new_group=1 28 | rw=randrw 29 | numjobs=3 30 | ioengine=libaio 31 | iodepth=32 32 | rate=300,300,300 33 | 34 | [slow2] 35 | stonewall 36 | rw=write 37 | numjobs=1 38 | ioengine=sync 39 | new_group=1 40 | thinktime=2000 41 | number_ios=1000 42 | exit_what=all 43 | 44 | [fast2] 45 | rw=randrw 46 | numjobs=3 47 | ioengine=libaio 48 | iodepth=32 49 | rate=300,300,300 50 | 51 | [runsnever] 52 | rw=randrw 53 | numjobs=3 54 | ioengine=libaio 55 | iodepth=32 56 | rate=300,300,300 57 | -------------------------------------------------------------------------------- /examples/exitwhat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/exitwhat.png -------------------------------------------------------------------------------- /examples/falloc.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=falloc 3 | iodepth=1 4 | direct=0 5 | buffered=0 6 | directory=/scratch 7 | nrfiles=1 8 | size=100M 9 | filesize=100M 10 | group_reporting 11 | 12 | 13 | # Run falloc and punch_hole threads in parallel 14 | # After activity file will be highly fragmented 15 | [falloc-fuzzer] 16 | stonewall 17 | runtime=10 18 | time_based 19 | bssplit=4k/10:64k/50:32k/40 20 | rw=randwrite 21 | numjobs=1 22 | filename=fragmented_file 23 | 24 | [punch hole-fuzzer] 25 | bs=4k 26 | runtime=10 27 | time_based 28 | rw=randtrim 29 | numjobs=2 30 | filename=fragmented_file 31 | 32 | ## Measure IO performance on fragmented file 33 | [sequential aio-dio write] 34 | stonewall 35 | ioengine=libaio 36 | numjobs=1 37 | iodepth=128 38 | buffered=0 39 | direct=1 40 | rw=write 41 | bs=64k 42 | filename=fragmented_file 43 | 44 | [sequential buffered read] 45 | stonewall 46 | ioengine=sync 47 | numjobs=1 48 | iodepth=1 49 | buffered=1 50 | direct=0 51 | rw=read 52 | bs=64k 53 | filename=fragmented_file 54 | 55 | -------------------------------------------------------------------------------- /examples/falloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/falloc.png -------------------------------------------------------------------------------- /examples/filecreate-ioengine.fio: -------------------------------------------------------------------------------- 1 | # Example filecreate job 2 | # 3 | # create_on_open is needed so that the open happens during the run and not the 4 | # setup. 5 | # 6 | # openfiles needs to be set so that you do not exceed the maximum allowed open 7 | # files. 8 | # 9 | # filesize needs to be set to a non zero value so fio will actually run, but the 10 | # IO will not really be done and the write latency numbers will only reflect the 11 | # open times. 12 | [global] 13 | create_on_open=1 14 | nrfiles=31250 15 | ioengine=filecreate 16 | fallocate=none 17 | filesize=4k 18 | openfiles=1 19 | 20 | [t0] 21 | [t1] 22 | [t2] 23 | [t3] 24 | [t4] 25 | [t5] 26 | [t6] 27 | [t7] 28 | [t8] 29 | [t9] 30 | [t10] 31 | [t11] 32 | [t12] 33 | [t13] 34 | [t14] 35 | [t15] 36 | -------------------------------------------------------------------------------- /examples/filecreate-ioengine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/filecreate-ioengine.png -------------------------------------------------------------------------------- /examples/filedelete-ioengine.fio: -------------------------------------------------------------------------------- 1 | # Example filedelete job 2 | 3 | # 'filedelete' engine only do 'unlink(filename)', file will not be open(). 4 | # 'filesize' must be set, then files will be created at setup stage. 5 | # 'unlink' is better set to 0, since the file is deleted in measurement. 6 | # the options disabled completion latency output such as 'disable_clat' and 'gtod_reduce' must not set. 7 | [global] 8 | ioengine=filedelete 9 | filesize=4k 10 | nrfiles=200 11 | unlink=0 12 | 13 | [t0] 14 | [t1] 15 | [t2] 16 | [t3] 17 | [t4] 18 | [t5] 19 | -------------------------------------------------------------------------------- /examples/filedelete-ioengine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/filedelete-ioengine.png -------------------------------------------------------------------------------- /examples/filestat-ioengine.fio: -------------------------------------------------------------------------------- 1 | # Example filestat job 2 | 3 | # 'filestat' engine only do 'stat(filename)', file will not be open(). 4 | # 'filesize' must be set, then files will be created at setup stage. 5 | 6 | [global] 7 | ioengine=filestat 8 | numjobs=1 9 | filesize=4k 10 | nrfiles=200 11 | thread 12 | 13 | [t0] 14 | [t1] 15 | [t2] 16 | [t3] 17 | [t4] 18 | [t5] 19 | 20 | -------------------------------------------------------------------------------- /examples/filestat-ioengine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/filestat-ioengine.png -------------------------------------------------------------------------------- /examples/fio-rand-RW.fio: -------------------------------------------------------------------------------- 1 | ; fio-rand-RW.job for fiotest 2 | 3 | [global] 4 | name=fio-rand-RW 5 | filename=fio-rand-RW 6 | rw=randrw 7 | rwmixread=60 8 | rwmixwrite=40 9 | bs=4K 10 | direct=0 11 | numjobs=4 12 | time_based 13 | runtime=900 14 | 15 | [file1] 16 | size=10G 17 | ioengine=libaio 18 | iodepth=16 19 | -------------------------------------------------------------------------------- /examples/fio-rand-RW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fio-rand-RW.png -------------------------------------------------------------------------------- /examples/fio-rand-read.fio: -------------------------------------------------------------------------------- 1 | ; fio-rand-read.job for fiotest 2 | 3 | [global] 4 | name=fio-rand-read 5 | filename=fio-rand-read 6 | rw=randread 7 | bs=4K 8 | direct=0 9 | numjobs=1 10 | time_based 11 | runtime=900 12 | 13 | [file1] 14 | size=10G 15 | ioengine=libaio 16 | iodepth=16 17 | -------------------------------------------------------------------------------- /examples/fio-rand-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fio-rand-read.png -------------------------------------------------------------------------------- /examples/fio-rand-write.fio: -------------------------------------------------------------------------------- 1 | ; fio-rand-write.job for fiotest 2 | 3 | [global] 4 | name=fio-rand-write 5 | filename=fio-rand-write 6 | rw=randwrite 7 | bs=4K 8 | direct=0 9 | numjobs=4 10 | time_based 11 | runtime=900 12 | 13 | [file1] 14 | size=10G 15 | ioengine=libaio 16 | iodepth=16 17 | -------------------------------------------------------------------------------- /examples/fio-rand-write.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fio-rand-write.png -------------------------------------------------------------------------------- /examples/fio-seq-RW.fio: -------------------------------------------------------------------------------- 1 | ; fio-seq-RW.job for fiotest 2 | 3 | [global] 4 | name=fio-seq-RW 5 | filename=fio-seq-RW 6 | rw=rw 7 | rwmixread=60 8 | rwmixwrite=40 9 | bs=256K 10 | direct=0 11 | numjobs=4 12 | time_based 13 | runtime=900 14 | 15 | [file1] 16 | size=10G 17 | ioengine=libaio 18 | iodepth=16 19 | -------------------------------------------------------------------------------- /examples/fio-seq-RW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fio-seq-RW.png -------------------------------------------------------------------------------- /examples/fio-seq-read.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | name=fio-seq-reads 3 | filename=fio-seq-reads 4 | rw=read 5 | bs=256K 6 | direct=1 7 | numjobs=1 8 | time_based 9 | runtime=900 10 | 11 | [file1] 12 | size=10G 13 | ioengine=libaio 14 | iodepth=16 15 | -------------------------------------------------------------------------------- /examples/fio-seq-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fio-seq-read.png -------------------------------------------------------------------------------- /examples/fio-seq-write.fio: -------------------------------------------------------------------------------- 1 | ; fio-seq-write.job for fiotest 2 | 3 | [global] 4 | name=fio-seq-write 5 | filename=fio-seq-write 6 | rw=write 7 | bs=256K 8 | direct=0 9 | numjobs=1 10 | time_based 11 | runtime=900 12 | 13 | [file1] 14 | size=10G 15 | ioengine=libaio 16 | iodepth=16 17 | -------------------------------------------------------------------------------- /examples/fio-seq-write.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fio-seq-write.png -------------------------------------------------------------------------------- /examples/fixed-rate-submission.fio: -------------------------------------------------------------------------------- 1 | [fixed-rate-submit] 2 | size=128m 3 | rw=read 4 | ioengine=libaio 5 | iodepth=32 6 | direct=1 7 | # by setting the submit mode to offload, we can guarantee a fixed rate of 8 | # submission regardless of what the device completion rate is. 9 | io_submit_mode=offload 10 | rate_iops=1000 11 | -------------------------------------------------------------------------------- /examples/fixed-rate-submission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fixed-rate-submission.png -------------------------------------------------------------------------------- /examples/flow.fio: -------------------------------------------------------------------------------- 1 | # Example usage of flows. The below will have roughly a 1:8 difference 2 | # between job2 and job1. 3 | [global] 4 | norandommap 5 | thread 6 | time_based 7 | runtime=30 8 | direct=1 9 | ioengine=libaio 10 | iodepth=256 11 | size=100g 12 | bs=8k 13 | filename=/tmp/testfile 14 | flow_sleep=1000 15 | 16 | [job2] 17 | numjobs=1 18 | rw=write 19 | flow=1 20 | 21 | [job1] 22 | numjobs=1 23 | rw=randread 24 | flow=8 25 | -------------------------------------------------------------------------------- /examples/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/flow.png -------------------------------------------------------------------------------- /examples/fsx.fio: -------------------------------------------------------------------------------- 1 | ; This job file works pretty works similarly to running fsx-linux 2 | ; with -r 4096 -w 4096 -Z -N 500000 3 | [file] 4 | ioengine=libaio 5 | iodepth=1 6 | rw=randrw 7 | size=256k 8 | bs=4k 9 | norandommap 10 | direct=1 11 | loops=500000 12 | -------------------------------------------------------------------------------- /examples/fsx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/fsx.png -------------------------------------------------------------------------------- /examples/ftruncate.fio: -------------------------------------------------------------------------------- 1 | # Example ftruncate engine jobs 2 | 3 | [global] 4 | ioengine=ftruncate 5 | directory=/scratch 6 | size=102404k ; 100Mb+4k 7 | stonewall 8 | filename=truncate 9 | runtime=10s 10 | time_based 11 | direct=1 12 | # 13 | # bs option is stub here. Truncation is performed on the current block offset. 14 | # blocksize value is ignored 15 | bs=4k 16 | 17 | # truncate the file to 4Kbytes then repeatedly grow the file back to just over 18 | # its original size using subsequent truncates 19 | [grow-truncate] 20 | rw=write 21 | 22 | # Repeatedly change a file to a random size between 0Kbytes and 100Mb 23 | # using truncates 24 | [rand-truncate] 25 | rw=randwrite 26 | norandommap 27 | 28 | -------------------------------------------------------------------------------- /examples/ftruncate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/ftruncate.png -------------------------------------------------------------------------------- /examples/gfapi.fio: -------------------------------------------------------------------------------- 1 | # Test opening a file from multiple jobs. 2 | # Originally authored by Castor Fu 3 | [global] 4 | ioengine=gfapi 5 | volume=vol 6 | brick=localhost 7 | create_on_open=1 8 | rw=write 9 | 10 | [reopen_file_test] 11 | nrfiles=4 12 | filesize=16k 13 | size=64k 14 | openfiles=2 15 | rw=write 16 | filename_format=reopen_test.$filenum 17 | -------------------------------------------------------------------------------- /examples/gfapi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/gfapi.png -------------------------------------------------------------------------------- /examples/gpudirect-rdmaio-client.fio: -------------------------------------------------------------------------------- 1 | # Example gpudirect rdma client job 2 | [global] 3 | ioengine=rdma 4 | hostname=[hostname] 5 | port=[port] 6 | verb=[read/write/send/recv] 7 | mem=cudamalloc 8 | gpu_dev_id=0 9 | bs=1m 10 | size=100g 11 | 12 | [sender] 13 | rw=write 14 | iodepth=1 15 | iodepth_batch_complete=1 16 | -------------------------------------------------------------------------------- /examples/gpudirect-rdmaio-client.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/gpudirect-rdmaio-client.png -------------------------------------------------------------------------------- /examples/gpudirect-rdmaio-server.fio: -------------------------------------------------------------------------------- 1 | # Example rdma server job 2 | [global] 3 | ioengine=rdma 4 | port=[port] 5 | mem=cudamalloc 6 | gpu_dev_id=0 7 | bs=1m 8 | size=100g 9 | 10 | [receiver] 11 | rw=read 12 | iodepth=16 13 | -------------------------------------------------------------------------------- /examples/gpudirect-rdmaio-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/gpudirect-rdmaio-server.png -------------------------------------------------------------------------------- /examples/http-s3-crypto.fio: -------------------------------------------------------------------------------- 1 | # Example test for the HTTP engine's S3 support against Amazon AWS. 2 | # Obviously, you have to adjust the S3 credentials; for this example, 3 | # they're passed in via the environment. 4 | # And you can set the SSE Customer Key and Algorithm to test Server 5 | # Side Encryption. 6 | # 7 | 8 | [global] 9 | ioengine=http 10 | name=test 11 | direct=1 12 | filename=/larsmb-fio-test/object 13 | http_verbose=0 14 | https=on 15 | http_mode=s3 16 | http_s3_key=${S3_KEY} 17 | http_s3_keyid=${S3_ID} 18 | http_host=s3.eu-central-1.amazonaws.com 19 | http_s3_region=eu-central-1 20 | http_s3_sse_customer_key=${SSE_KEY} 21 | http_s3_sse_customer_algorithm=AES256 22 | group_reporting 23 | 24 | # With verify, this both writes and reads the object 25 | [create] 26 | rw=write 27 | bs=4k 28 | size=64k 29 | io_size=4k 30 | verify=sha256 31 | 32 | [trim] 33 | stonewall 34 | rw=trim 35 | bs=4k 36 | size=64k 37 | io_size=4k 38 | 39 | -------------------------------------------------------------------------------- /examples/http-s3-crypto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/http-s3-crypto.png -------------------------------------------------------------------------------- /examples/http-s3-storage-class.fio: -------------------------------------------------------------------------------- 1 | # Example test for the HTTP engine's S3 support against Amazon AWS. 2 | # Obviously, you have to adjust the S3 credentials; for this example, 3 | # they're passed in via the environment. 4 | # And here add storage class parameter, you can set normal test for 5 | # STANDARD and compression test for another storage class. 6 | # 7 | 8 | [global] 9 | ioengine=http 10 | name=test 11 | direct=1 12 | filename=/larsmb-fio-test/object 13 | http_verbose=0 14 | https=on 15 | http_mode=s3 16 | http_s3_key=${S3_KEY} 17 | http_s3_keyid=${S3_ID} 18 | http_host=s3.eu-central-1.amazonaws.com 19 | http_s3_region=eu-central-1 20 | http_s3_storage_class=${STORAGE_CLASS} 21 | group_reporting 22 | 23 | # With verify, this both writes and reads the object 24 | [create] 25 | rw=write 26 | bs=4k 27 | size=64k 28 | io_size=4k 29 | verify=sha256 30 | 31 | [trim] 32 | stonewall 33 | rw=trim 34 | bs=4k 35 | size=64k 36 | io_size=4k 37 | 38 | -------------------------------------------------------------------------------- /examples/http-s3-storage-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/http-s3-storage-class.png -------------------------------------------------------------------------------- /examples/http-s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/http-s3.png -------------------------------------------------------------------------------- /examples/http-swift.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=http 3 | rw=randwrite 4 | name=test 5 | direct=1 6 | http_verbose=0 7 | http_mode=swift 8 | https=on 9 | # This is the hostname and port portion of the public access link for 10 | # the container: 11 | http_host=swift.srv.openstack.local:8081 12 | filename_format=/swift/v1/fio-test/bucket.$jobnum 13 | group_reporting 14 | bs=64k 15 | size=1M 16 | # Currently, fio cannot yet generate the Swift Auth-Token itself. 17 | # You need to set this prior to running fio via 18 | # eval $(openstack token issue -f shell --prefix SWIFT_) ; export SWIFT_id 19 | http_swift_auth_token=${SWIFT_id} 20 | 21 | [create] 22 | numjobs=1 23 | rw=randwrite 24 | io_size=256k 25 | verify=sha256 26 | 27 | # This will delete all created objects again 28 | [trim] 29 | stonewall 30 | numjobs=1 31 | rw=trim 32 | io_size=64k 33 | -------------------------------------------------------------------------------- /examples/http-swift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/http-swift.png -------------------------------------------------------------------------------- /examples/http-webdav.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=http 3 | rw=randwrite 4 | name=test 5 | direct=1 6 | http_verbose=0 7 | http_mode=webdav 8 | https=off 9 | http_host=localhost 10 | filename_format=/dav/bucket.$jobnum 11 | group_reporting 12 | bs=64k 13 | size=1M 14 | 15 | [create] 16 | numjobs=16 17 | rw=randwrite 18 | io_size=10M 19 | verify=sha256 20 | 21 | # This will delete all created objects again 22 | [trim] 23 | stonewall 24 | numjobs=16 25 | rw=trim 26 | io_size=1M 27 | -------------------------------------------------------------------------------- /examples/http-webdav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/http-webdav.png -------------------------------------------------------------------------------- /examples/ime.fio: -------------------------------------------------------------------------------- 1 | # This jobfile performs basic write+read operations using 2 | # DDN's Infinite Memory Engine. 3 | 4 | [global] 5 | 6 | # Use as much jobs as possible to maximize performance 7 | numjobs=8 8 | 9 | # The filename should be uniform so that "read" jobs can read what 10 | # the "write" jobs have written. 11 | filename_format=fio-test-ime.$jobnum.$filenum 12 | 13 | size=25g 14 | bs=128k 15 | 16 | # These settings are useful for the asynchronous ime_aio engine: 17 | # by setting the io depth to twice the size of a "batch", we can 18 | # queue IOs while other IOs are "in-flight". 19 | iodepth=32 20 | iodepth_batch=16 21 | iodepth_batch_complete=16 22 | 23 | [write-psync] 24 | stonewall 25 | rw=write 26 | ioengine=ime_psync 27 | 28 | [read-psync] 29 | stonewall 30 | rw=read 31 | ioengine=ime_psync 32 | 33 | [write-psyncv] 34 | stonewall 35 | rw=write 36 | ioengine=ime_psyncv 37 | 38 | [read-psyncv] 39 | stonewall 40 | rw=read 41 | ioengine=ime_psyncv 42 | 43 | [write-aio] 44 | stonewall 45 | rw=write 46 | ioengine=ime_aio 47 | 48 | [read-aio] 49 | stonewall 50 | rw=read 51 | ioengine=ime_aio -------------------------------------------------------------------------------- /examples/ime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/ime.png -------------------------------------------------------------------------------- /examples/iometer-file-access-server.fio: -------------------------------------------------------------------------------- 1 | # This job file tries to mimic the Intel IOMeter File Server Access Pattern 2 | [global] 3 | description=Emulation of Intel IOmeter File Server Access Pattern 4 | 5 | [iometer] 6 | bssplit=512/10:1k/5:2k/5:4k/60:8k/2:16k/4:32k/4:64k/10 7 | rw=randrw 8 | rwmixread=80 9 | direct=1 10 | size=4g 11 | ioengine=libaio 12 | # IOMeter defines the server loads as the following: 13 | # iodepth=1 Linear 14 | # iodepth=4 Very Light 15 | # iodepth=8 Light 16 | # iodepth=64 Moderate 17 | # iodepth=256 Heavy 18 | iodepth=64 19 | -------------------------------------------------------------------------------- /examples/iometer-file-access-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/iometer-file-access-server.png -------------------------------------------------------------------------------- /examples/jesd219.fio: -------------------------------------------------------------------------------- 1 | # Sample implementation of the JESD219 workload for SSD endurance 2 | # testing. It uses a specific distribution of block sizes and 3 | # read/write mix, as well as a specific distribution of where on 4 | # the device the IO accesses will land. Based on posting from 5 | # Jeff Furlong 6 | [JESD219] 7 | ioengine=libaio 8 | direct=1 9 | rw=randrw 10 | norandommap 11 | randrepeat=0 12 | rwmixread=40 13 | rwmixwrite=60 14 | iodepth=256 15 | numjobs=4 16 | bssplit=512/4:1024/1:1536/1:2048/1:2560/1:3072/1:3584/1:4k/67:8k/10:16k/7:32k/3:64k/3 17 | blockalign=4k 18 | random_distribution=zoned:50/5:30/15:20/80 19 | filename=/dev/nvme0n1 20 | group_reporting 21 | -------------------------------------------------------------------------------- /examples/jesd219.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/jesd219.png -------------------------------------------------------------------------------- /examples/latency-profile.fio: -------------------------------------------------------------------------------- 1 | # Test job that demonstrates how to use the latency target 2 | # profiling. Fio will find the queue depth between 1..128 3 | # that fits within the latency constraints of this 4k random 4 | # read workload. 5 | 6 | [global] 7 | bs=4k 8 | rw=randread 9 | random_generator=lfsr 10 | direct=1 11 | ioengine=libaio 12 | iodepth=128 13 | # Set max acceptable latency to 500msec 14 | latency_target=500000 15 | # profile over a 5s window 16 | latency_window=5000000 17 | # 99.9% of IOs must be below the target 18 | latency_percentile=99.9 19 | 20 | [device] 21 | filename=/dev/sda 22 | -------------------------------------------------------------------------------- /examples/latency-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/latency-profile.png -------------------------------------------------------------------------------- /examples/libblkio-io_uring.fio: -------------------------------------------------------------------------------- 1 | ; Benchmark accessing a regular file or block device using libblkio. 2 | ; 3 | ; Replace "/dev/nvme0n1" below with the path to your file or device, or override 4 | ; it by passing the '--libblkio_path=...' flag to fio. 5 | ; 6 | ; In the example below, the two subjobs of "job-B" *and* the single subjob of 7 | ; "job-C" will share a single libblkio instance, and "job-A" will use a separate 8 | ; libblkio instance. 9 | ; 10 | ; For information on libblkio, see: https://gitlab.com/libblkio/libblkio 11 | 12 | [global] 13 | ioengine=libblkio 14 | libblkio_driver=io_uring 15 | libblkio_path=/dev/nvme0n1 ; REPLACE THIS WITH THE RIGHT PATH 16 | rw=randread 17 | blocksize=4k 18 | direct=1 19 | time_based=1 20 | runtime=10s 21 | 22 | [job-A] 23 | 24 | [job-B] 25 | numjobs=2 ; run two copies of this job simultaneously 26 | thread=1 ; have each copy run as a separate thread in the *same* process 27 | 28 | [job-C] 29 | thread=1 ; have the job run as a thread in the *same* process as "job-B" 30 | -------------------------------------------------------------------------------- /examples/libblkio-io_uring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libblkio-io_uring.png -------------------------------------------------------------------------------- /examples/libblkio-virtio-blk-vfio-pci.fio: -------------------------------------------------------------------------------- 1 | ; Benchmark accessing a PCI virtio-blk device using libblkio. 2 | ; 3 | ; Replace "/sys/bus/pci/devices/0000:00:01.0" below with the path to your 4 | ; device's sysfs directory, or override it by passing the '--libblkio_path=...' 5 | ; flag to fio. 6 | ; 7 | ; In the example below, the two subjobs of "job-B" *and* the single subjob of 8 | ; "job-C" will share a single libblkio instance, and "job-A" will use a separate 9 | ; libblkio instance. 10 | ; 11 | ; For information on libblkio, see: https://gitlab.com/libblkio/libblkio 12 | 13 | [global] 14 | ioengine=libblkio 15 | libblkio_driver=virtio-blk-vfio-pci 16 | libblkio_path=/sys/bus/pci/devices/0000:00:01.0 ; REPLACE THIS WITH THE RIGHT PATH 17 | rw=randread 18 | blocksize=4k 19 | time_based=1 20 | runtime=10s 21 | 22 | [job-A] 23 | 24 | [job-B] 25 | numjobs=2 ; run two copies of this job simultaneously 26 | thread=1 ; have each copy run as a separate thread in the *same* process 27 | 28 | [job-C] 29 | thread=1 ; have the job run as a thread in the *same* process as "job-B" 30 | -------------------------------------------------------------------------------- /examples/libblkio-virtio-blk-vfio-pci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libblkio-virtio-blk-vfio-pci.png -------------------------------------------------------------------------------- /examples/libcufile-cufile.fio: -------------------------------------------------------------------------------- 1 | # Example libcufile job, using cufile I/O 2 | # 3 | # Required environment variables: 4 | # GPU_DEV_IDS : refer to option 'gpu_dev_ids' 5 | # FIO_DIR : 'directory'. This job uses cuda_io=cufile, so path(s) must 6 | # point to GPUDirect Storage filesystem(s) 7 | # 8 | 9 | [global] 10 | ioengine=libcufile 11 | directory=${FIO_DIR} 12 | gpu_dev_ids=${GPU_DEV_IDS} 13 | cuda_io=cufile 14 | # 'direct' must be 1 when using cuda_io=cufile 15 | direct=1 16 | # Performance is negatively affected if 'bs' is not a multiple of 4k. 17 | # Refer to GDS cuFile documentation. 18 | bs=1m 19 | size=1m 20 | numjobs=16 21 | # cudaMalloc fails if too many processes attach to the GPU, use threads. 22 | thread 23 | 24 | [read] 25 | rw=read 26 | 27 | [write] 28 | rw=write 29 | 30 | [randread] 31 | rw=randread 32 | 33 | [randwrite] 34 | rw=randwrite 35 | 36 | [verify] 37 | rw=write 38 | verify=md5 39 | 40 | [randverify] 41 | rw=randwrite 42 | verify=md5 43 | -------------------------------------------------------------------------------- /examples/libcufile-cufile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libcufile-cufile.png -------------------------------------------------------------------------------- /examples/libcufile-posix.fio: -------------------------------------------------------------------------------- 1 | # Example libcufile job, using POSIX I/O 2 | # 3 | # Required environment variables: 4 | # GPU_DEV_IDS : refer to option 'gpu_dev_ids' 5 | # FIO_DIR : 'directory'. cuda_io=posix, so the path(s) may point 6 | # to any POSIX filesystem(s) 7 | # 8 | 9 | [global] 10 | ioengine=libcufile 11 | directory=${FIO_DIR} 12 | gpu_dev_ids=${GPU_DEV_IDS} 13 | cuda_io=posix 14 | # 'direct' may be 1 or 0 when using cuda_io=posix 15 | direct=0 16 | # there are no unusual requirements for 'bs' when cuda_io=posix 17 | bs=1m 18 | size=1G 19 | numjobs=16 20 | # cudaMalloc fails if too many processes attach to the GPU, use threads 21 | thread 22 | 23 | [read] 24 | rw=read 25 | 26 | [write] 27 | rw=write 28 | 29 | [randread] 30 | rw=randread 31 | 32 | [randwrite] 33 | rw=randwrite 34 | 35 | [verify] 36 | rw=write 37 | verify=md5 38 | 39 | [randverify] 40 | rw=randwrite 41 | verify=md5 42 | -------------------------------------------------------------------------------- /examples/libcufile-posix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libcufile-posix.png -------------------------------------------------------------------------------- /examples/libhdfs.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | runtime=300 3 | 4 | [hdfs] 5 | filename=dfs-perftest-base.dfs-perftest-base,9000 6 | ioengine=libhdfs 7 | rw=read 8 | bs=256k 9 | -------------------------------------------------------------------------------- /examples/libhdfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libhdfs.png -------------------------------------------------------------------------------- /examples/libiscsi.fio: -------------------------------------------------------------------------------- 1 | [iscsi] 2 | ioengine=libiscsi 3 | filename=iscsi\://127.0.0.1/iqn.2016-02.com.fio\:system\:fio/1 4 | -------------------------------------------------------------------------------- /examples/libiscsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libiscsi.png -------------------------------------------------------------------------------- /examples/libpmem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libpmem.png -------------------------------------------------------------------------------- /examples/libzbc-rand-write.fio: -------------------------------------------------------------------------------- 1 | ; Using the libzbc ioengine, random write to a (zoned) block device, 2 | ; writing at most 32 zones at a time. Target zones are chosen randomly 3 | ; and writes directed at the write pointer of the chosen zones 4 | 5 | [global] 6 | name=libzbc-rand-write 7 | group_reporting 8 | rw=randwrite 9 | zonemode=zbd 10 | zonesize=256M 11 | max_open_zones=32 12 | bs=512K 13 | direct=1 14 | numjobs=16 15 | time_based 16 | runtime=300 17 | 18 | [dev1] 19 | filename=/dev/sdj 20 | ioengine=libzbc 21 | -------------------------------------------------------------------------------- /examples/libzbc-rand-write.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libzbc-rand-write.png -------------------------------------------------------------------------------- /examples/libzbc-seq-read.fio: -------------------------------------------------------------------------------- 1 | ; Using the libzbc ioengine, sequentially read 40 zones of a (zoned) 2 | ; block device, reading only written data from the 524th zone 3 | ; (524 * 256M = 140660178944) 4 | 5 | [global] 6 | name=libzbc-seq-read 7 | rw=read 8 | bs=1M 9 | direct=1 10 | numjobs=1 11 | zonemode=zbd 12 | zonesize=256M 13 | read_beyond_wp=0 14 | 15 | [dev1] 16 | filename=/dev/sdd 17 | offset=140660178944 18 | size=10G 19 | ioengine=libzbc 20 | -------------------------------------------------------------------------------- /examples/libzbc-seq-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/libzbc-seq-read.png -------------------------------------------------------------------------------- /examples/mtd.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | gtod_reduce=1 3 | filename=/dev/mtd0 4 | ioengine=mtd 5 | ignore_error=,EIO 6 | blocksize=512,512,16384 7 | skip_bad=1 8 | 9 | [trim] 10 | stonewall 11 | rw=trim 12 | 13 | [write] 14 | stonewall 15 | rw=write 16 | 17 | [trimwrite] 18 | stonewall 19 | block_error_percentiles=1 20 | rw=trimwrite 21 | loops=4 22 | -------------------------------------------------------------------------------- /examples/mtd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/mtd.png -------------------------------------------------------------------------------- /examples/nbd.fio: -------------------------------------------------------------------------------- 1 | # To use fio to test nbdkit + RAM disk: 2 | # 3 | # nbdkit -U - memory size=256M --run 'export uri; fio examples/nbd.fio' 4 | # 5 | # To use fio to test nbdkit + local file: 6 | # 7 | # rm -f /var/tmp/disk.img 8 | # truncate -s 256M /var/tmp/disk.img 9 | # nbdkit -U - file /var/tmp/disk.img --run 'export uri; fio examples/nbd.fio' 10 | # 11 | # To use fio to test qemu-nbd + local file: 12 | # 13 | # rm -f /var/tmp/disk.img /var/tmp/socket 14 | # truncate -s 256M /var/tmp/disk.img 15 | # export uri='nbd+unix:///?socket=/var/tmp/socket' 16 | # qemu-nbd -t -k /var/tmp/socket -f raw /var/tmp/disk.img & 17 | # fio examples/nbd.fio 18 | # killall qemu-nbd 19 | 20 | [global] 21 | ioengine=nbd 22 | uri=${uri} 23 | rw=randrw 24 | time_based 25 | runtime=60 26 | group_reporting 27 | iodepth=64 28 | 29 | [job0] 30 | offset=0 31 | 32 | [job1] 33 | offset=64m 34 | 35 | [job2] 36 | offset=128m 37 | 38 | [job3] 39 | offset=192m 40 | -------------------------------------------------------------------------------- /examples/nbd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/nbd.png -------------------------------------------------------------------------------- /examples/netio.fio: -------------------------------------------------------------------------------- 1 | # Example network job, just defines two clients that send/recv data 2 | [global] 3 | ioengine=net 4 | #Use hostname=/tmp.fio.sock for local unix domain sockets 5 | port=8888 6 | #Use =udp for UDP, =unix for local unix domain socket 7 | protocol=tcp 8 | bs=4k 9 | size=100g 10 | #set the below option to enable end-to-end data integrity tests 11 | #verify=md5 12 | 13 | [receiver] 14 | listen 15 | rw=read 16 | 17 | [sender] 18 | hostname=localhost 19 | startdelay=1 20 | rw=write 21 | -------------------------------------------------------------------------------- /examples/netio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/netio.png -------------------------------------------------------------------------------- /examples/netio_multicast.fio: -------------------------------------------------------------------------------- 1 | # netio UDP multicast example. Writers and readers can be run on separate hosts. 2 | [global] 3 | ioengine=net 4 | protocol=udp 5 | bs=64 6 | size=100m 7 | # Set interface IP to send/receive traffic through specific network interface 8 | #interface=10.8.16.22 9 | port=10000 10 | hostname=239.0.0.0 11 | ttl=1 12 | 13 | [pingpong_reader] 14 | pingpong=1 15 | rw=read 16 | 17 | [normal_reader] 18 | rw=read 19 | 20 | [pingpong_writer] 21 | startdelay=1 22 | pingpong=1 23 | rw=write 24 | -------------------------------------------------------------------------------- /examples/netio_multicast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/netio_multicast.png -------------------------------------------------------------------------------- /examples/netio_vsock.fio: -------------------------------------------------------------------------------- 1 | # Example network vsock job, just defines two clients that send/recv data 2 | [global] 3 | ioengine=net 4 | 5 | port=8888 6 | protocol=vsock 7 | bs=4k 8 | size=100g 9 | 10 | #set the below option to enable end-to-end data integrity tests 11 | #verify=md5 12 | 13 | [receiver] 14 | listen 15 | rw=read 16 | 17 | [sender] 18 | # 1 (VMADDR_CID_LOCAL) is the well-known address 19 | # for local communication (loopback) 20 | hostname=1 21 | startdelay=1 22 | rw=write 23 | -------------------------------------------------------------------------------- /examples/netio_vsock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/netio_vsock.png -------------------------------------------------------------------------------- /examples/netio_vsock_receiver.fio: -------------------------------------------------------------------------------- 1 | # Example network vsock job, just defines a receiver 2 | [global] 3 | ioengine=net 4 | port=8888 5 | protocol=vsock 6 | bs=4k 7 | size=100g 8 | 9 | #set the below option to enable end-to-end data integrity tests 10 | #verify=md5 11 | 12 | [receiver] 13 | listen 14 | rw=read 15 | -------------------------------------------------------------------------------- /examples/netio_vsock_receiver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/netio_vsock_receiver.png -------------------------------------------------------------------------------- /examples/netio_vsock_sender.fio: -------------------------------------------------------------------------------- 1 | # Example network vsock job, just defines a sender 2 | [global] 3 | ioengine=net 4 | port=8888 5 | protocol=vsock 6 | bs=4k 7 | size=100g 8 | 9 | #set the below option to enable end-to-end data integrity tests 10 | #verify=md5 11 | 12 | [sender] 13 | # set the 'hostname' option to the CID of the listening domain 14 | hostname=3 15 | startdelay=1 16 | rw=write 17 | 18 | -------------------------------------------------------------------------------- /examples/netio_vsock_sender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/netio_vsock_sender.png -------------------------------------------------------------------------------- /examples/nfs.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | nfs_url=nfs://127.0.0.1/nfs 3 | blocksize=524288 4 | iodepth=10 5 | ioengine=nfs 6 | size=104857600 7 | lat_percentiles=1 8 | group_reporting 9 | numjobs=10 10 | ramp_time=5s 11 | filename_format=myfiles.$clientuid.$jobnum.$filenum 12 | time_based=1 13 | 14 | [write] 15 | rw=write 16 | runtime=10s 17 | stonewall 18 | 19 | [read] 20 | wait_for=write 21 | rw=randread 22 | runtime=10s 23 | -------------------------------------------------------------------------------- /examples/nfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/nfs.png -------------------------------------------------------------------------------- /examples/null.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | bs=4k 3 | gtod_reduce=1 4 | 5 | [null] 6 | ioengine=null 7 | size=100g 8 | rw=randread 9 | norandommap 10 | -------------------------------------------------------------------------------- /examples/null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/null.png -------------------------------------------------------------------------------- /examples/numa.fio: -------------------------------------------------------------------------------- 1 | ; setup numa policy for each thread 2 | ; 'numactl --show' to determine the maximum numa nodes 3 | [global] 4 | ioengine=libaio 5 | buffered=0 6 | rw=randread 7 | bs=512K 8 | iodepth=16 9 | size=512m 10 | filename=/dev/sdb1 11 | 12 | ; Fix memory blocks (512K * 16) in numa node 0 13 | [job1] 14 | numa_cpu_nodes=0 15 | numa_mem_policy=bind:0 16 | 17 | ; Interleave memory blocks (512K * 16) in numa node 0 and 1 18 | [job2] 19 | numa_cpu_nodes=0-1 20 | numa_mem_policy=interleave:0-1 21 | 22 | -------------------------------------------------------------------------------- /examples/numa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/numa.png -------------------------------------------------------------------------------- /examples/poisson-rate-submission.fio: -------------------------------------------------------------------------------- 1 | [poisson-rate-submit] 2 | size=128m 3 | rw=randread 4 | ioengine=libaio 5 | iodepth=32 6 | direct=1 7 | # by setting the submit mode to offload, we can guarantee a fixed rate of 8 | # submission regardless of what the device completion rate is. 9 | io_submit_mode=offload 10 | rate_iops=50 11 | # Real world random request flow follows Poisson process. To give better 12 | # insight on latency distribution, we simulate request flow under Poisson 13 | # process. 14 | rate_process=poisson 15 | -------------------------------------------------------------------------------- /examples/poisson-rate-submission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/poisson-rate-submission.png -------------------------------------------------------------------------------- /examples/rados.fio: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Example test for the RADOS engine. 3 | # 4 | # Runs a 4k random write test against a RADOS via librados 5 | # 6 | # NOTE: Make sure you have either Ceph pool named 'rados' or change 7 | # the pool parameter. 8 | ###################################################################### 9 | [global] 10 | #logging 11 | #write_iops_log=write_iops_log 12 | #write_bw_log=write_bw_log 13 | #write_lat_log=write_lat_log 14 | ioengine=rados 15 | clientname=admin 16 | pool=rados 17 | conf=/etc/ceph/ceph.conf 18 | busy_poll=0 19 | rw=randwrite 20 | bs=4k 21 | 22 | [rbd_iodepth32] 23 | iodepth=32 24 | size=128m 25 | nr_files=32 26 | -------------------------------------------------------------------------------- /examples/rados.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/rados.png -------------------------------------------------------------------------------- /examples/rand-zones.fio: -------------------------------------------------------------------------------- 1 | # Sample job file demonstrating how to use zoned random distributionss 2 | # to have skewed random accesses. This example has 50% of the accesses 3 | # to the first 5% of the file (50/5), 30% to the next 15% (30/15), and 4 | # finally 20% of the IO will end up in the remaining 80%. 5 | [zones] 6 | size=2g 7 | direct=1 8 | bs=4k 9 | rw=randread 10 | norandommap 11 | random_distribution=zoned:50/5:30/15:20/ 12 | 13 | # It's also possible to use zoned_abs to specify absolute sizes. For 14 | # instance, if you do: 15 | # 16 | # random_distribution=zoned_abs:50/10G:30/100G:20/500G 17 | # 18 | # Then 50% of the access will be to the first 10G of the drive, 30% 19 | # will be to the next 100G, and 20% will be to the next 500G. 20 | 21 | # The above applies to all of reads/writes/trims. If we wanted to do 22 | # something differently for writes, let's say 50% for the first 10% 23 | # and 50% for the remaining 90%, we could do it by adding a new section 24 | # after a comma. 25 | 26 | # random_distribution=zoned:50/5:30/15:20/,50/10:50/90 27 | -------------------------------------------------------------------------------- /examples/rand-zones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/rand-zones.png -------------------------------------------------------------------------------- /examples/rbd.fio: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Example test for the RBD engine. 3 | # 4 | # Runs a 4k random write test against a RBD via librbd 5 | # 6 | # NOTE: Make sure you have either a RBD named 'fio_test' or change 7 | # the rbdname parameter. 8 | ###################################################################### 9 | [global] 10 | #logging 11 | #write_iops_log=write_iops_log 12 | #write_bw_log=write_bw_log 13 | #write_lat_log=write_lat_log 14 | ioengine=rbd 15 | clientname=admin 16 | pool=rbd 17 | rbdname=fio_test 18 | rw=randwrite 19 | bs=4k 20 | 21 | [rbd_iodepth32] 22 | iodepth=32 23 | -------------------------------------------------------------------------------- /examples/rbd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/rbd.png -------------------------------------------------------------------------------- /examples/rdmaio-client.fio: -------------------------------------------------------------------------------- 1 | # Example rdma client job 2 | [global] 3 | ioengine=rdma 4 | hostname=[hostname] 5 | port=[port] 6 | verb=[read/write/send/recv] 7 | bs=1m 8 | size=100g 9 | 10 | [sender] 11 | rw=write 12 | iodepth=1 13 | iodepth_batch_complete=1 14 | -------------------------------------------------------------------------------- /examples/rdmaio-client.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/rdmaio-client.png -------------------------------------------------------------------------------- /examples/rdmaio-server.fio: -------------------------------------------------------------------------------- 1 | # Example rdma server job 2 | [global] 3 | ioengine=rdma 4 | port=[port] 5 | bs=1m 6 | size=100g 7 | 8 | [receiver] 9 | rw=read 10 | iodepth=16 11 | -------------------------------------------------------------------------------- /examples/rdmaio-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/rdmaio-server.png -------------------------------------------------------------------------------- /examples/sg_verify-fail.fio: -------------------------------------------------------------------------------- 1 | # 2 | # ********************************** 3 | # * !!THIS IS A DESTRUCTIVE TEST!! * 4 | # * IF NOT CHANGED THIS TEST WILL * 5 | # * DESTROY DATA ON /dev/sdb * 6 | # ********************************** 7 | # 8 | # Test SCSI VERIFY commands issued via the sg ioengine 9 | # The jobs with fail in the name should produce errors 10 | # 11 | # job description 12 | # precon precondition the device by writing with a known 13 | # pattern 14 | # verify01 verify each block one at a time by comparing to known 15 | # pattern 16 | # verify01-fail verifying one too many blocks should produce a failure 17 | # verify11-one_ios verify all 20 blocks by sending only 512 bytes 18 | # verify11-fail verifying beyond the preconditioned region should 19 | # produce a failure 20 | 21 | [global] 22 | filename=/dev/sdb 23 | buffer_pattern=0x01 24 | ioengine=sg 25 | rw=write 26 | bs=512 27 | number_ios=20 28 | stonewall 29 | 30 | [precon] 31 | 32 | [verify01] 33 | sg_write_mode=verify_bytchk_01 34 | number_ios=20 35 | 36 | [verify01-fail] 37 | sg_write_mode=verify_bytchk_01 38 | number_ios=21 39 | 40 | [verify11-one_ios] 41 | sg_write_mode=verify_bytchk_11 42 | number_ios=1 43 | bs=10240 44 | 45 | [verify11-fail] 46 | sg_write_mode=verify_bytchk_11 47 | number_ios=1 48 | bs=10752 49 | -------------------------------------------------------------------------------- /examples/sg_verify-fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/sg_verify-fail.png -------------------------------------------------------------------------------- /examples/sg_verify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/sg_verify.png -------------------------------------------------------------------------------- /examples/sg_write_same_ndob.fio: -------------------------------------------------------------------------------- 1 | # 2 | # ********************************** 3 | # * !!THIS IS A DESTRUCTIVE TEST!! * 4 | # * IF NOT CHANGED THIS TEST WILL * 5 | # * DESTROY DATA ON /dev/sdb * 6 | # ********************************** 7 | # 8 | # Test WRITE SAME commands with the NDOB flag set 9 | # issued via the sg ioengine 10 | # All of the jobs below should complete without error 11 | # except the last one 12 | # 13 | # job description 14 | # precon Precondition the device by writing 20 blocks with a 15 | # known pattern 16 | # write_same_ndob Write 19 sectors of all zeroes with the NDOB flag set 17 | # verify-pass Verify 19 blocks of all zeroes 18 | # verify-fail Verify 20 blocks of all zeroes. This should fail. 19 | # 20 | 21 | [global] 22 | filename=/dev/sdb 23 | buffer_pattern=0x01 24 | ioengine=sg 25 | rw=write 26 | bs=512 27 | stonewall 28 | 29 | [precon] 30 | number_ios=20 31 | 32 | [write_same_ndob] 33 | sg_write_mode=write_same_ndob 34 | number_ios=19 35 | 36 | [verify-pass] 37 | sg_write_mode=verify_bytchk_01 38 | buffer_pattern=0x00 39 | number_ios=19 40 | 41 | [verify-fail] 42 | sg_write_mode=verify_bytchk_01 43 | buffer_pattern=0x00 44 | number_ios=20 45 | -------------------------------------------------------------------------------- /examples/sg_write_same_ndob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/sg_write_same_ndob.png -------------------------------------------------------------------------------- /examples/ssd-steadystate.fio: -------------------------------------------------------------------------------- 1 | # Get a decent idea about the steady state performance of an SSD. 2 | # 3 | # First we sequentially write the drive. Then we completely 4 | # overwrite the device again, this time randomly at 4K. The former gives 5 | # us a good idea of the ideal write performance, you should see flat graph 6 | # of steady write performance. The latter we would expect to start out at 7 | # approximately the same rate as the sequential fill, but at some point 8 | # hit a write cliff and hit steady state. The latency numbers of the steady 9 | # state also provide a good idea of what kind of latencies to expect when 10 | # the device is pushed to steady state instead of peak benchmark-like 11 | # numbers that are usually reported. 12 | # 13 | # Note that this is a DESTRUCTIVE test. It operates on the device itself. 14 | # It's not destructive in the sense that it will ruin the device, but 15 | # whatever data you have on there will be gone. 16 | # 17 | [global] 18 | ioengine=libaio 19 | direct=1 20 | group_reporting 21 | filename=/dev/fioa 22 | 23 | [sequential-fill] 24 | description=Sequential fill phase 25 | rw=write 26 | iodepth=16 27 | bs=1M 28 | 29 | [random-write-steady] 30 | stonewall 31 | description=Random write steady state phase 32 | rw=randwrite 33 | bs=4K 34 | iodepth=32 35 | numjobs=4 36 | write_bw_log=fioa-steady-state 37 | -------------------------------------------------------------------------------- /examples/ssd-steadystate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/ssd-steadystate.png -------------------------------------------------------------------------------- /examples/ssd-test.fio: -------------------------------------------------------------------------------- 1 | # Do some important numbers on SSD drives, to gauge what kind of 2 | # performance you might get out of them. 3 | # 4 | # Sequential read and write speeds are tested, these are expected to be 5 | # high. Random reads should also be fast, random writes are where crap 6 | # drives are usually separated from the good drives. 7 | # 8 | # This uses a queue depth of 4. New SATA SSD's will support up to 32 9 | # in flight commands, so it may also be interesting to increase the queue 10 | # depth and compare. Note that most real-life usage will not see that 11 | # large of a queue depth, so 4 is more representative of normal use. 12 | # 13 | [global] 14 | bs=4k 15 | ioengine=libaio 16 | iodepth=4 17 | size=10g 18 | direct=1 19 | runtime=60 20 | directory=/mount-point-of-ssd 21 | filename=ssd.test.file 22 | 23 | [seq-read] 24 | rw=read 25 | stonewall 26 | 27 | [rand-read] 28 | rw=randread 29 | stonewall 30 | 31 | [seq-write] 32 | rw=write 33 | stonewall 34 | 35 | [rand-write] 36 | rw=randwrite 37 | stonewall 38 | -------------------------------------------------------------------------------- /examples/ssd-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/ssd-test.png -------------------------------------------------------------------------------- /examples/steadystate.fio: -------------------------------------------------------------------------------- 1 | # 2 | # Example job file for steady state job termination 3 | # Use --output-format=json for detailed information 4 | # 5 | # For Windows, change the file names 6 | # 7 | 8 | [global] 9 | threads=1 10 | group_reporting 11 | time_based 12 | size=128m 13 | 14 | [ss-write] 15 | filename=/dev/null 16 | rw=write 17 | bs=128k 18 | numjobs=4 19 | runtime=5m 20 | ss=iops:10% 21 | ss_dur=30s 22 | ss_ramp=10s 23 | # 24 | # Begin ss detection 10s after job starts 25 | # Terminate job when largest deviation from mean IOPS is 10% 26 | # Use a rolling 30s window for deviations 27 | # 28 | 29 | 30 | [ss-read] 31 | new_group 32 | stonewall 33 | filename=/dev/zero 34 | rw=randread 35 | bs=4k 36 | numjobs=4 37 | runtime=5m 38 | ss=bw_slope:1% 39 | ss_dur=10s 40 | ss_ramp=5s 41 | # 42 | # Begin ss detection 5s after job starts 43 | # Terminate job when bandwidth slope is less than 1% of avg bw 44 | # Use a rolling 10s window for bw measurements 45 | # 46 | -------------------------------------------------------------------------------- /examples/steadystate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/steadystate.png -------------------------------------------------------------------------------- /examples/surface-scan.fio: -------------------------------------------------------------------------------- 1 | ; writes 512 byte verification blocks until the disk is full, 2 | ; then verifies written data 3 | [global] 4 | thread 5 | bs=64k 6 | direct=1 7 | ioengine=sync 8 | verify=meta 9 | verify_pattern=0xaa555aa5 10 | verify_interval=512 11 | 12 | [write-phase] 13 | filename=datafile.tmp ; or use a full disk, for example /dev/sda 14 | rw=write 15 | fill_device=1 16 | do_verify=0 17 | 18 | [verify-phase] 19 | stonewall 20 | create_serialize=0 21 | filename=datafile.tmp 22 | rw=read 23 | do_verify=1 24 | -------------------------------------------------------------------------------- /examples/surface-scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/surface-scan.png -------------------------------------------------------------------------------- /examples/tiobench-example.fio: -------------------------------------------------------------------------------- 1 | ; tiobench like setup, add more fX files between the stonewalls to 2 | ; create more threads 3 | 4 | [global] 5 | direct=1 6 | size=512m 7 | bsrange=4k-4k 8 | timeout=60 9 | numjobs=4 ; 4 simultaneous threads for each job 10 | 11 | [f1] 12 | rw=write 13 | 14 | [f2] 15 | stonewall 16 | rw=randwrite 17 | 18 | [f3] 19 | stonewall 20 | rw=read 21 | 22 | [f4] 23 | stonewall 24 | rw=randread 25 | -------------------------------------------------------------------------------- /examples/tiobench-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/tiobench-example.png -------------------------------------------------------------------------------- /examples/uring-cmd-fdp.fio: -------------------------------------------------------------------------------- 1 | # io_uring_cmd I/O engine for nvme-ns generic character device with FDP enabled 2 | # This assumes the namespace is already configured with FDP support and has at 3 | # least 8 available reclaim units. 4 | # 5 | # Each job targets different ranges of LBAs with different placement 6 | # identifiers, and has different write intensity. 7 | 8 | [global] 9 | filename=/dev/ng0n1 10 | ioengine=io_uring_cmd 11 | cmd_type=nvme 12 | iodepth=32 13 | bs=4K 14 | fdp=1 15 | time_based=1 16 | runtime=1000 17 | 18 | [write-heavy] 19 | rw=randrw 20 | rwmixwrite=90 21 | fdp_pli=0,1,2,3 22 | offset=0% 23 | size=30% 24 | 25 | [write-mid] 26 | rw=randrw 27 | rwmixwrite=30 28 | fdp_pli=4,5 29 | offset=30% 30 | size=30% 31 | 32 | [write-light] 33 | rw=randrw 34 | rwmixwrite=10 35 | fdp_pli=6 36 | offset=60% 37 | size=30% 38 | -------------------------------------------------------------------------------- /examples/uring-cmd-fdp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/uring-cmd-fdp.png -------------------------------------------------------------------------------- /examples/uring-cmd-ng.fio: -------------------------------------------------------------------------------- 1 | # io_uring_cmd I/O engine for nvme-ns generic character device 2 | 3 | [global] 4 | filename=/dev/ng0n1 5 | ioengine=io_uring_cmd 6 | cmd_type=nvme 7 | size=1G 8 | iodepth=32 9 | bs=4K 10 | thread=1 11 | stonewall=1 12 | 13 | [rand-write] 14 | rw=randwrite 15 | sqthread_poll=1 16 | 17 | [rand-read] 18 | rw=randread 19 | 20 | [write-opts] 21 | rw=write 22 | sqthread_poll=1 23 | sqthread_poll_cpu=0 24 | nonvectored=1 25 | registerfiles=1 26 | -------------------------------------------------------------------------------- /examples/uring-cmd-ng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/uring-cmd-ng.png -------------------------------------------------------------------------------- /examples/uring-cmd-pi-ext.fio: -------------------------------------------------------------------------------- 1 | # Protection information test with io_uring_cmd I/O engine for nvme-ns generic 2 | # character device. 3 | # 4 | # This requires nvme device to be formatted with extended LBA data size and 5 | # protection information enabled. This can be done with nvme-cli utility. 6 | # Replace bs below with the correct extended LBA size. 7 | # 8 | # First we sequentially write to the device, without protection information 9 | # action being set. FIO will generate and send necessary protection 10 | # information data as per the protection information check option. Later on we 11 | # sequentially read and verify the device returned protection information data. 12 | # 13 | [global] 14 | filename=/dev/ng0n1 15 | ioengine=io_uring_cmd 16 | cmd_type=nvme 17 | size=1G 18 | iodepth=32 19 | bs=4160 20 | pi_act=0 21 | pi_chk=GUARD,APPTAG,REFTAG 22 | apptag=0x0888 23 | apptag_mask=0xFFFF 24 | thread=1 25 | stonewall=1 26 | 27 | [write] 28 | rw=write 29 | 30 | [read] 31 | rw=read 32 | -------------------------------------------------------------------------------- /examples/uring-cmd-pi-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/uring-cmd-pi-ext.png -------------------------------------------------------------------------------- /examples/uring-cmd-pi-sb.fio: -------------------------------------------------------------------------------- 1 | # Protection information test with io_uring_cmd I/O engine for nvme-ns generic 2 | # character device. 3 | # 4 | # This requires nvme device to be formatted with separate metadata buffer and 5 | # protection information enabled. This can be done with nvme-cli utility. 6 | # Replace md_per_io_size as per the required metadata buffer size for each IO. 7 | # 8 | # First we sequentially write to the device, without protection information 9 | # action being set. FIO will generate and send necessary protection 10 | # information data as per the protection information check option. Later on we 11 | # sequentially read and verify the device returned protection information data. 12 | # 13 | [global] 14 | filename=/dev/ng0n1 15 | ioengine=io_uring_cmd 16 | cmd_type=nvme 17 | size=1G 18 | iodepth=32 19 | bs=4096 20 | md_per_io_size=64 21 | pi_act=0 22 | pi_chk=GUARD,APPTAG,REFTAG 23 | apptag=0x0888 24 | apptag_mask=0xFFFF 25 | thread=1 26 | stonewall=1 27 | 28 | [write] 29 | rw=write 30 | 31 | [read] 32 | rw=read 33 | -------------------------------------------------------------------------------- /examples/uring-cmd-pi-sb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/uring-cmd-pi-sb.png -------------------------------------------------------------------------------- /examples/uring-cmd-trim-multi-range.fio: -------------------------------------------------------------------------------- 1 | # Multi-range trim command test with io_uring_cmd I/O engine for nvme-ns 2 | # generic character device. 3 | # 4 | [global] 5 | filename=/dev/ng0n1 6 | ioengine=io_uring_cmd 7 | cmd_type=nvme 8 | size=10M 9 | iodepth=32 10 | thread=1 11 | stonewall=1 12 | 13 | [write_bs] 14 | bs=4096 15 | rw=randtrim 16 | num_range=8 17 | 18 | [write_bssplit] 19 | bssplit=4k/10:64k/50:32k/40 20 | rw=trim 21 | num_range=8 22 | -------------------------------------------------------------------------------- /examples/uring-cmd-trim-multi-range.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/uring-cmd-trim-multi-range.png -------------------------------------------------------------------------------- /examples/uring-cmd-zoned.fio: -------------------------------------------------------------------------------- 1 | # io_uring_cmd I/O engine for nvme-ns generic zoned character device 2 | # 3 | # NOTE: 4 | # Regular writes against a zone should be limited to QD1, as the device can 5 | # reorder the requests. 6 | # 7 | # As the passthrough path do not use an IO scheduler (such as mq-deadline), 8 | # the queue depth should be limited to 1 to avoid zone invalid writes. 9 | 10 | [global] 11 | filename=/dev/ng0n1 12 | ioengine=io_uring_cmd 13 | cmd_type=nvme 14 | zonemode=zbd 15 | size=1G 16 | iodepth=1 17 | bs=256K 18 | verify=crc32c 19 | stonewall=1 20 | 21 | [rand-write] 22 | rw=randwrite 23 | 24 | [write-opts] 25 | rw=write 26 | registerfiles=1 27 | sqthread_poll=1 28 | sqthread_poll_cpu=0 29 | 30 | [randwrite-opts] 31 | rw=randwrite 32 | sqthread_poll=1 33 | sqthread_poll_cpu=0 34 | nonvectored=1 35 | registerfiles=1 36 | -------------------------------------------------------------------------------- /examples/uring-cmd-zoned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/uring-cmd-zoned.png -------------------------------------------------------------------------------- /examples/waitfor.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | threads=1 3 | group_reporting 4 | filename=/tmp/data 5 | filesize=128m 6 | 7 | [writers] 8 | rw=write 9 | bs=128k 10 | numjobs=4 11 | runtime=10 12 | 13 | [readers] 14 | new_group 15 | wait_for=writers 16 | rw=randread 17 | bs=4k 18 | numjobs=4 19 | runtime=10 20 | 21 | [writers2] 22 | new_group 23 | wait_for=readers 24 | rw=randwrite 25 | bs=4k 26 | numjobs=4 27 | runtime=10 28 | 29 | [readers2] 30 | new_group 31 | wait_for=writers2 32 | rw=randread 33 | bs=4k 34 | numjobs=4 35 | runtime=10 36 | -------------------------------------------------------------------------------- /examples/waitfor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/waitfor.png -------------------------------------------------------------------------------- /examples/xnvme-compare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/xnvme-compare.png -------------------------------------------------------------------------------- /examples/xnvme-fdp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/xnvme-fdp.png -------------------------------------------------------------------------------- /examples/xnvme-pi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/xnvme-pi.png -------------------------------------------------------------------------------- /examples/xnvme-zoned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/xnvme-zoned.png -------------------------------------------------------------------------------- /examples/zbd-rand-write-trim-gc.fio: -------------------------------------------------------------------------------- 1 | ; Using the libaio ioengine, random write to a (zoned) block device. Write 2 | ; target zones are chosen randomly among the first 128 zones starting from 3 | ; device offset corresponding to the 524th zone of the device (524 x 256 MB). 4 | ; For first 3 seconds, run only random write. After that, run random write job 5 | ; and garbage collection simulation job in parallel. The garbage collection 6 | ; simulation job runs trim workload to reset the 128 zones randomly. Use flow 7 | ; option to make the zone resets happen every 128 blocks writes by the other 8 | ; job. This example does not specify max_open_zones. The limit of maximum 9 | ; open zones is obtained from the target block device. 10 | 11 | [global] 12 | group_reporting 13 | zonemode=zbd 14 | zonesize=256M 15 | direct=1 16 | time_based 17 | runtime=30 18 | 19 | filename=/dev/sdb 20 | offset=524z 21 | 22 | [warmup] 23 | rw=randwrite 24 | bs=2M 25 | size=128z 26 | ioengine=libaio 27 | runtime=3 28 | 29 | [wjob] 30 | wait_for=warmup 31 | rw=randwrite 32 | bs=2M 33 | size=128z 34 | ioengine=libaio 35 | flow=128 36 | 37 | [trimjob] 38 | wait_for=warmup 39 | rw=randtrim 40 | bs=256M 41 | size=128z 42 | ioengine=psync 43 | flow=1 44 | -------------------------------------------------------------------------------- /examples/zbd-rand-write-trim-gc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/zbd-rand-write-trim-gc.png -------------------------------------------------------------------------------- /examples/zbd-rand-write-zone-reset-gc.fio: -------------------------------------------------------------------------------- 1 | ; Using the psync ioengine, random write to a (zoned) block device. Write 2 | ; target zones are chosen randomly among the first 8 zones starting from device 3 | ; offset corresponding to the 524th zone of the device (524 x 256 MB). Simulate 4 | ; garbage collection operation using zone_reset_threshold and 5 | ; zone_reset_frequency options. The zone resets happen when total written data 6 | ; bytes is beyond 70% of 8 zones, and 8 = 1 / 0.125 blocks are written. This 7 | ; example does not specify max_open_zones. The limit of maximum open zones is 8 | ; obtained from the target block device. 9 | 10 | [global] 11 | name=zbd-rand-write-gc 12 | group_reporting 13 | rw=randwrite 14 | zonemode=zbd 15 | zonesize=256M 16 | bs=32M 17 | direct=1 18 | time_based 19 | runtime=40 20 | 21 | [dev1] 22 | filename=/dev/sdb 23 | size=8z 24 | offset=524z 25 | ioengine=psync 26 | zone_reset_threshold=0.7 27 | zone_reset_frequency=0.125 28 | -------------------------------------------------------------------------------- /examples/zbd-rand-write-zone-reset-gc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/zbd-rand-write-zone-reset-gc.png -------------------------------------------------------------------------------- /examples/zbd-rand-write.fio: -------------------------------------------------------------------------------- 1 | ; Using the psync ioengine, random write to a (zoned) block device, 2 | ; writing at most 32 zones at a time. Target zones are chosen randomly 3 | ; and writes directed at the write pointer of the chosen zones 4 | 5 | [global] 6 | name=zbd-rand-write 7 | group_reporting 8 | rw=randwrite 9 | zonemode=zbd 10 | zonesize=256M 11 | max_open_zones=32 12 | bs=512K 13 | direct=1 14 | numjobs=16 15 | time_based 16 | runtime=180 17 | 18 | [dev1] 19 | filename=/dev/sdj 20 | ioengine=psync 21 | -------------------------------------------------------------------------------- /examples/zbd-rand-write.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/zbd-rand-write.png -------------------------------------------------------------------------------- /examples/zbd-seq-read.fio: -------------------------------------------------------------------------------- 1 | ; Sequentially read 40 zones of a (zoned) block device, reading only 2 | ; written data from the 524th zone (524 * 256M = 140660178944) 3 | 4 | [global] 5 | name=zbd-seq-read 6 | rw=read 7 | bs=256K 8 | direct=1 9 | numjobs=1 10 | zonemode=zbd 11 | zonesize=256M 12 | read_beyond_wp=0 13 | 14 | [dev1] 15 | filename=/dev/sdd 16 | offset=140660178944 17 | size=10G 18 | ioengine=libaio 19 | iodepth=16 20 | -------------------------------------------------------------------------------- /examples/zbd-seq-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/zbd-seq-read.png -------------------------------------------------------------------------------- /examples/zipf.fio: -------------------------------------------------------------------------------- 1 | # Example job file for using a zipf distribution instead 2 | # of a purely random workload where each block is read 3 | # or written once. 4 | [job] 5 | ioengine=null 6 | rw=randread 7 | norandommap 8 | size=1280m 9 | bs=4k 10 | random_distribution=zipf:0.5 11 | -------------------------------------------------------------------------------- /examples/zipf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/examples/zipf.png -------------------------------------------------------------------------------- /filehash.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_FILE_HASH_H 2 | #define FIO_FILE_HASH_H 3 | 4 | #include "lib/types.h" 5 | 6 | extern void file_hash_init(void); 7 | extern void file_hash_exit(void); 8 | extern struct fio_file *lookup_file_hash(const char *); 9 | extern struct fio_file *add_file_hash(struct fio_file *); 10 | extern void remove_file_hash(struct fio_file *); 11 | extern void fio_file_hash_lock(void); 12 | extern void fio_file_hash_unlock(void); 13 | extern bool file_bloom_exists(const char *, bool); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /filelock.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_LOCK_FILE_H 2 | #define FIO_LOCK_FILE_H 3 | 4 | #include "lib/types.h" 5 | 6 | extern void fio_lock_file(const char *); 7 | extern bool fio_trylock_file(const char *); 8 | extern void fio_unlock_file(const char *); 9 | 10 | extern int fio_filelock_init(void); 11 | extern void fio_filelock_exit(void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /fio_sem.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_SEM_H 2 | #define FIO_SEM_H 3 | 4 | #include 5 | #include "lib/types.h" 6 | 7 | #define FIO_SEM_MAGIC 0x4d555445U 8 | 9 | struct fio_sem { 10 | pthread_mutex_t lock; 11 | pthread_cond_t cond; 12 | int value; 13 | int waiters; 14 | int magic; 15 | }; 16 | 17 | enum { 18 | FIO_SEM_LOCKED = 0, 19 | FIO_SEM_UNLOCKED = 1, 20 | }; 21 | 22 | extern int __fio_sem_init(struct fio_sem *, int); 23 | extern struct fio_sem *fio_sem_init(int); 24 | extern struct fio_sem *fio_shared_sem_init(int); 25 | extern void __fio_sem_remove(struct fio_sem *); 26 | extern void fio_sem_remove(struct fio_sem *); 27 | extern void fio_shared_sem_remove(struct fio_sem *); 28 | extern void fio_sem_up(struct fio_sem *); 29 | extern void fio_sem_down(struct fio_sem *); 30 | extern bool fio_sem_down_trylock(struct fio_sem *); 31 | extern int fio_sem_down_timeout(struct fio_sem *, unsigned int); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /fio_shared_sem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Separate out the two helper functions for fio_sem from "fio_sem.c". 3 | * These two functions depend on fio shared memory. Other fio_sem 4 | * functions in "fio_sem.c" are used for fio shared memory. This file 5 | * separation is required to avoid build failures caused by circular 6 | * dependency. 7 | */ 8 | 9 | #include 10 | 11 | #include "fio_sem.h" 12 | #include "smalloc.h" 13 | 14 | /* 15 | * Allocate and initialize fio_sem lock object in the same manner as 16 | * fio_sem_init(), except the lock object is allocated from the fio 17 | * shared memory. This allows the parent process to free the lock 18 | * allocated by child processes. 19 | */ 20 | struct fio_sem *fio_shared_sem_init(int value) 21 | { 22 | struct fio_sem *sem; 23 | 24 | sem = smalloc(sizeof(struct fio_sem)); 25 | if (!sem) 26 | return NULL; 27 | 28 | if (!__fio_sem_init(sem, value)) 29 | return sem; 30 | 31 | fio_shared_sem_remove(sem); 32 | return NULL; 33 | } 34 | 35 | /* 36 | * Free the fio_sem lock object allocated by fio_shared_sem_init(). 37 | */ 38 | void fio_shared_sem_remove(struct fio_sem *sem) 39 | { 40 | __fio_sem_remove(sem); 41 | sfree(sem); 42 | } 43 | -------------------------------------------------------------------------------- /flow.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_FLOW_H 2 | #define FIO_FLOW_H 3 | 4 | #define FLOW_MAX_WEIGHT 1000 5 | 6 | int flow_threshold_exceeded(struct thread_data *td); 7 | void flow_init_job(struct thread_data *td); 8 | void flow_exit_job(struct thread_data *td); 9 | 10 | void flow_exit(void); 11 | void flow_init(void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /gclient.h: -------------------------------------------------------------------------------- 1 | #ifndef GFIO_CLIENT_H 2 | #define GFIO_CLIENT_H 3 | 4 | extern struct client_ops gfio_client_ops; 5 | 6 | extern void gfio_display_end_results(struct gfio_client *); 7 | 8 | #define GFIO_READ_R 0.13 9 | #define GFIO_READ_G 0.54 10 | #define GFIO_READ_B 0.13 11 | #define GFIO_WRITE_R 1.00 12 | #define GFIO_WRITE_G 0.00 13 | #define GFIO_WRITE_B 0.00 14 | #define GFIO_TRIM_R 0.24 15 | #define GFIO_TRIM_G 0.18 16 | #define GFIO_TRIM_B 0.52 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /gerror.h: -------------------------------------------------------------------------------- 1 | #ifndef GFIO_ERROR_H 2 | #define GFIO_ERROR_H 3 | 4 | extern void gfio_report_error(struct gui_entry *ge, const char *format, ...); 5 | extern void gfio_report_info(struct gui *ui, const char *title, const char *message); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /gettime.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_GETTIME_H 2 | #define FIO_GETTIME_H 3 | 4 | #include 5 | 6 | #include "arch/arch.h" 7 | #include "lib/seqlock.h" 8 | 9 | /* 10 | * Clock sources 11 | */ 12 | enum fio_cs { 13 | CS_GTOD = 1, 14 | CS_CGETTIME, 15 | CS_CPUCLOCK, 16 | CS_INVAL, 17 | }; 18 | 19 | extern int fio_get_mono_time(struct timespec *); 20 | extern void fio_gettime(struct timespec *, void *); 21 | extern void fio_gtod_init(void); 22 | extern void fio_clock_init(void); 23 | extern int fio_start_gtod_thread(void); 24 | extern int fio_monotonic_clocktest(int debug); 25 | extern void fio_local_clock_init(void); 26 | 27 | extern struct fio_ts { 28 | struct seqlock seqlock; 29 | struct timespec ts; 30 | } *fio_ts; 31 | 32 | static inline int fio_gettime_offload(struct timespec *ts) 33 | { 34 | unsigned int seq; 35 | 36 | if (!fio_ts) 37 | return 0; 38 | 39 | do { 40 | seq = read_seqlock_begin(&fio_ts->seqlock); 41 | *ts = fio_ts->ts; 42 | } while (read_seqlock_retry(&fio_ts->seqlock, seq)); 43 | 44 | return 1; 45 | } 46 | 47 | extern void fio_gtod_set_cpu(unsigned int cpu); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /goptions.h: -------------------------------------------------------------------------------- 1 | #ifndef GFIO_OPTIONS_H 2 | #define GFIO_OPTIONS_H 3 | 4 | #include 5 | 6 | void gopt_get_options_window(GtkWidget *window, struct gfio_client *gc); 7 | void gopt_init(void); 8 | void gopt_exit(void); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /helper_thread.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_HELPER_THREAD_H 2 | #define FIO_HELPER_THREAD_H 3 | 4 | #include 5 | 6 | struct fio_sem; 7 | struct sk_out; 8 | 9 | extern void helper_reset(void); 10 | extern void helper_do_stat(void); 11 | extern bool helper_should_exit(void); 12 | extern void helper_thread_destroy(void); 13 | extern void helper_thread_exit(void); 14 | extern int helper_thread_create(struct fio_sem *, struct sk_out *); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /helpers.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "helpers.h" 4 | 5 | #ifndef CONFIG_LINUX_FALLOCATE 6 | int fallocate(int fd, int mode, off_t offset, off_t len) 7 | { 8 | errno = ENOSYS; 9 | return -1; 10 | } 11 | #endif 12 | 13 | #ifndef CONFIG_POSIX_FALLOCATE 14 | int posix_fallocate(int fd, off_t offset, off_t len) 15 | { 16 | return 0; 17 | } 18 | #endif 19 | 20 | #ifndef CONFIG_SYNC_FILE_RANGE 21 | int sync_file_range(int fd, uint64_t offset, uint64_t nbytes, 22 | unsigned int flags) 23 | { 24 | errno = ENOSYS; 25 | return -1; 26 | } 27 | #endif 28 | 29 | #ifndef CONFIG_POSIX_FADVISE 30 | int posix_fadvise(int fd, off_t offset, off_t len, int advice) 31 | { 32 | return 0; 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_HELPERS_H 2 | #define FIO_HELPERS_H 3 | 4 | #include 5 | 6 | #include "os/os.h" 7 | 8 | extern int fallocate(int fd, int mode, off_t offset, off_t len); 9 | extern int posix_fallocate(int fd, off_t offset, off_t len); 10 | #ifndef CONFIG_SYNC_FILE_RANGE 11 | extern int sync_file_range(int fd, uint64_t offset, uint64_t nbytes, 12 | unsigned int flags); 13 | #endif 14 | extern int posix_fadvise(int fd, off_t offset, off_t len, int advice); 15 | 16 | #endif /* FIO_HELPERS_H_ */ 17 | -------------------------------------------------------------------------------- /io_u_queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "io_u_queue.h" 4 | #include "smalloc.h" 5 | 6 | bool io_u_qinit(struct io_u_queue *q, unsigned int nr, bool shared) 7 | { 8 | if (shared) 9 | q->io_us = smalloc(nr * sizeof(struct io_u *)); 10 | else 11 | q->io_us = calloc(nr, sizeof(struct io_u *)); 12 | 13 | if (!q->io_us) 14 | return false; 15 | 16 | q->nr = 0; 17 | q->max = nr; 18 | return true; 19 | } 20 | 21 | void io_u_qexit(struct io_u_queue *q, bool shared) 22 | { 23 | if (shared) 24 | sfree(q->io_us); 25 | else 26 | free(q->io_us); 27 | } 28 | 29 | bool io_u_rinit(struct io_u_ring *ring, unsigned int nr) 30 | { 31 | ring->max = nr + 1; 32 | if (ring->max & (ring->max - 1)) { 33 | ring->max--; 34 | ring->max |= ring->max >> 1; 35 | ring->max |= ring->max >> 2; 36 | ring->max |= ring->max >> 4; 37 | ring->max |= ring->max >> 8; 38 | ring->max |= ring->max >> 16; 39 | ring->max++; 40 | } 41 | 42 | ring->ring = calloc(ring->max, sizeof(struct io_u *)); 43 | if (!ring->ring) 44 | return false; 45 | 46 | ring->head = ring->tail = 0; 47 | return true; 48 | } 49 | 50 | void io_u_rexit(struct io_u_ring *ring) 51 | { 52 | free(ring->ring); 53 | } 54 | -------------------------------------------------------------------------------- /lib/axmap.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_BITMAP_H 2 | #define FIO_BITMAP_H 3 | 4 | #include 5 | #include "types.h" 6 | 7 | struct axmap; 8 | struct axmap *axmap_new(uint64_t nr_bits); 9 | void axmap_free(struct axmap *bm); 10 | 11 | void axmap_set(struct axmap *axmap, uint64_t bit_nr); 12 | unsigned int axmap_set_nr(struct axmap *axmap, uint64_t bit_nr, unsigned int nr_bits); 13 | bool axmap_isset(struct axmap *axmap, uint64_t bit_nr); 14 | uint64_t axmap_next_free(struct axmap *axmap, uint64_t bit_nr); 15 | void axmap_reset(struct axmap *axmap); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lib/bloom.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_BLOOM_H 2 | #define FIO_BLOOM_H 3 | 4 | #include 5 | #include "../lib/types.h" 6 | 7 | struct bloom; 8 | 9 | struct bloom *bloom_new(uint64_t entries); 10 | void bloom_free(struct bloom *b); 11 | bool bloom_set(struct bloom *b, uint32_t *data, unsigned int nwords); 12 | bool bloom_string(struct bloom *b, const char *data, unsigned int len, bool); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lib/bswap.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_BSWAP_H 2 | #define FIO_BSWAP_H 3 | 4 | #include 5 | 6 | #ifdef CONFIG_LITTLE_ENDIAN 7 | static inline uint32_t __be32_to_cpu(uint32_t val) 8 | { 9 | uint32_t c1, c2, c3, c4; 10 | 11 | c1 = (val >> 24) & 0xff; 12 | c2 = (val >> 16) & 0xff; 13 | c3 = (val >> 8) & 0xff; 14 | c4 = val & 0xff; 15 | 16 | return c1 | c2 << 8 | c3 << 16 | c4 << 24; 17 | } 18 | 19 | static inline uint64_t __be64_to_cpu(uint64_t val) 20 | { 21 | uint64_t c1, c2, c3, c4, c5, c6, c7, c8; 22 | 23 | c1 = (val >> 56) & 0xff; 24 | c2 = (val >> 48) & 0xff; 25 | c3 = (val >> 40) & 0xff; 26 | c4 = (val >> 32) & 0xff; 27 | c5 = (val >> 24) & 0xff; 28 | c6 = (val >> 16) & 0xff; 29 | c7 = (val >> 8) & 0xff; 30 | c8 = val & 0xff; 31 | 32 | return c1 | c2 << 8 | c3 << 16 | c4 << 24 | c5 << 32 | c6 << 40 | c7 << 48 | c8 << 56; 33 | } 34 | #else 35 | static inline uint64_t __be64_to_cpu(uint64_t val) 36 | { 37 | return val; 38 | } 39 | 40 | static inline uint32_t __be32_to_cpu(uint32_t val) 41 | { 42 | return val; 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /lib/ffz.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_FFZ_H 2 | #define FIO_FFZ_H 3 | 4 | #include 5 | 6 | static inline int ffs64(uint64_t word) 7 | { 8 | int r = 0; 9 | 10 | if ((word & 0xffffffff) == 0) { 11 | r += 32; 12 | word >>= 32; 13 | } 14 | if (!(word & 0xffff)) { 15 | word >>= 16; 16 | r += 16; 17 | } 18 | if (!(word & 0xff)) { 19 | word >>= 8; 20 | r += 8; 21 | } 22 | if (!(word & 0xf)) { 23 | word >>= 4; 24 | r += 4; 25 | } 26 | if (!(word & 3)) { 27 | word >>= 2; 28 | r += 2; 29 | } 30 | if (!(word & 1)) 31 | r += 1; 32 | 33 | return r; 34 | } 35 | 36 | #ifndef ARCH_HAVE_FFZ 37 | 38 | static inline int ffz(unsigned long bitmask) 39 | { 40 | return ffs64(~bitmask); 41 | } 42 | 43 | #else 44 | #define ffz(bitmask) arch_ffz(bitmask) 45 | #endif 46 | 47 | static inline int ffz64(uint64_t bitmask) 48 | { 49 | return ffs64(~bitmask); 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /lib/fls.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASM_GENERIC_BITOPS_FLS_H_ 2 | #define _ASM_GENERIC_BITOPS_FLS_H_ 3 | 4 | /** 5 | * fls - find last (most-significant) bit set 6 | * @x: the word to search 7 | * 8 | * This is defined the same way as ffs. 9 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 10 | */ 11 | 12 | static inline int __fls(int x) 13 | { 14 | int r = 32; 15 | 16 | if (!x) 17 | return 0; 18 | if (!(x & 0xffff0000u)) { 19 | x <<= 16; 20 | r -= 16; 21 | } 22 | if (!(x & 0xff000000u)) { 23 | x <<= 8; 24 | r -= 8; 25 | } 26 | if (!(x & 0xf0000000u)) { 27 | x <<= 4; 28 | r -= 4; 29 | } 30 | if (!(x & 0xc0000000u)) { 31 | x <<= 2; 32 | r -= 2; 33 | } 34 | if (!(x & 0x80000000u)) { 35 | r -= 1; 36 | } 37 | return r; 38 | } 39 | 40 | #endif /* _ASM_GENERIC_BITOPS_FLS_H_ */ 41 | -------------------------------------------------------------------------------- /lib/gauss.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_GAUSS_H 2 | #define FIO_GAUSS_H 3 | 4 | #include 5 | #include "rand.h" 6 | 7 | struct gauss_state { 8 | struct frand_state r; 9 | uint64_t nranges; 10 | unsigned int stddev; 11 | unsigned int rand_off; 12 | bool disable_hash; 13 | }; 14 | 15 | void gauss_init(struct gauss_state *gs, unsigned long nranges, double dev, 16 | double center, unsigned int seed); 17 | unsigned long long gauss_next(struct gauss_state *gs); 18 | void gauss_disable_hash(struct gauss_state *gs); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/getrusage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "getrusage.h" 3 | 4 | int fio_getrusage(struct rusage *ru) 5 | { 6 | #ifdef CONFIG_RUSAGE_THREAD 7 | if (!getrusage(RUSAGE_THREAD, ru)) 8 | return 0; 9 | if (errno != EINVAL) 10 | return -1; 11 | /* Fall through to RUSAGE_SELF */ 12 | #endif 13 | return getrusage(RUSAGE_SELF, ru); 14 | } 15 | -------------------------------------------------------------------------------- /lib/getrusage.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_GETRUSAGE_H 2 | #define FIO_GETRUSAGE_H 3 | 4 | #include 5 | #include 6 | 7 | extern int fio_getrusage(struct rusage *ru); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /lib/hweight.c: -------------------------------------------------------------------------------- 1 | #include "hweight.h" 2 | 3 | unsigned int hweight8(uint8_t w) 4 | { 5 | unsigned int res = w - ((w >> 1) & 0x55); 6 | 7 | res = (res & 0x33) + ((res >> 2) & 0x33); 8 | return (res + (res >> 4)) & 0x0F; 9 | } 10 | 11 | unsigned int hweight32(uint32_t w) 12 | { 13 | unsigned int res = w - ((w >> 1) & 0x55555555); 14 | 15 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); 16 | res = (res + (res >> 4)) & 0x0F0F0F0F; 17 | res = res + (res >> 8); 18 | return (res + (res >> 16)) & 0x000000FF; 19 | } 20 | 21 | unsigned int hweight64(uint64_t w) 22 | { 23 | #if BITS_PER_LONG == 32 24 | return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); 25 | #else 26 | uint64_t res = w - ((w >> 1) & 0x5555555555555555ULL); 27 | res = (res & 0x3333333333333333ULL) + ((res >> 2) & 0x3333333333333333ULL); 28 | res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 29 | res = res + (res >> 8); 30 | res = res + (res >> 16); 31 | return (res + (res >> 32)) & 0x00000000000000FFULL; 32 | #endif 33 | } 34 | -------------------------------------------------------------------------------- /lib/hweight.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_HWEIGHT_H 2 | #define FIO_HWEIGHT_H 3 | 4 | #include 5 | 6 | unsigned int hweight8(uint8_t w); 7 | unsigned int hweight32(uint32_t w); 8 | unsigned int hweight64(uint64_t w); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /lib/ieee754.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_IEEE754_H 2 | #define FIO_IEEE754_H 3 | 4 | #include 5 | 6 | extern uint64_t pack754(long double f, unsigned bits, unsigned expbits); 7 | extern long double unpack754(uint64_t i, unsigned bits, unsigned expbits); 8 | 9 | #define fio_double_to_uint64(val) pack754((val), 64, 11) 10 | #define fio_uint64_to_double(val) unpack754((val), 64, 11) 11 | 12 | typedef struct fio_fp64 { 13 | union { 14 | uint64_t i; 15 | double f; 16 | uint8_t filler[16]; 17 | } u; 18 | } fio_fp64_t; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/lfsr.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_LFSR_H 2 | #define FIO_LFSR_H 3 | 4 | #include 5 | 6 | #define FIO_MAX_TAPS 6 7 | 8 | struct lfsr_taps { 9 | unsigned int length; 10 | unsigned int taps[FIO_MAX_TAPS]; 11 | }; 12 | 13 | 14 | struct fio_lfsr { 15 | uint64_t xormask; 16 | uint64_t last_val; 17 | uint64_t cached_bit; 18 | uint64_t max_val; 19 | uint64_t num_vals; 20 | uint64_t cycle_length; 21 | uint64_t cached_cycle_length; 22 | unsigned int spin; 23 | }; 24 | 25 | int lfsr_next(struct fio_lfsr *fl, uint64_t *off); 26 | int lfsr_init(struct fio_lfsr *fl, uint64_t size, 27 | uint64_t seed, unsigned int spin); 28 | int lfsr_reset(struct fio_lfsr *fl, uint64_t seed); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /lib/memalign.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "memalign.h" 5 | #include "smalloc.h" 6 | 7 | #define PTR_ALIGN(ptr, mask) \ 8 | (char *)((uintptr_t)((ptr) + (mask)) & ~(mask)) 9 | 10 | struct align_footer { 11 | unsigned int offset; 12 | }; 13 | 14 | void *__fio_memalign(size_t alignment, size_t size, malloc_fn fn) 15 | { 16 | struct align_footer *f; 17 | void *ptr, *ret = NULL; 18 | 19 | assert(!(alignment & (alignment - 1))); 20 | 21 | ptr = fn(size + alignment + sizeof(*f) - 1); 22 | if (ptr) { 23 | ret = PTR_ALIGN(ptr, alignment - 1); 24 | f = ret + size; 25 | f->offset = (uintptr_t) ret - (uintptr_t) ptr; 26 | } 27 | 28 | return ret; 29 | } 30 | 31 | void __fio_memfree(void *ptr, size_t size, free_fn fn) 32 | { 33 | struct align_footer *f = ptr + size; 34 | 35 | fn(ptr - f->offset); 36 | } 37 | -------------------------------------------------------------------------------- /lib/memalign.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_MEMALIGN_H 2 | #define FIO_MEMALIGN_H 3 | 4 | #include 5 | #include 6 | 7 | typedef void* (*malloc_fn)(size_t); 8 | typedef void (*free_fn)(void*); 9 | 10 | extern void *__fio_memalign(size_t alignment, size_t size, malloc_fn fn); 11 | extern void __fio_memfree(void *ptr, size_t size, free_fn fn); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /lib/memcpy.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_MEMCPY_H 2 | #define FIO_MEMCPY_H 3 | 4 | int fio_memcpy_test(const char *type); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /lib/mountcheck.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_MOUNT_CHECK_H 2 | #define FIO_MOUNT_CHECK_H 3 | 4 | extern int device_is_mounted(const char *); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /lib/nowarn_snprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef _NOWARN_SNPRINTF_H_ 2 | #define _NOWARN_SNPRINTF_H_ 3 | 4 | #include 5 | #include 6 | 7 | static inline int nowarn_snprintf(char *str, size_t size, const char *format, 8 | ...) 9 | { 10 | va_list args; 11 | int res; 12 | 13 | va_start(args, format); 14 | #if __GNUC__ -0 >= 8 15 | #pragma GCC diagnostic push "-Wformat-truncation" 16 | #pragma GCC diagnostic ignored "-Wformat-truncation" 17 | #endif 18 | res = vsnprintf(str, size, format, args); 19 | #if __GNUC__ -0 >= 8 20 | #pragma GCC diagnostic pop "-Wformat-truncation" 21 | #endif 22 | va_end(args); 23 | 24 | return res; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /lib/num2str.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_NUM2STR_H 2 | #define FIO_NUM2STR_H 3 | 4 | #include 5 | 6 | enum n2s_unit { 7 | N2S_NONE = 0, 8 | N2S_PERSEC = 1, 9 | N2S_BYTE = 2, 10 | N2S_BIT = 3, 11 | N2S_BYTEPERSEC = 4, 12 | N2S_BITPERSEC = 5, 13 | }; 14 | 15 | extern char *num2str(uint64_t, int, int, int, enum n2s_unit); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lib/output_buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "output_buffer.h" 5 | #include "../minmax.h" 6 | 7 | #define BUF_INC 1024 8 | 9 | void buf_output_init(struct buf_output *out) 10 | { 11 | out->max_buflen = 0; 12 | out->buflen = 0; 13 | out->buf = NULL; 14 | } 15 | 16 | void buf_output_free(struct buf_output *out) 17 | { 18 | free(out->buf); 19 | buf_output_init(out); 20 | } 21 | 22 | size_t buf_output_add(struct buf_output *out, const char *buf, size_t len) 23 | { 24 | if (out->max_buflen - out->buflen < len) { 25 | size_t need = len - (out->max_buflen - out->buflen); 26 | size_t old_max = out->max_buflen; 27 | 28 | need = max((size_t) BUF_INC, need); 29 | out->max_buflen += need; 30 | out->buf = realloc(out->buf, out->max_buflen); 31 | 32 | old_max = max(old_max, out->buflen + len); 33 | if (old_max + need > out->max_buflen) 34 | need = out->max_buflen - old_max; 35 | memset(&out->buf[old_max], 0, need); 36 | } 37 | 38 | memcpy(&out->buf[out->buflen], buf, len); 39 | out->buflen += len; 40 | return len; 41 | } 42 | -------------------------------------------------------------------------------- /lib/output_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_OUTPUT_BUFFER_H 2 | #define FIO_OUTPUT_BUFFER_H 3 | 4 | #include 5 | 6 | struct buf_output { 7 | char *buf; 8 | size_t buflen; 9 | size_t max_buflen; 10 | }; 11 | 12 | void buf_output_init(struct buf_output *out); 13 | void buf_output_free(struct buf_output *out); 14 | size_t buf_output_add(struct buf_output *out, const char *buf, size_t len); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /lib/pow2.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_POW2_H 2 | #define FIO_POW2_H 3 | 4 | #include 5 | #include "types.h" 6 | 7 | static inline bool is_power_of_2(uint64_t val) 8 | { 9 | return (val != 0 && ((val & (val - 1)) == 0)); 10 | } 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /lib/roundup.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_ROUNDUP_H 2 | #define FIO_ROUNDUP_H 3 | 4 | #include "lib/fls.h" 5 | 6 | static inline unsigned roundup_pow2(unsigned depth) 7 | { 8 | return 1UL << __fls(depth - 1); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /lib/seqlock.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_SEQLOCK_H 2 | #define FIO_SEQLOCK_H 3 | 4 | #include "types.h" 5 | #include "../arch/arch.h" 6 | 7 | struct seqlock { 8 | #ifdef __cplusplus 9 | std::atomic sequence; 10 | #else 11 | volatile unsigned int sequence; 12 | #endif 13 | }; 14 | 15 | static inline void seqlock_init(struct seqlock *s) 16 | { 17 | s->sequence = 0; 18 | } 19 | 20 | static inline unsigned int read_seqlock_begin(struct seqlock *s) 21 | { 22 | unsigned int seq; 23 | 24 | do { 25 | seq = atomic_load_acquire(&s->sequence); 26 | if (!(seq & 1)) 27 | break; 28 | nop; 29 | } while (1); 30 | 31 | return seq; 32 | } 33 | 34 | static inline bool read_seqlock_retry(struct seqlock *s, unsigned int seq) 35 | { 36 | read_barrier(); 37 | return s->sequence != seq; 38 | } 39 | 40 | static inline void write_seqlock_begin(struct seqlock *s) 41 | { 42 | s->sequence = atomic_load_acquire(&s->sequence) + 1; 43 | } 44 | 45 | static inline void write_seqlock_end(struct seqlock *s) 46 | { 47 | atomic_store_release(&s->sequence, s->sequence + 1); 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /lib/strntol.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "strntol.h" 6 | 7 | long strntol(const char *str, size_t sz, char **end, int base) 8 | { 9 | /* Expect that digit representation of LONG_MAX/MIN 10 | * not greater than this buffer */ 11 | char buf[24]; 12 | long ret; 13 | const char *beg = str; 14 | 15 | /* Catch up leading spaces */ 16 | for (; beg && sz && *beg == ' '; beg++, sz--) 17 | ; 18 | 19 | if (!sz || sz >= sizeof(buf)) { 20 | if (end) 21 | *end = (char *)str; 22 | return 0; 23 | } 24 | 25 | memcpy(buf, beg, sz); 26 | buf[sz] = '\0'; 27 | ret = strtol(buf, end, base); 28 | if (ret == LONG_MIN || ret == LONG_MAX) 29 | return ret; 30 | if (end) 31 | *end = (char *)beg + (*end - buf); 32 | return ret; 33 | } 34 | -------------------------------------------------------------------------------- /lib/strntol.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_STRNTOL_H 2 | #define FIO_STRNTOL_H 3 | 4 | #include 5 | 6 | long strntol(const char *str, size_t sz, char **end, int base); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /lib/types.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_TYPES_H 2 | #define FIO_TYPES_H 3 | 4 | #if !defined(CONFIG_HAVE_BOOL) && !defined(__cplusplus) 5 | typedef int bool; 6 | #ifndef false 7 | #define false 0 8 | #endif 9 | #ifndef true 10 | #define true 1 11 | #endif 12 | #else 13 | #include /* IWYU pragma: export */ 14 | #endif 15 | 16 | #if !defined(CONFIG_HAVE_KERNEL_RWF_T) 17 | typedef int __kernel_rwf_t; 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lib/zipf.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_ZIPF_H 2 | #define FIO_ZIPF_H 3 | 4 | #include 5 | #include "rand.h" 6 | #include "types.h" 7 | 8 | struct zipf_state { 9 | uint64_t nranges; 10 | double theta; 11 | double zeta2; 12 | double zetan; 13 | double pareto_pow; 14 | struct frand_state rand; 15 | uint64_t rand_off; 16 | bool disable_hash; 17 | }; 18 | 19 | void zipf_init(struct zipf_state *zs, uint64_t nranges, double theta, 20 | double center, unsigned int seed); 21 | uint64_t zipf_next(struct zipf_state *zs); 22 | 23 | void pareto_init(struct zipf_state *zs, uint64_t nranges, double h, 24 | double center, unsigned int seed); 25 | uint64_t pareto_next(struct zipf_state *zs); 26 | void zipf_disable_hash(struct zipf_state *zs); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_LOG_H 2 | #define FIO_LOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "lib/output_buffer.h" 9 | 10 | extern FILE *f_out; 11 | extern FILE *f_err; 12 | 13 | extern ssize_t log_err(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2))); 14 | extern ssize_t log_info(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2))); 15 | extern size_t __log_buf(struct buf_output *, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); 16 | extern size_t log_valist(const char *str, va_list); 17 | extern void log_prevalist(int type, const char *str, va_list); 18 | extern size_t log_info_buf(const char *buf, size_t len); 19 | extern int log_info_flush(void); 20 | 21 | #define log_buf(buf, format, args...) \ 22 | ({ \ 23 | size_t __ret; \ 24 | if ((buf) != NULL) \ 25 | __ret = __log_buf(buf, format, ##args); \ 26 | else \ 27 | __ret = log_info(format, ##args); \ 28 | __ret; \ 29 | }) 30 | 31 | enum { 32 | FIO_LOG_DEBUG = 1, 33 | FIO_LOG_INFO = 2, 34 | FIO_LOG_ERR = 3, 35 | FIO_LOG_NR = 4, 36 | }; 37 | 38 | extern const char *log_get_level(int level); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /minmax.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_MIN_MAX_H 2 | #define FIO_MIN_MAX_H 3 | 4 | #ifndef min 5 | #define min(x,y) ({ \ 6 | __typeof__(x) _x = (x); \ 7 | __typeof__(y) _y = (y); \ 8 | (void) (&_x == &_y); \ 9 | _x < _y ? _x : _y; }) 10 | #endif 11 | 12 | #ifndef max 13 | #define max(x,y) ({ \ 14 | __typeof__(x) _x = (x); \ 15 | __typeof__(y) _y = (y); \ 16 | (void) (&_x == &_y); \ 17 | _x > _y ? _x : _y; }) 18 | #endif 19 | 20 | #define min_not_zero(x, y) ({ \ 21 | __typeof__(x) __x = (x); \ 22 | __typeof__(y) __y = (y); \ 23 | __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /os/kcompat.h: -------------------------------------------------------------------------------- 1 | #ifndef _KCOMPAT_H_ 2 | #define _KCOMPAT_H_ 3 | 4 | #include 5 | 6 | #define u64 uint64_t 7 | #define u32 uint32_t 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /os/os-aix.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_OS_AIX_H 2 | #define FIO_OS_AIX_H 3 | 4 | #define FIO_OS os_aix 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../file.h" 12 | 13 | #define FIO_HAVE_ODIRECT 14 | #define FIO_USE_GENERIC_INIT_RANDOM_STATE 15 | 16 | #define OS_MAP_ANON MAP_ANON 17 | #define OS_MSG_DONTWAIT 0 18 | 19 | #define FIO_USE_GENERIC_SWAP 20 | 21 | #ifdef CONFIG_PTHREAD_GETAFFINITY 22 | #define FIO_HAVE_GET_THREAD_AFFINITY 23 | #define fio_get_thread_affinity(mask) \ 24 | pthread_getaffinity_np(pthread_self(), sizeof(mask), &(mask)) 25 | #endif 26 | 27 | static inline int blockdev_invalidate_cache(struct fio_file *f) 28 | { 29 | return ENOTSUP; 30 | } 31 | 32 | static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 33 | { 34 | struct devinfo info; 35 | 36 | if (!ioctl(f->fd, IOCINFO, &info)) { 37 | *bytes = (unsigned long long)info.un.scdk.numblks * 38 | info.un.scdk.blksize; 39 | return 0; 40 | } 41 | 42 | return errno; 43 | } 44 | 45 | static inline unsigned long long os_phys_mem(void) 46 | { 47 | long mem = sysconf(_SC_AIX_REALMEM); 48 | 49 | if (mem == -1) 50 | return 0; 51 | 52 | return (unsigned long long) mem * 1024; 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /os/os-windows-7.h: -------------------------------------------------------------------------------- 1 | #define FIO_MAX_CPUS 512 /* From Hyper-V 2016's max logical processors */ 2 | #define FIO_CPU_MASK_STRIDE 64 3 | #define FIO_CPU_MASK_ROWS (FIO_MAX_CPUS / FIO_CPU_MASK_STRIDE) 4 | 5 | typedef struct { 6 | uint64_t row[FIO_CPU_MASK_ROWS]; 7 | } os_cpu_mask_t; 8 | -------------------------------------------------------------------------------- /os/windows/WixUI_fio.wxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | The Setup Wizard will install [ProductName] on your computer. Click Install to continue or Cancel to exit the Setup Wizard. 11 | 12 | -------------------------------------------------------------------------------- /os/windows/posix.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_WINDOWS_POSIX_H 2 | #define FIO_WINDOWS_POSIX_H 3 | 4 | typedef int clockid_t; 5 | 6 | extern int clock_gettime(clockid_t clock_id, struct timespec *tp); 7 | extern int inet_aton(const char *, struct in_addr *); 8 | extern int win_to_posix_error(DWORD winerr); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /os/windows/posix/include/arpa/inet.h: -------------------------------------------------------------------------------- 1 | #ifndef ARPA_INET_H 2 | #define ARPA_INET_H 3 | 4 | #include 5 | #include 6 | 7 | typedef int socklen_t; 8 | typedef int in_addr_t; 9 | 10 | /* EAI_SYSTEM isn't used on Windows, so map it to EAI_FAIL */ 11 | #define EAI_SYSTEM EAI_FAIL 12 | 13 | in_addr_t inet_network(const char *cp); 14 | 15 | #endif /* ARPA_INET_H */ 16 | -------------------------------------------------------------------------------- /os/windows/posix/include/asm/types.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_TYPES_H 2 | #define ASM_TYPES_H 3 | 4 | typedef unsigned short __u16; 5 | typedef unsigned int __u32; 6 | typedef unsigned long long __u64; 7 | 8 | #endif /* ASM_TYPES_H */ 9 | -------------------------------------------------------------------------------- /os/windows/posix/include/dirent.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRENT_H 2 | #define DIRENT_H 3 | 4 | #include 5 | 6 | struct dirent 7 | { 8 | ino_t d_ino; /* File serial number */ 9 | char d_name[MAX_PATH]; /* Name of entry */ 10 | }; 11 | 12 | struct dirent_ctx 13 | { 14 | HANDLE find_handle; 15 | char dirname[MAX_PATH]; 16 | }; 17 | 18 | typedef struct dirent_ctx DIR; 19 | 20 | DIR *opendir(const char *dirname); 21 | struct dirent *readdir(DIR *dirp); 22 | int closedir(DIR *dirp); 23 | 24 | #endif /* DIRENT_H */ 25 | -------------------------------------------------------------------------------- /os/windows/posix/include/dlfcn.h: -------------------------------------------------------------------------------- 1 | #ifndef DLFCN_H 2 | #define DLFCN_H 3 | 4 | #define RTLD_LAZY 1 5 | 6 | void *dlopen(const char *file, int mode); 7 | int dlclose(void *handle); 8 | void *dlsym(void *restrict handle, const char *restrict name); 9 | char *dlerror(void); 10 | 11 | #endif /* DLFCN_H */ 12 | -------------------------------------------------------------------------------- /os/windows/posix/include/libgen.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBGEN_H 2 | #define LIBGEN_H 3 | 4 | char *basename(char *path); 5 | 6 | #endif /* LIBGEN_H */ 7 | -------------------------------------------------------------------------------- /os/windows/posix/include/netdb.h: -------------------------------------------------------------------------------- 1 | #ifndef NETDB_H 2 | #define NETDB_H 3 | 4 | #endif /* NETDB_H */ 5 | -------------------------------------------------------------------------------- /os/windows/posix/include/netinet/in.h: -------------------------------------------------------------------------------- 1 | #ifndef NETINET_IN_H 2 | #define NETINET_IN_H 3 | 4 | #include 5 | #include 6 | 7 | 8 | #endif /* NETINET_IN_H */ 9 | -------------------------------------------------------------------------------- /os/windows/posix/include/netinet/tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef NETINET_TCP_H 2 | #define NETINET_TCP_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /os/windows/posix/include/poll.h: -------------------------------------------------------------------------------- 1 | #ifndef POLL_H 2 | #define POLL_H 3 | 4 | #include 5 | 6 | typedef int nfds_t; 7 | 8 | int poll(struct pollfd fds[], nfds_t nfds, int timeout); 9 | 10 | #endif /* POLL_H */ 11 | -------------------------------------------------------------------------------- /os/windows/posix/include/semaphore.h: -------------------------------------------------------------------------------- 1 | #ifndef SEMAPHORE_H 2 | #define SEMAPHORE_H 3 | 4 | #endif /* SEMAPHORE_H */ 5 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/ioctl.h: -------------------------------------------------------------------------------- 1 | #ifndef IOCTL_H 2 | #define IOCTL_H 3 | 4 | /* This file is empty since it only needs to exist on Windows 5 | but isn't otherwise used */ 6 | 7 | #endif /* IOCTL_H */ -------------------------------------------------------------------------------- /os/windows/posix/include/sys/ipc.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_IPC_H 2 | #define SYS_IPC_H 3 | 4 | #endif /* SYS_IPC_H */ 5 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/mman.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_MMAN_H 2 | #define SYS_MMAN_H 3 | 4 | #include 5 | 6 | #define PROT_NONE 0x1 7 | #define PROT_READ 0x2 8 | #define PROT_WRITE 0x4 9 | 10 | #define MAP_ANON 0x1 11 | #define MAP_ANONYMOUS MAP_ANON 12 | #define MAP_FIXED 0x2 13 | #define MAP_HASSEMAPHORE 0x4 14 | #define MAP_INHERIT 0x8 15 | #define MAP_NOCORE 0x10 16 | #define MAP_NOSYNC 0x20 17 | #define MAP_PREFAULT_READ 0x40 18 | #define MAP_PRIVATE 0x80 19 | #define MAP_SHARED 0x100 20 | #define MAP_STACK 0x200 21 | 22 | #define MAP_FAILED NULL 23 | 24 | #define MS_ASYNC 0x1 25 | #define MS_SYNC 0x2 26 | #define MS_INVALIDATE 0x3 27 | 28 | int posix_madvise(void *addr, size_t len, int advice); 29 | void *mmap(void *addr, size_t len, int prot, int flags, 30 | int fildes, off_t off); 31 | int munmap(void *addr, size_t len); 32 | int msync(void *addr, size_t len, int flags); 33 | int munlock(const void * addr, size_t len); 34 | int mlock(const void *addr, size_t len); 35 | 36 | #endif /* SYS_MMAN_H */ 37 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/resource.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_RESOURCE_H 2 | #define SYS_RESOURCE_H 3 | 4 | #define RUSAGE_SELF 0 5 | #define RUSAGE_THREAD 1 6 | 7 | struct rusage 8 | { 9 | struct timeval ru_utime; 10 | struct timeval ru_stime; 11 | int ru_nvcsw; 12 | int ru_minflt; 13 | int ru_majflt; 14 | int ru_nivcsw; 15 | }; 16 | 17 | int getrusage(int who, struct rusage *r_usage); 18 | 19 | #endif /* SYS_RESOURCE_H */ 20 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/shm.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_SHM_H 2 | #define SYS_SHM_H 3 | 4 | #define IPC_RMID 0x1 5 | #define IPC_CREAT 0x2 6 | #define IPC_PRIVATE 0x4 7 | 8 | typedef int uid_t; 9 | typedef int gid_t; 10 | 11 | typedef int shmatt_t; 12 | typedef int key_t; 13 | 14 | struct ipc_perm 15 | { 16 | uid_t uid; /* owner's user ID */ 17 | gid_t gid; /* owner's group ID */ 18 | uid_t cuid; /* creator's user ID */ 19 | gid_t cgid; /* creator's group ID */ 20 | mode_t mode; /* read/write permission */ 21 | }; 22 | 23 | 24 | struct shmid_ds 25 | { 26 | struct ipc_perm shm_perm; /* operation permission structure */ 27 | size_t shm_segsz; /* size of segment in bytes */ 28 | pid_t shm_lpid; /* process ID of last shared memory operation */ 29 | pid_t shm_cpid; /* process ID of creator */ 30 | shmatt_t shm_nattch; /* number of current attaches */ 31 | time_t shm_atime; /* time of last shmat() */ 32 | time_t shm_dtime; /* time of last shmdt() */ 33 | time_t shm_ctime; /* time of last change by shmctl() */ 34 | }; 35 | 36 | int shmctl(int shmid, int cmd, struct shmid_ds *buf); 37 | int shmget(key_t key, size_t size, int shmflg); 38 | void *shmat(int shmid, const void *shmaddr, int shmflg); 39 | int shmdt(const void *shmaddr); 40 | 41 | #endif /* SYS_SHM_H */ 42 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/socket.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_SOCKET_H 2 | #define SYS_SOCKET_H 3 | 4 | #endif /* SYS_SOCKET_H */ 5 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/uio.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_UIO_H 2 | #define SYS_UIO_H 3 | 4 | #include 5 | #include 6 | 7 | struct iovec 8 | { 9 | void *iov_base; /* Base address of a memory region for input or output */ 10 | size_t iov_len; /* The size of the memory pointed to by iov_base */ 11 | }; 12 | 13 | ssize_t readv(int fildes, const struct iovec *iov, int iovcnt); 14 | ssize_t writev(int fildes, const struct iovec *iov, int iovcnt); 15 | 16 | #endif /* SYS_UIO_H */ 17 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/un.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_UN_H 2 | #define SYS_UN_H 3 | 4 | typedef int sa_family_t; 5 | typedef int in_port_t; 6 | 7 | struct sockaddr_un 8 | { 9 | sa_family_t sun_family; /* Address family */ 10 | char sun_path[260]; /* Socket pathname */ 11 | }; 12 | 13 | #endif /* SYS_UN_H */ 14 | -------------------------------------------------------------------------------- /os/windows/posix/include/sys/wait.h: -------------------------------------------------------------------------------- 1 | #ifndef SYS_WAIT_H 2 | #define SYS_WAIT_H 3 | 4 | #define WIFSIGNALED(a) 0 5 | #define WIFEXITED(a) 0 6 | #define WTERMSIG(a) 0 7 | #define WEXITSTATUS(a) 0 8 | #define WNOHANG 1 9 | 10 | pid_t waitpid(pid_t, int *stat_loc, int options); 11 | 12 | #endif /* SYS_WAIT_H */ 13 | -------------------------------------------------------------------------------- /os/windows/posix/include/syslog.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSLOG_H 2 | #define SYSLOG_H 3 | 4 | int syslog(int priority, const char *format, ...); 5 | 6 | #define LOG_INFO 0x1 7 | #define LOG_ERROR 0x2 8 | #define LOG_WARN 0x4 9 | 10 | #define LOG_NDELAY 0x1 11 | #define LOG_NOWAIT 0x2 12 | #define LOG_PID 0x4 13 | #define LOG_USER 0x8 14 | 15 | void closelog(void); 16 | void openlog(const char *ident, int logopt, int facility); 17 | 18 | #endif /* SYSLOG_H */ 19 | -------------------------------------------------------------------------------- /oslib/asprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "oslib/asprintf.h" 4 | 5 | #ifndef CONFIG_HAVE_VASPRINTF 6 | int vasprintf(char **strp, const char *fmt, va_list ap) 7 | { 8 | va_list ap_copy; 9 | char *str; 10 | int len; 11 | 12 | #ifdef va_copy 13 | va_copy(ap_copy, ap); 14 | #else 15 | __va_copy(ap_copy, ap); 16 | #endif 17 | len = vsnprintf(NULL, 0, fmt, ap_copy); 18 | va_end(ap_copy); 19 | 20 | if (len < 0) 21 | return len; 22 | 23 | len++; 24 | str = malloc(len); 25 | *strp = str; 26 | return str ? vsnprintf(str, len, fmt, ap) : -1; 27 | } 28 | #endif 29 | 30 | #ifndef CONFIG_HAVE_ASPRINTF 31 | int asprintf(char **strp, const char *fmt, ...) 32 | { 33 | va_list arg; 34 | int done; 35 | 36 | va_start(arg, fmt); 37 | done = vasprintf(strp, fmt, arg); 38 | va_end(arg); 39 | 40 | return done; 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /oslib/asprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_ASPRINTF_H 2 | #define FIO_ASPRINTF_H 3 | 4 | #include 5 | 6 | #ifndef CONFIG_HAVE_VASPRINTF 7 | int vasprintf(char **strp, const char *fmt, va_list ap); 8 | #endif 9 | #ifndef CONFIG_HAVE_ASPRINTF 10 | int asprintf(char **strp, const char *fmt, ...); 11 | #endif 12 | 13 | #endif /* FIO_ASPRINTF_H */ 14 | -------------------------------------------------------------------------------- /oslib/getopt.h: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_GETOPT_LONG_ONLY 2 | 3 | #include 4 | 5 | #else 6 | 7 | #ifndef _GETOPT_H 8 | #define _GETOPT_H 9 | 10 | struct option { 11 | const char *name; 12 | int has_arg; 13 | int *flag; 14 | int val; 15 | }; 16 | 17 | enum { 18 | no_argument = 0, 19 | required_argument = 1, 20 | optional_argument = 2, 21 | }; 22 | 23 | int getopt_long_only(int, char *const *, const char *, const struct option *, int *); 24 | 25 | #endif 26 | #endif 27 | -------------------------------------------------------------------------------- /oslib/inet_aton.c: -------------------------------------------------------------------------------- 1 | #include "inet_aton.h" 2 | 3 | int inet_aton(const char *cp, struct in_addr *inp) 4 | { 5 | return inet_pton(AF_INET, cp, inp); 6 | } 7 | -------------------------------------------------------------------------------- /oslib/inet_aton.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_INET_ATON_LIB_H 2 | #define FIO_INET_ATON_LIB_H 3 | 4 | #include 5 | 6 | int inet_aton(const char *cp, struct in_addr *inp); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /oslib/linux-dev-lookup.h: -------------------------------------------------------------------------------- 1 | #ifndef LINUX_DEV_LOOKUP 2 | #define LINUX_DEV_LOOKUP 3 | 4 | int blktrace_lookup_device(const char *redirect, char *path, unsigned int maj, 5 | unsigned int min); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /oslib/statx.c: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_HAVE_STATX 2 | #include "statx.h" 3 | 4 | #ifdef CONFIG_HAVE_STATX_SYSCALL 5 | #include 6 | #include 7 | 8 | int statx(int dfd, const char *pathname, int flags, unsigned int mask, 9 | struct statx *buffer) 10 | { 11 | return syscall(__NR_statx, dfd, pathname, flags, mask, buffer); 12 | } 13 | #else 14 | #include 15 | 16 | int statx(int dfd, const char *pathname, int flags, unsigned int mask, 17 | struct statx *buffer) 18 | { 19 | errno = EINVAL; 20 | return -1; 21 | } 22 | #endif 23 | #endif 24 | -------------------------------------------------------------------------------- /oslib/statx.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_HAVE_STATX 2 | #ifdef CONFIG_HAVE_STATX_SYSCALL 3 | #include 4 | #include 5 | #else 6 | #define STATX_ALL 0 7 | #undef statx 8 | struct statx 9 | { 10 | }; 11 | #endif 12 | int statx(int dfd, const char *pathname, int flags, unsigned int mask, 13 | struct statx *buffer); 14 | #endif 15 | -------------------------------------------------------------------------------- /oslib/strcasestr.c: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_STRCASESTR 2 | 3 | #include 4 | #include 5 | #include "strcasestr.h" 6 | 7 | char *strcasestr(const char *s1, const char *s2) 8 | { 9 | const char *s = s1; 10 | const char *p = s2; 11 | 12 | do { 13 | if (!*p) 14 | return (char *) s1; 15 | if ((*p == *s) || 16 | (tolower(*p) == tolower(*s))) { 17 | ++p; 18 | ++s; 19 | } else { 20 | p = s2; 21 | if (!*s) 22 | return NULL; 23 | s = ++s1; 24 | } 25 | } while (1); 26 | 27 | return *p ? NULL : (char *) s1; 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /oslib/strcasestr.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_STRCASESTR 2 | 3 | #ifndef FIO_STRCASESTR_H 4 | #define FIO_STRCASESTR_H 5 | 6 | char *strcasestr(const char *haystack, const char *needle); 7 | 8 | #endif 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /oslib/strlcat.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_STRLCAT 2 | 3 | #ifndef FIO_STRLCAT_H 4 | #define FIO_STRLCAT_H 5 | 6 | #include 7 | 8 | size_t strlcat(char *dst, const char *src, size_t dsize); 9 | 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /oslib/strndup.c: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_HAVE_STRNDUP 2 | 3 | #include 4 | #include 5 | #include "strndup.h" 6 | 7 | char *strndup(const char *s, size_t n) 8 | { 9 | char *str = malloc(n + 1); 10 | 11 | if (str) { 12 | strncpy(str, s, n); 13 | str[n] = '\0'; 14 | } 15 | 16 | return str; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /oslib/strndup.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_HAVE_STRNDUP 2 | 3 | #ifndef FIO_STRNDUP_LIB_H 4 | #define FIO_STRNDUP_LIB_H 5 | 6 | #include 7 | 8 | char *strndup(const char *s, size_t n); 9 | 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /oslib/strsep.c: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_STRSEP 2 | 3 | #include 4 | #include "strsep.h" 5 | 6 | char *strsep(char **stringp, const char *delim) 7 | { 8 | char *s, *tok; 9 | const char *spanp; 10 | int c, sc; 11 | 12 | s = *stringp; 13 | if (!s) 14 | return NULL; 15 | 16 | tok = s; 17 | do { 18 | c = *s++; 19 | spanp = delim; 20 | do { 21 | sc = *spanp++; 22 | if (sc == c) { 23 | if (c == 0) 24 | s = NULL; 25 | else 26 | s[-1] = 0; 27 | *stringp = s; 28 | return tok; 29 | } 30 | } while (sc != 0); 31 | } while (1); 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /oslib/strsep.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_STRSEP 2 | 3 | #ifndef FIO_STRSEP_LIB_H 4 | #define FIO_STRSEP_LIB_H 5 | 6 | char *strsep(char **, const char *); 7 | 8 | #endif 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /printing.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINTING_H 2 | #define PRINTING_H 3 | 4 | void gfio_print_results(struct gui_entry *ge); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /profile.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_PROFILE_H 2 | #define FIO_PROFILE_H 3 | 4 | #include "flist.h" 5 | 6 | /* 7 | * Functions for overriding internal fio io_u functions 8 | */ 9 | struct prof_io_ops { 10 | int (*td_init)(struct thread_data *); 11 | void (*td_exit)(struct thread_data *); 12 | 13 | int (*io_u_lat)(struct thread_data *, uint64_t); 14 | }; 15 | 16 | struct profile_ops { 17 | struct flist_head list; 18 | char name[32]; 19 | char desc[64]; 20 | int flags; 21 | 22 | /* 23 | * Profile specific options 24 | */ 25 | struct fio_option *options; 26 | void *opt_data; 27 | 28 | /* 29 | * Called after parsing options, to prepare 'cmdline' 30 | */ 31 | int (*prep_cmd)(void); 32 | 33 | /* 34 | * The complete command line 35 | */ 36 | const char **cmdline; 37 | 38 | struct prof_io_ops *io_ops; 39 | }; 40 | 41 | int register_profile(struct profile_ops *); 42 | void unregister_profile(struct profile_ops *); 43 | int load_profile(const char *); 44 | struct profile_ops *find_profile(const char *); 45 | void profile_add_hooks(struct thread_data *); 46 | 47 | int profile_td_init(struct thread_data *); 48 | void profile_td_exit(struct thread_data *); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /pshared.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_PSHARED_H 2 | #define FIO_PSHARED_H 3 | 4 | #include 5 | 6 | extern int mutex_init_pshared_with_type(pthread_mutex_t *, int); 7 | extern int mutex_init_pshared(pthread_mutex_t *); 8 | extern int cond_init_pshared(pthread_cond_t *); 9 | extern int mutex_cond_init_pshared(pthread_mutex_t *, pthread_cond_t *); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /rate-submit.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_RATE_SUBMIT 2 | #define FIO_RATE_SUBMIT 3 | 4 | int rate_submit_init(struct thread_data *, struct sk_out *); 5 | void rate_submit_exit(struct thread_data *); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /rwlock.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_RWLOCK_H 2 | #define FIO_RWLOCK_H 3 | 4 | #include 5 | 6 | #define FIO_RWLOCK_MAGIC 0x52574c4fU 7 | 8 | struct fio_rwlock { 9 | pthread_rwlock_t lock; 10 | int magic; 11 | }; 12 | 13 | extern void fio_rwlock_read(struct fio_rwlock *); 14 | extern void fio_rwlock_write(struct fio_rwlock *); 15 | extern void fio_rwlock_unlock(struct fio_rwlock *); 16 | extern struct fio_rwlock *fio_rwlock_init(void); 17 | extern void fio_rwlock_remove(struct fio_rwlock *); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /smalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_SMALLOC_H 2 | #define FIO_SMALLOC_H 3 | 4 | #include 5 | 6 | extern void *smalloc(size_t); 7 | extern void *scalloc(size_t, size_t); 8 | extern void sfree(void *); 9 | extern char *smalloc_strdup(const char *); 10 | extern void sinit(void); 11 | extern void scleanup(void); 12 | extern void smalloc_debug(size_t); 13 | 14 | extern unsigned int smalloc_pool_size; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /t/arch.c: -------------------------------------------------------------------------------- 1 | #include "../arch/arch.h" 2 | 3 | unsigned long arch_flags = 0; 4 | int arch_random; 5 | -------------------------------------------------------------------------------- /t/client_server/test01.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=null 3 | time_based 4 | runtime=3s 5 | filesize=1T 6 | 7 | [test1] 8 | description=test1 9 | 10 | [test2] 11 | description=test2 12 | 13 | [test3] 14 | description=test3 15 | -------------------------------------------------------------------------------- /t/client_server/test04-noglobal.fio: -------------------------------------------------------------------------------- 1 | [test1] 2 | description=test1 3 | ioengine=null 4 | time_based 5 | runtime=3s 6 | filesize=1T 7 | 8 | [test2] 9 | description=test2 10 | ioengine=null 11 | time_based 12 | runtime=3s 13 | filesize=1T 14 | 15 | [test3] 16 | description=test3 17 | ioengine=null 18 | time_based 19 | runtime=3s 20 | filesize=1T 21 | -------------------------------------------------------------------------------- /t/client_server/test07-slat.fio: -------------------------------------------------------------------------------- 1 | [test] 2 | ioengine=null 3 | iodepth=2 4 | filesize=1T 5 | time_based 6 | runtime=3s 7 | slat_percentiles=1 8 | -------------------------------------------------------------------------------- /t/client_server/test08-clat.fio: -------------------------------------------------------------------------------- 1 | [test] 2 | ioengine=null 3 | iodepth=2 4 | filesize=1T 5 | time_based 6 | runtime=3s 7 | clat_percentiles=1 8 | -------------------------------------------------------------------------------- /t/client_server/test09-lat.fio: -------------------------------------------------------------------------------- 1 | [test] 2 | ioengine=null 3 | iodepth=2 4 | filesize=1T 5 | time_based 6 | runtime=3s 7 | lat_percentiles=1 8 | -------------------------------------------------------------------------------- /t/client_server/test10-noclat.fio: -------------------------------------------------------------------------------- 1 | [test] 2 | ioengine=null 3 | iodepth=2 4 | filesize=1T 5 | time_based 6 | runtime=3s 7 | clat_percentiles=0 8 | -------------------------------------------------------------------------------- /t/client_server/test11-alllat.fio: -------------------------------------------------------------------------------- 1 | [test] 2 | ioengine=null 3 | iodepth=2 4 | filesize=1T 5 | time_based 6 | runtime=3s 7 | slat_percentiles=1 8 | clat_percentiles=1 9 | lat_percentiles=1 10 | -------------------------------------------------------------------------------- /t/debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | FILE *f_err; 4 | void *fio_ts; 5 | unsigned long fio_debug = 0; 6 | 7 | void __dprint(int type, const char *str, ...) 8 | { 9 | } 10 | 11 | void debug_init(void) 12 | { 13 | f_err = stderr; 14 | } 15 | -------------------------------------------------------------------------------- /t/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_DEBUG_INC_H 2 | #define FIO_DEBUG_INC_H 3 | 4 | extern void debug_init(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /t/fuzz/fuzz_parseini.c: -------------------------------------------------------------------------------- 1 | #include "fio.h" 2 | 3 | static int initialized = 0; 4 | 5 | const char *const fakeargv[] = {(char *) "fuzz", 6 | (char *) "--output", (char *) "/dev/null", 7 | (char *) "--parse-only", 8 | 0}; 9 | 10 | int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) 11 | { 12 | char *fuzzedini; 13 | 14 | if (size < 2) 15 | return 0; 16 | 17 | if (initialized == 0) { 18 | if (fio_init_options()) { 19 | printf("Failed fio_init_options\n"); 20 | return 1; 21 | } 22 | 23 | parse_cmd_line(4, (char **) fakeargv, 0); 24 | sinit(); 25 | 26 | initialized = 1; 27 | } 28 | fuzzedini = malloc(size); 29 | if (!fuzzedini) { 30 | printf("Failed malloc\n"); 31 | return 1; 32 | } 33 | /* final character is type for parse_jobs_ini */ 34 | memcpy(fuzzedini, data, size - 1); 35 | /* ensures final 0 */ 36 | fuzzedini[size - 1] = 0; 37 | 38 | parse_jobs_ini(fuzzedini, 1, 0, data[size - 1]); 39 | free(fuzzedini); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /t/fuzz/onefile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 6 | 7 | int main(int argc, char** argv) 8 | { 9 | FILE *fp; 10 | uint8_t *data; 11 | size_t size; 12 | 13 | if (argc != 2) 14 | return 1; 15 | 16 | /* opens the file, get its size, and reads it into a buffer */ 17 | fp = fopen(argv[1], "rb"); 18 | if (fp == NULL) 19 | return 2; 20 | 21 | if (fseek(fp, 0L, SEEK_END) != 0) { 22 | fclose(fp); 23 | return 2; 24 | } 25 | size = ftell(fp); 26 | if (size == (size_t) -1) { 27 | fclose(fp); 28 | return 2; 29 | } 30 | if (fseek(fp, 0L, SEEK_SET) != 0) { 31 | fclose(fp); 32 | return 2; 33 | } 34 | data = malloc(size); 35 | if (data == NULL) { 36 | fclose(fp); 37 | return 2; 38 | } 39 | if (fread(data, size, 1, fp) != 1) { 40 | fclose(fp); 41 | free(data); 42 | return 2; 43 | } 44 | 45 | /* launch fuzzer */ 46 | LLVMFuzzerTestOneInput(data, size); 47 | free(data); 48 | fclose(fp); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /t/ieee754.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../lib/ieee754.h" 3 | 4 | static double values[] = { -17.23, 17.23, 123.4567, 98765.4321, 5 | 3.14159265358979323, 0.0 }; 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | uint64_t i; 10 | double f, delta; 11 | int j, differences = 0; 12 | 13 | j = 0; 14 | do { 15 | i = fio_double_to_uint64(values[j]); 16 | f = fio_uint64_to_double(i); 17 | delta = values[j] - f; 18 | printf("%26.20lf -> %26.20lf, delta = %26.20lf\n", values[j], 19 | f, delta); 20 | if (f != values[j]) 21 | differences++; 22 | j++; 23 | } while (values[j] != 0.0); 24 | 25 | return differences; 26 | } 27 | -------------------------------------------------------------------------------- /t/jobs/t0001-52c58027.fio: -------------------------------------------------------------------------------- 1 | #Commit 52c580272d87d2b9b8a65d317bf7c2d432a30fec 2 | [foo] 3 | size=20000 4 | bsrange=1k-4k 5 | rw=randread 6 | ioengine=null 7 | -------------------------------------------------------------------------------- /t/jobs/t0002-13af05ae-post.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=libaio 3 | direct=1 4 | filename=t0002file 5 | iodepth=128 6 | size=1G 7 | loops=1 8 | group_reporting=1 9 | readwrite=read 10 | do_verify=1 11 | verify=md5 12 | verify_fatal=1 13 | numjobs=1 14 | thread 15 | bssplit=512/50:1M/50 16 | 17 | [thread0] 18 | offset=0G 19 | 20 | [thread-mix0] 21 | offset=4G 22 | size=1G 23 | readwrite=rw 24 | bsrange=512:1M 25 | -------------------------------------------------------------------------------- /t/jobs/t0002-13af05ae-pre.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=libaio 3 | direct=1 4 | filename=t0002file 5 | iodepth=128 6 | size=1G 7 | loops=1 8 | group_reporting=1 9 | readwrite=write 10 | do_verify=0 11 | verify=md5 12 | numjobs=1 13 | thread 14 | bssplit=512/50:1M/50 15 | 16 | [thread0] 17 | offset=0G 18 | 19 | [thread-mix0] 20 | offset=4G 21 | readwrite=rw 22 | size=1G 23 | bsrange=512:1M 24 | -------------------------------------------------------------------------------- /t/jobs/t0003-0ae2c6e1-post.fio: -------------------------------------------------------------------------------- 1 | # Expected result: verify fails. 2 | # Buggy result: fio segfaults 3 | [global] 4 | ioengine=libaio 5 | direct=1 6 | filename=foo 7 | iodepth=128 8 | size=1M 9 | loops=1 10 | group_reporting=1 11 | readwrite=read 12 | do_verify=1 13 | verify=md5 14 | verify_fatal=1 15 | numjobs=1 16 | thread 17 | verify_dump=1 18 | bs=4k 19 | 20 | [large_reads] 21 | offset=0G 22 | blocksize=1M 23 | 24 | [small_reads] 25 | offset=1G 26 | blocksize=512 27 | -------------------------------------------------------------------------------- /t/jobs/t0003-0ae2c6e1-pre.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | ioengine=libaio 3 | direct=1 4 | filename=foo 5 | iodepth=128 6 | size=10M 7 | loops=1 8 | group_reporting=1 9 | readwrite=write 10 | do_verify=0 11 | verify=md5 12 | numjobs=1 13 | thread 14 | verify_dump=1 15 | 16 | [small_writes] 17 | offset=0G 18 | blocksize=512 19 | 20 | [large_writes] 21 | offset=1G 22 | blocksize=1M 23 | -------------------------------------------------------------------------------- /t/jobs/t0004-8a99fdf6.fio: -------------------------------------------------------------------------------- 1 | # Expected result: fio runs to completion 2 | # Buggy result: fio segfaults 3 | [global] 4 | ioengine=libaio 5 | direct=1 6 | filename=foo 7 | iodepth=128 8 | size=10M 9 | loops=1 10 | group_reporting=1 11 | readwrite=write 12 | do_verify=0 13 | verify=md5 14 | numjobs=1 15 | thread 16 | verify_dump=1 17 | 18 | [small_writes] 19 | offset=0G 20 | blocksize=512 21 | verify_interval=1M 22 | 23 | [large_writes] 24 | stonewall 25 | offset=1G 26 | blocksize=1M 27 | verify_interval=512 28 | -------------------------------------------------------------------------------- /t/jobs/t0005-f7078f7b.fio: -------------------------------------------------------------------------------- 1 | # Expected result: fio reads and writes 100m 2 | # Buggy result: fio reads and writes ~100m/2 3 | [global] 4 | bs=4k 5 | ioengine=sync 6 | size=100m 7 | direct=1 8 | filename=xxx 9 | 10 | [write] 11 | verify=md5 12 | verify_backlog=32 13 | rw=write 14 | -------------------------------------------------------------------------------- /t/jobs/t0006-82af2a7c.fio: -------------------------------------------------------------------------------- 1 | # Expected results: workload runs and switches between 'm' and 'V' state 2 | # Buggy result: workload stays in 'm' mode, never doing actual verifies 3 | [global] 4 | rw=randrw 5 | bs=4k 6 | direct=1 7 | ioengine=libaio 8 | iodepth=32 9 | verify=meta 10 | verify_backlog=1024 11 | verify_fatal=1 12 | 13 | [ver-test] 14 | filename=foo 15 | size=4g 16 | verify_pattern=0xaaa 17 | -------------------------------------------------------------------------------- /t/jobs/t0007-37cf9e3c.fio: -------------------------------------------------------------------------------- 1 | # Expected result: fio reads 87040KB of data: 2 | # first read is at offset 0, then 2nd read is at offset 1.5m, then the 3rd 3 | # read is at offset 3m, and after the last read at offset 127m - we have only 4 | # read 87,040K data. 5 | # Buggy result: fio reads the full 128MB of data 6 | [foo] 7 | size=128mb 8 | rw=read:512k 9 | bs=1m 10 | norandommap 11 | write_iolog=log 12 | direct=1 13 | -------------------------------------------------------------------------------- /t/jobs/t0008-ae2fafc8.fio: -------------------------------------------------------------------------------- 1 | # Expected result: fio writes 16MB, reads 16+16MB 2 | # Buggy result: fio writes 16MB, reads ~21MB 3 | [global] 4 | bs=4k 5 | verify=crc32c 6 | rw=readwrite 7 | direct=1 8 | 9 | [foo] 10 | size=32m 11 | do_verify=1 12 | verify_backlog=1 13 | -------------------------------------------------------------------------------- /t/jobs/t0009-f8b0bd10.fio: -------------------------------------------------------------------------------- 1 | # Expected result: fio verifies and runs for 1m 2 | # Buggy result: fio crashes with: 3 | # __get_io_u: Assertion `io_u->flags & IO_U_F_FREE' failed 4 | 5 | [global] 6 | direct=1 7 | ioengine=null 8 | size=20g 9 | norandommap 10 | randrepeat=0 11 | bs=4096 12 | iodepth=170 13 | #iodepth=96 14 | #numjobs=1 15 | numjobs=1 16 | #numjobs=24 17 | # number_ios=1 18 | # runtime=216000 19 | #runtime=3600 20 | time_based=1 21 | group_reporting=1 22 | thread 23 | gtod_reduce=1 24 | iodepth_batch=4 25 | iodepth_batch_complete=4 26 | cpus_allowed=0-3 27 | cpus_allowed_policy=split 28 | rw=randwrite 29 | verify=crc32c-intel 30 | verify_backlog=1m 31 | do_verify=1 32 | verify_async=6 33 | verify_async_cpus=0-3 34 | runtime=1m 35 | 36 | [4_KiB_RR_drive_r] 37 | 38 | [4_KiB_RR_drive_s] 39 | 40 | 41 | -------------------------------------------------------------------------------- /t/jobs/t0010-b7aae4ba.fio: -------------------------------------------------------------------------------- 1 | # Expected result: fio runs and completes the job 2 | # Buggy result: fio segfaults 3 | # 4 | [test] 5 | ioengine=null 6 | size=10g 7 | io_submit_mode=offload 8 | iodepth=16 9 | -------------------------------------------------------------------------------- /t/jobs/t0011-5d2788d5.fio: -------------------------------------------------------------------------------- 1 | # Expected results: no parse warnings, runs and with roughly 1/8 iops between 2 | # the two jobs. 3 | # Buggy result: parse warning on flow value overflow, no 1/8 division between 4 | # jobs. 5 | # 6 | [global] 7 | bs=4k 8 | ioengine=null 9 | size=100g 10 | runtime=10 11 | flow_id=1 12 | 13 | [flow1] 14 | flow=1 15 | rate_iops=1000 16 | 17 | [flow2] 18 | flow=8 19 | -------------------------------------------------------------------------------- /t/jobs/t0012.fio: -------------------------------------------------------------------------------- 1 | # Expected results: no parse warnings, runs and with roughly 1:5:10 iops 2 | # between the three jobs. 3 | # Buggy result: parse warning on flow value overflow, no 1:5:10 division 4 | # between jobs. 5 | # 6 | 7 | [global] 8 | bs=4k 9 | ioengine=null 10 | size=100g 11 | runtime=12 12 | flow_id=1 13 | flow_sleep=100 14 | thread 15 | log_avg_msec=1000 16 | write_iops_log=t0012.fio 17 | time_based 18 | 19 | [flow1] 20 | flow=1 21 | 22 | [flow2] 23 | flow=5 24 | 25 | [flow3] 26 | flow=10 27 | -------------------------------------------------------------------------------- /t/jobs/t0013.fio: -------------------------------------------------------------------------------- 1 | # Trigger the fio code that serializes overlapping I/O. The job size is very 2 | # small to make overlapping I/O more likely. 3 | 4 | [test] 5 | ioengine=null 6 | thread=1 7 | size=4K 8 | blocksize=4K 9 | io_submit_mode=offload 10 | iodepth=1 11 | serialize_overlap=1 12 | numjobs=8 13 | loops=1000000 14 | runtime=10 15 | -------------------------------------------------------------------------------- /t/jobs/t0014.fio: -------------------------------------------------------------------------------- 1 | # Expected results: no parse warnings, runs and with roughly 1:2:3 iops 2 | # between the three jobs for the first 5 seconds, then 3 | # runs with roughly 1:2 iops between the two jobs for 4 | # the remaining 5 seconds. 5 | # 6 | # Buggy result: parse warning on flow value overflow, no 1:2:3 division between 7 | # the three jobs for the first 5 seconds or no 1:2 division between 8 | # the first two jobs for the remaining 5 seconds. 9 | # 10 | 11 | [global] 12 | bs=4k 13 | ioengine=null 14 | size=100g 15 | runtime=12 16 | flow_id=1 17 | thread 18 | log_avg_msec=1000 19 | write_iops_log=t0014.fio 20 | time_based 21 | 22 | [flow1] 23 | flow=1 24 | 25 | [flow2] 26 | flow=2 27 | 28 | [flow3] 29 | flow=3 30 | runtime=5 31 | -------------------------------------------------------------------------------- /t/jobs/t0015-4e7e7898.fio: -------------------------------------------------------------------------------- 1 | # Expected result: mean(slat) + mean(clat) = mean(lat) 2 | # Buggy result: equality does not hold 3 | 4 | [test] 5 | ioengine=libaio 6 | size=1M 7 | iodepth=16 8 | -------------------------------------------------------------------------------- /t/jobs/t0016-d54ae22.fio: -------------------------------------------------------------------------------- 1 | # Expected result: mean(slat) + mean(clat) = mean(lat) 2 | # Buggy result: equality does not hold 3 | 4 | [test] 5 | ioengine=null 6 | size=1M 7 | iodepth=16 8 | -------------------------------------------------------------------------------- /t/jobs/t0017.fio: -------------------------------------------------------------------------------- 1 | # Expected result: mean(slat) + mean(clat) = mean(lat) 2 | # Buggy result: equality does not hold 3 | # This is similar to t0015 and t0016 except that is uses posixaio which is 4 | # available on more platforms and does not have a commit hook 5 | 6 | [test] 7 | ioengine=posixaio 8 | size=1M 9 | iodepth=16 10 | -------------------------------------------------------------------------------- /t/jobs/t0018.fio: -------------------------------------------------------------------------------- 1 | # Expected result: job completes without error 2 | # Buggy result: job fails 3 | 4 | [test] 5 | ioengine=io_uring 6 | filesize=256K 7 | time_based 8 | runtime=3s 9 | rw=randrw 10 | -------------------------------------------------------------------------------- /t/jobs/t0019.fio: -------------------------------------------------------------------------------- 1 | # Expected result: offsets are accessed sequentially and all offsets are read 2 | # Buggy result: offsets are not accessed sequentially and one or more offsets are missed 3 | # run with --debug=io or logging to see which offsets are accessed 4 | 5 | [test] 6 | ioengine=null 7 | filesize=1M 8 | write_bw_log=test 9 | per_job_logs=0 10 | log_offset=1 11 | -------------------------------------------------------------------------------- /t/jobs/t0020.fio: -------------------------------------------------------------------------------- 1 | # Expected result: offsets are not accessed sequentially and all offsets are touched 2 | # Buggy result: offsets are accessed sequentially and one or more offsets are missed 3 | # run with --debug=io or logging to see which offsets are read 4 | 5 | [test] 6 | ioengine=null 7 | filesize=1M 8 | rw=randread 9 | write_bw_log=test 10 | per_job_logs=0 11 | log_offset=1 12 | -------------------------------------------------------------------------------- /t/jobs/t0021.fio: -------------------------------------------------------------------------------- 1 | # make sure the lfsr random generator actually does touch all the offsets 2 | # 3 | # Expected result: offsets are not accessed sequentially and all offsets are touched 4 | # Buggy result: offsets are accessed sequentially and one or more offsets are missed 5 | # run with --debug=io or logging to see which offsets are read 6 | 7 | [test] 8 | ioengine=null 9 | filesize=1M 10 | rw=randread 11 | write_bw_log=test 12 | per_job_logs=0 13 | log_offset=1 14 | norandommap=1 15 | random_generator=lfsr 16 | -------------------------------------------------------------------------------- /t/jobs/t0022.fio: -------------------------------------------------------------------------------- 1 | # make sure that when we enable norandommap we touch some offsets more than once 2 | # 3 | # Expected result: at least one offset is touched more than once 4 | # Buggy result: each offset is touched only once 5 | 6 | [test] 7 | ioengine=null 8 | filesize=1M 9 | rw=randread 10 | write_bw_log=test 11 | per_job_logs=0 12 | log_offset=1 13 | norandommap=1 14 | -------------------------------------------------------------------------------- /t/jobs/t0024.fio: -------------------------------------------------------------------------------- 1 | # trimwrite data direction tests 2 | [global] 3 | filesize=1M 4 | ioengine=null 5 | rw=trimwrite 6 | log_offset=1 7 | per_job_logs=0 8 | randrepeat=0 9 | write_bw_log 10 | 11 | # Expected result: trim issued to sequential offsets followed by write to same offset 12 | # all offsets touched 13 | # block sizes match 14 | # Buggy result: something else 15 | [basic] 16 | 17 | # Expected result: trim issued to sequential offsets followed by write to same offset 18 | # all offsets trimmed 19 | # block sizes 8k for both write and trim 20 | # Buggy result: something else 21 | [bs] 22 | bs=8k,8k,8k 23 | 24 | # Expected result: trim issued to sequential offsets followed by write to same offset 25 | # all offsets trimmed 26 | # block sizes match 27 | # Buggy result: something else 28 | [bsrange] 29 | bsrange=512-4k 30 | 31 | # Expected result: trim issued to sequential offsets followed by write to same offset 32 | # all offsets trimmed 33 | # block sizes match 34 | # Buggy result: something else 35 | [bssplit] 36 | bssplit=512/25:1k/:2k/:4k/ 37 | -------------------------------------------------------------------------------- /t/jobs/t0025.fio: -------------------------------------------------------------------------------- 1 | [job] 2 | filename=t0025file 3 | size=128k 4 | readwrite=write 5 | do_verify=1 6 | verify=md5 7 | experimental_verify=1 8 | -------------------------------------------------------------------------------- /t/jobs/t0026.fio: -------------------------------------------------------------------------------- 1 | [job1] 2 | filename=t0026file 3 | size=1M 4 | readwrite=randwrite 5 | loops=8 6 | do_verify=1 7 | verify=md5 8 | experimental_verify=1 9 | 10 | [job2] 11 | stonewall=1 12 | filename=t0026file 13 | size=1M 14 | readwrite=randrw 15 | time_based 16 | runtime=5 17 | do_verify=1 18 | verify=md5 19 | experimental_verify=1 20 | -------------------------------------------------------------------------------- /t/jobs/t0027.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | filename=t0027file 3 | size=16k 4 | bs=16k 5 | 6 | [write_job] 7 | readwrite=write 8 | buffer_pattern='t0027.pattern' 9 | 10 | [read_job] 11 | stonewall=1 12 | readwrite=read 13 | verify=pattern 14 | verify_pattern='t0027.pattern' 15 | -------------------------------------------------------------------------------- /t/jobs/t0028-c6cade16.fio: -------------------------------------------------------------------------------- 1 | [test] 2 | size=16k 3 | readwrite=write 4 | buffer_pattern="abcd"-120xdeadface 5 | ioengine=null 6 | -------------------------------------------------------------------------------- /t/jobs/t0029.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | filename=t0029file 3 | size=4k 4 | verify=md5 5 | 6 | [write] 7 | rw=write 8 | do_verify=0 9 | 10 | [read] 11 | stonewall=1 12 | rw=read 13 | loops=2 14 | do_verify=1 15 | -------------------------------------------------------------------------------- /t/jobs/t0030.fio: -------------------------------------------------------------------------------- 1 | # run with --bandwidth-log 2 | # broken behavior: seg fault 3 | # successful behavior: test runs to completion with 0 as the exit code 4 | 5 | [test] 6 | ioengine=null 7 | filesize=1T 8 | rw=read 9 | time_based 10 | runtime=2s 11 | -------------------------------------------------------------------------------- /t/jobs/t0031-pre.fio: -------------------------------------------------------------------------------- 1 | [job] 2 | rw=write 3 | ioengine=libaio 4 | size=1mb 5 | time_based=1 6 | runtime=1 7 | filename=t0030file 8 | write_iolog=iolog 9 | -------------------------------------------------------------------------------- /t/jobs/t0031.fio: -------------------------------------------------------------------------------- 1 | [job] 2 | rw=read 3 | ioengine=libaio 4 | iodepth=128 5 | filename=t0030file 6 | read_iolog=iolog 7 | write_lat_log=lat_log 8 | -------------------------------------------------------------------------------- /t/jobs/t0032-43063a1c.fio: -------------------------------------------------------------------------------- 1 | # Expected results: max offset is ~1280K 2 | # Buggy result: max offset is ~640K 3 | # 4 | 5 | [global] 6 | ioengine=null 7 | size=1280K 8 | io_size=2560k 9 | bs=128K 10 | 11 | [test1] 12 | rw=rw 13 | -------------------------------------------------------------------------------- /t/jobs/t0033.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | rw=read 3 | filename=t0033file 4 | size=8k 5 | time_based 6 | runtime=2s 7 | ioengine=libaio 8 | iodepth=1 9 | 10 | [job1] 11 | write_bw_log=log 12 | log_prio=1 13 | 14 | [job2] 15 | write_lat_log=log 16 | log_avg_msec=100 17 | log_window_value=both 18 | 19 | [job3] 20 | write_iops_log=log 21 | log_offset=1 22 | log_prio=1 23 | 24 | [job4] 25 | write_iops_log=log 26 | log_avg_msec=100 27 | log_window_value=both 28 | log_offset=1 29 | -------------------------------------------------------------------------------- /t/jobs/t0034.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | rw=read 3 | filename=t0034file 4 | size=8k 5 | time_based 6 | runtime=2s 7 | ioengine=libaio 8 | iodepth=1 9 | 10 | [job1] 11 | write_lat_log=log 12 | log_offset=1 13 | log_issue_time=1 14 | 15 | [job2] 16 | write_lat_log=log 17 | log_offset=1 18 | log_issue_time=1 19 | log_avg_msec=100 20 | log_window_value=both 21 | 22 | [job3] 23 | write_lat_log=log 24 | write_bw_log=log 25 | write_iops_log=log 26 | log_offset=1 27 | log_issue_time=1 28 | -------------------------------------------------------------------------------- /t/jobs/t0035.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | size=4k 3 | write_lat_log=log 4 | 5 | [job1] 6 | ioengine=filecreate 7 | filename=t0035file1 8 | 9 | [job2] 10 | ioengine=filestat 11 | filename=t0035file2 12 | 13 | [job3] 14 | ioengine=filedelete 15 | filename=t0035file3 16 | 17 | [job4] 18 | ioengine=dircreate 19 | filename=t0035dir1 20 | 21 | [job5] 22 | ioengine=dirstat 23 | filename=t0035dir2 24 | 25 | [job6] 26 | ioengine=dirdelete 27 | filename=t0035dir3 28 | -------------------------------------------------------------------------------- /t/jobs/t0036-post.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | filename=t0036file 3 | verify=md5 4 | size=512k 5 | 6 | [job] 7 | readwrite=read 8 | verify_state_load=1 9 | -------------------------------------------------------------------------------- /t/jobs/t0036-pre.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | filename=t0036file 3 | verify=md5 4 | size=512k 5 | 6 | [job] 7 | readwrite=write 8 | verify_state_save=1 9 | -------------------------------------------------------------------------------- /t/jobs/t0037-post.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | filename=t0037file.1:t0037file.2:t0037file.3:t0037file.4 3 | verify=md5 4 | ioengine=libaio 5 | iodepth=32 6 | size=512k 7 | loops=4 8 | 9 | [job] 10 | readwrite=read 11 | verify_state_load=1 12 | 13 | -------------------------------------------------------------------------------- /t/jobs/t0037-pre.fio: -------------------------------------------------------------------------------- 1 | [global] 2 | filename=t0037file.1:t0037file.2:t0037file.3:t0037file.4 3 | verify=md5 4 | ioengine=libaio 5 | iodepth=32 6 | size=512k 7 | loops=4 8 | 9 | [job] 10 | readwrite=write 11 | verify_state_save=1 12 | 13 | -------------------------------------------------------------------------------- /t/log.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../minmax.h" 4 | 5 | size_t log_err(const char *format, ...) 6 | { 7 | char buffer[1024]; 8 | va_list args; 9 | size_t len; 10 | 11 | va_start(args, format); 12 | len = vsnprintf(buffer, sizeof(buffer), format, args); 13 | va_end(args); 14 | len = min(len, sizeof(buffer) - 1); 15 | 16 | return fwrite(buffer, len, 1, stderr); 17 | } 18 | 19 | size_t log_info(const char *format, ...) 20 | { 21 | char buffer[1024]; 22 | va_list args; 23 | size_t len; 24 | 25 | va_start(args, format); 26 | len = vsnprintf(buffer, sizeof(buffer), format, args); 27 | va_end(args); 28 | len = min(len, sizeof(buffer) - 1); 29 | 30 | return fwrite(buffer, len, 1, stdout); 31 | } 32 | -------------------------------------------------------------------------------- /t/zbd/run-tests-against-scsi_debug: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2020 Western Digital Corporation or its affiliates. 4 | # 5 | # SPDX-License-Identifier: GPL-2.0 6 | # 7 | # A couple of test cases in t/zbd/test-zbd-support script depend on the error 8 | # injection feature of scsi_debug. Prepare a zoned scsi_debug device and run 9 | # only for the test cases. 10 | 11 | declare dev sg scriptdir 12 | 13 | scriptdir="$(cd "$(dirname "$0")" && pwd)" 14 | 15 | modprobe -qr scsi_debug 16 | modprobe scsi_debug add_host=1 zbc=host-managed zone_nr_conv=0 17 | 18 | dev=$(dmesg | tail -5 | grep "Attached SCSI disk" | grep -Po ".* \[\Ksd[a-z]*") 19 | 20 | if ! grep -qe scsi_debug /sys/block/"${dev}"/device/vpd_pg83; then 21 | echo "Failed to create scsi_debug device" 22 | exit 1 23 | fi 24 | 25 | sg=$(echo /sys/block/"${dev}"/device/scsi_generic/*) 26 | sg=${sg##*/} 27 | 28 | echo standard engine: 29 | "${scriptdir}"/test-zbd-support -t 72 -t 73 /dev/"${dev}" 30 | echo libzbc engine with block device: 31 | "${scriptdir}"/test-zbd-support -t 72 -t 73 -l /dev/"${dev}" 32 | echo libzbc engine with sg node: 33 | "${scriptdir}"/test-zbd-support -t 72 -t 73 -l /dev/"${sg}" 34 | -------------------------------------------------------------------------------- /td_error.c: -------------------------------------------------------------------------------- 1 | #include "fio.h" 2 | #include "io_ddir.h" 3 | #include "td_error.h" 4 | 5 | static int __NON_FATAL_ERR[] = { EIO, EILSEQ }; 6 | 7 | enum error_type_bit td_error_type(enum fio_ddir ddir, int err) 8 | { 9 | if (err == EILSEQ) 10 | return ERROR_TYPE_VERIFY_BIT; 11 | if (ddir == DDIR_READ) 12 | return ERROR_TYPE_READ_BIT; 13 | return ERROR_TYPE_WRITE_BIT; 14 | } 15 | 16 | int td_non_fatal_error(struct thread_data *td, enum error_type_bit etype, 17 | int err) 18 | { 19 | unsigned int i; 20 | 21 | if (!td->o.ignore_error[etype]) { 22 | td->o.ignore_error[etype] = __NON_FATAL_ERR; 23 | td->o.ignore_error_nr[etype] = FIO_ARRAY_SIZE(__NON_FATAL_ERR); 24 | } 25 | 26 | if (!(td->o.continue_on_error & (1 << etype))) 27 | return 0; 28 | for (i = 0; i < td->o.ignore_error_nr[etype]; i++) 29 | if (td->o.ignore_error[etype][i] == err) 30 | return 1; 31 | 32 | return 0; 33 | } 34 | 35 | void update_error_count(struct thread_data *td, int err) 36 | { 37 | td->total_err_count++; 38 | if (td->total_err_count == 1) 39 | td->first_error = err; 40 | } 41 | -------------------------------------------------------------------------------- /td_error.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_TD_ERROR_H 2 | #define FIO_TD_ERROR_H 3 | 4 | #include "io_ddir.h" 5 | 6 | /* 7 | * What type of errors to continue on when continue_on_error is used, 8 | * and what type of errors to ignore when ignore_error is used. 9 | */ 10 | enum error_type_bit { 11 | ERROR_TYPE_READ_BIT = 0, 12 | ERROR_TYPE_WRITE_BIT = 1, 13 | ERROR_TYPE_VERIFY_BIT = 2, 14 | ERROR_TYPE_CNT = 3, 15 | }; 16 | 17 | enum error_type { 18 | ERROR_TYPE_NONE = 0, 19 | ERROR_TYPE_READ = 1 << ERROR_TYPE_READ_BIT, 20 | ERROR_TYPE_WRITE = 1 << ERROR_TYPE_WRITE_BIT, 21 | ERROR_TYPE_VERIFY = 1 << ERROR_TYPE_VERIFY_BIT, 22 | ERROR_TYPE_ANY = 0xffff, 23 | }; 24 | 25 | enum error_type_bit td_error_type(enum fio_ddir ddir, int err); 26 | int td_non_fatal_error(struct thread_data *td, enum error_type_bit etype, 27 | int err); 28 | void update_error_count(struct thread_data *td, int err); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tickmarks.h: -------------------------------------------------------------------------------- 1 | #ifndef TICKMARKS_H 2 | #define TICKMARKS_H 3 | 4 | struct tickmark { 5 | double value; 6 | char string[20]; 7 | }; 8 | 9 | int calc_tickmarks(double min, double max, int nticks, struct tickmark **tm, 10 | int *power_of_ten, int use_KMG_symbols, int base_off); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /tools/fio.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Flexible I/O tester server 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/usr/bin/fio --server 8 | 9 | [Install] 10 | WantedBy=multi-user.target 11 | -------------------------------------------------------------------------------- /tools/hist/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.ipynb 3 | .ipynb_checkpoints 4 | -------------------------------------------------------------------------------- /tools/plot/math.gpm: -------------------------------------------------------------------------------- 1 | # This Gnuplot file has been generated by eNovance 2 | if (exists("ARGC") && ARGC > 5) \ 3 | found_args = 1; \ 4 | else if (strlen("$$#") < 3 && "$#" > 5) \ 5 | found_args = 1; \ 6 | ARG1 = "$0"; \ 7 | ARG2 = "$1"; \ 8 | ARG3 = "$2"; \ 9 | ARG4 = "$3"; \ 10 | ARG5 = "$4"; \ 11 | ARG6 = "$5"; \ 12 | else \ 13 | found_args = 0; \ 14 | print "Aborting: could not find all arguments"; \ 15 | exit 16 | 17 | avg_num = ARG6 + 0 18 | avg_str = sprintf("%g", avg_num) 19 | 20 | set title ARG1 21 | 22 | set terminal png size 1280,1024 23 | set output ARG4 . '.png' 24 | 25 | set palette rgbformulae 7,5,15 26 | set style line 100 lt 7 lw 0.5 27 | set style fill transparent solid 0.9 noborder 28 | set auto x 29 | set ylabel ARG5 30 | set xlabel "Disk" 31 | set yrange [0:] 32 | set style data histogram 33 | set style histogram cluster gap 1 34 | set style fill solid border -1 35 | set boxwidth 2 36 | #set xtic rotate by -10 scale 10 font ",8" 37 | set bmargin 3 38 | set xtics axis out 39 | set xtic rotate by 45 scale 0 font ",8" autojustify 40 | set xtics offset 0,-1 border -5,1,5 41 | set style line 1 lt 1 lw 3 pt 3 linecolor rgb "green" 42 | plot ARG2 using 2:xtic(1) ti col, avg_num w l ls 1 ti 'Global average value (' . avg_str . ')' 43 | -------------------------------------------------------------------------------- /tools/plot/samples/Makefile: -------------------------------------------------------------------------------- 1 | all: clean m2sw1-128k-sdb-randwrite-para.results_bw.log io bandwidth 2 | 3 | m2sw1-128k-sdb-randwrite-para.results_bw.log: 4 | tar -xf fio-logs.tar.gz 5 | 6 | io: setup 7 | ./fio2gnuplot.py -p 'm2sw1-128k-*-read-para*iops.log' -g 8 | 9 | bandwidth: setup 10 | ./fio2gnuplot.py -p 'm2sw1-128k-*-read-para*bw.log' -g 11 | 12 | setup: 13 | ln -sf ../*py ../*gpm . 14 | 15 | clean: 16 | rm -rf *png mygraph mymath *py *gpm gnuplot_temp_file* *~ 17 | rm -rf *.average *.stddev *.min *.max *.global 18 | rm -rf m2sw1-128k-read-para-bw m2sw1-128k-read-para-iops 19 | rm -rf *log 20 | -------------------------------------------------------------------------------- /tools/plot/samples/fio-logs.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axboe/fio/02fe4fb04a141d5e72b641f7a36b3ea1e5a2b147/tools/plot/samples/fio-logs.tar.gz -------------------------------------------------------------------------------- /trim.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_TRIM_H 2 | #define FIO_TRIM_H 3 | 4 | #ifdef FIO_HAVE_TRIM 5 | #include "flist.h" 6 | #include "iolog.h" 7 | #include "compiler/compiler.h" 8 | #include "lib/types.h" 9 | #include "os/os.h" 10 | 11 | extern bool __must_check get_next_trim(struct thread_data *td, struct io_u *io_u); 12 | extern bool io_u_should_trim(struct thread_data *td, struct io_u *io_u); 13 | 14 | /* 15 | * Determine whether a given io_u should be logged for verify or 16 | * for discard 17 | */ 18 | static inline void remove_trim_entry(struct thread_data *td, struct io_piece *ipo) 19 | { 20 | if (!flist_empty(&ipo->trim_list)) { 21 | flist_del_init(&ipo->trim_list); 22 | td->trim_entries--; 23 | } 24 | } 25 | 26 | #else 27 | static inline bool get_next_trim(struct thread_data *td, struct io_u *io_u) 28 | { 29 | return false; 30 | } 31 | static inline bool io_u_should_trim(struct thread_data *td, struct io_u *io_u) 32 | { 33 | return false; 34 | } 35 | static inline void remove_trim_entry(struct thread_data *td, struct io_piece *ipo) 36 | { 37 | } 38 | #endif 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /unittests/lib/memalign.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../unittest.h" 3 | 4 | #include "../../lib/memalign.h" 5 | 6 | static void test_memalign_1(void) 7 | { 8 | size_t align = 4096; 9 | void *p = __fio_memalign(align, 1234, malloc); 10 | 11 | if (p) 12 | CU_ASSERT_EQUAL(((int)(uintptr_t)p) & (align - 1), 0); 13 | } 14 | 15 | static struct fio_unittest_entry tests[] = { 16 | { 17 | .name = "memalign/1", 18 | .fn = test_memalign_1, 19 | }, 20 | { 21 | .name = NULL, 22 | }, 23 | }; 24 | 25 | CU_ErrorCode fio_unittest_lib_memalign(void) 26 | { 27 | return fio_unittest_add_suite("lib/memalign.c", NULL, NULL, tests); 28 | } 29 | -------------------------------------------------------------------------------- /unittests/oslib/strlcat.c: -------------------------------------------------------------------------------- 1 | #include "../unittest.h" 2 | 3 | #ifndef CONFIG_STRLCAT 4 | #include "../../oslib/strlcat.h" 5 | #else 6 | #include 7 | #endif 8 | 9 | static void test_strlcat_1(void) 10 | { 11 | char dst[32]; 12 | char src[] = "test"; 13 | size_t ret; 14 | 15 | dst[0] = '\0'; 16 | ret = strlcat(dst, src, sizeof(dst)); 17 | 18 | CU_ASSERT_EQUAL(strcmp(dst, "test"), 0); 19 | CU_ASSERT_EQUAL(ret, 4); /* total length it tried to create */ 20 | } 21 | 22 | static void test_strlcat_2(void) 23 | { 24 | char dst[32]; 25 | char src[] = "test"; 26 | size_t ret; 27 | 28 | dst[0] = '\0'; 29 | ret = strlcat(dst, src, strlen(dst)); 30 | 31 | CU_ASSERT_EQUAL(strcmp(dst, ""), 0); 32 | CU_ASSERT_EQUAL(ret, 4); /* total length it tried to create */ 33 | } 34 | 35 | static struct fio_unittest_entry tests[] = { 36 | { 37 | .name = "strlcat/1", 38 | .fn = test_strlcat_1, 39 | }, 40 | { 41 | .name = "strlcat/2", 42 | .fn = test_strlcat_2, 43 | }, 44 | { 45 | .name = NULL, 46 | }, 47 | }; 48 | 49 | CU_ErrorCode fio_unittest_oslib_strlcat(void) 50 | { 51 | return fio_unittest_add_suite("oslib/strlcat.c", NULL, NULL, tests); 52 | } 53 | -------------------------------------------------------------------------------- /unittests/oslib/strndup.c: -------------------------------------------------------------------------------- 1 | #include "../unittest.h" 2 | 3 | #ifndef CONFIG_HAVE_STRNDUP 4 | #include "../../oslib/strndup.h" 5 | #else 6 | #include 7 | #endif 8 | 9 | static void test_strndup_1(void) 10 | { 11 | char s[] = "test"; 12 | char *p = strndup(s, 3); 13 | 14 | if (p) { 15 | CU_ASSERT_EQUAL(strcmp(p, "tes"), 0); 16 | CU_ASSERT_EQUAL(strlen(p), 3); 17 | } 18 | } 19 | 20 | static void test_strndup_2(void) 21 | { 22 | char s[] = "test"; 23 | char *p = strndup(s, 4); 24 | 25 | if (p) { 26 | CU_ASSERT_EQUAL(strcmp(p, s), 0); 27 | CU_ASSERT_EQUAL(strlen(p), 4); 28 | } 29 | } 30 | 31 | static void test_strndup_3(void) 32 | { 33 | char s[] = "test"; 34 | char *p = strndup(s, 5); 35 | 36 | if (p) { 37 | CU_ASSERT_EQUAL(strcmp(p, s), 0); 38 | CU_ASSERT_EQUAL(strlen(p), 4); 39 | } 40 | } 41 | 42 | static struct fio_unittest_entry tests[] = { 43 | { 44 | .name = "strndup/1", 45 | .fn = test_strndup_1, 46 | }, 47 | { 48 | .name = "strndup/2", 49 | .fn = test_strndup_2, 50 | }, 51 | { 52 | .name = "strndup/3", 53 | .fn = test_strndup_3, 54 | }, 55 | { 56 | .name = NULL, 57 | }, 58 | }; 59 | 60 | CU_ErrorCode fio_unittest_oslib_strndup(void) 61 | { 62 | return fio_unittest_add_suite("oslib/strndup.c", NULL, NULL, tests); 63 | } 64 | -------------------------------------------------------------------------------- /unittests/unittest.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_UNITTEST_H 2 | #define FIO_UNITTEST_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | struct fio_unittest_entry { 10 | const char *name; 11 | CU_TestFunc fn; 12 | }; 13 | 14 | CU_ErrorCode fio_unittest_add_suite(const char*, CU_InitializeFunc, 15 | CU_CleanupFunc, struct fio_unittest_entry*); 16 | 17 | CU_ErrorCode fio_unittest_lib_memalign(void); 18 | CU_ErrorCode fio_unittest_lib_num2str(void); 19 | CU_ErrorCode fio_unittest_lib_strntol(void); 20 | CU_ErrorCode fio_unittest_oslib_strlcat(void); 21 | CU_ErrorCode fio_unittest_oslib_strndup(void); 22 | CU_ErrorCode fio_unittest_oslib_strcasestr(void); 23 | CU_ErrorCode fio_unittest_oslib_strsep(void); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /zone-dist.h: -------------------------------------------------------------------------------- 1 | #ifndef FIO_ZONE_DIST_H 2 | #define FIO_ZONE_DIST_H 3 | 4 | void td_zone_gen_index(struct thread_data *td); 5 | void td_zone_free_index(struct thread_data *td); 6 | 7 | #endif 8 | --------------------------------------------------------------------------------