verify: ensure that verify_interval is always a factor of min/max bs
authorJens Axboe <axboe@fb.com>
Thu, 5 Jan 2017 17:26:08 +0000 (10:26 -0700)
committerJens Axboe <axboe@fb.com>
Thu, 5 Jan 2017 17:26:08 +0000 (10:26 -0700)
A previous commit force aligned the buffer length to the
verify_interval, but that breaks if max_bs isn't a multiple
of min_bs. If that isn't the case, we can align the block size
bigger than the IO unit really is. This causes corruption and
failures.

Fixes: a9f70b1f5087 ("Make sure io_u->buflen is aligned to the verify_interval")
Signed-off-by: Jens Axboe <axboe@fb.com>
init.c
io_u.c

diff --git a/init.c b/init.c
index c9bf78f6223f00f36ab7c410f46f269464979db3..1ba8fe6e5b08f359d92f582ff10b51099d3ef46e 100644 (file)
--- a/init.c
+++ b/init.c
@@ -564,6 +564,24 @@ static unsigned long long get_rand_start_delay(struct thread_data *td)
        return delayrange;
 }
 
        return delayrange;
 }
 
+static unsigned int gcd(unsigned int m, unsigned int n)
+{
+       unsigned int r;
+
+       if (!m || !n)
+               return 0;
+
+       do {
+               r = m % n;
+               if (!r)
+                       break;
+               m = n;
+               n = r;
+       } while (1);
+
+       return n;
+}
+
 /*
  * Lazy way of fixing up options that depend on each other. We could also
  * define option callback handlers, but this is easier.
 /*
  * Lazy way of fixing up options that depend on each other. We could also
  * define option callback handlers, but this is easier.
@@ -739,6 +757,15 @@ static int fixup_options(struct thread_data *td)
                        o->verify_interval = o->min_bs[DDIR_WRITE];
                else if (td_read(td) && o->verify_interval > o->min_bs[DDIR_READ])
                        o->verify_interval = o->min_bs[DDIR_READ];
                        o->verify_interval = o->min_bs[DDIR_WRITE];
                else if (td_read(td) && o->verify_interval > o->min_bs[DDIR_READ])
                        o->verify_interval = o->min_bs[DDIR_READ];
+
+               /*
+                * Verify interval must be a factor or both min and max
+                * write size
+                */
+               if (o->verify_interval % o->min_bs[DDIR_WRITE] ||
+                   o->verify_interval % o->max_bs[DDIR_WRITE])
+                       o->verify_interval = gcd(o->min_bs[DDIR_WRITE],
+                                                       o->max_bs[DDIR_WRITE]);
        }
 
        if (o->pre_read) {
        }
 
        if (o->pre_read) {
diff --git a/io_u.c b/io_u.c
index 7420629740f458ca644fcc2de47891f359d78cd5..1daaf7bea48407c1e6b21f5143730a7c3d22ff97 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -576,10 +576,6 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
                        }
                }
 
                        }
                }
 
-               if (td->o.verify != VERIFY_NONE)
-                       buflen = (buflen + td->o.verify_interval - 1) &
-                               ~(td->o.verify_interval - 1);
-
                if (!td->o.bs_unaligned && is_power_of_2(minbs))
                        buflen &= ~(minbs - 1);
 
                if (!td->o.bs_unaligned && is_power_of_2(minbs))
                        buflen &= ~(minbs - 1);