lfsr: ensure we don't generate an offset + buflen that exceeds the max size
authorJens Axboe <axboe@kernel.dk>
Fri, 11 Jan 2013 13:03:25 +0000 (14:03 +0100)
committerJens Axboe <axboe@kernel.dk>
Fri, 11 Jan 2013 13:03:25 +0000 (14:03 +0100)
Currently we check for the max value, but that doesn't always
work since it may not fit the minimum block size (even if it
is guaranteed to be smaller than the max offset). Pass in the
last valid block.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_u.c
lib/lfsr.c
lib/lfsr.h

diff --git a/io_u.c b/io_u.c
index 91d1290f388ef53a2b9ebd55302c051df8f8983b..94fd1234650d658fe9fdd6db3143710665283614 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -49,11 +49,11 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u)
                io_u->buflen = nr_blocks * min_bs;
 }
 
                io_u->buflen = nr_blocks * min_bs;
 }
 
-static unsigned long long last_block(struct thread_data *td, struct fio_file *f,
-                                    enum fio_ddir ddir)
+static uint64_t last_block(struct thread_data *td, struct fio_file *f,
+                          enum fio_ddir ddir)
 {
 {
-       unsigned long long max_blocks;
-       unsigned long long max_size;
+       uint64_t max_blocks;
+       uint64_t max_size;
 
        assert(ddir_rw(ddir));
 
 
        assert(ddir_rw(ddir));
 
@@ -77,14 +77,14 @@ static unsigned long long last_block(struct thread_data *td, struct fio_file *f,
 static int __get_next_rand_offset(struct thread_data *td, struct fio_file *f,
                                  enum fio_ddir ddir, unsigned long long *b)
 {
 static int __get_next_rand_offset(struct thread_data *td, struct fio_file *f,
                                  enum fio_ddir ddir, unsigned long long *b)
 {
-       unsigned long long r;
+       unsigned long long r, lastb;
 
 
-       if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE) {
-               unsigned long long rmax, lastb;
+       lastb = last_block(td, f, ddir);
+       if (!lastb)
+               return 1;
 
 
-               lastb = last_block(td, f, ddir);
-               if (!lastb)
-                       return 1;
+       if (td->o.random_generator == FIO_RAND_GEN_TAUSWORTHE) {
+               unsigned long long rmax;
 
                rmax = td->o.use_os_rand ? OS_RAND_MAX : FRAND_MAX;
 
 
                rmax = td->o.use_os_rand ? OS_RAND_MAX : FRAND_MAX;
 
@@ -102,7 +102,7 @@ static int __get_next_rand_offset(struct thread_data *td, struct fio_file *f,
        } else {
                uint64_t off = 0;
 
        } else {
                uint64_t off = 0;
 
-               if (lfsr_next(&f->lfsr, &off))
+               if (lfsr_next(&f->lfsr, &off, lastb))
                        return 1;
 
                *b = off;
                        return 1;
 
                *b = off;
index 8a70029627a34ccbec53a104f879c94ec6498234..975c6a5aaf6b813e5a1d4e6bd7ec63e65e67a5ae 100644 (file)
@@ -216,14 +216,15 @@ static uint64_t __lfsr_next(uint64_t v, struct lfsr_taps *lt)
        return xor_mask | (v >> 1);
 }
 
        return xor_mask | (v >> 1);
 }
 
-int lfsr_next(struct fio_lfsr *fl, uint64_t *off)
+int lfsr_next(struct fio_lfsr *fl, uint64_t *off, uint64_t last)
 {
        if (fl->num_vals > fl->max_val)
                return 1;
 
        do {
                fl->last_val = __lfsr_next(fl->last_val, &fl->taps);
 {
        if (fl->num_vals > fl->max_val)
                return 1;
 
        do {
                fl->last_val = __lfsr_next(fl->last_val, &fl->taps);
-               if (fl->last_val - 1 <= fl->max_val)
+               if (fl->last_val - 1 <= fl->max_val &&
+                   fl->last_val <= last)
                        break;
        } while (1);
 
                        break;
        } while (1);
 
index 09f5ac0bd3d73f63541a16ea46778a9d5cecf178..898646e27b4207cbec289a675aa669d9a660d626 100644 (file)
@@ -18,7 +18,7 @@ struct fio_lfsr {
        struct lfsr_taps taps;
 };
 
        struct lfsr_taps taps;
 };
 
-int lfsr_next(struct fio_lfsr *fl, uint64_t *off);
+int lfsr_next(struct fio_lfsr *fl, uint64_t *off, uint64_t);
 int lfsr_init(struct fio_lfsr *fl, uint64_t size, unsigned long seed);
 
 #endif
 int lfsr_init(struct fio_lfsr *fl, uint64_t size, unsigned long seed);
 
 #endif