aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/zdb/zdb.c
diff options
context:
space:
mode:
authorPaul Dagnelie <[email protected]>2019-06-25 12:50:38 -0700
committerBrian Behlendorf <[email protected]>2019-06-25 12:50:37 -0700
commit3fab4d9e08aa1471c5c34bf7fdc2632bf4a7d494 (patch)
tree682288be0f0b010760ec8fd05c68ab62a3bd5a2d /cmd/zdb/zdb.c
parentfc7546777ba15a7fff651cd803bf521f592d8379 (diff)
zdb -vvvvv on ztest pool dies with "out of memory"
ztest creates some extremely large files as part of its operation. When zdb tries to dump a large enough file, it can run out of memory or spend an extremely long time attempting to print millions or billions of uint64_ts. We cap the amount of data from a uint64 object that we are willing to read and print. Reviewed-by: Don Brady <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Paul Dagnelie <[email protected]> External-issue: DLPX-53814 Closes #8947
Diffstat (limited to 'cmd/zdb/zdb.c')
-rw-r--r--cmd/zdb/zdb.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 969c8f1b7..e0ea07280 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -424,23 +424,35 @@ static void
dump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
{
uint64_t *arr;
-
+ uint64_t oursize;
if (dump_opt['d'] < 6)
return;
+
if (data == NULL) {
dmu_object_info_t doi;
VERIFY0(dmu_object_info(os, object, &doi));
size = doi.doi_max_offset;
- arr = kmem_alloc(size, KM_SLEEP);
+ /*
+ * We cap the size at 1 mebibyte here to prevent
+ * allocation failures and nigh-infinite printing if the
+ * object is extremely large.
+ */
+ oursize = MIN(size, 1 << 20);
+ arr = kmem_alloc(oursize, KM_SLEEP);
- int err = dmu_read(os, object, 0, size, arr, 0);
+ int err = dmu_read(os, object, 0, oursize, arr, 0);
if (err != 0) {
(void) printf("got error %u from dmu_read\n", err);
- kmem_free(arr, size);
+ kmem_free(arr, oursize);
return;
}
} else {
+ /*
+ * Even though the allocation is already done in this code path,
+ * we still cap the size to prevent excessive printing.
+ */
+ oursize = MIN(size, 1 << 20);
arr = data;
}
@@ -450,16 +462,18 @@ dump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
}
(void) printf("\t\t[%0llx", (u_longlong_t)arr[0]);
- for (size_t i = 1; i * sizeof (uint64_t) < size; i++) {
+ for (size_t i = 1; i * sizeof (uint64_t) < oursize; i++) {
if (i % 4 != 0)
(void) printf(", %0llx", (u_longlong_t)arr[i]);
else
(void) printf(",\n\t\t%0llx", (u_longlong_t)arr[i]);
}
+ if (oursize != size)
+ (void) printf(", ... ");
(void) printf("]\n");
if (data == NULL)
- kmem_free(arr, size);
+ kmem_free(arr, oursize);
}
/*ARGSUSED*/