Whamcloud - gitweb
LU-8378 obd: move s3 in lmd_parse to inner loop
[fs/lustre-release.git] / lustre / obdclass / obd_mount.c
index d592459..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, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -95,9 +91,11 @@ int lustre_process_log(struct super_block *sb, char *logname,
         lustre_cfg_bufs_set(bufs, 2, cfg, sizeof(*cfg));
         lustre_cfg_bufs_set(bufs, 3, &sb, sizeof(sb));
         lcfg = lustre_cfg_new(LCFG_LOG_START, bufs);
-        rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
-        lustre_cfg_free(lcfg);
-
+       if (lcfg == NULL)
+               GOTO(out, rc = -ENOMEM);
+       rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
+       lustre_cfg_free(lcfg);
+out:
         OBD_FREE_PTR(bufs);
 
         if (rc == -EINVAL)
@@ -140,6 +138,8 @@ int lustre_end_log(struct super_block *sb, char *logname,
         if (cfg)
                 lustre_cfg_bufs_set(&bufs, 2, cfg, sizeof(*cfg));
         lcfg = lustre_cfg_new(LCFG_LOG_END, &bufs);
+       if (lcfg == NULL)
+               RETURN(-ENOMEM);
         rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
         lustre_cfg_free(lcfg);
         RETURN(rc);
@@ -172,12 +172,13 @@ int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
 
         lcfg = lustre_cfg_new(cmd, &bufs);
+       if (lcfg == NULL)
+               return -ENOMEM;
         lcfg->lcfg_nid = nid;
         rc = class_process_config(lcfg);
         lustre_cfg_free(lcfg);
         return(rc);
 }
-EXPORT_SYMBOL(do_lcfg);
 
 /** Call class_attach and class_setup.  These methods in turn call
  * obd type-specific methods.
@@ -188,7 +189,7 @@ int lustre_start_simple(char *obdname, char *type, char *uuid,
        int rc;
        CDEBUG(D_MOUNT, "Starting obd %s (typ=%s)\n", obdname, type);
 
-       rc = do_lcfg(obdname, 0, LCFG_ATTACH, type, uuid, 0, 0);
+       rc = do_lcfg(obdname, 0, LCFG_ATTACH, type, uuid, NULL, NULL);
        if (rc) {
                CERROR("%s attach error %d\n", obdname, rc);
                return rc;
@@ -196,12 +197,12 @@ int lustre_start_simple(char *obdname, char *type, char *uuid,
        rc = do_lcfg(obdname, 0, LCFG_SETUP, s1, s2, s3, s4);
        if (rc) {
                CERROR("%s setup error %d\n", obdname, rc);
-               do_lcfg(obdname, 0, LCFG_DETACH, 0, 0, 0, 0);
+               do_lcfg(obdname, 0, LCFG_DETACH, NULL, NULL, NULL, NULL);
        }
        return rc;
 }
 
-DEFINE_MUTEX(mgc_start_lock);
+static DEFINE_MUTEX(mgc_start_lock);
 
 /** Set up a mgc obd to process startup logs
  *
@@ -218,15 +219,16 @@ int lustre_start_mgc(struct super_block *sb)
         struct obd_uuid *uuid;
         class_uuid_t uuidc;
         lnet_nid_t nid;
+       char nidstr[LNET_NIDSTR_SIZE];
         char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
         char *ptr;
-        int recov_bk;
-        int rc = 0, i = 0, j, len;
-        ENTRY;
+       int rc = 0, i = 0, j;
+       size_t len;
+       ENTRY;
 
-        LASSERT(lsi->lsi_lmd);
+       LASSERT(lsi->lsi_lmd);
 
-        /* Find the first non-lo MGS nid for our MGC name */
+       /* Find the first non-lo MGS nid for our MGC name */
        if (IS_SERVER(lsi)) {
                /* mount -o mgsnode=nid */
                ptr = lsi->lsi_lmd->lmd_mgs;
@@ -256,12 +258,13 @@ int lustre_start_mgc(struct super_block *sb)
 
        mutex_lock(&mgc_start_lock);
 
-        len = strlen(LUSTRE_MGC_OBDNAME) + strlen(libcfs_nid2str(nid)) + 1;
-        OBD_ALLOC(mgcname, len);
-        OBD_ALLOC(niduuid, len + 2);
-        if (!mgcname || !niduuid)
-                GOTO(out_free, rc = -ENOMEM);
-        sprintf(mgcname, "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
+       libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
+       len = strlen(LUSTRE_MGC_OBDNAME) + strlen(nidstr) + 1;
+       OBD_ALLOC(mgcname, len);
+       OBD_ALLOC(niduuid, len + 2);
+       if (mgcname == NULL || niduuid == NULL)
+               GOTO(out_free, rc = -ENOMEM);
+       snprintf(mgcname, len, "%s%s", LUSTRE_MGC_OBDNAME, nidstr);
 
         mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";
 
@@ -271,6 +274,8 @@ int lustre_start_mgc(struct super_block *sb)
 
         obd = class_name2obd(mgcname);
         if (obd && !obd->obd_stopping) {
+               int recov_bk;
+
                 rc = obd_set_info_async(NULL, obd->obd_self_export,
                                         strlen(KEY_MGSSEC), KEY_MGSSEC,
                                         strlen(mgssec), mgssec, NULL);
@@ -286,9 +291,9 @@ int lustre_start_mgc(struct super_block *sb)
                         int vallen = sizeof(*data);
                         __u32 *flags = &lsi->lsi_lmd->lmd_flags;
 
-                        rc = obd_get_info(NULL, obd->obd_self_export,
-                                          strlen(KEY_CONN_DATA), KEY_CONN_DATA,
-                                          &vallen, data, NULL);
+                       rc = obd_get_info(NULL, obd->obd_self_export,
+                                         strlen(KEY_CONN_DATA), KEY_CONN_DATA,
+                                         &vallen, data);
                         LASSERT(rc == 0);
                         has_ir = OCD_HAS_FLAG(data, IMP_RECOV);
                         if (has_ir ^ !(*flags & LMD_FLG_NOIR)) {
@@ -331,7 +336,7 @@ int lustre_start_mgc(struct super_block *sb)
 
         /* Add the primary nids for the MGS */
         i = 0;
-        sprintf(niduuid, "%s_%x", mgcname, i);
+       snprintf(niduuid, len + 2, "%s_%x", mgcname, i);
        if (IS_SERVER(lsi)) {
                ptr = lsi->lsi_lmd->lmd_mgs;
                CDEBUG(D_MOUNT, "mgs nids %s.\n", ptr);
@@ -340,7 +345,7 @@ int lustre_start_mgc(struct super_block *sb)
                        lnet_process_id_t id;
                        while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
                                rc = do_lcfg(mgcname, id.nid, LCFG_ADD_UUID,
-                                            niduuid, 0, 0, 0);
+                                            niduuid, NULL, NULL, NULL);
                        }
                } else {
                        /* Use mgsnode= nids */
@@ -361,7 +366,7 @@ int lustre_start_mgc(struct super_block *sb)
                         */
                        while (class_parse_nid(ptr, &nid, &ptr) == 0) {
                                rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID,
-                                            niduuid, 0, 0, 0);
+                                            niduuid, NULL, NULL, NULL);
                                if (rc == 0) {
                                        i = 1;
                                        break;
@@ -373,7 +378,7 @@ int lustre_start_mgc(struct super_block *sb)
                 ptr = lsi->lsi_lmd->lmd_dev;
                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
                        rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID,
-                                    niduuid, 0, 0, 0);
+                                    niduuid, NULL, NULL, NULL);
                        if (rc == 0)
                                ++i;
                         /* Stop at the first failover nid */
@@ -389,13 +394,16 @@ 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);
 
         /* Start the MGC */
         rc = lustre_start_simple(mgcname, LUSTRE_MGC_NAME,
                                 (char *)uuid->uuid, LUSTRE_MGS_OBDNAME,
-                                niduuid, 0, 0);
+                                niduuid, NULL, NULL);
         OBD_FREE_PTR(uuid);
         if (rc)
                 GOTO(out_free, rc);
@@ -409,7 +417,7 @@ int lustre_start_mgc(struct super_block *sb)
                j = 0;
                while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) {
                        rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID,
-                                    niduuid, 0, 0, 0);
+                                    niduuid, NULL, NULL, NULL);
                        if (rc == 0)
                                ++j;
                        if (*ptr == ':')
@@ -417,7 +425,7 @@ int lustre_start_mgc(struct super_block *sb)
                }
                if (j > 0) {
                        rc = do_lcfg(mgcname, 0, LCFG_ADD_CONN,
-                                    niduuid, 0, 0, 0);
+                                    niduuid, NULL, NULL, NULL);
                        if (rc == 0)
                                ++i;
                 } else {
@@ -443,25 +451,13 @@ int lustre_start_mgc(struct super_block *sb)
            so we know when we can get rid of the mgc. */
        atomic_set(&obd->u.cli.cl_mgc_refcount, 1);
 
-        /* Try all connections, but only once. */
-        recov_bk = 1;
-        rc = obd_set_info_async(NULL, obd->obd_self_export,
-                                sizeof(KEY_INIT_RECOV_BACKUP),
-                                KEY_INIT_RECOV_BACKUP,
-                                sizeof(recov_bk), &recov_bk, NULL);
-        if (rc)
-                /* nonfatal */
-                CWARN("can't set %s %d\n", KEY_INIT_RECOV_BACKUP, rc);
-
        /* We connect to the MGS at setup, and don't disconnect until cleanup */
        data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT |
                                  OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV |
-                                 OBD_CONNECT_LVB_TYPE;
+                                 OBD_CONNECT_LVB_TYPE | OBD_CONNECT_BULK_MBITS;
 
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0)
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
        data->ocd_connect_flags |= OBD_CONNECT_MNE_SWAB;
-#else
-#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab"
 #endif
 
         if (lmd_is_client(lsi->lsi_lmd) &&
@@ -496,7 +492,7 @@ static int lustre_stop_mgc(struct super_block *sb)
 {
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct obd_device *obd;
-        char *niduuid = 0, *ptr = 0;
+       char *niduuid = NULL, *ptr = NULL;
         int i, rc = 0, len = 0;
         ENTRY;
 
@@ -549,7 +545,7 @@ static int lustre_stop_mgc(struct super_block *sb)
         for (i = 0; i < lsi->lsi_lmd->lmd_mgs_failnodes; i++) {
                 sprintf(ptr, "_%x", i);
                 rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_DEL_UUID,
-                             niduuid, 0, 0, 0);
+                            niduuid, NULL, NULL, NULL);
                 if (rc)
                         CERROR("del MDC UUID %s failed: rc = %d\n",
                                niduuid, rc);
@@ -565,7 +561,7 @@ out:
 
 /***************** lustre superblock **************/
 
-struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
+static struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
 {
         struct lustre_sb_info *lsi;
         ENTRY;
@@ -596,32 +592,35 @@ struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
 
 static int lustre_free_lsi(struct super_block *sb)
 {
-        struct lustre_sb_info *lsi = s2lsi(sb);
-        ENTRY;
+       struct lustre_sb_info *lsi = s2lsi(sb);
+       ENTRY;
 
-        LASSERT(lsi != NULL);
-        CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
+       LASSERT(lsi != NULL);
+       CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
 
-        /* someone didn't call server_put_mount. */
+       /* someone didn't call server_put_mount. */
        LASSERT(atomic_read(&lsi->lsi_mounts) == 0);
 
-        if (lsi->lsi_lmd != NULL) {
-                if (lsi->lsi_lmd->lmd_dev != NULL)
-                        OBD_FREE(lsi->lsi_lmd->lmd_dev,
-                                 strlen(lsi->lsi_lmd->lmd_dev) + 1);
-                if (lsi->lsi_lmd->lmd_profile != NULL)
-                        OBD_FREE(lsi->lsi_lmd->lmd_profile,
-                                 strlen(lsi->lsi_lmd->lmd_profile) + 1);
-                if (lsi->lsi_lmd->lmd_mgssec != NULL)
-                        OBD_FREE(lsi->lsi_lmd->lmd_mgssec,
-                                 strlen(lsi->lsi_lmd->lmd_mgssec) + 1);
-                if (lsi->lsi_lmd->lmd_opts != NULL)
-                        OBD_FREE(lsi->lsi_lmd->lmd_opts,
-                                 strlen(lsi->lsi_lmd->lmd_opts) + 1);
-                if (lsi->lsi_lmd->lmd_exclude_count)
-                        OBD_FREE(lsi->lsi_lmd->lmd_exclude,
-                                 sizeof(lsi->lsi_lmd->lmd_exclude[0]) *
-                                 lsi->lsi_lmd->lmd_exclude_count);
+       if (lsi->lsi_lmd != NULL) {
+               if (lsi->lsi_lmd->lmd_dev != NULL)
+                       OBD_FREE(lsi->lsi_lmd->lmd_dev,
+                               strlen(lsi->lsi_lmd->lmd_dev) + 1);
+               if (lsi->lsi_lmd->lmd_profile != NULL)
+                       OBD_FREE(lsi->lsi_lmd->lmd_profile,
+                               strlen(lsi->lsi_lmd->lmd_profile) + 1);
+               if (lsi->lsi_lmd->lmd_fileset != NULL)
+                       OBD_FREE(lsi->lsi_lmd->lmd_fileset,
+                               strlen(lsi->lsi_lmd->lmd_fileset) + 1);
+               if (lsi->lsi_lmd->lmd_mgssec != NULL)
+                       OBD_FREE(lsi->lsi_lmd->lmd_mgssec,
+                               strlen(lsi->lsi_lmd->lmd_mgssec) + 1);
+               if (lsi->lsi_lmd->lmd_opts != NULL)
+                       OBD_FREE(lsi->lsi_lmd->lmd_opts,
+                               strlen(lsi->lsi_lmd->lmd_opts) + 1);
+               if (lsi->lsi_lmd->lmd_exclude_count)
+                       OBD_FREE(lsi->lsi_lmd->lmd_exclude,
+                               sizeof(lsi->lsi_lmd->lmd_exclude[0]) *
+                               lsi->lsi_lmd->lmd_exclude_count);
                if (lsi->lsi_lmd->lmd_mgs != NULL)
                        OBD_FREE(lsi->lsi_lmd->lmd_mgs,
                                 strlen(lsi->lsi_lmd->lmd_mgs) + 1);
@@ -630,25 +629,28 @@ 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(lsi->lsi_lmd, sizeof(*lsi->lsi_lmd));
-        }
+               OBD_FREE_PTR(lsi->lsi_lmd);
+       }
 
-        LASSERT(lsi->lsi_llsbi == NULL);
-        OBD_FREE(lsi, sizeof(*lsi));
-        s2lsi_nocast(sb) = NULL;
+       LASSERT(lsi->lsi_llsbi == NULL);
+       OBD_FREE_PTR(lsi);
+       s2lsi_nocast(sb) = NULL;
 
-        RETURN(0);
+       RETURN(0);
 }
 
 /* The lsi has one reference for every server that is using the disk -
    e.g. MDT, MGS, and potentially MGC */
 int lustre_put_lsi(struct super_block *sb)
 {
-        struct lustre_sb_info *lsi = s2lsi(sb);
-        ENTRY;
+       struct lustre_sb_info *lsi = s2lsi(sb);
+       ENTRY;
 
-        LASSERT(lsi != NULL);
+       LASSERT(lsi != NULL);
 
        CDEBUG(D_MOUNT, "put %p %d\n", sb, atomic_read(&lsi->lsi_mounts));
        if (atomic_dec_and_test(&lsi->lsi_mounts)) {
@@ -660,17 +662,17 @@ int lustre_put_lsi(struct super_block *sb)
                        /* wait till OSD is gone */
                        obd_zombie_barrier();
                }
-                lustre_free_lsi(sb);
-                RETURN(1);
-        }
-        RETURN(0);
+               lustre_free_lsi(sb);
+               RETURN(1);
+       }
+       RETURN(0);
 }
 
 /*** SERVER NAME ***
- * <FSNAME><SEPERATOR><TYPE><INDEX>
+ * <FSNAME><SEPARATOR><TYPE><INDEX>
  * FSNAME is between 1 and 8 characters (inclusive).
  *     Excluded characters are '/' and ':'
- * SEPERATOR is either ':' or '-'
+ * SEPARATOR is either ':' or '-'
  * TYPE: "OST", "MDT", etc.
  * INDEX: Hex representation of the index
  */
@@ -834,8 +836,8 @@ int lustre_common_put_super(struct super_block *sb)
         }
         /* Drop a ref to the mounted disk */
         lustre_put_lsi(sb);
-        lu_types_stop();
-        RETURN(rc);
+
+       RETURN(rc);
 }
 EXPORT_SYMBOL(lustre_common_put_super);
 
@@ -896,7 +898,8 @@ int lustre_check_exclusion(struct super_block *sb, char *svname)
 static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr)
 {
        const char *s1 = ptr, *s2;
-       __u32 index, *exclude_list;
+       __u32 *exclude_list;
+       __u32 index = 0;
        int rc = 0, devmax;
        ENTRY;
 
@@ -974,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;
@@ -1041,77 +1069,167 @@ static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
        return 0;
 }
 
+/**
+ * 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;
+}
+
 /** 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
  */
 static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 {
-        char *s1, *s2, *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, 4096);
+       OBD_ALLOC(lmd->lmd_params, LMD_PARAMS_MAXLEN);
        if (lmd->lmd_params == NULL)
                RETURN(-ENOMEM);
        lmd->lmd_params[0] = '\0';
 
-        /* Set default flags here */
-
-        s1 = options;
-        while (*s1) {
-                int clear = 0;
-                int time_min = OBD_RECOVERY_TIME_MIN;
-
-                /* Skip whitespace and extra commas */
-                while (*s1 == ' ' || *s1 == ',')
-                        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++;
+       /* Set default flags here */
+
+       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++;
+               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++;
                } else if (strncmp(s1, "noscrub", 7) == 0) {
                        lmd->lmd_flags |= LMD_FLG_NOSCRUB;
                        clear++;
+               } else if (strncmp(s1, "skip_lfsck", 10) == 0) {
+                       lmd->lmd_flags |= LMD_FLG_SKIP_LFSCK;
+                       clear++;
                } else if (strncmp(s1, PARAM_MGSNODE,
                                   sizeof(PARAM_MGSNODE) - 1) == 0) {
                        s2 = s1 + sizeof(PARAM_MGSNODE) - 1;
@@ -1120,10 +1238,11 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                        rc = lmd_parse_mgs(lmd, &s2);
                        if (rc)
                                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++;
@@ -1133,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;
@@ -1154,91 +1273,140 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                                goto invalid;
                        clear++;
                } else if (strncmp(s1, "param=", 6) == 0) {
-                       int length;
-                       char *tail = strchr(s1 + 6, ',');
-                       if (tail == NULL)
+                       size_t length, params_length;
+                       char  *tail = s1;
+                       if (lmd_find_delimiter(s1 + 6, &tail) != 0)
                                length = strlen(s1);
-                       else
-                               length = tail - s1;
+                       else {
+                               char *param_str = tail + 1;
+                               int   supplementary = 1;
+                               while (lmd_parse_nidlist(param_str,
+                                                        &param_str) == 0) {
+                                       supplementary = 0;
+                               }
+                               length = param_str - s1 - supplementary;
+                       }
                        length -= 6;
+                       params_length = strlen(lmd->lmd_params);
+                       if (params_length + length + 1 >= LMD_PARAMS_MAXLEN)
+                               RETURN(-E2BIG);
                        strncat(lmd->lmd_params, s1 + 6, length);
-                       strcat(lmd->lmd_params, " ");
+                       lmd->lmd_params[params_length + length] = '\0';
+                       strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN);
+                       s3 = s1 + 6 + length;
                        clear++;
                } else if (strncmp(s1, "osd=", 4) == 0) {
                        rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4);
                        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(s1, ',');
-                if (s2 == NULL) {
-                        if (clear)
-                                *s1 = '\0';
-                        break;
-                }
-                s2++;
-                if (clear)
-                        memmove(s1, s2, strlen(s2) + 1);
-                else
-                        s1 = s2;
-        }
+               /* 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 (!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) {
-                ++s1;
-                lmd->lmd_flags |= LMD_FLG_CLIENT;
-                /* Remove leading /s from fsname */
-                while (*++s1 == '/') ;
-                /* Freed in lustre_free_lsi */
-                OBD_ALLOC(lmd->lmd_profile, strlen(s1) + 8);
-                if (!lmd->lmd_profile)
-                        RETURN(-ENOMEM);
-                sprintf(lmd->lmd_profile, "%s-client", s1);
-        }
+       s1 = strstr(devname, ":/");
+       if (s1) {
+               ++s1;
+               lmd->lmd_flags |= LMD_FLG_CLIENT;
+               /* Remove leading /s from fsname */
+               while (*++s1 == '/')
+                       ;
+               s2 = s1;
+               while (*s2 != '/' && *s2 != '\0')
+                       s2++;
+               /* Freed in lustre_free_lsi */
+               OBD_ALLOC(lmd->lmd_profile, s2 - s1 + 8);
+               if (!lmd->lmd_profile)
+                       RETURN(-ENOMEM);
+
+               strncat(lmd->lmd_profile, s1, s2 - s1);
+               strncat(lmd->lmd_profile, "-client", 7);
 
-        /* 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);
-        }
+               s1 = s2;
+               s2 = s1 + strlen(s1) - 1;
+               /* Remove padding /s from fileset */
+               while (*s2 == '/')
+                       s2--;
+               if (s2 > s1) {
+                       OBD_ALLOC(lmd->lmd_fileset, s2 - s1 + 2);
+                       if (lmd->lmd_fileset == NULL) {
+                               OBD_FREE(lmd->lmd_profile,
+                                        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);
+               }
+       }
 
-        lmd_print(lmd);
-        lmd->lmd_magic = LMD_MAGIC;
+       /* 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);
+       }
 
-        RETURN(rc);
+       lmd_print(lmd);
+       lmd->lmd_magic = LMD_MAGIC;
+
+       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 {
@@ -1251,7 +1419,7 @@ struct lustre_mount_data2 {
  * and this is where we start setting things up.
  * @param data Mount options (e.g. -o flock,abort_recov)
  */
-int lustre_fill_super(struct super_block *sb, void *data, int silent)
+static int lustre_fill_super(struct super_block *sb, void *data, int silent)
 {
         struct lustre_mount_data *lmd;
         struct lustre_mount_data2 *lmd2 = data;
@@ -1283,26 +1451,28 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent)
                 GOTO(out, rc = -EINVAL);
         }
 
-        if (lmd_is_client(lmd)) {
-                CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
-                if (!client_fill_super) {
-                        LCONSOLE_ERROR_MSG(0x165, "Nothing registered for "
-                                           "client mount! Is the 'lustre' "
-                                           "module loaded?\n");
-                        lustre_put_lsi(sb);
-                        rc = -ENODEV;
-                } else {
-                        rc = lustre_start_mgc(sb);
-                        if (rc) {
-                                lustre_put_lsi(sb);
-                                GOTO(out, rc);
-                        }
-                        /* Connect and start */
-                        /* (should always be ll_fill_super) */
-                        rc = (*client_fill_super)(sb, lmd2->lmd2_mnt);
-                        /* c_f_s will call lustre_common_put_super on failure */
-                }
-        } else {
+       if (lmd_is_client(lmd)) {
+               CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
+               if (client_fill_super == NULL)
+                       request_module("lustre");
+               if (client_fill_super == NULL) {
+                       LCONSOLE_ERROR_MSG(0x165, "Nothing registered for "
+                                          "client mount! Is the 'lustre' "
+                                          "module loaded?\n");
+                       lustre_put_lsi(sb);
+                       rc = -ENODEV;
+               } else {
+                       rc = lustre_start_mgc(sb);
+                       if (rc) {
+                               lustre_common_put_super(sb);
+                               GOTO(out, rc);
+                       }
+                       /* Connect and start */
+                       /* (should always be ll_fill_super) */
+                       rc = (*client_fill_super)(sb, lmd2->lmd2_mnt);
+                       /* c_f_s will call lustre_common_put_super on failure */
+               }
+       } else {
 #ifdef HAVE_SERVER_SUPPORT
                CDEBUG(D_MOUNT, "Mounting server from %s\n", lmd->lmd_dev);
                rc = server_fill_super(sb);
@@ -1315,7 +1485,7 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent)
                       "cannot handle server mount.\n");
                rc = -EINVAL;
 #endif
-        }
+       }
 
         /* If error happens in fill_super() call, @lsi will be killed there.
          * This is why we do not put it here. */
@@ -1350,24 +1520,29 @@ EXPORT_SYMBOL(lustre_register_kill_super_cb);
 
 /***************** FS registration ******************/
 #ifdef HAVE_FSTYPE_MOUNT
-struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
-                               const char *devname, void *data)
+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);
 }
 #else
-int lustre_get_sb(struct file_system_type *fs_type, int flags,
-                  const char *devname, void * data, struct vfsmount *mnt)
+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);
 }
 #endif
 
-void lustre_kill_super(struct super_block *sb)
+static void lustre_kill_super(struct super_block *sb)
 {
         struct lustre_sb_info *lsi = s2lsi(sb);
 
@@ -1379,7 +1554,7 @@ void lustre_kill_super(struct super_block *sb)
 
 /** Register the "lustre" fs type
  */
-struct file_system_type lustre_fs_type = {
+static struct file_system_type lustre_fs_type = {
         .owner        = THIS_MODULE,
         .name         = "lustre",
 #ifdef HAVE_FSTYPE_MOUNT
@@ -1388,9 +1563,9 @@ struct file_system_type lustre_fs_type = {
         .get_sb       = lustre_get_sb,
 #endif
         .kill_sb      = lustre_kill_super,
-       .fs_flags     = FS_BINARY_MOUNTDATA | FS_REQUIRES_DEV |
-                       FS_HAS_FIEMAP | FS_RENAME_DOES_D_MOVE,
+       .fs_flags     = FS_REQUIRES_DEV | FS_HAS_FIEMAP | FS_RENAME_DOES_D_MOVE,
 };
+MODULE_ALIAS_FS("lustre");
 
 int lustre_register_fs(void)
 {