lfs check takes an optional path argument that should restrict its
output to the targets that are related to the specified file system.
To determine which MGC should be shown the NID embedded in the OBD
name is compared against a NID that is parsed from the mount command
line. There are a few problems with this code:
1. The NID is parsed from the mount command by looking for a ':', but
IPv6 NIDs can contain this character.
2. It doesn't handle case where multiple NIDs are listed on mount
command separated by commas. e.g. "1@kfi,2@kfi:3@kfi,4@kfi:/lustre"
will parse to "1@kfi,2@kfi" which is not a valid NID.
3. Even in the case where we have just two NIDs separated by ':', it
assumes that the first one will be the one we are connected to.
To resolve these issues get_root_path_slow() will now store the entire
NID string used at mount time (after it has been processed by
convert_hostnames()) in the struct root_cache::nid. do_target_check()
will then iterate over each NID in the string using a new nidstrings
function, cfs_nidstr_find_delimiter(). This function contains logic
that was formerly in convert_hostnames(). This should ensure that
each MGS NID is checked.
convert_hostnames() is updated to use cfs_nidstr_find_delimiter() as
well.
Fixes:
6301419509 ("LU-17367 utils: improved hostname and IPv6 NID support")
Fixes:
f5ca6853b8 ("LU-16076 utils: enhance 'lfs check' command")
Test-Parameters: testlist=sanityn env=ONLY=113,FORCE_LARGE_NID=true,LOAD_MODULES_REMOTE=true
Signed-off-by: Chris Horn <chris.horn@hpe.com>
Change-Id: I478c66d77a2b241b910324210475d61b3786c986
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56286
Tested-by: Maloo <maloo@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Feng Lei <flei@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Maximilian Dilger <mdilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
#define DEBUG_SUBSYSTEM S_LNET
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
free(addrs);
return max_nids - count;
}
+
+/* returns pointer to the next delimiter in nidstr or if no delimiters are
+ * found then it returns a pointer to the termining NUL character
+ * A delimiter can be a comma, colon, or space.
+ */
+char *cfs_nidstr_find_delimiter(char *nidstr)
+{
+ char *delimiter = nidstr;
+ int hex_count = 0;
+ int hex_sections = 0;
+ bool is_ipv6 = true;
+
+ /* address parsing */
+ while (*delimiter != ',' && *delimiter != ' ' && *delimiter != '\0') {
+ /* Need to skip : in IPv6 / GUID NIDs. Lustre also uses
+ * ':' as a separator, which makes this complicated.
+ */
+ if (*delimiter == '@') {
+ while (*delimiter != ':' && *delimiter != ',' &&
+ *delimiter != ' ' && *delimiter != '\0')
+ delimiter++;
+ break;
+ }
+ /* IPv6 addresses are in 0-4 hex digit groups */
+ else if ((isxdigit(*delimiter) || *delimiter == ':') &&
+ hex_count <= 4 && is_ipv6) {
+ if (*delimiter == ':') {
+ hex_sections++;
+ hex_count = 0;
+ } else {
+ hex_count++;
+ }
+ } else { /* NID is not IPv6 */
+ is_ipv6 = false;
+ if (*delimiter == ':')
+ break;
+
+ }
+ delimiter++;
+ }
+ return delimiter;
+}
int cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
char *max_nid, __kernel_size_t nidstr_length);
void cfs_expr_list_free_list(struct list_head *list);
+char *cfs_nidstr_find_delimiter(char *buf);
#endif /* _LNET_NIDSTRINGS_H */
struct check_target_filter *filter = args;
if (filter != NULL) {
- /* check nid if obd type is mgc */
+ /* check NIDs if obd type is mgc */
if (strcmp(obd_type_name, "mgc") == 0) {
- if (strcmp(obd_name + 3, filter->nid) != 0)
+ char *delimiter = filter->nid;
+ char *nidstr = filter->nid;
+ bool found = false;
+
+ while (*nidstr && *delimiter) {
+ delimiter = cfs_nidstr_find_delimiter(nidstr);
+ if (!strncmp(obd_name + 3, nidstr,
+ delimiter - nidstr)) {
+ found = true;
+ break;
+ }
+ nidstr = delimiter + 1;
+ }
+ if (!found)
return;
}
/* check instance for other types of device (osc/mdc) */
strncpy(root_cached.mnt_dir, mnt.mnt_dir, mntlen);
root_cached.mnt_dir[mntlen] = '\0';
root_cached.dev = devmnt;
- ptr_end = strchr(mnt.mnt_fsname, ':');
+ ptr_end = strstr(mnt.mnt_fsname, ":/");
strncpy(root_cached.nid, mnt.mnt_fsname,
ptr_end - mnt.mnt_fsname);
root_cached.nid[ptr_end - mnt.mnt_fsname] = '\0';
char *delimiter = buf;
int left = MAXNIDSTR;
struct lnet_nid nid;
- int hex_count = 0;
- int hex_sections = 0;
- bool is_ipv6 = true;
converted = malloc(left);
if (!converted) {
/* parse all NIDs */
while ((left > 0) && (delimiter < end)) {
int rc;
- hex_count = 0;
- hex_sections = 0;
- is_ipv6 = true;
-
- /* previous delimiter */
- if (*delimiter == ',' || *delimiter == ':')
- delimiter++;
-
- /* address parsing */
- while (*delimiter != ',' && *delimiter != ' ' && *delimiter != '\0') {
- /* Need to skip : in IPv6 / GUID NIDs. Lustre also uses
- * ':' as a separator, which makes this complicated.
- */
- if (*delimiter == '@') {
- while (*delimiter != ':' && *delimiter != ','
- && *delimiter != ' ' && *delimiter != '\0')
- delimiter++;
- break;
- }
- /* IPv6 addresses are in 0-4 hex digit groups */
- else if ((isxdigit(*delimiter) || *delimiter == ':') &&
- hex_count <= 4 && is_ipv6) {
- if (*delimiter == ':') {
- hex_sections++;
- hex_count = 0;
- } else {
- hex_count++;
- }
- } else { /* NID is not IPv6 */
- is_ipv6 = false;
- if (*delimiter == ':')
- break;
- }
- delimiter++;
- }
+ delimiter = cfs_nidstr_find_delimiter(buf);
/* sets the position of the found delimiter to null
* temporarily so when we pass it into parse_nid
* or parse_net it only uses the found NID