diff options
Diffstat (limited to 'plugins/zns/zns.c')
-rw-r--r-- | plugins/zns/zns.c | 116 |
1 files changed, 89 insertions, 27 deletions
diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index e558317..2f765b6 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -565,13 +565,25 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi const char *state = "state of zones to list"; const char *ext = "set to use the extended report zones"; const char *part = "set to use the partial report"; - const char *human_readable = "show report zones in readable format"; + const char *verbose = "show report zones verbosity"; enum nvme_print_flags flags; int fd, zdes = 0, err = -1; __u32 report_size; void *report; bool huge = false; + struct nvme_zone_report *buff; + + unsigned int nr_zones_chunks = 1024, /* 1024 entries * 64 bytes per entry = 64k byte transfer */ + nr_zones_retrieved = 0, + nr_zones, + offset, + log_len; + int total_nr_zones = 0; + struct nvme_zns_id_ns id_zns; + struct nvme_id_ns id_ns; + uint8_t lbaf; + __le64 zsze; struct config { char *output_format; @@ -579,7 +591,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi __u32 namespace_id; int num_descs; int state; - int human_readable; + int verbose; bool extended; bool partial; }; @@ -595,7 +607,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi OPT_UINT("descs", 'd', &cfg.num_descs, num_descs), OPT_UINT("state", 'S', &cfg.state, state), OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), + OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), OPT_FLAG("extended", 'e', &cfg.extended, ext), OPT_FLAG("partial", 'p', &cfg.partial, part), OPT_END() @@ -608,7 +620,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi flags = validate_output_format(cfg.output_format); if (flags < 0) goto close_fd; - if (cfg.human_readable) + if (cfg.verbose) flags |= VERBOSE; if (!cfg.namespace_id) { @@ -627,23 +639,53 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } } - if (cfg.num_descs == -1) { - struct nvme_zone_report r; + err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns); + if (err) { + nvme_show_status(err); + goto close_fd; + } - err = nvme_zns_report_zones(fd, cfg.namespace_id, 0, - 0, cfg.state, 0, sizeof(r), &r); - if (err > 0) { - nvme_show_status(err); - goto close_fd; - } else if (err < 0) { - perror("zns report-zones"); - goto close_fd; - } - cfg.num_descs = le64_to_cpu(r.nr_zones); + err = nvme_zns_identify_ns(fd, cfg.namespace_id, &id_zns); + if (!err) { + /* get zsze field from zns id ns data - needed for offset calculation */ + lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK; + zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze); + } + else { + nvme_show_status(err); + goto close_fd; + } + + log_len = sizeof(struct nvme_zone_report); + buff = calloc(1, log_len); + if (!buff) { + err = -ENOMEM; + goto close_fd; + } + + err = nvme_zns_report_zones(fd, cfg.namespace_id, 0, + 0, cfg.state, 0, log_len, buff); + if (err > 0) { + nvme_show_status(err); + goto free_buff; + } + else if (err < 0) { + perror("zns report-zones"); + goto free_buff; + } + + total_nr_zones = le64_to_cpu(buff->nr_zones); + + if (cfg.num_descs == -1) { + cfg.num_descs = total_nr_zones; } - report_size = sizeof(struct nvme_zone_report) + cfg.num_descs * - (sizeof(struct nvme_zns_desc) + cfg.num_descs * zdes); + nr_zones = cfg.num_descs; + if (nr_zones < nr_zones_chunks) + nr_zones_chunks = nr_zones; + + log_len = sizeof(struct nvme_zone_report) + ((sizeof(struct nvme_zns_desc) * nr_zones_chunks) + (nr_zones_chunks * zdes)); + report_size = log_len; report = nvme_alloc(report_size, &huge); if (!report) { @@ -652,17 +694,37 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi goto close_fd; } - err = nvme_zns_report_zones(fd, cfg.namespace_id, cfg.zslba, - cfg.extended, cfg.state, cfg.partial, report_size, report); - if (!err) - nvme_show_zns_report_zones(report, cfg.num_descs, zdes, - report_size, flags); - else if (err > 0) - nvme_show_status(err); - else - perror("zns report-zones"); + offset = cfg.zslba; + printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones)); + + while (nr_zones_retrieved < nr_zones) { + if (nr_zones_retrieved >= nr_zones) + break; + + if (nr_zones_retrieved + nr_zones_chunks > nr_zones) { + nr_zones_chunks = nr_zones - nr_zones_retrieved; + log_len = sizeof(struct nvme_zone_report) + ((sizeof(struct nvme_zns_desc) * nr_zones_chunks) + (nr_zones_chunks * zdes)); + } + + err = nvme_zns_report_zones(fd, cfg.namespace_id, offset, + cfg.extended, cfg.state, cfg.partial, log_len, report); + if (err > 0) { + nvme_show_status(err); + break; + } + + if (!err) + nvme_show_zns_report_zones(report, nr_zones_chunks, zdes, + log_len, flags); + + nr_zones_retrieved += nr_zones_chunks; + offset = (nr_zones_retrieved * zsze); + } nvme_free(report, huge); + +free_buff: + free(buff); close_fd: close(fd); return nvme_status_to_errno(err, false); |