From: Jian Yu Date: Fri, 20 Nov 2015 19:13:18 +0000 (-0800) Subject: LU-5690 mount: fix lmd_parse() to handle commas in expr_list X-Git-Tag: 2.7.65~74 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F36%2F17036%2F6;p=fs%2Flustre-release.git LU-5690 mount: fix lmd_parse() to handle commas in expr_list The lmd_parse() function parses mount options with comma as delimiter without considering commas in expr_list as follows is a valid LNET nid range syntax: :== '[' [ ',' ] ']' This patch fixes the above issue by using cfs_parse_nidlist() to parse nid range list instead of using class_parse_nid_quiet() to parse only one nid. Signed-off-by: Jian Yu Change-Id: I8ba6ee6eb31b4bb078a83d9db213cfca27b0fe66 Reviewed-on: http://review.whamcloud.com/17036 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Niu Yawei Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin --- diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index 880f7b8..c8b0338 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -1039,6 +1039,89 @@ static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr) return 0; } +/** + * Find the first comma delimiter from the specified \a buf and make \a *endh + * point to the string starting with the comma. The commas in expression list + * [...] will be skipped. + * + * \param[in] buf a comma-separated string + * \param[in] endh a pointer to a pointer that will point to the string + * starting with the comma + * + * \retval 0 if comma delimiter is found + * \retval 1 if comma delimiter is not found + */ +static int lmd_find_comma(char *buf, char **endh) +{ + char *c = buf; + int skip = 0; + + if (buf == NULL) + return 1; + + while (*c != '\0') { + if (*c == '[') + skip++; + else if (*c == ']') + skip--; + + if (*c == ',' && skip == 0) { + if (endh != NULL) + *endh = c; + return 0; + } + + c++; + } + + return 1; +} + +/** + * Find the first valid string delimited by comma from the specified \a buf + # and parse it to see whether it's a valid nid list. If yes, \a *endh will + * point to the next string starting with the comma. + * + * \param[in] buf a comma-separated string + * \param[in] endh a pointer to a pointer that will point to the string + * starting with the comma + * + * \retval 0 if the string is a valid nid list + * \retval 1 if the string is not a valid nid list + */ +static int lmd_parse_nidlist(char *buf, char **endh) +{ + struct list_head nidlist; + char *endp = buf; + char tmp; + int rc = 0; + + if (buf == NULL) + return 1; + while (*buf == ',' || *buf == ':') + buf++; + if (*buf == ' ' || *buf == '/' || *buf == '\0') + return 1; + + if (lmd_find_comma(buf, &endp) != 0) + endp = buf + strlen(buf); + + tmp = *endp; + *endp = '\0'; + + INIT_LIST_HEAD(&nidlist); + if (cfs_parse_nidlist(buf, strlen(buf), &nidlist) <= 0) + rc = 1; + cfs_free_nidlist(&nidlist); + + *endp = tmp; + if (rc != 0) + return rc; + if (endh != NULL) + *endh = endp; + return 0; +} + /** Parse mount line options * e.g. mount -v -t lustre -o abort_recov uml1:uml2:/lustre-client /mnt/lustre * dev is passed as device=uml1:/lustre by mount.lustre @@ -1155,16 +1238,14 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) clear++; } else if (strncmp(s1, "param=", 6) == 0) { size_t length, params_length; - char *tail = strchr(s1 + 6, ','); - if (tail == NULL) { + char *tail = s1; + if (lmd_find_comma(s1 + 6, &tail) != 0) length = strlen(s1); - } else { - lnet_nid_t nid; - char *param_str = tail + 1; - int supplementary = 1; - - while (class_parse_nid_quiet(param_str, &nid, - ¶m_str) == 0) { + else { + char *param_str = tail + 1; + int supplementary = 1; + while (lmd_parse_nidlist(param_str, + ¶m_str) == 0) { supplementary = 0; } length = param_str - s1 - supplementary; diff --git a/lustre/tests/conf-sanity.sh b/lustre/tests/conf-sanity.sh index 30eb1ff..c3a4881 100644 --- a/lustre/tests/conf-sanity.sh +++ b/lustre/tests/conf-sanity.sh @@ -2872,7 +2872,7 @@ test_42() { #bug 14693 } run_test 42 "allow client/server mount/unmount with invalid config param" -test_43() { +test_43a() { [[ $(lustre_version_code mgs) -ge $(version_code 2.5.58) ]] || { skip "Need MDS version at least 2.5.58" && return 0; } [ $UID -ne 0 -o $RUNAS_ID -eq 0 ] && skip_env "run as root" @@ -3020,8 +3020,43 @@ test_43() { touch $DIR/$tdir-rootdir/tfile-2 || error "$ST: root create permission is denied" echo "$ST: root create permission is granted - ok" + cleanup || error "cleanup failed with $?" +} +run_test 43a "check root_squash and nosquash_nids" + +test_43b() { # LU-5690 + [[ $(lustre_version_code mgs) -ge $(version_code 2.7.62) ]] || + { skip "Need MGS version 2.7.62+"; return; } + + if [[ -z "$fs2mds_DEV" ]]; then + is_blkdev $SINGLEMDS $(mdsdevname ${SINGLEMDS//mds/}) && + skip_env "mixed loopback and real device not working" && return + fi + + local fs2mdsdev=$(mdsdevname 1_2) + local fs2mdsvdev=$(mdsvdevname 1_2) + + # temporarily use fs2mds as fs2mgs + local fs2mgs=fs2mds + local fs2mgsdev=$fs2mdsdev + local fs2mgsvdev=$fs2mdsvdev + + local fsname=test1234 + + load_module llite/lustre + local client_ip=$(host_nids_address $HOSTNAME $NETTYPE) + local host=${client_ip//*./} + local net=${client_ip/%$host/} + local nosquash_nids=$(h2$NETTYPE $net[$host,$host,$host]) + + add $fs2mgs $(mkfs_opts mgs $fs2mgsdev) --fsname=$fsname \ + --param mdt.root_squash=$RUNAS_ID:$RUNAS_ID \ + --param mdt.nosquash_nids=$nosquash_nids \ + --reformat $fs2mgsdev $fs2mgsvdev || error "add fs2mgs failed" + start $fs2mgs $fs2mgsdev $MGS_MOUNT_OPTS || error "start fs2mgs failed" + stop $fs2mgs -f || error "stop fs2mgs failed" } -run_test 43 "check root_squash and nosquash_nids" +run_test 43b "parse nosquash_nids with commas in expr_list" umount_client $MOUNT cleanup_nocli