1a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe/*
2da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * null engine
3da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe *
4da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * IO engine that doesn't do any real IO transfers, it just pretends to.
5da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * The main purpose is to test fio itself.
6a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe *
746a674786944e964517dd652fbf41807c9395cc4Daniel Gollub * It also can act as external C++ engine - compiled with:
846a674786944e964517dd652fbf41807c9395cc4Daniel Gollub *
946a674786944e964517dd652fbf41807c9395cc4Daniel Gollub * g++ -O2 -g -shared -rdynamic -fPIC -o null.so null.c -DFIO_EXTERNAL_ENGINE
1046a674786944e964517dd652fbf41807c9395cc4Daniel Gollub *
11a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe */
12a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe#include <stdio.h>
13a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe#include <stdlib.h>
14a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe#include <unistd.h>
15a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe#include <errno.h>
16a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe#include <assert.h>
17a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe
18a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe#include "../fio.h"
19a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe
2065afa5f2146ee010b7129934f68e691faee54982Jens Axboestruct null_data {
2165afa5f2146ee010b7129934f68e691faee54982Jens Axboe	struct io_u **io_us;
2265afa5f2146ee010b7129934f68e691faee54982Jens Axboe	int queued;
2365afa5f2146ee010b7129934f68e691faee54982Jens Axboe	int events;
2465afa5f2146ee010b7129934f68e691faee54982Jens Axboe};
2565afa5f2146ee010b7129934f68e691faee54982Jens Axboe
2665afa5f2146ee010b7129934f68e691faee54982Jens Axboestatic struct io_u *fio_null_event(struct thread_data *td, int event)
2765afa5f2146ee010b7129934f68e691faee54982Jens Axboe{
2846a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct null_data *nd = (struct null_data *) td->io_ops->data;
2965afa5f2146ee010b7129934f68e691faee54982Jens Axboe
3065afa5f2146ee010b7129934f68e691faee54982Jens Axboe	return nd->io_us[event];
3165afa5f2146ee010b7129934f68e691faee54982Jens Axboe}
3265afa5f2146ee010b7129934f68e691faee54982Jens Axboe
33e7d2e61694c62b90a2fb84c012b4edcc1973d72cJens Axboestatic int fio_null_getevents(struct thread_data *td, unsigned int min_events,
34e7d2e61694c62b90a2fb84c012b4edcc1973d72cJens Axboe			      unsigned int fio_unused max,
35e7d2e61694c62b90a2fb84c012b4edcc1973d72cJens Axboe			      struct timespec fio_unused *t)
3665afa5f2146ee010b7129934f68e691faee54982Jens Axboe{
3746a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct null_data *nd = (struct null_data *) td->io_ops->data;
387401c088106ba35dcfba62ec753b6b20b72ad0e2Jens Axboe	int ret = 0;
397401c088106ba35dcfba62ec753b6b20b72ad0e2Jens Axboe
407401c088106ba35dcfba62ec753b6b20b72ad0e2Jens Axboe	if (min_events) {
417401c088106ba35dcfba62ec753b6b20b72ad0e2Jens Axboe		ret = nd->events;
427401c088106ba35dcfba62ec753b6b20b72ad0e2Jens Axboe		nd->events = 0;
437401c088106ba35dcfba62ec753b6b20b72ad0e2Jens Axboe	}
4465afa5f2146ee010b7129934f68e691faee54982Jens Axboe
4565afa5f2146ee010b7129934f68e691faee54982Jens Axboe	return ret;
4665afa5f2146ee010b7129934f68e691faee54982Jens Axboe}
4765afa5f2146ee010b7129934f68e691faee54982Jens Axboe
4865afa5f2146ee010b7129934f68e691faee54982Jens Axboestatic int fio_null_commit(struct thread_data *td)
4965afa5f2146ee010b7129934f68e691faee54982Jens Axboe{
5046a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct null_data *nd = (struct null_data *) td->io_ops->data;
5165afa5f2146ee010b7129934f68e691faee54982Jens Axboe
52ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe	if (!nd->events) {
5346a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#ifndef FIO_EXTERNAL_ENGINE
54838bc709279964bdcc64070d4eb2777a0f79bcbbJens Axboe		io_u_mark_submit(td, nd->queued);
5546a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#endif
56ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe		nd->events = nd->queued;
57ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe		nd->queued = 0;
58ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe	}
59ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe
6065afa5f2146ee010b7129934f68e691faee54982Jens Axboe	return 0;
6165afa5f2146ee010b7129934f68e691faee54982Jens Axboe}
6265afa5f2146ee010b7129934f68e691faee54982Jens Axboe
63f0c48a70c5cb8e9f04d263999e0b8d9188f08562Jens Axboestatic int fio_null_queue(struct thread_data *td, struct io_u *io_u)
64a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe{
6546a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct null_data *nd = (struct null_data *) td->io_ops->data;
6665afa5f2146ee010b7129934f68e691faee54982Jens Axboe
677101d9c24abec4be58a086d85d6d92ec6e6492e9Jens Axboe	fio_ro_check(td, io_u);
687101d9c24abec4be58a086d85d6d92ec6e6492e9Jens Axboe
6965afa5f2146ee010b7129934f68e691faee54982Jens Axboe	if (td->io_ops->flags & FIO_SYNCIO)
7065afa5f2146ee010b7129934f68e691faee54982Jens Axboe		return FIO_Q_COMPLETED;
71ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe	if (nd->events)
72ed8bd849b04b336b8f666a547aafa2661b0d8c89Jens Axboe		return FIO_Q_BUSY;
7365afa5f2146ee010b7129934f68e691faee54982Jens Axboe
7465afa5f2146ee010b7129934f68e691faee54982Jens Axboe	nd->io_us[nd->queued++] = io_u;
7565afa5f2146ee010b7129934f68e691faee54982Jens Axboe	return FIO_Q_QUEUED;
76a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe}
77a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe
78b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_null_open(struct thread_data fio_unused *td,
79b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe			 struct fio_file fio_unused *f)
80b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
81b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
82b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
83b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
8465afa5f2146ee010b7129934f68e691faee54982Jens Axboestatic void fio_null_cleanup(struct thread_data *td)
8565afa5f2146ee010b7129934f68e691faee54982Jens Axboe{
8646a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct null_data *nd = (struct null_data *) td->io_ops->data;
8765afa5f2146ee010b7129934f68e691faee54982Jens Axboe
8865afa5f2146ee010b7129934f68e691faee54982Jens Axboe	if (nd) {
8965afa5f2146ee010b7129934f68e691faee54982Jens Axboe		if (nd->io_us)
9065afa5f2146ee010b7129934f68e691faee54982Jens Axboe			free(nd->io_us);
9165afa5f2146ee010b7129934f68e691faee54982Jens Axboe		free(nd);
9265afa5f2146ee010b7129934f68e691faee54982Jens Axboe	}
9365afa5f2146ee010b7129934f68e691faee54982Jens Axboe}
9465afa5f2146ee010b7129934f68e691faee54982Jens Axboe
9565afa5f2146ee010b7129934f68e691faee54982Jens Axboestatic int fio_null_init(struct thread_data *td)
9665afa5f2146ee010b7129934f68e691faee54982Jens Axboe{
9746a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct null_data *nd = (struct null_data *) malloc(sizeof(*nd));
9865afa5f2146ee010b7129934f68e691faee54982Jens Axboe
9965afa5f2146ee010b7129934f68e691faee54982Jens Axboe	memset(nd, 0, sizeof(*nd));
10065afa5f2146ee010b7129934f68e691faee54982Jens Axboe
1012dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	if (td->o.iodepth != 1) {
10246a674786944e964517dd652fbf41807c9395cc4Daniel Gollub		nd->io_us = (struct io_u **) malloc(td->o.iodepth * sizeof(struct io_u *));
1032dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe		memset(nd->io_us, 0, td->o.iodepth * sizeof(struct io_u *));
10465afa5f2146ee010b7129934f68e691faee54982Jens Axboe	} else
10565afa5f2146ee010b7129934f68e691faee54982Jens Axboe		td->io_ops->flags |= FIO_SYNCIO;
10665afa5f2146ee010b7129934f68e691faee54982Jens Axboe
10765afa5f2146ee010b7129934f68e691faee54982Jens Axboe	td->io_ops->data = nd;
10865afa5f2146ee010b7129934f68e691faee54982Jens Axboe	return 0;
10965afa5f2146ee010b7129934f68e691faee54982Jens Axboe}
11065afa5f2146ee010b7129934f68e691faee54982Jens Axboe
11146a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#ifndef __cplusplus
112a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboestatic struct ioengine_ops ioengine = {
113a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe	.name		= "null",
114a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe	.version	= FIO_IOOPS_VERSION,
115a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe	.queue		= fio_null_queue,
11665afa5f2146ee010b7129934f68e691faee54982Jens Axboe	.commit		= fio_null_commit,
11765afa5f2146ee010b7129934f68e691faee54982Jens Axboe	.getevents	= fio_null_getevents,
11865afa5f2146ee010b7129934f68e691faee54982Jens Axboe	.event		= fio_null_event,
11965afa5f2146ee010b7129934f68e691faee54982Jens Axboe	.init		= fio_null_init,
12065afa5f2146ee010b7129934f68e691faee54982Jens Axboe	.cleanup	= fio_null_cleanup,
121b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	.open_file	= fio_null_open,
12265afa5f2146ee010b7129934f68e691faee54982Jens Axboe	.flags		= FIO_DISKLESSIO,
123a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe};
124a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe
125a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboestatic void fio_init fio_null_register(void)
126a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe{
127a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe	register_ioengine(&ioengine);
128a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe}
129a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe
130a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboestatic void fio_exit fio_null_unregister(void)
131a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe{
132a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe	unregister_ioengine(&ioengine);
133a94ea28b13429c38036546c36bcfd7355dc1441dJens Axboe}
13446a674786944e964517dd652fbf41807c9395cc4Daniel Gollub
13546a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#else
13646a674786944e964517dd652fbf41807c9395cc4Daniel Gollub
13746a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#ifdef FIO_EXTERNAL_ENGINE
13846a674786944e964517dd652fbf41807c9395cc4Daniel Gollubextern "C" {
1398d6ecac27d36b3001c8fed00eab7f32cd573636aJens Axboevoid get_ioengine(struct ioengine_ops **ioengine_ptr)
1408d6ecac27d36b3001c8fed00eab7f32cd573636aJens Axboe{
14146a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	struct ioengine_ops *ioengine;
1428d6ecac27d36b3001c8fed00eab7f32cd573636aJens Axboe
14346a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	*ioengine_ptr = (struct ioengine_ops *) malloc(sizeof(struct ioengine_ops));
14446a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine = *ioengine_ptr;
14546a674786944e964517dd652fbf41807c9395cc4Daniel Gollub
14646a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	strcpy(ioengine->name, "cpp_null");
14746a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->version        = FIO_IOOPS_VERSION;
14846a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->queue          = fio_null_queue;
14946a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->commit         = fio_null_commit;
15046a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->getevents      = fio_null_getevents;
15146a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->event          = fio_null_event;
15246a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->init           = fio_null_init;
15346a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->cleanup        = fio_null_cleanup;
15446a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->open_file      = fio_null_open;
15546a674786944e964517dd652fbf41807c9395cc4Daniel Gollub	ioengine->flags	         = FIO_DISKLESSIO;
15646a674786944e964517dd652fbf41807c9395cc4Daniel Gollub}
15746a674786944e964517dd652fbf41807c9395cc4Daniel Gollub}
15846a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#endif /* FIO_EXTERNAL_ENGINE */
15946a674786944e964517dd652fbf41807c9395cc4Daniel Gollub
16046a674786944e964517dd652fbf41807c9395cc4Daniel Gollub#endif /* __cplusplus */
161