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 <behlendorf1@llnl.gov>
Signed-off-by: Gvozden Neskovic <neskovic@gmail.com>
Closes #4479
This commit is contained in:
Brian Behlendorf 2016-06-29 13:59:51 -07:00
parent a0cacb760a
commit fcf64f45d9
2 changed files with 23 additions and 4 deletions

View File

@ -3414,7 +3414,8 @@ zdb_read_block(char *thing, spa_t *spa)
psize = size; psize = size;
lsize = 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); lbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
BP_ZERO(bp); BP_ZERO(bp);
@ -3481,9 +3482,18 @@ zdb_read_block(char *thing, spa_t *spa)
VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize, VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize,
SPA_MAXBLOCKSIZE - psize) == 0); 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++) { 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, if (zio_decompress_data(c, pbuf, lbuf,
psize, lsize) == 0 && psize, lsize) == 0 &&
zio_decompress_data(c, pbuf2, lbuf2, zio_decompress_data(c, pbuf2, lbuf2,

View File

@ -143,12 +143,21 @@ zio_init(void)
*/ */
if (arc_watch && !IS_P2ALIGNED(size, PAGESIZE)) if (arc_watch && !IS_P2ALIGNED(size, PAGESIZE))
continue; 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) { if (size <= 4 * SPA_MINBLOCKSIZE) {
align = SPA_MINBLOCKSIZE; align = SPA_MINBLOCKSIZE;
} else if (IS_P2ALIGNED(size, p2 >> 2)) { } else if (IS_P2ALIGNED(size, p2 >> 2)) {
align = MIN(p2 >> 2, PAGESIZE); align = MIN(p2 >> 2, PAGESIZE);
} }
#endif
if (align != 0) { if (align != 0) {
char name[36]; char name[36];