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>
+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.
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 (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);