Skip to content

Commit a6ead8d

Browse files
ikegami-tigaw
authored andcommitted
feat: add perf-characteristics command
The feature supported by NVM command set specification revision 1.1. Signed-off-by: Tokunori Ikegami <[email protected]>
1 parent c7b24c0 commit a6ead8d

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

plugins/feat/feat-nvme.c

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#include <errno.h>
3+
#include <fcntl.h>
24
#include "nvme.h"
35
#include "plugin.h"
46
#include "nvme-print.h"
57

68
#define CREATE_CMD
79
#include "feat-nvme.h"
810

11+
struct perfc_config {
12+
__u32 namespace_id;
13+
__u8 attri;
14+
bool rvspa;
15+
__u8 r4karl;
16+
char *paid;
17+
__u16 attrl;
18+
char *vs_data;
19+
bool save;
20+
__u8 sel;
21+
};
22+
923
static const char *power_mgmt_feat = "power management feature";
1024
static const char *sel = "[0-3]: current/default/saved/supported";
1125
static const char *save = "Specifies that the controller shall save the attribute";
26+
static const char *perfc_feat = "performance characteristics feature";
1227

1328
static int power_mgmt_get(struct nvme_dev *dev, const __u8 fid, __u8 sel)
1429
{
@@ -106,3 +121,140 @@ static int feat_power_mgmt(int argc, char **argv, struct command *cmd, struct pl
106121

107122
return err;
108123
}
124+
125+
static int perfc_get(struct nvme_dev *dev, struct perfc_config *cfg)
126+
{
127+
__u32 result;
128+
int err;
129+
130+
struct nvme_get_features_args args = {
131+
.args_size = sizeof(args),
132+
.fd = dev_fd(dev),
133+
.fid = NVME_FEAT_FID_PERF_CHARACTERISTICS,
134+
.cdw11 = NVME_SET(cfg->attri, FEAT_PERFC_ATTRI) |
135+
NVME_SET(cfg->rvspa, FEAT_PERFC_RVSPA),
136+
.sel = cfg->sel,
137+
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
138+
.result = &result,
139+
};
140+
141+
err = nvme_get_features(&args);
142+
if (!err) {
143+
if (NVME_CHECK(args.sel, GET_FEATURES_SEL, SUPPORTED))
144+
nvme_show_select_result(args.fid, result);
145+
else
146+
nvme_feature_show_fields(args.fid, result, NULL);
147+
} else {
148+
nvme_show_error("Get %s", perfc_feat);
149+
}
150+
151+
return err;
152+
}
153+
154+
static int perfc_set(struct nvme_dev *dev, struct perfc_config *cfg)
155+
{
156+
__u32 result;
157+
int err;
158+
159+
_cleanup_fd_ int ffd = STDIN_FILENO;
160+
161+
struct nvme_perf_characteristics data = {
162+
.attr_buf = { 0 },
163+
};
164+
165+
struct nvme_set_features_args args = {
166+
.args_size = sizeof(args),
167+
.fd = dev_fd(dev),
168+
.fid = NVME_FEAT_FID_PERF_CHARACTERISTICS,
169+
.cdw11 = NVME_SET(cfg->attri, FEAT_PERFC_ATTRI) |
170+
NVME_SET(cfg->rvspa, FEAT_PERFC_RVSPA),
171+
.save = save,
172+
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
173+
.result = &result,
174+
.data = &data,
175+
.data_len = sizeof(data),
176+
};
177+
178+
switch (cfg->attri) {
179+
case NVME_FEAT_PERFC_ATTRI_STD:
180+
data.std_perf->r4karl = cfg->r4karl;
181+
break;
182+
case NVME_FEAT_PERFC_ATTRI_VS_MIN ... NVME_FEAT_PERFC_ATTRI_VS_MAX:
183+
nvme_uuid_from_string(cfg->paid, data.vs_perf->paid);
184+
data.vs_perf->attrl = cfg->attrl;
185+
if (data.vs_perf->attrl && strlen(cfg->vs_data)) {
186+
ffd = open(cfg->vs_data, O_RDONLY);
187+
if (ffd < 0) {
188+
nvme_show_error("Failed to open file %s: %s", cfg->vs_data,
189+
strerror(errno));
190+
return -EINVAL;
191+
}
192+
err = read(ffd, data.vs_perf->vs, data.vs_perf->attrl);
193+
if (err < 0) {
194+
nvme_show_error("failed to read data buffer from input file: %s",
195+
strerror(errno));
196+
return -errno;
197+
}
198+
}
199+
break;
200+
default:
201+
break;
202+
}
203+
204+
err = nvme_set_features(&args);
205+
206+
nvme_show_init();
207+
208+
if (err > 0) {
209+
nvme_show_status(err);
210+
} else if (err < 0) {
211+
nvme_show_perror("Set %s", perfc_feat);
212+
} else {
213+
nvme_show_result("Set %s: 0x%04x (%s)", perfc_feat, args.cdw11,
214+
save ? "Save" : "Not save");
215+
nvme_feature_show_fields(args.fid, args.cdw11, NULL);
216+
}
217+
218+
nvme_show_finish();
219+
220+
return err;
221+
}
222+
223+
static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin *plugin)
224+
{
225+
const char *namespace_id_optional = "optional namespace attached to controller";
226+
const char *attri = "attribute index";
227+
const char *rvspa = "revert vendor specific performance attribute";
228+
const char *r4karl = "random 4 kib average read latency";
229+
const char *paid = "performance attribute identifier";
230+
const char *attrl = "attribute length";
231+
const char *vs_data = "vendor specific data";
232+
233+
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
234+
int err;
235+
236+
struct perfc_config cfg = { 0 };
237+
238+
NVME_ARGS(opts,
239+
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_optional),
240+
OPT_BYTE("attri", 'a', &cfg.attri, attri),
241+
OPT_FLAG("rvspa", 'r', &cfg.rvspa, rvspa),
242+
OPT_BYTE("r4karl", 'R', &cfg.r4karl, r4karl),
243+
OPT_STR("paid", 'p', &cfg.paid, paid),
244+
OPT_SHRT("attrl", 'A', &cfg.attrl, attrl),
245+
OPT_FILE("vs-data", 'V', &cfg.vs_data, vs_data),
246+
OPT_FLAG("save", 's', &cfg.save, save),
247+
OPT_BYTE("sel", 'S', &cfg.sel, sel));
248+
249+
err = parse_and_open(&dev, argc, argv, PERFC_DESC, opts);
250+
if (err)
251+
return err;
252+
253+
if (argconfig_parse_seen(opts, "rvspa") || argconfig_parse_seen(opts, "r4karl") ||
254+
argconfig_parse_seen(opts, "paid"))
255+
err = perfc_set(dev, &cfg);
256+
else
257+
err = perfc_get(dev, &cfg);
258+
259+
return err;
260+
}

plugins/feat/feat-nvme.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111

1212
#define FEAT_PLUGIN_VERSION "1.0"
1313
#define POWER_MGMT_DESC "Get and set power management feature"
14+
#define PERFC_DESC "Get and set perf characteristics feature"
1415

1516
PLUGIN(NAME("feat", "NVMe feature extensions", FEAT_PLUGIN_VERSION),
1617
COMMAND_LIST(
1718
ENTRY("power-mgmt", POWER_MGMT_DESC, feat_power_mgmt)
19+
ENTRY("perf-characteristics", PERFC_DESC, feat_perfc)
1820
)
1921
);
2022
#endif /* !FEAT_NVME || CMD_HEADER_MULTI_READ */

0 commit comments

Comments
 (0)