From a5f3027cb0495dfe217b2626d248fcc054e7e878 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 19 Jul 2010 16:19:55 -0600 Subject: [PATCH] Initial commit for TRIM/DISCARD support Signed-off-by: Jens Axboe --- engines/libaio.c | 8 ++++++++ engines/posixaio.c | 8 +++++++- engines/splice.c | 2 ++ engines/sync.c | 4 ++++ io_ddir.h | 1 + ioengine.h | 3 ++- ioengines.c | 18 ++++++++++++++++++ os/os-linux.h | 19 +++++++++++++++++++ 8 files changed, 61 insertions(+), 2 deletions(-) diff --git a/engines/libaio.c b/engines/libaio.c index ff5709b4..44b7dfa7 100644 --- a/engines/libaio.c +++ b/engines/libaio.c @@ -105,6 +105,14 @@ static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u) return FIO_Q_COMPLETED; } + if (io_u->ddir == DDIR_TRIM) { + if (ld->iocbs_nr) + return FIO_Q_BUSY; + + do_io_u_trim(td, io_u); + return FIO_Q_COMPLETED; + } + ld->iocbs[ld->iocbs_nr] = &io_u->iocb; ld->io_us[ld->iocbs_nr] = io_u; ld->iocbs_nr++; diff --git a/engines/posixaio.c b/engines/posixaio.c index 4c39a771..b454aa01 100644 --- a/engines/posixaio.c +++ b/engines/posixaio.c @@ -165,7 +165,13 @@ static int fio_posixaio_queue(struct thread_data fio_unused *td, ret = aio_read(aiocb); else if (io_u->ddir == DDIR_WRITE) ret = aio_write(aiocb); - else { + else if (io_u->ddir == DDIR_TRIM) { + if (pd->queued) + return FIO_Q_BUSY; + + do_io_u_trim(td, io_u); + return FIO_Q_COMPLETED; + } else { #ifdef FIO_HAVE_POSIXAIO_FSYNC ret = aio_fsync(O_SYNC, aiocb); #else diff --git a/engines/splice.c b/engines/splice.c index e9b6aadd..427b4e5f 100644 --- a/engines/splice.c +++ b/engines/splice.c @@ -223,6 +223,8 @@ static int fio_spliceio_queue(struct thread_data *td, struct io_u *io_u) ret = fio_splice_read_old(td, io_u); } else if (io_u->ddir == DDIR_WRITE) ret = fio_splice_write(td, io_u); + else if (io_u->ddir == DDIR_TRIM) + ret = do_io_u_trim(td, io_u); else ret = do_io_u_sync(td, io_u); diff --git a/engines/sync.c b/engines/sync.c index 5194f0f8..3dbce47b 100644 --- a/engines/sync.c +++ b/engines/sync.c @@ -75,6 +75,8 @@ static int fio_psyncio_queue(struct thread_data *td, struct io_u *io_u) ret = pread(f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset); else if (io_u->ddir == DDIR_WRITE) ret = pwrite(f->fd, io_u->xfer_buf, io_u->xfer_buflen, io_u->offset); + else if (io_u->ddir == DDIR_TRIM) + ret = do_io_u_trim(td, io_u); else ret = do_io_u_sync(td, io_u); @@ -92,6 +94,8 @@ static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u) ret = read(f->fd, io_u->xfer_buf, io_u->xfer_buflen); else if (io_u->ddir == DDIR_WRITE) ret = write(f->fd, io_u->xfer_buf, io_u->xfer_buflen); + else if (io_u->ddir == DDIR_TRIM) + ret = do_io_u_trim(td, io_u); else ret = do_io_u_sync(td, io_u); diff --git a/io_ddir.h b/io_ddir.h index 87cded46..f83fc9b2 100644 --- a/io_ddir.h +++ b/io_ddir.h @@ -8,6 +8,7 @@ enum fio_ddir { DDIR_DATASYNC, DDIR_SYNC_FILE_RANGE, DDIR_WAIT, + DDIR_TRIM, DDIR_INVAL = -1, }; diff --git a/ioengine.h b/ioengine.h index e9f5d927..ff3069bf 100644 --- a/ioengine.h +++ b/ioengine.h @@ -1,7 +1,7 @@ #ifndef FIO_IOENGINE_H #define FIO_IOENGINE_H -#define FIO_IOOPS_VERSION 11 +#define FIO_IOOPS_VERSION 12 enum { IO_U_F_FREE = 1 << 0, @@ -160,6 +160,7 @@ void io_u_mark_complete(struct thread_data *, unsigned int); void io_u_mark_submit(struct thread_data *, unsigned int); int do_io_u_sync(struct thread_data *, struct io_u *); +int do_io_u_trim(struct thread_data *, struct io_u *); #ifdef FIO_INC_DEBUG static inline void dprint_io_u(struct io_u *io_u, const char *p) diff --git a/ioengines.c b/ioengines.c index f8c52e57..4e059a81 100644 --- a/ioengines.c +++ b/ioengines.c @@ -478,3 +478,21 @@ int do_io_u_sync(struct thread_data *td, struct io_u *io_u) return ret; } + +int do_io_u_trim(struct thread_data *td, struct io_u *io_u) +{ +#ifndef FIO_HAVE_TRIM + io_u->error = EINVAL; + return io_u->xfer_buflen; +#else + struct fio_file *f = io_u->file; + int ret; + + ret = os_trim(f->fd, io_u->offset + f->file_offset, io_u->xfer_buflen); + if (!ret) + return 0; + + io_u->error = errno; + return io_u->xfer_buflen; +#endif +} diff --git a/os/os-linux.h b/os/os-linux.h index df0ec2db..f7154a4a 100644 --- a/os/os-linux.h +++ b/os/os-linux.h @@ -36,6 +36,7 @@ #define FIO_HAVE_CGROUPS #define FIO_HAVE_FDATASYNC #define FIO_HAVE_FS_STAT +#define FIO_HAVE_TRIM #ifdef SYNC_FILE_RANGE_WAIT_BEFORE #define FIO_HAVE_SYNC_FILE_RANGE @@ -185,6 +186,10 @@ enum { #define BLKFLSBUF _IO(0x12,97) #endif +#ifndef BLKDISCARD +#define BLKDISCARD _IO(0x12,119) +#endif + static inline int blockdev_invalidate_cache(int fd) { return ioctl(fd, BLKFLSBUF); @@ -298,4 +303,18 @@ static inline unsigned long long get_fs_size(const char *path) return ret; } +static inline int os_trim(int fd, unsigned long long start, + unsigned long long len) +{ + uint64_t range[2]; + + range[0] = start; + range[1] = len; + + if (!ioctl(fd, BLKDISCARD, range)) + return 0; + + return errno; +} + #endif -- 2.25.1