+/**
+ * Find the first delimiter (comma or colon) from the specified \a buf and
+ * make \a *endh point to the string starting with the delimiter. The commas
+ * in expression list [...] will be skipped.
+ *
+ * \param[in] buf a delimiter-separated string
+ * \param[in] endh a pointer to a pointer that will point to the string
+ * starting with the delimiter
+ *
+ * \retval 0 if delimiter is found
+ * \retval 1 if delimiter is not found
+ */
+static int lmd_find_delimiter(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 == ',' || *c == ':') && skip == 0) {
+ if (endh != NULL)
+ *endh = c;
+ return 0;
+ }
+
+ c++;
+ }
+
+ return 1;
+}
+
+/**
+ * Find the first valid string delimited by comma or colon 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 delimiter.
+ *
+ * \param[in] buf a delimiter-separated string
+ * \param[in] endh a pointer to a pointer that will point to the string
+ * starting with the delimiter
+ *
+ * \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_delimiter(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;
+}
+