Initial commit for TRIM/DISCARD support
authorJens Axboe <jaxboe@fusionio.com>
Mon, 19 Jul 2010 22:19:55 +0000 (16:19 -0600)
committerJens Axboe <jaxboe@fusionio.com>
Mon, 19 Jul 2010 22:19:55 +0000 (16:19 -0600)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
engines/libaio.c
engines/posixaio.c
engines/splice.c
engines/sync.c
io_ddir.h
ioengine.h
ioengines.c
os/os-linux.h

index ff5709b4e9e35c593ed6b219b73ded16c13ef3ea..44b7dfa7eb20f811b8d91af67711925c8381a289 100644 (file)
@@ -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++;
index 4c39a771e12419e9690c9e6cd93ee4a7ad17f791..b454aa01e2b50495db4bbcfa1bd6a632dafb6b93 100644 (file)
@@ -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
index e9b6aadd696bf4daeb62dc0422a75a89c9710ae5..427b4e5fc85d68071977ed3cdf52b08cc06daef0 100644 (file)
@@ -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);
 
index 5194f0f8799d68bf659a03d7969e3ed3bfc44769..3dbce47bc307a6410092f70fe601055f48bc5b10 100644 (file)
@@ -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);
 
index 87cded4642b5ea367d0146c8f19d2e70aa29c0c6..f83fc9b2e9601721f08f549773886af10edb9a5b 100644 (file)
--- 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,
 };
 
index e9f5d9273563db2bf3de35e998dd637cf155630b..ff3069bf73f8a7dc724a85aa4cfc394572be5e00 100644 (file)
@@ -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)
index f8c52e572dc59172303a28b0008e7d95e0a318d4..4e059a8159b3cc59f15b5bd414eb5dd85e5ac7fb 100644 (file)
@@ -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
+}
index df0ec2dbdb51a692cc52f93097a0238844aad1ef..f7154a4af2c16e32ea9e51989f22e4e7af9a8d21 100644 (file)
@@ -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