summaryrefslogtreecommitdiffstats
path: root/plugins/zns/zns.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/zns/zns.c')
-rw-r--r--plugins/zns/zns.c116
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);