diff options
author | Brian Behlendorf <[email protected]> | 2016-06-29 13:59:51 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-07-27 13:38:46 -0700 |
commit | fcf64f45d9bf4270f6c6bfe9df6ef253a7bfc766 (patch) | |
tree | 94d97899f6eb1e8e18e1c1a53fef3ba8eee033cc | |
parent | a0cacb760a0d9de2be3f2f569cb0febd77d7064a (diff) |
Fix zdb crash with 4K-only devices
Here's the problem - on 4K native devices in userland on
Linux using O_DIRECT, buffers must be 4K aligned or I/O
will fail with EINVAL, causing zdb (and others) to coredump.
Since userland probably doesn't need optimized buffer caches,
we just force 4K alignment on everything.
Signed-off-by: Brian Behlendorf <[email protected]>
Signed-off-by: Gvozden Neskovic <[email protected]>
Closes #4479
-rw-r--r-- | cmd/zdb/zdb.c | 16 | ||||
-rw-r--r-- | module/zfs/zio.c | 11 |
2 files changed, 23 insertions, 4 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 967d74216..e35d62cab 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -3414,7 +3414,8 @@ zdb_read_block(char *thing, spa_t *spa) psize = size; lsize = size; - pbuf = umem_alloc_aligned(SPA_MAXBLOCKSIZE, 512, UMEM_NOFAIL); + /* Some 4K native devices require 4K buffer alignment */ + pbuf = umem_alloc_aligned(SPA_MAXBLOCKSIZE, PAGESIZE, UMEM_NOFAIL); lbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); BP_ZERO(bp); @@ -3481,9 +3482,18 @@ zdb_read_block(char *thing, spa_t *spa) VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize, SPA_MAXBLOCKSIZE - psize) == 0); - for (lsize = SPA_MAXBLOCKSIZE; lsize > psize; - lsize -= SPA_MINBLOCKSIZE) { + /* + * XXX - On the one hand, with SPA_MAXBLOCKSIZE at 16MB, + * this could take a while and we should let the user know + * we are not stuck. On the other hand, printing progress + * info gets old after a while. What to do? + */ + for (lsize = psize + SPA_MINBLOCKSIZE; + lsize <= SPA_MAXBLOCKSIZE; lsize += SPA_MINBLOCKSIZE) { for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) { + (void) printf("Trying %05llx -> %05llx (%s)\n", + (u_longlong_t)psize, (u_longlong_t)lsize, + zio_compress_table[c].ci_name); if (zio_decompress_data(c, pbuf, lbuf, psize, lsize) == 0 && zio_decompress_data(c, pbuf2, lbuf2, diff --git a/module/zfs/zio.c b/module/zfs/zio.c index de56a1283..3dd8cffe9 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -143,12 +143,21 @@ zio_init(void) */ if (arc_watch && !IS_P2ALIGNED(size, PAGESIZE)) continue; -#endif + /* + * Here's the problem - on 4K native devices in userland on + * Linux using O_DIRECT, buffers must be 4K aligned or I/O + * will fail with EINVAL, causing zdb (and others) to coredump. + * Since userland probably doesn't need optimized buffer caches, + * we just force 4K alignment on everything. + */ + align = 8 * SPA_MINBLOCKSIZE; +#else if (size <= 4 * SPA_MINBLOCKSIZE) { align = SPA_MINBLOCKSIZE; } else if (IS_P2ALIGNED(size, p2 >> 2)) { align = MIN(p2 >> 2, PAGESIZE); } +#endif if (align != 0) { char name[36]; |