posixaio.c revision 5f350952eff89948bfbf1eb6ac4d3d08a9109581
12866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe/*
22866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe * posix aio io engine
32866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe *
42866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe */
52866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <stdio.h>
62866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <stdlib.h>
72866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <unistd.h>
82866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <errno.h>
92866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#include <assert.h>
105f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
115f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe#include "../fio.h"
125f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe#include "../os.h"
132866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe#ifdef FIO_HAVE_POSIXAIO
1534cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
162866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestruct posixaio_data {
172866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct io_u **aio_events;
182866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe};
192866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
202866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fill_timespec(struct timespec *ts)
212866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
222866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#ifdef _POSIX_TIMERS
232866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (!clock_gettime(CLOCK_MONOTONIC, ts))
242866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 0;
252866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
262866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	perror("clock_gettime");
272866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe#endif
282866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 1;
292866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
302866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
312866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic unsigned long long ts_utime_since_now(struct timespec *t)
322866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
332866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	long long sec, nsec;
342866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct timespec now;
352866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
362866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (fill_timespec(&now))
372866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 0;
382866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
392866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	sec = now.tv_sec - t->tv_sec;
402866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	nsec = now.tv_nsec - t->tv_nsec;
412866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (sec > 0 && nsec < 0) {
422866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		sec--;
432866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		nsec += 1000000000;
442866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
452866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
462866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	sec *= 1000000;
472866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	nsec /= 1000;
482866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return sec + nsec;
492866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
502866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
517a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboestatic int fio_posixaio_cancel(struct thread_data fio_unused *td,
527a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboe			       struct io_u *io_u)
532866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
5453cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	struct fio_file *f = io_u->file;
5553cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	int r = aio_cancel(f->fd, &io_u->aiocb);
562866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
572866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (r == 1 || r == AIO_CANCELED)
582866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 0;
592866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
602866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 1;
612866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
622866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
637a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboestatic int fio_posixaio_prep(struct thread_data fio_unused *td,
647a16dd027f83d7ff8ff0e72bb6bb12fae046fcbfJens Axboe			     struct io_u *io_u)
652866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
662866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct aiocb *aiocb = &io_u->aiocb;
6753cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	struct fio_file *f = io_u->file;
682866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
6953cdc6864f7471b28cc9b40a5314ab43e5b1cb5eJens Axboe	aiocb->aio_fildes = f->fd;
702866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	aiocb->aio_buf = io_u->buf;
712866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	aiocb->aio_nbytes = io_u->buflen;
722866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	aiocb->aio_offset = io_u->offset;
732866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
742866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	io_u->seen = 0;
752866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 0;
762866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
772866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
782866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_posixaio_getevents(struct thread_data *td, int min, int max,
792866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				  struct timespec *t)
802866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
812866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = td->io_ops->data;
822866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct list_head *entry;
832866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct timespec start;
842866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	int r, have_timeout = 0;
852866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
862866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (t && !fill_timespec(&start))
872866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		have_timeout = 1;
882866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
892866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	r = 0;
902866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboerestart:
912866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	list_for_each(entry, &td->io_u_busylist) {
922866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		struct io_u *io_u = list_entry(entry, struct io_u, list);
932866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		int err;
942866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
952866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		if (io_u->seen)
962866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			continue;
972866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
982866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		err = aio_error(&io_u->aiocb);
992866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		switch (err) {
1002866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			default:
1012866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				io_u->error = err;
1022866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			case ECANCELED:
1032866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			case 0:
1042866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				pd->aio_events[r++] = io_u;
1052866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				io_u->seen = 1;
1062866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				break;
1072866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			case EINPROGRESS:
1082866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe				break;
1092866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		}
1102866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1112866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		if (r >= max)
1122866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			break;
1132866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
1142866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1152866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (r >= min)
1162866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return r;
1172866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1182866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (have_timeout) {
1192866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		unsigned long long usec;
1202866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1212866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		usec = (t->tv_sec * 1000000) + (t->tv_nsec / 1000);
1222866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		if (ts_utime_since_now(&start) > usec)
1232866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			return r;
1242866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
1252866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1262866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	/*
1272866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	 * hrmpf, we need to wait for more. we should use aio_suspend, for
1282866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	 * now just sleep a little and recheck status of busy-and-not-seen
1292866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	 */
1302866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	usleep(1000);
1312866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	goto restart;
1322866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1332866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1342866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic struct io_u *fio_posixaio_event(struct thread_data *td, int event)
1352866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1362866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = td->io_ops->data;
1372866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1382866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return pd->aio_events[event];
1392866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1402866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1412866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_posixaio_queue(struct thread_data fio_unused *td,
1422866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe			      struct io_u *io_u)
1432866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1442866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct aiocb *aiocb = &io_u->aiocb;
1452866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	int ret;
1462866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1472866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (io_u->ddir == DDIR_READ)
1482866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		ret = aio_read(aiocb);
14987dc1ab1b4df7b977f60e3d43533a896e2ee665bJens Axboe	else if (io_u->ddir == DDIR_WRITE)
1502866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		ret = aio_write(aiocb);
15187dc1ab1b4df7b977f60e3d43533a896e2ee665bJens Axboe	else
15287dc1ab1b4df7b977f60e3d43533a896e2ee665bJens Axboe		ret = aio_fsync(O_SYNC, aiocb);
1532866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1542866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (ret)
1552866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		io_u->error = errno;
1562866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1572866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return io_u->error;
1582866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1592866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1602866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic void fio_posixaio_cleanup(struct thread_data *td)
1612866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1622866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = td->io_ops->data;
1632866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1642866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	if (pd) {
1652866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		free(pd->aio_events);
1662866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		free(pd);
1672866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		td->io_ops->data = NULL;
1682866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	}
1692866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1702866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1712866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_posixaio_init(struct thread_data *td)
1722866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
1732866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	struct posixaio_data *pd = malloc(sizeof(*pd));
1742866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
175cb781c758e5df7ff4c6f655c1e4f9df3043a4be9Jens Axboe	memset(pd, 0, sizeof(*pd));
1762866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	pd->aio_events = malloc(td->iodepth * sizeof(struct io_u *));
177cb781c758e5df7ff4c6f655c1e4f9df3043a4be9Jens Axboe	memset(pd->aio_events, 0, td->iodepth * sizeof(struct io_u *));
1782866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1792866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	td->io_ops->data = pd;
1802866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 0;
1812866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1822866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1835f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic struct ioengine_ops ioengine = {
1842866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.name		= "posixaio",
1852866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.version	= FIO_IOOPS_VERSION,
1862866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.init		= fio_posixaio_init,
1872866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.prep		= fio_posixaio_prep,
1882866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.queue		= fio_posixaio_queue,
1892866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.cancel		= fio_posixaio_cancel,
1902866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.getevents	= fio_posixaio_getevents,
1912866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.event		= fio_posixaio_event,
1922866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.cleanup	= fio_posixaio_cleanup,
1932866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe};
19434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
19534cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe#else /* FIO_HAVE_POSIXAIO */
19634cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
19734cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe/*
19834cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe * When we have a proper configure system in place, we simply wont build
19934cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe * and install this io engine. For now install a crippled version that
20034cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe * just complains and fails to load.
20134cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe */
20234cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboestatic int fio_posixaio_init(struct thread_data fio_unused *td)
20334cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe{
20434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	fprintf(stderr, "fio: posixaio not available\n");
20534cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	return 1;
20634cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe}
20734cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
2085f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic struct ioengine_ops ioengine = {
20934cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	.name		= "posixaio",
21034cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	.version	= FIO_IOOPS_VERSION,
21134cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe	.init		= fio_posixaio_init,
21234cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe};
21334cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe
21434cfcdafa994a0a75120e498c51eda08bde5df72Jens Axboe#endif
2155f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
2165f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic void fio_init fio_posixaio_register(void)
2175f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe{
2185f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe	register_ioengine(&ioengine);
2195f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe}
2205f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
2215f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic void fio_exit fio_posixaio_unregister(void)
2225f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe{
2235f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe	unregister_ioengine(&ioengine);
2245f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe}
225