aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/zdb
diff options
context:
space:
mode:
authorPaul Zuchowski <[email protected]>2022-01-20 12:28:55 -0500
committerGitHub <[email protected]>2022-01-20 10:28:55 -0700
commit5a4d282f55f3237a4baafa04a897e738aa98f6d2 (patch)
tree71c82b4bf84bae4a33a6ffacca1b7d16c97b2115 /cmd/zdb
parente1c720de7d1abb7c0f2f4b685fe8c1906bb8060a (diff)
Fix problem with zdb -d
zdb -d <pool>/<objset ID> does not work when other command line arguments are included i.e. zdb -U <cachefile> -d <pool>/<objset ID> This change fixes the command line parsing to handle this situation. Also fix issue where zdb -r <dataset> <file> does not handle the root <dataset> of the pool. Introduce -N option to force <objset ID> to be interpreted as a numeric objsetID. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Rich Ercolani <[email protected]> Reviewed-by: Tony Nguyen <[email protected]> Signed-off-by: Paul Zuchowski <[email protected]> Closes #12845 Closes #12944
Diffstat (limited to 'cmd/zdb')
-rw-r--r--cmd/zdb/zdb.c114
1 files changed, 84 insertions, 30 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index a40bf4742..c0b1a62a3 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -8389,6 +8389,23 @@ zdb_embedded_block(char *thing)
free(buf);
}
+/* check for valid hex or decimal numeric string */
+static boolean_t
+zdb_numeric(char *str)
+{
+ int i = 0;
+
+ if (strlen(str) == 0)
+ return (B_FALSE);
+ if (strncmp(str, "0x", 2) == 0 || strncmp(str, "0X", 2) == 0)
+ i = 2;
+ for (; i < strlen(str); i++) {
+ if (!isxdigit(str[i]))
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
int
main(int argc, char **argv)
{
@@ -8452,6 +8469,7 @@ main(int argc, char **argv)
{"disable-leak-tracking", no_argument, NULL, 'L'},
{"metaslabs", no_argument, NULL, 'm'},
{"metaslab-groups", no_argument, NULL, 'M'},
+ {"numeric", no_argument, NULL, 'N'},
{"option", required_argument, NULL, 'o'},
{"object-lookups", no_argument, NULL, 'O'},
{"path", required_argument, NULL, 'p'},
@@ -8475,7 +8493,7 @@ main(int argc, char **argv)
};
while ((c = getopt_long(argc, argv,
- "AbcCdDeEFGhiI:klLmMo:Op:PqrRsSt:uU:vVx:XYyZ",
+ "AbcCdDeEFGhiI:klLmMNo:Op:PqrRsSt:uU:vVx:XYyZ",
long_options, NULL)) != -1) {
switch (c) {
case 'b':
@@ -8490,6 +8508,7 @@ main(int argc, char **argv)
case 'l':
case 'm':
case 'M':
+ case 'N':
case 'O':
case 'r':
case 'R':
@@ -8581,32 +8600,6 @@ main(int argc, char **argv)
(void) fprintf(stderr, "-p option requires use of -e\n");
usage();
}
- if (dump_opt['d'] || dump_opt['r']) {
- /* <pool>[/<dataset | objset id> is accepted */
- if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL &&
- objset_str++ != NULL) {
- char *endptr;
- errno = 0;
- objset_id = strtoull(objset_str, &endptr, 0);
- /* dataset 0 is the same as opening the pool */
- if (errno == 0 && endptr != objset_str &&
- objset_id != 0) {
- target_is_spa = B_FALSE;
- dataset_lookup = B_TRUE;
- } else if (objset_id != 0) {
- printf("failed to open objset %s "
- "%llu %s", objset_str,
- (u_longlong_t)objset_id,
- strerror(errno));
- exit(1);
- }
- /* normal dataset name not an objset ID */
- if (endptr == objset_str) {
- objset_id = -1;
- }
- }
- }
-
#if defined(_LP64)
/*
* ZDB does not typically re-read blocks; therefore limit the ARC
@@ -8645,7 +8638,7 @@ main(int argc, char **argv)
verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) {
- if (dump_all && strchr("AeEFklLOPrRSXy", c) == NULL)
+ if (dump_all && strchr("AeEFklLNOPrRSXy", c) == NULL)
dump_opt[c] = 1;
if (dump_opt[c])
dump_opt[c] += verbose;
@@ -8684,6 +8677,7 @@ main(int argc, char **argv)
return (dump_path(argv[0], argv[1], NULL));
}
if (dump_opt['r']) {
+ target_is_spa = B_FALSE;
if (argc != 3)
usage();
dump_opt['v'] = verbose;
@@ -8694,6 +8688,10 @@ main(int argc, char **argv)
rewind = ZPOOL_DO_REWIND |
(dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
+ /* -N implies -d */
+ if (dump_opt['N'] && dump_opt['d'] == 0)
+ dump_opt['d'] = dump_opt['N'];
+
if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 ||
nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, max_txg) != 0 ||
nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, rewind) != 0)
@@ -8712,6 +8710,35 @@ main(int argc, char **argv)
targetlen = strlen(target);
if (targetlen && target[targetlen - 1] == '/')
target[targetlen - 1] = '\0';
+
+ /*
+ * See if an objset ID was supplied (-d <pool>/<objset ID>).
+ * To disambiguate tank/100, consider the 100 as objsetID
+ * if -N was given, otherwise 100 is an objsetID iff
+ * tank/100 as a named dataset fails on lookup.
+ */
+ objset_str = strchr(target, '/');
+ if (objset_str && strlen(objset_str) > 1 &&
+ zdb_numeric(objset_str + 1)) {
+ char *endptr;
+ errno = 0;
+ objset_str++;
+ objset_id = strtoull(objset_str, &endptr, 0);
+ /* dataset 0 is the same as opening the pool */
+ if (errno == 0 && endptr != objset_str &&
+ objset_id != 0) {
+ if (dump_opt['N'])
+ dataset_lookup = B_TRUE;
+ }
+ /* normal dataset name not an objset ID */
+ if (endptr == objset_str) {
+ objset_id = -1;
+ }
+ } else if (objset_str && !zdb_numeric(objset_str + 1) &&
+ dump_opt['N']) {
+ printf("Supply a numeric objset ID with -N\n");
+ exit(1);
+ }
} else {
target_pool = target;
}
@@ -8829,13 +8856,27 @@ main(int argc, char **argv)
}
return (error);
} else {
+ target_pool = strdup(target);
+ if (strpbrk(target, "/@") != NULL)
+ *strpbrk(target_pool, "/@") = '\0';
+
zdb_set_skip_mmp(target);
+ /*
+ * If -N was supplied, the user has indicated that
+ * zdb -d <pool>/<objsetID> is in effect. Otherwise
+ * we first assume that the dataset string is the
+ * dataset name. If dmu_objset_hold fails with the
+ * dataset string, and we have an objset_id, retry the
+ * lookup with the objsetID.
+ */
+ boolean_t retry = B_TRUE;
+retry_lookup:
if (dataset_lookup == B_TRUE) {
/*
* Use the supplied id to get the name
* for open_objset.
*/
- error = spa_open(target, &spa, FTAG);
+ error = spa_open(target_pool, &spa, FTAG);
if (error == 0) {
error = name_from_objset_id(spa,
objset_id, dsname);
@@ -8844,10 +8885,23 @@ main(int argc, char **argv)
target = dsname;
}
}
- if (error == 0)
+ if (error == 0) {
+ if (objset_id > 0 && retry) {
+ int err = dmu_objset_hold(target, FTAG,
+ &os);
+ if (err) {
+ dataset_lookup = B_TRUE;
+ retry = B_FALSE;
+ goto retry_lookup;
+ } else {
+ dmu_objset_rele(os, FTAG);
+ }
+ }
error = open_objset(target, FTAG, &os);
+ }
if (error == 0)
spa = dmu_objset_spa(os);
+ free(target_pool);
}
}
nvlist_free(policy);