summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <jaxboe@fusionio.com>2010-07-19 16:19:55 -0600
committerJens Axboe <jaxboe@fusionio.com>2010-07-19 16:19:55 -0600
commita5f3027cb0495dfe217b2626d248fcc054e7e878 (patch)
tree474ccfab087fa70c46f4d23cffb8f20a901093c7
parent366badd3f5c92433b1972ac85e2b4ef46b441011 (diff)
downloadfio-a5f3027cb0495dfe217b2626d248fcc054e7e878.tar.gz
Initial commit for TRIM/DISCARD support
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--engines/libaio.c8
-rw-r--r--engines/posixaio.c8
-rw-r--r--engines/splice.c2
-rw-r--r--engines/sync.c4
-rw-r--r--io_ddir.h1
-rw-r--r--ioengine.h3
-rw-r--r--ioengines.c18
-rw-r--r--os/os-linux.h19
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