From ba0d5ffc1c0eaa0ac0b59cacc992928e80a15bf2 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 12 Jan 2023 09:02:54 -0500 Subject: [PATCH] LU-9680 utils: new llapi_param_display_value(). Currently the special YAML handling is done in lustre_cfg.c for param handling. Other functionality internal to liblustreapi.so will use this as well so move the handling internal to liblustreapi.so. Currently we only make the new llapi_param_display_value() function visible only to the liblustreapi internal code. Later when we support /sys access we can make this available for general use. The "lctl get_param" and "lctl list_param" generally worked for non-root users, but not for parameters under /sys/kernel/debug due to permission changes in the kernel. We still lacked proper non-root access for lctl get_param and lctl list_param. Implement full lctl get_param functionality for non-root users. Also make lctl list_param work for non-root users. These changes will also work with any parameters implemented with Netlink. Change-Id: Ifd9aad16decb0803a336314d4dea38664ff41aa4 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49491 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin --- lustre/doc/Makefile.am | 2 + lustre/doc/lctl-device_list.8 | 38 ++++ lustre/doc/lctl-dl.8 | 1 + lustre/doc/lctl-get_param.8 | 26 +++ lustre/utils/Makefile.am | 6 +- lustre/utils/lctl.c | 4 +- lustre/utils/liblustreapi_param.c | 368 +++++++++++++++++++++++++++++++++ lustre/utils/lustre_cfg.c | 420 ++++++++++---------------------------- lustre/utils/lustreapi_internal.h | 9 + lustre/utils/obdctl.h | 2 +- 10 files changed, 563 insertions(+), 313 deletions(-) create mode 100644 lustre/doc/lctl-device_list.8 create mode 100644 lustre/doc/lctl-dl.8 diff --git a/lustre/doc/Makefile.am b/lustre/doc/Makefile.am index 2c6e699..56dabd7 100644 --- a/lustre/doc/Makefile.am +++ b/lustre/doc/Makefile.am @@ -33,6 +33,8 @@ MANFILES = \ lctl.8 \ + lctl-dl.8 \ + lctl-device_list.8 \ lctl-get_param.8 \ lctl-list_param.8 \ lctl-network.8 \ diff --git a/lustre/doc/lctl-device_list.8 b/lustre/doc/lctl-device_list.8 new file mode 100644 index 0000000..b693b9c --- /dev/null +++ b/lustre/doc/lctl-device_list.8 @@ -0,0 +1,38 @@ +.TH lctl-device_list 8 "2023-01-09" Lustre "configuration utilities" +.SH NAME +lctl device_list \- show all local Lustre Object Based Devices +.SH SYNOPSIS +.B lctl device_list +.RB "[ --target|-t ]" +.RB "[ --yaml|-y ]" + +.B lctl dl +is the same command. +.SH DESCRIPTION +.B lctl device_list +reports details about the local Lustre OBDs. The information reported for the +OBD are the type, name, and UUID. Also reported are the device number, status +and reference count of the OBD device. The device number is needed for lctl +--device argument. +.TP +.SH OPTIONS +.TP +\fB\-t\fR, \fB\-\-target\fR +Retrieve the servers' export NID that communicates with the local OBD. +.TP +\fB\-y\fR, \fB\-\-yaml\fR +An option provided so that the OBD information can be provided in YAML format +.TP +.SH EXAMPLES +.TP +.B $ lctl --device_list -t -y +.SH AVAILABILITY +.B lctl device_list +is a subcommand of +.BR lctl (8) +and is distributed as part of the +.BR lustre (7) +filesystem package. +.SH SEE ALSO +.BR lctl (8), +.BR lustre (7) diff --git a/lustre/doc/lctl-dl.8 b/lustre/doc/lctl-dl.8 new file mode 100644 index 0000000..c5980e8 --- /dev/null +++ b/lustre/doc/lctl-dl.8 @@ -0,0 +1 @@ +.so man8/lctl-device_list.8 diff --git a/lustre/doc/lctl-get_param.8 b/lustre/doc/lctl-get_param.8 index e1c992d..97d6879 100644 --- a/lustre/doc/lctl-get_param.8 +++ b/lustre/doc/lctl-get_param.8 @@ -47,6 +47,12 @@ useful when using patterns. .TP .B -R Recursively show all of the parameter names below the specified name. +.TP +.B -y +Some paramters can be presented in a YAML format but are not by default. This +will format the parameter data in YAML. If the YAML provides a source: field +it can be suppressed with the -n option. + .SH EXAMPLES .B $ lctl get_param osc.*.max_pages_per_rpc .br @@ -73,6 +79,26 @@ osc.testfs-OST0000-osc-ffff8803c9c0f000.max_rpcs_in_flight=8 osc.testfs-OST0001-osc-ffff8803c9c0f000.max_rpcs_in_flight=8 .br osc.testfs-OST0002-osc-ffff8803c9c0f000.max_rpcs_in_flight=8 +.br +.B $ lctl get_param -n devices +.br + 0 UP osd-ldiskfs MGS-osd MGS-osd_UUID 4 +.br +.B $ lctl get_param -y devices +.br +devices: +.br +- index: 0 +.br + status: UP +.br + type: osd-ldiskfs +.br + name: MGS-osd +.br + uuid: MGS-osd_UUID +.br + refcount: 4 .SH SEE ALSO .BR lustre (7), .BR lctl (8), diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index e1c078c..9dfa304 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -111,11 +111,15 @@ liblustreapi_la_SOURCES = liblustreapi.c liblustreapi_hsm.c \ liblustreapi_heat.c liblustreapi_pcc.c \ liblustreapi_root.c \ liblustreapi_lseek.c liblustreapi_swap.c +liblustreapi_la_CFLAGS = -fPIC -D_GNU_SOURCE $(LIBNL3_CFLAGS) \ + -I $(top_builddir)/lnet/utils \ + -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 \ + -DLUSTRE_UTILS=1 liblustreapi_la_LDFLAGS = $(LIBREADLINE) -version-info 1:0:0 \ -Wl,--version-script=liblustreapi.map liblustreapi_la_LIBADD = $(top_builddir)/libcfs/libcfs/libcfs.la \ $(top_builddir)/lnet/utils/lnetconfig/liblnetconfig.la \ - -lpthread + $(LIBNL3_LIBS) -lpthread pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = lustre.pc diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index 5a6db60..a149b8c 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -182,9 +182,9 @@ command_t cmdlist[] = { {"cfg_device", jt_obd_device, 0, "set current device to , same as 'device'\n" "usage: cfg_device "}, - {"device_list", jt_obd_list, 0, "show all devices\n" + {"device_list", jt_device_list, 0, "show all devices\n" "usage: device_list [--target|-t] [--yaml|-y]"}, - {"dl", jt_obd_list, 0, "show all devices, same as 'device_list'\n" + {"dl", jt_device_list, 0, "show all devices, same as 'device_list'\n" "usage: dl [--target|-t] [--yaml|-y]"}, /* Device operations */ diff --git a/lustre/utils/liblustreapi_param.c b/lustre/utils/liblustreapi_param.c index 8a8ae45..a1f52ca 100644 --- a/lustre/utils/liblustreapi_param.c +++ b/lustre/utils/liblustreapi_param.c @@ -32,9 +32,12 @@ #include #include #include +#include #include +#include #include +#include #include #include "lustreapi_internal.h" @@ -364,6 +367,371 @@ out: return rc; } +static void print_obd_line(char *s) +{ + const char *param = "osc/%s/ost_conn_uuid"; + char obd_name[MAX_OBD_NAME]; + char buf[MAX_OBD_NAME]; + FILE *fp = NULL; + glob_t path; + char *ptr; +retry: + /* obd device type is the first 3 characters of param name */ + snprintf(buf, sizeof(buf), " %%*d %%*s %.3s %%%zus %%*s %%*d ", + param, sizeof(obd_name) - 1); + if (sscanf(s, buf, obd_name) == 0) + goto try_mdc; + if (cfs_get_param_paths(&path, param, obd_name) != 0) + goto try_mdc; + fp = fopen(path.gl_pathv[0], "r"); + if (!fp) { + /* need to free path data before retry */ + cfs_free_param_data(&path); +try_mdc: + if (param[0] == 'o') { /* failed with osc, try mdc */ + param = "mdc/%s/mds_conn_uuid"; + goto retry; + } + buf[0] = '\0'; + goto fail_print; + } + + /* should not ignore fgets(3)'s return value */ + if (!fgets(buf, sizeof(buf), fp)) { + fprintf(stderr, "reading from %s: %s", buf, strerror(errno)); + goto fail_close; + } + +fail_close: + fclose(fp); + cfs_free_param_data(&path); + + /* trim trailing newlines */ + ptr = strrchr(buf, '\n'); + if (ptr) + *ptr = '\0'; +fail_print: + ptr = strrchr(s, '\n'); + if (ptr) + *ptr = '\0'; + printf("%s%s%s\n", s, buf[0] ? " " : "", buf); +} + +static int print_out_devices(yaml_parser_t *reply, enum lctl_param_flags flags) +{ + char buf[PATH_MAX / 2], *tmp = NULL; + size_t buf_len = sizeof(buf); + yaml_event_t event; + bool done = false; + int rc; + + if (flags & PARAM_FLAGS_SHOW_SOURCE) { + snprintf(buf, buf_len, "devices="); + printf("%s\n", buf); + } + bzero(buf, sizeof(buf)); + + while (!done) { + rc = yaml_parser_parse(reply, &event); + if (rc == 0) + break; + + if (event.type == YAML_MAPPING_START_EVENT) { + size_t len = strlen(buf); + + if (len > 0 && strcmp(buf, "devices=\n") != 0) { + /* eat last white space */ + buf[len - 1] = '\0'; + if (flags & PARAM_FLAGS_EXTRA_DETAILS) + print_obd_line(buf); + else + printf("%s\n", buf); + } + bzero(buf, sizeof(buf)); + tmp = buf; + } + + if (event.type == YAML_SCALAR_EVENT) { + char *value = (char *)event.data.scalar.value; + + if (strcmp(value, "index") == 0) { + yaml_event_delete(&event); + rc = yaml_parser_parse(reply, &event); + if (rc == 0) + break; + + value = (char *)event.data.scalar.value; + snprintf(tmp, buf_len, "%3s ", value); + buf_len -= 4; + tmp += 4; + } + + if (strcmp(value, "status") == 0 || + strcmp(value, "type") == 0 || + strcmp(value, "name") == 0 || + strcmp(value, "uuid") == 0 || + strcmp(value, "refcount") == 0) { + yaml_event_delete(&event); + rc = yaml_parser_parse(reply, &event); + if (rc == 0) + break; + + value = (char *)event.data.scalar.value; + snprintf(tmp, buf_len, "%s ", value); + buf_len -= strlen(value) + 1; + tmp += strlen(value) + 1; + } + } + + done = (event.type == YAML_DOCUMENT_END_EVENT); + if (done) { + size_t len = strlen(buf); + + if (len > 0) { + /* eat last white space */ + buf[len - 1] = '\0'; + if (flags & PARAM_FLAGS_EXTRA_DETAILS) + print_obd_line(buf); + else + printf("%s\n", buf); + } + bzero(buf, sizeof(buf)); + tmp = buf; + } + yaml_event_delete(&event); + } + + return rc; +} + +int lcfg_param_get_yaml(yaml_parser_t *reply, struct nl_sock *sk, + int version, char *pattern) +{ + char source[PATH_MAX / 2], group[GENL_NAMSIZ + 1]; + char *family = "lustre", *tmp; + yaml_emitter_t request; + yaml_event_t event; + int cmd = 0; + int rc; + + bzero(source, sizeof(source)); + /* replace '/' with '.' to match conf_param and sysctl */ + for (tmp = strchr(pattern, '/'); tmp != NULL; + tmp = strchr(tmp, '/')) + *tmp = '.'; + + tmp = strrchr(pattern, '.'); + if (tmp) { + size_t len = tmp - pattern; + + strncpy(group, tmp + 1, GENL_NAMSIZ); + strncpy(source, pattern, len); + } else { + strncpy(group, pattern, GENL_NAMSIZ); + } + + if (strcmp(group, "devices") == 0) + cmd = LUSTRE_CMD_DEVICES; + + if (!cmd) + return -EOPNOTSUPP; + + /* Setup parser to recieve Netlink packets */ + rc = yaml_parser_initialize(reply); + if (rc == 0) + return -EOPNOTSUPP; + + rc = yaml_parser_set_input_netlink(reply, sk, false); + if (rc == 0) + return -EOPNOTSUPP; + + /* Create Netlink emitter to send request to kernel */ + yaml_emitter_initialize(&request); + rc = yaml_emitter_set_output_netlink(&request, sk, + family, version, + cmd, NLM_F_DUMP); + if (rc == 0) + goto error; + + yaml_emitter_open(&request); + + yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_mapping_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_MAP_TAG, + 1, YAML_ANY_MAPPING_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, + (yaml_char_t *)group, + strlen(group), 1, 0, + YAML_PLAIN_SCALAR_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + if (source[0]) { + const char *key = cmd == LUSTRE_CMD_DEVICES ? "name" : "source"; + + /* Now fill in 'path' filter */ + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_SEQ_TAG, + 1, YAML_ANY_SEQUENCE_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_mapping_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_MAP_TAG, + 1, YAML_ANY_MAPPING_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, + (yaml_char_t *)key, strlen(key), + 1, 0, YAML_PLAIN_SCALAR_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, + (yaml_char_t *)source, + strlen(source), 1, 0, + YAML_PLAIN_SCALAR_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_mapping_end_event_initialize(&event); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_sequence_end_event_initialize(&event); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + } else { + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, + (yaml_char_t *)"", + strlen(""), 1, 0, + YAML_PLAIN_SCALAR_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + } + yaml_mapping_end_event_initialize(&event); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_document_end_event_initialize(&event, 0); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_emitter_close(&request); +error: + if (rc == 0) { + yaml_emitter_log_error(&request, stderr); + rc = -EINVAL; + } + yaml_emitter_delete(&request); + + return rc == 1 ? 0 : -EINVAL; +} + +int llapi_param_display_value(char *path, int version, + enum lctl_param_flags flags, FILE *fp) +{ + yaml_parser_t reply; + struct nl_sock *sk; + int rc; + + /* version zero means just list sources. "devices is special case */ + if (!version && strcmp(path, "devices") == 0) { + fprintf(fp, "devices\n"); + return 0; + } + + sk = nl_socket_alloc(); + if (!sk) + return -ENOMEM; + + rc = lcfg_param_get_yaml(&reply, sk, version, path); + if (rc < 0) + return rc; + + if (flags & PARAM_FLAGS_YAML_FORMAT) { + yaml_document_t results; + yaml_emitter_t output; + + /* load the reply results */ + rc = yaml_parser_load(&reply, &results); + if (rc == 0) { + yaml_parser_log_error(&reply, stderr, "get_param: "); + yaml_document_delete(&results); + rc = -EINVAL; + goto free_reply; + } + + /* create emitter to output results */ + rc = yaml_emitter_initialize(&output); + if (rc == 1) { + yaml_emitter_set_output_file(&output, fp); + + rc = yaml_emitter_dump(&output, &results); + } + + yaml_document_delete(&results); + if (rc == 0) { + yaml_emitter_log_error(&output, stderr); + rc = -EINVAL; + } + yaml_emitter_delete(&output); + } else { + yaml_event_t event; + bool done = false; + + while (!done) { + rc = yaml_parser_parse(&reply, &event); + if (rc == 0) + break; + + if (event.type == YAML_SCALAR_EVENT) { + char *value = (char *)event.data.scalar.value; + + if (strcmp(value, "devices") == 0) + rc = print_out_devices(&reply, flags); + if (rc == 0) + break; + } + + done = (event.type == YAML_STREAM_END_EVENT); + yaml_event_delete(&event); + } + + if (rc == 0) { + yaml_parser_log_error(&reply, stderr, "get_param: "); + rc = -EINVAL; + } + } +free_reply: + yaml_parser_delete(&reply); + nl_socket_free(sk); + return rc == 1 ? 0 : rc; +} + /** * Read the value of the file with location \a path * into a buffer. diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index 0b2a603..8adddcd 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -939,137 +939,33 @@ fail_print: printf("%s%s%s\n", s, buf[0] ? " " : "", buf); } -static int print_out_devices(yaml_parser_t *reply, struct param_opts *popt) +int yaml_get_device_index(char *source) { - char buf[MAX_OBD_NAME], *tmp = NULL; - size_t buf_len = sizeof(buf); - yaml_event_t event; - bool done = false; - int rc; - - bzero(buf, sizeof(buf)); - - while (!done) { - rc = yaml_parser_parse(reply, &event); - if (rc == 0) - break; - - if (event.type == YAML_MAPPING_START_EVENT) { - size_t len = strlen(buf); - - if (len > 0) { - /* eat last white space */ - buf[len - 1] = '\0'; - if (popt->po_detail) - print_obd_line(buf); - else - printf("%s\n", buf); - } - bzero(buf, sizeof(buf)); - tmp = buf; - } - - if (event.type == YAML_SCALAR_EVENT) { - char *value = (char *)event.data.scalar.value; - - if (strcmp(value, "index") == 0) { - yaml_event_delete(&event); - rc = yaml_parser_parse(reply, &event); - if (rc == 0) - break; - - value = (char *)event.data.scalar.value; - - snprintf(tmp, buf_len, "%3s ", value); - buf_len -= 4; - tmp += 4; - } - - if (strcmp(value, "status") == 0 || - strcmp(value, "type") == 0 || - strcmp(value, "name") == 0 || - strcmp(value, "uuid") == 0 || - strcmp(value, "refcount") == 0) { - yaml_event_delete(&event); - rc = yaml_parser_parse(reply, &event); - if (rc == 0) - break; - - value = (char *)event.data.scalar.value; - - snprintf(tmp, buf_len, "%s ", value); - buf_len -= strlen(value) + 1; - tmp += strlen(value) + 1; - } - } - - done = (event.type == YAML_DOCUMENT_END_EVENT); - if (done) { - size_t len = strlen(buf); - - if (len > 0) { - /* eat last white space */ - buf[len - 1] = '\0'; - if (popt->po_detail) - print_obd_line(buf); - else - printf("%s\n", buf); - } - bzero(buf, sizeof(buf)); - tmp = buf; - } - yaml_event_delete(&event); - } - - return rc; -} - -int lcfg_param_get_yaml(yaml_parser_t *reply, struct nl_sock *sk, char *pattern) -{ - char source[MAX_OBD_NAME], group[GENL_NAMSIZ + 1]; - int version = LUSTRE_GENL_VERSION; - char *family = "lustre", *tmp; yaml_emitter_t request; + yaml_parser_t reply; yaml_event_t event; - int cmd = 0; + struct nl_sock *sk; + bool done = false; int rc; - bzero(source, sizeof(source)); - tmp = strrchr(pattern, '/'); - if (tmp) { - size_t len = tmp - pattern; - - strncpy(group, tmp + 1, GENL_NAMSIZ); - strncpy(source, pattern, len); - - /* replace '/' with '.' to match conf_param and sysctl */ - for (tmp = strchr(pattern, '/'); tmp != NULL; - tmp = strchr(tmp, '/')) - *tmp = '.'; - } else { - strncpy(group, pattern, GENL_NAMSIZ); - } - - if (strcmp(group, "devices") == 0) - cmd = LUSTRE_CMD_DEVICES; - - if (!cmd) + sk = nl_socket_alloc(); + if (!sk) return -EOPNOTSUPP; /* Setup parser to recieve Netlink packets */ - rc = yaml_parser_initialize(reply); + rc = yaml_parser_initialize(&reply); if (rc == 0) return -EOPNOTSUPP; - rc = yaml_parser_set_input_netlink(reply, sk, false); + rc = yaml_parser_set_input_netlink(&reply, sk, false); if (rc == 0) return -EOPNOTSUPP; /* Create Netlink emitter to send request to kernel */ yaml_emitter_initialize(&request); - rc = yaml_emitter_set_output_netlink(&request, sk, - family, version, - cmd, NLM_F_DUMP); + rc = yaml_emitter_set_output_netlink(&request, sk, "lustre", + LUSTRE_GENL_VERSION, + LUSTRE_CMD_DEVICES, NLM_F_DUMP); if (rc == 0) goto error; @@ -1089,67 +985,55 @@ int lcfg_param_get_yaml(yaml_parser_t *reply, struct nl_sock *sk, char *pattern) yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG, - (yaml_char_t *)group, - strlen(group), 1, 0, + (yaml_char_t *)"devices", + strlen("devices"), 1, 0, YAML_PLAIN_SCALAR_STYLE); rc = yaml_emitter_emit(&request, &event); if (rc == 0) goto error; - if (source[0]) { - const char *key = "name"; + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_SEQ_TAG, + 1, YAML_ANY_SEQUENCE_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; - /* Now fill in 'path' filter */ - yaml_sequence_start_event_initialize(&event, NULL, - (yaml_char_t *)YAML_SEQ_TAG, - 1, YAML_ANY_SEQUENCE_STYLE); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; + yaml_mapping_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_MAP_TAG, + 1, YAML_ANY_MAPPING_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; - yaml_mapping_start_event_initialize(&event, NULL, - (yaml_char_t *)YAML_MAP_TAG, - 1, YAML_ANY_MAPPING_STYLE); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, + (yaml_char_t *)"name", + strlen("name"), + 1, 0, YAML_PLAIN_SCALAR_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; - yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_STR_TAG, - (yaml_char_t *)key, strlen(key), - 1, 0, YAML_PLAIN_SCALAR_STYLE); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; - - yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_STR_TAG, - (yaml_char_t *)source, - strlen(source), 1, 0, - YAML_PLAIN_SCALAR_STYLE); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, + (yaml_char_t *)source, + strlen(source), 1, 0, + YAML_PLAIN_SCALAR_STYLE); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; - yaml_mapping_end_event_initialize(&event); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; + yaml_mapping_end_event_initialize(&event); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; + + yaml_sequence_end_event_initialize(&event); + rc = yaml_emitter_emit(&request, &event); + if (rc == 0) + goto error; - yaml_sequence_end_event_initialize(&event); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; - } else { - yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_STR_TAG, - (yaml_char_t *)"", - strlen(""), 1, 0, - YAML_PLAIN_SCALAR_STYLE); - rc = yaml_emitter_emit(&request, &event); - if (rc == 0) - goto error; - } yaml_mapping_end_event_initialize(&event); rc = yaml_emitter_emit(&request, &event); if (rc == 0) @@ -1168,81 +1052,39 @@ error: } yaml_emitter_delete(&request); - return rc == 1 ? 0 : -EINVAL; -} - -int lcfg_getparam_yaml(char *path, struct param_opts *popt) -{ - yaml_parser_t reply; - struct nl_sock *sk; - int rc; - - sk = nl_socket_alloc(); - if (!sk) - return -ENOMEM; - - rc = lcfg_param_get_yaml(&reply, sk, path); - if (rc < 0) - return rc; - - if (popt->po_yaml) { - yaml_document_t results; - yaml_emitter_t output; - - /* load the reply results */ - rc = yaml_parser_load(&reply, &results); + while (!done) { + rc = yaml_parser_parse(&reply, &event); if (rc == 0) { - yaml_parser_log_error(&reply, stderr, "get_param: "); - yaml_document_delete(&results); + yaml_parser_log_error(&reply, stdout, "lctl: "); rc = -EINVAL; - goto free_reply; - } - - /* create emitter to output results */ - rc = yaml_emitter_initialize(&output); - if (rc == 1) { - yaml_emitter_set_output_file(&output, stdout); - - rc = yaml_emitter_dump(&output, &results); + break; } - yaml_document_delete(&results); - if (rc == 0) { - yaml_emitter_log_error(&output, stderr); - rc = -EINVAL; - } - yaml_emitter_delete(&output); - } else { - yaml_event_t event; - bool done = false; - - while (!done) { - rc = yaml_parser_parse(&reply, &event); - if (rc == 0) - break; - - if (event.type == YAML_SCALAR_EVENT) { - char *value = (char *)event.data.scalar.value; + if (event.type == YAML_SCALAR_EVENT) { + char *value = (char *)event.data.scalar.value; - if (strcmp(value, "devices") == 0) - rc = print_out_devices(&reply, popt); - if (rc == 0) - break; + if (strcmp(value, "index") == 0) { + yaml_event_delete(&event); + rc = yaml_parser_parse(&reply, &event); + if (rc == 1) { + value = (char *)event.data.scalar.value; + errno = 0; + rc = strtoul(value, NULL, 10); + if (errno) { + yaml_event_delete(&event); + rc = -errno; + } + return rc; + } } - - done = (event.type == YAML_STREAM_END_EVENT); - yaml_event_delete(&event); - } - - if (rc == 0) { - yaml_parser_log_error(&reply, stderr, "get_param: "); - rc = -EINVAL; } + done = (event.type == YAML_STREAM_END_EVENT); + yaml_event_delete(&event); } -free_reply: - yaml_parser_delete(&reply); + nl_socket_free(sk); - return rc == 1 ? 0 : rc; + + return rc; } /** @@ -1487,10 +1329,17 @@ int jt_lcfg_listparam(int argc, char **argv) rc2 = param_display(&popt, path, NULL, LIST_PARAM); if (rc2 < 0) { - fprintf(stderr, "error: %s: listing '%s': %s\n", - jt_cmdname(argv[0]), path, strerror(-rc2)); + if (rc2 == -ENOENT && getuid() != 0) + rc2 = llapi_param_display_value(path, 0, 0, + stdout); if (rc == 0) rc = rc2; + + if (rc < 0) { + fprintf(stderr, "error: %s: listing '%s': %s\n", + jt_cmdname(argv[0]), path, + strerror(-rc2)); + } continue; } } @@ -1504,7 +1353,7 @@ static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) popt->po_show_path = 1; - while ((ch = getopt(argc, argv, "FnNR")) != -1) { + while ((ch = getopt(argc, argv, "FnNRy")) != -1) { switch (ch) { case 'F': popt->po_show_type = 1; @@ -1518,6 +1367,9 @@ static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) case 'R': popt->po_recursive = 1; break; + case 'y': + popt->po_yaml = 1; + break; default: return -1; } @@ -1528,9 +1380,11 @@ static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) int jt_lcfg_getparam(int argc, char **argv) { + int version = LUSTRE_GENL_VERSION; enum parameter_operation mode; int rc = 0, index, i; struct param_opts popt; + int flags = 0; char *path; memset(&popt, 0, sizeof(popt)); @@ -1539,6 +1393,14 @@ int jt_lcfg_getparam(int argc, char **argv) return CMD_HELP; mode = popt.po_only_path ? LIST_PARAM : GET_PARAM; + if (mode == LIST_PARAM) + version = 0; + + if (popt.po_yaml) + flags |= PARAM_FLAGS_YAML_FORMAT; + if (popt.po_show_path) + flags |= PARAM_FLAGS_SHOW_SOURCE; + for (i = index; i < argc; i++) { int rc2; @@ -1555,10 +1417,9 @@ int jt_lcfg_getparam(int argc, char **argv) rc2 = param_display(&popt, path, NULL, mode); if (rc2 < 0) { - if (mode == GET_PARAM && rc2 == -ENOENT && - getuid() != 0) - rc2 = lcfg_getparam_yaml(path, &popt); - + if (rc2 == -ENOENT && getuid() != 0) + rc2 = llapi_param_display_value(path, version, + flags, stdout); if (rc == 0) rc = rc2; continue; @@ -1569,7 +1430,7 @@ int jt_lcfg_getparam(int argc, char **argv) } /* get device list by netlink or debugfs */ -int jt_obd_list(int argc, char **argv) +int jt_device_list(int argc, char **argv) { static const struct option long_opts[] = { { .name = "target", .has_arg = no_argument, .val = 't' }, @@ -1578,12 +1439,12 @@ int jt_obd_list(int argc, char **argv) }; struct param_opts opts; char buf[MAX_OBD_NAME]; - struct nl_sock *sk; + int flags = 0; glob_t path; int rc, c; FILE *fp; - if (optind < argc) + if (optind + 1 < argc) return CMD_HELP; memset(&opts, 0, sizeof(opts)); @@ -1591,9 +1452,11 @@ int jt_obd_list(int argc, char **argv) while ((c = getopt_long(argc, argv, "ty", long_opts, NULL)) != -1) { switch (c) { case 't': + flags |= PARAM_FLAGS_EXTRA_DETAILS; opts.po_detail = true; break; case 'y': + flags |= PARAM_FLAGS_YAML_FORMAT; opts.po_yaml = true; break; default: @@ -1607,21 +1470,12 @@ int jt_obd_list(int argc, char **argv) } optind = 1; - sk = nl_socket_alloc(); - if (!sk) - goto non_netlink; - /* Use YAML to list all devices */ - rc = lcfg_getparam_yaml("devices", &opts); + rc = llapi_param_display_value("devices", LUSTRE_GENL_VERSION, flags, + stdout); if (rc == 0) return 0; -non_netlink: - if (sk) { - nl_close(sk); - nl_socket_free(sk); - } - rc = llapi_param_get_paths("devices", &path); if (rc < 0) return rc; @@ -1647,63 +1501,11 @@ static int do_name2dev(char *func, char *name, int dev_id) { struct obd_ioctl_data data; char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf; - yaml_parser_t output; - yaml_event_t event; - struct nl_sock *sk; - bool done = false; - int rc = 0; - - memset(buf, 0, sizeof(rawbuf)); - scnprintf(buf, sizeof(rawbuf), "%s/devices", - name); - - sk = nl_socket_alloc(); - if (!sk) - goto ioctl; - - /* Use YAML to list all devices */ - rc = lcfg_param_get_yaml(&output, sk, buf); - if (rc < 0) { - if (rc == -EOPNOTSUPP) - goto ioctl; - return rc; - } - - while (!done) { - rc = yaml_parser_parse(&output, &event); - if (rc == 0) { - yaml_parser_log_error(&output, stdout, "lctl: "); - rc = -EINVAL; - break; - } - - if (event.type == YAML_SCALAR_EVENT) { - char *value = (char *)event.data.scalar.value; - - if (strcmp(value, "index") == 0) { - yaml_event_delete(&event); - rc = yaml_parser_parse(&output, &event); - if (rc == 1) { - value = (char *)event.data.scalar.value; - errno = 0; - rc = strtoul(value, NULL, 10); - if (errno) { - yaml_event_delete(&event); - rc = -errno; - goto ioctl; - } - return rc; - } - } - } - done = (event.type == YAML_STREAM_END_EVENT); - yaml_event_delete(&event); - } -ioctl: - if (sk) - nl_socket_free(sk); + int rc; - if (rc > 0 || rc != -EOPNOTSUPP) + /* Use YAML to find device index */ + rc = yaml_get_device_index(name); + if (rc >= 0 || rc != -EOPNOTSUPP) return rc; memset(&data, 0, sizeof(data)); diff --git a/lustre/utils/lustreapi_internal.h b/lustre/utils/lustreapi_internal.h index 72e2ecc..a66cee4 100644 --- a/lustre/utils/lustreapi_internal.h +++ b/lustre/utils/lustreapi_internal.h @@ -184,6 +184,15 @@ int libcfs_ukuc_get_rfd(struct lustre_kernelcomm *link); int libcfs_ukuc_msg_get(struct lustre_kernelcomm *l, char *buf, int maxsize, int transport); +enum lctl_param_flags { + PARAM_FLAGS_YAML_FORMAT = 0x0001, + PARAM_FLAGS_SHOW_SOURCE = 0x0002, + PARAM_FLAGS_EXTRA_DETAILS = 0x0004, +}; + +int llapi_param_display_value(char *path, int version, + enum lctl_param_flags flags, FILE *fp); + enum get_lmd_info_type { GET_LMD_INFO = 1, GET_LMD_STRIPE = 2, diff --git a/lustre/utils/obdctl.h b/lustre/utils/obdctl.h index d3f5908..8ceeb5a 100644 --- a/lustre/utils/obdctl.h +++ b/lustre/utils/obdctl.h @@ -97,7 +97,7 @@ int jt_obd_no_transno(int argc, char **argv); int jt_obd_set_readonly(int argc, char **argv); int jt_obd_abort_recovery(int argc, char **argv); int jt_obd_abort_recovery_mdt(int argc, char **argv); -int jt_obd_list(int argc, char **argv); +int jt_device_list(int argc, char **argv); int jt_obd_create(int argc, char **argv); int jt_obd_test_create(int argc, char **argv); int jt_obd_test_mkdir(int argc, char **argv); -- 1.8.3.1