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 ff5709b..44b7dfa 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 4c39a77..b454aa0 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 e9b6aad..427b4e5 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 5194f0f..3dbce47 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 87cded4..f83fc9b 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 e9f5d92..ff3069b 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 f8c52e5..4e059a8 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 df0ec2d..f7154a4 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