Merge branch 'dedupe_and_compression' of https://github.com/bardavid/fio
[fio.git] / t / io_uring.c
index 1b729ebf95443f0922a327165420f10bb5c93515..7bf215c7188a6269e8a910749c7300c64055660a 100644 (file)
@@ -28,6 +28,7 @@
 #include "../arch/arch.h"
 #include "../lib/types.h"
 #include "../lib/roundup.h"
+#include "../lib/rand.h"
 #include "../minmax.h"
 #include "../os/linux/io_uring.h"
 
@@ -59,6 +60,8 @@ static unsigned sq_ring_mask, cq_ring_mask;
 
 struct file {
        unsigned long max_blocks;
+       unsigned long max_size;
+       unsigned long cur_off;
        unsigned pending_ios;
        int real_fd;
        int fixed_fd;
@@ -86,6 +89,8 @@ struct submitter {
 
        __s32 *fds;
 
+       struct taus258_state rand_state;
+
        unsigned long *clock_batch;
        int clock_index;
        unsigned long *plat;
@@ -103,6 +108,7 @@ struct submitter {
 static struct submitter *submitter;
 static volatile int finish;
 static int stats_running;
+static unsigned long max_iops;
 
 static int depth = DEPTH;
 static int batch_submit = BATCH_SUBMIT;
@@ -119,7 +125,8 @@ static int do_nop = 0;              /* no-op SQ ring commands */
 static int nthreads = 1;
 static int stats = 0;          /* generate IO stats */
 static int aio = 0;            /* use libaio */
-static int runtime = 0;        /* runtime */
+static int runtime = 0;                /* runtime */
+static int random_io = 1;      /* random or sequential IO */
 
 static unsigned long tsc_rate;
 
@@ -377,6 +384,13 @@ static int io_uring_register_files(struct submitter *s)
 
 static int io_uring_setup(unsigned entries, struct io_uring_params *p)
 {
+       /*
+        * Clamp CQ ring size at our SQ ring size, we don't need more entries
+        * than that.
+        */
+       p->flags |= IORING_SETUP_CQSIZE;
+       p->cq_entries = entries;
+
        return syscall(__NR_io_uring_setup, entries, p);
 }
 
@@ -447,8 +461,15 @@ static void init_io(struct submitter *s, unsigned index)
        }
        f->pending_ios++;
 
-       r = lrand48();
-       offset = (r % (f->max_blocks - 1)) * bs;
+       if (random_io) {
+               r = __rand64(&s->rand_state);
+               offset = (r % (f->max_blocks - 1)) * bs;
+       } else {
+               offset = f->cur_off;
+               f->cur_off += bs;
+               if (f->cur_off + bs > f->max_size)
+                       f->cur_off = 0;
+       }
 
        if (register_files) {
                sqe->flags = IOSQE_FIXED_FILE;
@@ -516,9 +537,11 @@ static int get_file_size(struct file *f)
                        return -1;
 
                f->max_blocks = bytes / bs;
+               f->max_size = bytes;
                return 0;
        } else if (S_ISREG(st.st_mode)) {
                f->max_blocks = st.st_size / bs;
+               f->max_size = st.st_size;
                return 0;
        }
 
@@ -585,6 +608,7 @@ static int submitter_init(struct submitter *s)
        s->tid = gettid();
        printf("submitter=%d, tid=%d\n", s->index, s->tid);
 
+       __init_rand64(&s->rand_state, pthread_self());
        srand48(pthread_self());
 
        for (i = 0; i < MAX_FDS; i++)
@@ -882,6 +906,10 @@ static void do_finish(const char *reason)
                struct submitter *s = get_submitter(j);
                s->finish = 1;
        }
+       if (max_iops > 100000)
+               printf("Maximum IOPS=%luK\n", max_iops / 1000);
+       else if (max_iops)
+               printf("Maximum IOPS=%lu\n", max_iops);
        finish = 1;
 }
 
@@ -1054,18 +1082,19 @@ static void usage(char *argv, int status)
                " -b <int>  : Block size, default %d\n"
                " -p <bool> : Polled IO, default %d\n"
                " -B <bool> : Fixed buffers, default %d\n"
-               " -R <bool> : DMA map fixed buffers, default %d\n"
+               " -D <bool> : DMA map fixed buffers, default %d\n"
                " -F <bool> : Register files, default %d\n"
                " -n <int>  : Number of threads, default %d\n"
                " -O <bool> : Use O_DIRECT, default %d\n"
                " -N <bool> : Perform just no-op requests, default %d\n"
                " -t <bool> : Track IO latencies, default %d\n"
                " -T <int>  : TSC rate in HZ\n"
-               " -a <bool> : Use legacy aio, default %d\n"
-               " -r <int>  : Runtime in seconds, default %s\n",
+               " -r <int>  : Runtime in seconds, default %s\n"
+               " -R <bool> : Use random IO, default %d\n"
+               " -a <bool> : Use legacy aio, default %d\n",
                argv, DEPTH, BATCH_SUBMIT, BATCH_COMPLETE, BS, polled,
                fixedbufs, dma_map, register_files, nthreads, !buffered, do_nop,
-               stats, aio, runtime == 0 ? "unlimited" : runtime_str);
+               stats, runtime == 0 ? "unlimited" : runtime_str, aio, random_io);
        exit(status);
 }
 
@@ -1125,7 +1154,7 @@ int main(int argc, char *argv[])
        if (!do_nop && argc < 2)
                usage(argv[0], 1);
 
-       while ((opt = getopt(argc, argv, "d:s:c:b:p:B:F:n:N:O:t:T:a:r:D:h?")) != -1) {
+       while ((opt = getopt(argc, argv, "d:s:c:b:p:B:F:n:N:O:t:T:a:r:D:R:h?")) != -1) {
                switch (opt) {
                case 'a':
                        aio = !!atoi(optarg);
@@ -1189,6 +1218,9 @@ int main(int argc, char *argv[])
                case 'D':
                        dma_map = !!atoi(optarg);
                        break;
+               case 'R':
+                       random_io = !!atoi(optarg);
+                       break;
                case 'h':
                case '?':
                default:
@@ -1343,6 +1375,7 @@ int main(int argc, char *argv[])
                        stats_running = 1;
 
                for (j = 0; j < nthreads; j++) {
+                       s = get_submitter(j);
                        this_done += s->done;
                        this_call += s->calls;
                        this_reap += s->reaps;
@@ -1362,6 +1395,7 @@ int main(int argc, char *argv[])
                        printf("IOPS=%luK, ", iops / 1000);
                else
                        printf("IOPS=%lu, ", iops);
+               max_iops = max(max_iops, iops);
                if (!do_nop)
                        printf("BW=%luMiB/s, ", bw);
                printf("IOS/call=%ld/%ld, inflight=(%s)\n", rpc, ipc, fdepths);