1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
// 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"
typedef struct __attribute__((packed)) gc_item {
__le32 timer_type;
__le64 timestamp;
} gc_item_t;
#define VU_GC_MAX_ITEMS 100
typedef struct garbage_control_collection_log {
__le16 version_major;
__le16 version_minor;
gc_item_t item[VU_GC_MAX_ITEMS];
__u8 reserved[2892];
} garbage_control_collection_log_t;
static void vu_gc_log_show_json(garbage_control_collection_log_t *payload, const char *devname)
{
struct json_object *gc_entries = json_create_array();
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
gc_item_t 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(garbage_control_collection_log_t *payload, const char *devname)
{
printf("Solidigm Garbage Collection Log for NVME device: %s\n", devname);
printf("Timestamp Timer Type\n");
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
gc_item_t item = payload->item[i];
printf("%-13lu %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 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()
};
int fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
return fd;
}
enum nvme_print_flags flags = validate_output_format(cfg.output_format);
if (flags == -EINVAL) {
fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
close(fd);
return flags;
}
garbage_control_collection_log_t gc_log;
const int solidigm_vu_gc_log_id = 0xfd;
int err = nvme_get_log_simple(fd, solidigm_vu_gc_log_id, sizeof(gc_log), &gc_log);
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, devicename);
} else {
vu_gc_log_show(&gc_log, devicename);
}
}
else if (err > 0) {
nvme_show_status(err);
}
close(fd);
return err;
}
|