1
0
Fork 0
nvme-cli/plugins/solidigm/solidigm-garbage-collection.c
Daniel Baumann ee6621a5b2
Merging upstream version 2.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-16 12:24:13 +01:00

138 lines
3.4 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Solidigm.
*
* Author: leonardo.da.cunha@solidigm.com
*/
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#include "linux/types.h"
#include "nvme-print.h"
#include "solidigm-garbage-collection.h"
#include "solidigm-util.h"
struct __packed gc_item {
__le32 timer_type;
__le64 timestamp;
};
#define VU_GC_MAX_ITEMS 100
struct garbage_control_collection_log {
__le16 version_major;
__le16 version_minor;
struct __packed gc_item item[VU_GC_MAX_ITEMS];
__u8 reserved[2892];
};
static void vu_gc_log_show_json(struct garbage_control_collection_log *payload, const char *devname)
{
struct json_object *gc_entries = json_create_array();
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
struct __packed gc_item item = payload->item[i];
struct json_object *entry = json_create_object();
json_object_add_value_int(entry, "timestamp", le64_to_cpu(item.timestamp));
json_object_add_value_int(entry, "timer_type", le32_to_cpu(item.timer_type));
json_array_add_value_object(gc_entries, entry);
}
json_print_object(gc_entries, NULL);
json_free_object(gc_entries);
}
static void vu_gc_log_show(struct garbage_control_collection_log *payload, const char *devname,
__u8 uuid_index)
{
printf("Solidigm Garbage Collection Log for NVME device:%s UUID-idx:%d\n", devname,
uuid_index);
printf("Timestamp Timer Type\n");
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
struct __packed gc_item item = payload->item[i];
printf("%-13" PRIu64 " %d\n", le64_to_cpu(item.timestamp), le32_to_cpu(item.timer_type));
}
}
int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Get and parse Solidigm vendor specific garbage collection event log.";
struct nvme_dev *dev;
int err;
__u8 uuid_index;
struct config {
char *output_format;
};
struct config cfg = {
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_END()
};
err = parse_and_open(&dev, argc, argv, desc, opts);
if (err)
return err;
enum nvme_print_flags flags = validate_output_format(cfg.output_format);
if (flags == -EINVAL) {
fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
dev_close(dev);
return -EINVAL;
}
uuid_index = solidigm_get_vu_uuid_index(dev);
struct garbage_control_collection_log gc_log;
const int solidigm_vu_gc_log_id = 0xfd;
struct nvme_get_log_args args = {
.lpo = 0,
.result = NULL,
.log = &gc_log,
.args_size = sizeof(args),
.fd = dev_fd(dev),
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.lid = solidigm_vu_gc_log_id,
.len = sizeof(gc_log),
.nsid = NVME_NSID_ALL,
.csi = NVME_CSI_NVM,
.lsi = NVME_LOG_LSI_NONE,
.lsp = NVME_LOG_LSP_NONE,
.uuidx = uuid_index,
.rae = false,
.ot = false,
};
err = nvme_get_log(&args);
if (!err) {
if (flags & BINARY)
d_raw((unsigned char *)&gc_log, sizeof(gc_log));
else if (flags & JSON)
vu_gc_log_show_json(&gc_log, dev->name);
else
vu_gc_log_show(&gc_log, dev->name, uuid_index);
} else if (err > 0) {
nvme_show_status(err);
}
/* Redundant close() to make static code analysis happy */
close(dev->direct.fd);
dev_close(dev);
return err;
}