mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-27 18:34:22 +03:00
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:
parent
a0cacb760a
commit
fcf64f45d9
@ -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,
|
||||||
|
@ -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];
|
||||||
|
Loading…
Reference in New Issue
Block a user