diff options
author | Paul Zuchowski <[email protected]> | 2022-01-20 12:28:55 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2022-01-20 10:28:55 -0700 |
commit | 5a4d282f55f3237a4baafa04a897e738aa98f6d2 (patch) | |
tree | 71c82b4bf84bae4a33a6ffacca1b7d16c97b2115 /cmd | |
parent | e1c720de7d1abb7c0f2f4b685fe8c1906bb8060a (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')
-rw-r--r-- | cmd/zdb/zdb.c | 114 |
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); |