]> granicus.if.org Git - zfs/commitdiff
Fix zdb crash with 4K-only devices
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 29 Jun 2016 20:59:51 +0000 (13:59 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 27 Jul 2016 20:38:46 +0000 (13:38 -0700)
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

cmd/zdb/zdb.c
module/zfs/zio.c

index 967d74216c060a88aaaf50be6d0850fc36d1d220..e35d62cab9d1096a21398f946d45f0d438888f0c 100644 (file)
@@ -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,
index de56a1283c0284900ac38d2c3e637fcf5e4f4f40..3dd8cffe9ca290f4d11fa0a7df123de5d5068f1b 100644 (file)
@@ -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];