Whamcloud - gitweb
LU-8378 obd: move s3 in lmd_parse to inner loop
[fs/lustre-release.git] / lustre / obdclass / obd_mount.c
index 6b1ae94..ab7b6ba 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2015, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -398,6 +394,9 @@ int lustre_start_mgc(struct super_block *sb)
 
         /* Random uuid for MGC allows easier reconnects */
         OBD_ALLOC_PTR(uuid);
+       if (uuid == NULL)
+               GOTO(out_free, rc = -ENOMEM);
+
         ll_generate_random_uuid(uuidc);
         class_uuid_unparse(uuidc, uuid);
 
@@ -630,6 +629,9 @@ static int lustre_free_lsi(struct super_block *sb)
                                 strlen(lsi->lsi_lmd->lmd_osd_type) + 1);
                if (lsi->lsi_lmd->lmd_params != NULL)
                        OBD_FREE(lsi->lsi_lmd->lmd_params, 4096);
+               if (lsi->lsi_lmd->lmd_nidnet != NULL)
+                       OBD_FREE(lsi->lsi_lmd->lmd_nidnet,
+                               strlen(lsi->lsi_lmd->lmd_nidnet) + 1);
 
                OBD_FREE_PTR(lsi->lsi_lmd);
        }
@@ -975,6 +977,31 @@ static int lmd_parse_mgssec(struct lustre_mount_data *lmd, char *ptr)
         return 0;
 }
 
+static int lmd_parse_network(struct lustre_mount_data *lmd, char *ptr)
+{
+       char   *tail;
+       int     length;
+
+       if (lmd->lmd_nidnet != NULL) {
+               OBD_FREE(lmd->lmd_nidnet, strlen(lmd->lmd_nidnet) + 1);
+               lmd->lmd_nidnet = NULL;
+       }
+
+       tail = strchr(ptr, ',');
+       if (tail == NULL)
+               length = strlen(ptr);
+       else
+               length = tail - ptr;
+
+       OBD_ALLOC(lmd->lmd_nidnet, length + 1);
+       if (lmd->lmd_nidnet == NULL)
+               return -ENOMEM;
+
+       memcpy(lmd->lmd_nidnet, ptr, length);
+       lmd->lmd_nidnet[length] = '\0';
+       return 0;
+}
+
 static int lmd_parse_string(char **handle, char *ptr)
 {
        char   *tail;
@@ -1043,18 +1070,18 @@ static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
 }
 
 /**
- * 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.
+ * 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 comma-separated string
+ * \param[in] buf      a delimiter-separated string
  * \param[in] endh     a pointer to a pointer that will point to the string
- *                     starting with the comma
+ *                     starting with the delimiter
  *
- * \retval 0           if comma delimiter is found
- * \retval 1           if comma delimiter is not found
+ * \retval 0           if delimiter is found
+ * \retval 1           if delimiter is not found
  */
-static int lmd_find_comma(char *buf, char **endh)
+static int lmd_find_delimiter(char *buf, char **endh)
 {
        char *c = buf;
        int   skip = 0;
@@ -1068,7 +1095,7 @@ static int lmd_find_comma(char *buf, char **endh)
                else if (*c == ']')
                        skip--;
 
-               if (*c == ',' && skip == 0) {
+               if ((*c == ',' || *c == ':') && skip == 0) {
                        if (endh != NULL)
                                *endh = c;
                        return 0;
@@ -1081,13 +1108,13 @@ static int lmd_find_comma(char *buf, char **endh)
 }
 
 /**
- * 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.
+ * 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 comma-separated string
+ * \param[in] buf      a delimiter-separated string
  * \param[in] endh     a pointer to a pointer that will point to the string
- *                     starting with the comma
+ *                     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
@@ -1106,7 +1133,7 @@ static int lmd_parse_nidlist(char *buf, char **endh)
        if (*buf == ' ' || *buf == '/' || *buf == '\0')
                return 1;
 
-       if (lmd_find_comma(buf, &endp) != 0)
+       if (lmd_find_delimiter(buf, &endp) != 0)
                endp = buf + strlen(buf);
 
        tmp = *endp;
@@ -1131,69 +1158,72 @@ static int lmd_parse_nidlist(char *buf, char **endh)
  */
 static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 {
-       char *s1, *s2, *s3, *devname = NULL;
-        struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
-        int rc = 0;
-        ENTRY;
+       char *s1, *s2, *devname = NULL;
+       struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
+       int rc = 0;
+       ENTRY;
 
-        LASSERT(lmd);
-        if (!options) {
-                LCONSOLE_ERROR_MSG(0x162, "Missing mount data: check that "
-                                   "/sbin/mount.lustre is installed.\n");
-                RETURN(-EINVAL);
-        }
+       LASSERT(lmd);
+       if (!options) {
+               LCONSOLE_ERROR_MSG(0x162, "Missing mount data: check that "
+                                  "/sbin/mount.lustre is installed.\n");
+               RETURN(-EINVAL);
+       }
 
-        /* Options should be a string - try to detect old lmd data */
-        if ((raw->lmd_magic & 0xffffff00) == (LMD_MAGIC & 0xffffff00)) {
-                LCONSOLE_ERROR_MSG(0x163, "You're using an old version of "
-                                   "/sbin/mount.lustre.  Please install "
-                                   "version %s\n", LUSTRE_VERSION_STRING);
-                RETURN(-EINVAL);
-        }
-        lmd->lmd_magic = LMD_MAGIC;
+       /* Options should be a string - try to detect old lmd data */
+       if ((raw->lmd_magic & 0xffffff00) == (LMD_MAGIC & 0xffffff00)) {
+               LCONSOLE_ERROR_MSG(0x163, "You're using an old version of "
+                                  "/sbin/mount.lustre.  Please install "
+                                  "version %s\n", LUSTRE_VERSION_STRING);
+               RETURN(-EINVAL);
+       }
+       lmd->lmd_magic = LMD_MAGIC;
 
        OBD_ALLOC(lmd->lmd_params, LMD_PARAMS_MAXLEN);
        if (lmd->lmd_params == NULL)
                RETURN(-ENOMEM);
        lmd->lmd_params[0] = '\0';
 
-        /* Set default flags here */
+       /* Set default flags here */
 
-        s1 = options;
-        while (*s1) {
-                int clear = 0;
-                int time_min = OBD_RECOVERY_TIME_MIN;
+       s1 = options;
+       while (*s1) {
+               int clear = 0;
+               int time_min = OBD_RECOVERY_TIME_MIN;
+               char *s3;
 
-                /* Skip whitespace and extra commas */
-                while (*s1 == ' ' || *s1 == ',')
-                        s1++;
+               /* Skip whitespace and extra commas */
+               while (*s1 == ' ' || *s1 == ',')
+                       s1++;
                s3 = s1;
 
-                /* Client options are parsed in ll_options: eg. flock,
-                   user_xattr, acl */
-
-                /* Parse non-ldiskfs options here. Rather than modifying
-                   ldiskfs, we just zero these out here */
-                if (strncmp(s1, "abort_recov", 11) == 0) {
-                        lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
-                        clear++;
-                } else if (strncmp(s1, "recovery_time_soft=", 19) == 0) {
-                        lmd->lmd_recovery_time_soft = max_t(int,
-                                simple_strtoul(s1 + 19, NULL, 10), time_min);
-                        clear++;
-                } else if (strncmp(s1, "recovery_time_hard=", 19) == 0) {
-                        lmd->lmd_recovery_time_hard = max_t(int,
-                                simple_strtoul(s1 + 19, NULL, 10), time_min);
-                        clear++;
-                } else if (strncmp(s1, "noir", 4) == 0) {
-                        lmd->lmd_flags |= LMD_FLG_NOIR; /* test purpose only. */
-                        clear++;
-                } else if (strncmp(s1, "nosvc", 5) == 0) {
-                        lmd->lmd_flags |= LMD_FLG_NOSVC;
-                        clear++;
-                } else if (strncmp(s1, "nomgs", 5) == 0) {
-                        lmd->lmd_flags |= LMD_FLG_NOMGS;
-                        clear++;
+               /* Client options are parsed in ll_options: eg. flock,
+                  user_xattr, acl */
+
+               /* Parse non-ldiskfs options here. Rather than modifying
+                  ldiskfs, we just zero these out here */
+               if (strncmp(s1, "abort_recov", 11) == 0) {
+                       lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
+                       clear++;
+               } else if (strncmp(s1, "recovery_time_soft=", 19) == 0) {
+                       lmd->lmd_recovery_time_soft =
+                               max_t(int, simple_strtoul(s1 + 19, NULL, 10),
+                                     time_min);
+                       clear++;
+               } else if (strncmp(s1, "recovery_time_hard=", 19) == 0) {
+                       lmd->lmd_recovery_time_hard =
+                               max_t(int, simple_strtoul(s1 + 19, NULL, 10),
+                                     time_min);
+                       clear++;
+               } else if (strncmp(s1, "noir", 4) == 0) {
+                       lmd->lmd_flags |= LMD_FLG_NOIR; /* test purpose only. */
+                       clear++;
+               } else if (strncmp(s1, "nosvc", 5) == 0) {
+                       lmd->lmd_flags |= LMD_FLG_NOSVC;
+                       clear++;
+               } else if (strncmp(s1, "nomgs", 5) == 0) {
+                       lmd->lmd_flags |= LMD_FLG_NOMGS;
+                       clear++;
                } else if (strncmp(s1, "noscrub", 7) == 0) {
                        lmd->lmd_flags |= LMD_FLG_NOSCRUB;
                        clear++;
@@ -1210,9 +1240,9 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                                goto invalid;
                        s3 = s2;
                        clear++;
-                } else if (strncmp(s1, "writeconf", 9) == 0) {
-                        lmd->lmd_flags |= LMD_FLG_WRITECONF;
-                        clear++;
+               } else if (strncmp(s1, "writeconf", 9) == 0) {
+                       lmd->lmd_flags |= LMD_FLG_WRITECONF;
+                       clear++;
                } else if (strncmp(s1, "update", 6) == 0) {
                        lmd->lmd_flags |= LMD_FLG_UPDATE;
                        clear++;
@@ -1222,17 +1252,17 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                } else if (strncmp(s1, "noprimnode", 10) == 0) {
                        lmd->lmd_flags |= LMD_FLG_NO_PRIMNODE;
                        clear++;
-                } else if (strncmp(s1, "mgssec=", 7) == 0) {
-                        rc = lmd_parse_mgssec(lmd, s1 + 7);
-                        if (rc)
-                                goto invalid;
-                        clear++;
-                /* ost exclusion list */
-                } else if (strncmp(s1, "exclude=", 8) == 0) {
-                        rc = lmd_make_exclusion(lmd, s1 + 7);
-                        if (rc)
-                                goto invalid;
-                        clear++;
+               } else if (strncmp(s1, "mgssec=", 7) == 0) {
+                       rc = lmd_parse_mgssec(lmd, s1 + 7);
+                       if (rc)
+                               goto invalid;
+                       clear++;
+                       /* ost exclusion list */
+               } else if (strncmp(s1, "exclude=", 8) == 0) {
+                       rc = lmd_make_exclusion(lmd, s1 + 7);
+                       if (rc)
+                               goto invalid;
+                       clear++;
                } else if (strncmp(s1, "mgs", 3) == 0) {
                        /* We are an MGS */
                        lmd->lmd_flags |= LMD_FLG_MGS;
@@ -1245,7 +1275,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                } else if (strncmp(s1, "param=", 6) == 0) {
                        size_t length, params_length;
                        char  *tail = s1;
-                       if (lmd_find_comma(s1 + 6, &tail) != 0)
+                       if (lmd_find_delimiter(s1 + 6, &tail) != 0)
                                length = strlen(s1);
                        else {
                                char *param_str = tail + 1;
@@ -1270,36 +1300,41 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                        if (rc)
                                goto invalid;
                        clear++;
-                }
-                /* Linux 2.4 doesn't pass the device, so we stuck it at the
-                   end of the options. */
-                else if (strncmp(s1, "device=", 7) == 0) {
-                        devname = s1 + 7;
-                        /* terminate options right before device.  device
-                           must be the last one. */
-                        *s1 = '\0';
-                        break;
-                }
+               }
+               /* Linux 2.4 doesn't pass the device, so we stuck it at the
+                  end of the options. */
+               else if (strncmp(s1, "device=", 7) == 0) {
+                       devname = s1 + 7;
+                       /* terminate options right before device.  device
+                          must be the last one. */
+                       *s1 = '\0';
+                       break;
+               } else if (strncmp(s1, "network=", 8) == 0) {
+                       rc = lmd_parse_network(lmd, s1 + 8);
+                       if (rc)
+                               goto invalid;
+                       clear++;
+               }
 
                /* Find next opt */
                s2 = strchr(s3, ',');
-                if (s2 == NULL) {
-                        if (clear)
-                                *s1 = '\0';
-                        break;
-                }
-                s2++;
-                if (clear)
-                        memmove(s1, s2, strlen(s2) + 1);
-                else
-                        s1 = s2;
-        }
+               if (s2 == NULL) {
+                       if (clear)
+                               *s1 = '\0';
+                       break;
+               }
+               s2++;
+               if (clear)
+                       memmove(s1, s2, strlen(s2) + 1);
+               else
+                       s1 = s2;
+       }
 
-        if (!devname) {
-                LCONSOLE_ERROR_MSG(0x164, "Can't find the device name "
-                                   "(need mount option 'device=...')\n");
-                goto invalid;
-        }
+       if (!devname) {
+               LCONSOLE_ERROR_MSG(0x164, "Can't find the device name "
+                                  "(need mount option 'device=...')\n");
+               goto invalid;
+       }
 
        s1 = strstr(devname, ":/");
        if (s1) {
@@ -1328,39 +1363,50 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                        OBD_ALLOC(lmd->lmd_fileset, s2 - s1 + 2);
                        if (lmd->lmd_fileset == NULL) {
                                OBD_FREE(lmd->lmd_profile,
-                                       strlen(lmd->lmd_profile) + 1);
+                                        strlen(lmd->lmd_profile) + 1);
                                RETURN(-ENOMEM);
                        }
                        strncat(lmd->lmd_fileset, s1, s2 - s1 + 1);
                }
+       } else {
+               /* server mount */
+               if (lmd->lmd_nidnet != NULL) {
+                       /* 'network=' mount option forbidden for server */
+                       OBD_FREE(lmd->lmd_nidnet, strlen(lmd->lmd_nidnet) + 1);
+                       lmd->lmd_nidnet = NULL;
+                       rc = -EINVAL;
+                       CERROR("%s: option 'network=' not allowed for Lustre "
+                              "servers: rc = %d\n", devname, rc);
+                       RETURN(rc);
+               }
        }
 
-        /* Freed in lustre_free_lsi */
-        OBD_ALLOC(lmd->lmd_dev, strlen(devname) + 1);
-        if (!lmd->lmd_dev)
-                RETURN(-ENOMEM);
-        strcpy(lmd->lmd_dev, devname);
-
-        /* Save mount options */
-        s1 = options + strlen(options) - 1;
-        while (s1 >= options && (*s1 == ',' || *s1 == ' '))
-                *s1-- = 0;
-        if (*options != 0) {
-                /* Freed in lustre_free_lsi */
-                OBD_ALLOC(lmd->lmd_opts, strlen(options) + 1);
-                if (!lmd->lmd_opts)
-                        RETURN(-ENOMEM);
-                strcpy(lmd->lmd_opts, options);
-        }
+       /* Freed in lustre_free_lsi */
+       OBD_ALLOC(lmd->lmd_dev, strlen(devname) + 1);
+       if (!lmd->lmd_dev)
+               RETURN(-ENOMEM);
+       strncpy(lmd->lmd_dev, devname, strlen(devname)+1);
+
+       /* Save mount options */
+       s1 = options + strlen(options) - 1;
+       while (s1 >= options && (*s1 == ',' || *s1 == ' '))
+               *s1-- = 0;
+       if (*options != 0) {
+               /* Freed in lustre_free_lsi */
+               OBD_ALLOC(lmd->lmd_opts, strlen(options) + 1);
+               if (!lmd->lmd_opts)
+                       RETURN(-ENOMEM);
+               strncpy(lmd->lmd_opts, options, strlen(options)+1);
+       }
 
-        lmd_print(lmd);
-        lmd->lmd_magic = LMD_MAGIC;
+       lmd_print(lmd);
+       lmd->lmd_magic = LMD_MAGIC;
 
-        RETURN(rc);
+       RETURN(rc);
 
 invalid:
-        CERROR("Bad mount options %s\n", options);
-        RETURN(-EINVAL);
+       CERROR("Bad mount options %s\n", options);
+       RETURN(-EINVAL);
 }
 
 struct lustre_mount_data2 {
@@ -1418,7 +1464,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
                } else {
                        rc = lustre_start_mgc(sb);
                        if (rc) {
-                               lustre_put_lsi(sb);
+                               lustre_common_put_super(sb);
                                GOTO(out, rc);
                        }
                        /* Connect and start */
@@ -1477,7 +1523,9 @@ EXPORT_SYMBOL(lustre_register_kill_super_cb);
 static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
                                   const char *devname, void *data)
 {
-       struct lustre_mount_data2 lmd2 = { data, NULL };
+       struct lustre_mount_data2 lmd2 = {
+               .lmd2_data = data,
+       };
 
        return mount_nodev(fs_type, flags, &lmd2, lustre_fill_super);
 }
@@ -1485,7 +1533,10 @@ static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
 static int lustre_get_sb(struct file_system_type *fs_type, int flags,
                         const char *devname, void *data, struct vfsmount *mnt)
 {
-       struct lustre_mount_data2 lmd2 = { data, mnt };
+       struct lustre_mount_data2 lmd2 = {
+               .lmd2_data = data,
+               .lmd2_mnt = mnt,
+       };
 
        return get_sb_nodev(fs_type, flags, &lmd2, lustre_fill_super, mnt);
 }