summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2016-06-29 13:59:51 -0700
committerBrian Behlendorf <[email protected]>2016-07-27 13:38:46 -0700
commitfcf64f45d9bf4270f6c6bfe9df6ef253a7bfc766 (patch)
tree94d97899f6eb1e8e18e1c1a53fef3ba8eee033cc
parenta0cacb760a0d9de2be3f2f569cb0febd77d7064a (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.c16
-rw-r--r--module/zfs/zio.c11
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];