Improved NID parsing to accept hostnames, IPv4 and IPv6 addresses.
IPv6 addresses need @network to be parsed properly. The following
is a valid IPv6 address: "6699:7654::1234:1234:d84@tcp"
All other non IPv6 addresses can be passed in without a network
identifier.
Signed-off-by: Maximilian Dilger <mdilger@whamcloud.com>
Change-Id: I131c8b2d1f7b0fe593564af90308d2d3ea278a0c
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55706
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Mikhail Pershin <mpershin@whamcloud.com>
}
run_test 153a "bypass invalid NIDs quickly"
+#LU-17367
+test_153b() {
+ reformat_and_config
+ setupall
+
+ local IPv6_1="6699:7654::1234:1234:d84@tcp"
+ local IPv6_2="2001:0db8:85a3:0000:0000:8a2e:0370:7334@tcp"
+ local IPv6_3="5031:db8:85a3:8d3:1319:8a2e:370:7348@tcp"
+ local IPv4_1="127.0.0.5"
+ local IPv4_2="193.168.0.240@tcp"
+ local IPv4_3="162.32.0.100"
+
+ local mgslist
+
+ umount $MOUNT
+
+ mgslist="$IPv6_1:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$mgs_HOST:$mgs_HOST:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$mgs_HOST:$IPv6_1"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$mgs_HOST:$IPv4_1"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$IPv4_1:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$IPv4_2:$IPv4_1:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$IPv6_1,$IPv4_2,$IPv4_1:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\
+:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\
+:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\
+:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\
+:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\
+:$IPv4_1:$IPv4_1:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3,$IPv6_2:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+
+ mgslist="$IPv4_2,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2\
+,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2,$IPv6_1,$IPv4_2\
+,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3\
+,$IPv4_3:$IPv6_2,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2\
+:$mgs_HOST"
+ mount -t lustre $mgslist:/$FSNAME $MOUNT ||
+ error "mount failed with $mgslist:/$FSNAME $MOUNT"
+ umount $MOUNT
+}
+run_test 153b "added IPv6 NID support"
+
test_154() {
[ "$mds1_FSTYPE" == "ldiskfs" ] || skip "ldiskfs only test"
(( $MDS1_VERSION >= $(version_code 2.15.63.1) )) ||
/* Get rid of symbolic hostnames for tcp, since kernel can't do lookups */
#define MAXNIDSTR 1024
-char *convert_hostnames(char *s1, bool mount)
+char *convert_hostnames(char *buf, bool mount)
{
- char *converted, *s2 = 0, *c, *end, sep;
+ char *converted, *c, *end, sep;
+ 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) {
/* end is different between mount and mkfs case */
if (mount) {
- end = strchr(s1, '/');
+ end = strchr(buf, '/');
if (!end) {
fprintf(stderr, "%s: Invalid mount string: %s\n",
- progname, s1);
+ progname, buf);
goto out_bad_mnt_str;
}
end--;
} else {
- end = s1 + strlen(s1);
+ end = buf + strlen(buf);
}
c = converted;
- while ((left > 0) && (s1 < end)) {
+ /* 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;
- /* Needed to skip : in IPv6 / GUID strings. Lustre uses
- * ':' as a seperator as well which makes this complicated.
- */
- s2 = strchr(s1, '@');
- if (!s2 || s2 > end) {
- fprintf(stderr, "%s: Invalid NID string '%s'\n",
- progname, s1);
- goto out_free;
- }
-
- s2 = strpbrk(s2, ",:");
- if (!s2) {
- s2 = end;
- } else if (s2 > end) {
- fprintf(stderr, "%s: Invalid NID string '%s'\n",
- progname, s1);
- goto out_free;
+ }
+ delimiter++;
}
- sep = *s2;
- *s2 = '\0';
+ /* 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
+ */
+ sep = *delimiter;
+ *delimiter = '\0';
- rc = libcfs_strnid(&nid, s1);
+ rc = libcfs_strnid(&nid, buf);
if (rc < 0) {
fprintf(stderr, "%s: Unsupported NID '%s': rc = %s.\n",
- progname, s1, strerror(rc));
+ progname, buf, strerror(rc));
goto out_free;
}
- *s2 = sep; /* back to original string */
+ *delimiter = sep; /* back to original string */
if (LNET_NID_IS_ANY(&nid)) {
fprintf(stderr, "%s: Cannot resolve hostname '%s'.\n",
- progname, s1);
+ progname, buf);
goto out_free;
}
sep);
else
c += scnprintf(c, left, "%s", libcfs_nidstr(&nid));
+
left = converted + MAXNIDSTR - c;
- s1 = s2 + 1;
+ buf = delimiter + 1;
}
if (mount)
- snprintf(c, left, "%s", s1);
+ snprintf(c, left, "%s", buf);
return converted;
out_free:
- fprintf(stderr, "%s: Can't parse NID '%s'\n", progname, s1);
+ fprintf(stderr, "%s: Can't parse NID '%s'\n", progname, buf);
out_bad_mnt_str:
free(converted);
return NULL;
int update_utab_entry(struct mount_opts *mop);
int check_mountfsoptions(char *mountopts, char *wanted_mountopts);
void trim_mountfsoptions(char *s);
-char *convert_hostnames(char *s1, bool mount);
+char *convert_hostnames(char *buf, bool mount);
#ifdef HAVE_SERVER_SUPPORT
__u64 get_device_size(char* device);
int lustre_rename_fsname(struct mkfs_opts *mop, const char *mntpt,