posixaio.c revision 2dc1bbeb58edc85f2829eed6729862c438ea2353
12866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe/*
2da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * posixaio engine
3da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe *
4da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * IO engine that uses the posix defined aio interface.
52866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe *
62866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe */
72866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <stdio.h>
82866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <stdlib.h>
92866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <unistd.h>
102866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <errno.h>
112866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <assert.h>
125f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
135f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe#include "../fio.h"
145f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe#include "../os.h"
152866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1634cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe#ifdef FIO_HAVE_POSIXAIO
1734cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
182866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestruct posixaio_data {
192866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct io_u **aio_events;
202866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe};
212866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
222866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fill_timespec(struct timespec *ts)
232866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
242866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#ifdef _POSIX_TIMERS
252866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (!clock_gettime(CLOCK_MONOTONIC, ts))
262866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 0;
272866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
282866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	perror("clock_gettime");
292866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#endif
302866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 1;
312866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
322866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
332866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic unsigned long long ts_utime_since_now(struct timespec *t)
342866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
352866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	long long sec, nsec;
362866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct timespec now;
372866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
382866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (fill_timespec(&now))
392866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 0;
402866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
412866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	sec = now.tv_sec - t->tv_sec;
422866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	nsec = now.tv_nsec - t->tv_nsec;
432866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (sec > 0 && nsec < 0) {
442866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		sec--;
452866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		nsec += 1000000000;
462866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
472866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
482866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	sec *= 1000000;
492866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	nsec /= 1000;
502866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return sec + nsec;
512866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
522866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
537a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboestatic int fio_posixaio_cancel(struct thread_data fio_unused *td,
547a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboe			       struct io_u *io_u)
552866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
5653cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	struct fio_file *f = io_u->file;
5753cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	int r = aio_cancel(f->fd, &io_u->aiocb);
582866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
592866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (r == 1 || r == AIO_CANCELED)
602866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 0;
612866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
622866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 1;
632866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
642866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
657a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboestatic int fio_posixaio_prep(struct thread_data fio_unused *td,
667a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboe			     struct io_u *io_u)
672866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
682866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct aiocb *aiocb = &io_u->aiocb;
6953cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	struct fio_file *f = io_u->file;
702866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
7153cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	aiocb->aio_fildes = f->fd;
72cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe	aiocb->aio_buf = io_u->xfer_buf;
73cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe	aiocb->aio_nbytes = io_u->xfer_buflen;
742866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	aiocb->aio_offset = io_u->offset;
752866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
762866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	io_u->seen = 0;
772866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 0;
782866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
792866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
802866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_posixaio_getevents(struct thread_data *td, int min, int max,
812866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				  struct timespec *t)
822866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
832866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = td->io_ops->data;
842866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct list_head *entry;
852866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct timespec start;
862866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	int r, have_timeout = 0;
872866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
882866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (t && !fill_timespec(&start))
892866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		have_timeout = 1;
902866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
912866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	r = 0;
922866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboerestart:
932866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	list_for_each(entry, &td->io_u_busylist) {
942866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		struct io_u *io_u = list_entry(entry, struct io_u, list);
952866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		int err;
962866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
972866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		if (io_u->seen)
982866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			continue;
992866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1002866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		err = aio_error(&io_u->aiocb);
1013f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe		if (err == EINPROGRESS)
1023f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe			continue;
1033f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe
1043f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe		io_u->seen = 1;
1053f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe		pd->aio_events[r++] = io_u;
1063f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe
1073f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe		if (err == ECANCELED)
1083f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe			io_u->resid = io_u->xfer_buflen;
1093f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe		else if (!err) {
1103f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe			ssize_t retval = aio_return(&io_u->aiocb);
1113f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe
1123f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe			io_u->resid = io_u->xfer_buflen - retval;
1133f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe		} else
1143f344316b3200143f413c9a4a8fd6476ca5899cfJens Axboe			io_u->error = err;
1152866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1162866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		if (r >= max)
1172866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			break;
1182866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
1192866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1202866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (r >= min)
1212866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return r;
1222866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1232866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (have_timeout) {
1242866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		unsigned long long usec;
1252866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1262866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		usec = (t->tv_sec * 1000000) + (t->tv_nsec / 1000);
1272866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		if (ts_utime_since_now(&start) > usec)
1282866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			return r;
1292866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
1302866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1312866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	/*
1322866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	 * hrmpf, we need to wait for more. we should use aio_suspend, for
1332866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	 * now just sleep a little and recheck status of busy-and-not-seen
1342866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	 */
1352866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	usleep(1000);
1362866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	goto restart;
1372866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1382866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1392866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic struct io_u *fio_posixaio_event(struct thread_data *td, int event)
1402866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1412866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = td->io_ops->data;
1422866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1432866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return pd->aio_events[event];
1442866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1452866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1462866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_posixaio_queue(struct thread_data fio_unused *td,
1472866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			      struct io_u *io_u)
1482866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1492866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct aiocb *aiocb = &io_u->aiocb;
1502866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	int ret;
1512866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1522866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (io_u->ddir == DDIR_READ)
1532866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		ret = aio_read(aiocb);
15487dc1ab1b4df7b977f60e3d43533a896e2ee665bJens Axboe	else if (io_u->ddir == DDIR_WRITE)
1552866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		ret = aio_write(aiocb);
15687dc1ab1b4df7b977f60e3d43533a896e2ee665bJens Axboe	else
15787dc1ab1b4df7b977f60e3d43533a896e2ee665bJens Axboe		ret = aio_fsync(O_SYNC, aiocb);
1582866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
15995bcd815e5ce55d6cdd8eb83bda5ee411f37bdc9Jens Axboe	if (ret) {
1602866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		io_u->error = errno;
161e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, io_u->error, "xfer");
16236167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe		return FIO_Q_COMPLETED;
16395bcd815e5ce55d6cdd8eb83bda5ee411f37bdc9Jens Axboe	}
16436167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe
16536167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	return FIO_Q_QUEUED;
1662866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1672866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1682866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic void fio_posixaio_cleanup(struct thread_data *td)
1692866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1702866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = td->io_ops->data;
1712866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1722866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (pd) {
1732866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		free(pd->aio_events);
1742866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		free(pd);
1752866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		td->io_ops->data = NULL;
1762866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
1772866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1782866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1792866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_posixaio_init(struct thread_data *td)
1802866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1812866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = malloc(sizeof(*pd));
1822866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
183cb781c758e5df7ff4c6f655c1e4f9df3043a4be9Jens Axboe	memset(pd, 0, sizeof(*pd));
1842dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	pd->aio_events = malloc(td->o.iodepth * sizeof(struct io_u *));
1852dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	memset(pd->aio_events, 0, td->o.iodepth * sizeof(struct io_u *));
1862866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1872866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	td->io_ops->data = pd;
1882866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 0;
1892866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1902866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1915f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic struct ioengine_ops ioengine = {
1922866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.name		= "posixaio",
1932866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.version	= FIO_IOOPS_VERSION,
1942866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.init		= fio_posixaio_init,
1952866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.prep		= fio_posixaio_prep,
1962866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.queue		= fio_posixaio_queue,
1972866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.cancel		= fio_posixaio_cancel,
1982866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.getevents	= fio_posixaio_getevents,
1992866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.event		= fio_posixaio_event,
2002866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.cleanup	= fio_posixaio_cleanup,
201b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	.open_file	= generic_open_file,
202b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	.close_file	= generic_close_file,
2032866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe};
20434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
20534cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe#else /* FIO_HAVE_POSIXAIO */
20634cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
20734cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe/*
20834cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe * When we have a proper configure system in place, we simply wont build
20934cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe * and install this io engine. For now install a crippled version that
21034cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe * just complains and fails to load.
21134cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe */
21234cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboestatic int fio_posixaio_init(struct thread_data fio_unused *td)
21334cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe{
21434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	fprintf(stderr, "fio: posixaio not available\n");
21534cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	return 1;
21634cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe}
21734cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
2185f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic struct ioengine_ops ioengine = {
21934cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	.name		= "posixaio",
22034cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	.version	= FIO_IOOPS_VERSION,
22134cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	.init		= fio_posixaio_init,
22234cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe};
22334cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
22434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe#endif
2255f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
2265f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic void fio_init fio_posixaio_register(void)
2275f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe{
2285f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe	register_ioengine(&ioengine);
2295f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe}
2305f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
2315f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic void fio_exit fio_posixaio_unregister(void)
2325f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe{
2335f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe	unregister_ioengine(&ioengine);
2345f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe}
235