Esempio n. 1
0
void print_ldd(char *str, struct lustre_disk_data *ldd)
{
        printf("\n   %s:\n", str);
        printf("Target:     %s\n", ldd->ldd_svname);
        if (ldd->ldd_svindex == INDEX_UNASSIGNED)
                printf("Index:      unassigned\n");
        else
                printf("Index:      %d\n", ldd->ldd_svindex);
        if (ldd->ldd_uuid[0])
                printf("UUID:       %s\n", (char *)ldd->ldd_uuid);
        printf("Lustre FS:  %s\n", ldd->ldd_fsname);
        printf("Mount type: %s\n", MT_STR(ldd));
        printf("Flags:      %#x\n", ldd->ldd_flags);
	printf("              (%s%s%s%s%s%s%s%s%s)\n",
               IS_MDT(ldd) ? "MDT ":"",
               IS_OST(ldd) ? "OST ":"",
               IS_MGS(ldd) ? "MGS ":"",
               ldd->ldd_flags & LDD_F_NEED_INDEX ? "needs_index ":"",
               ldd->ldd_flags & LDD_F_VIRGIN     ? "first_time ":"",
               ldd->ldd_flags & LDD_F_UPDATE     ? "update ":"",
               ldd->ldd_flags & LDD_F_WRITECONF  ? "writeconf ":"",
               ldd->ldd_flags & LDD_F_NO_PRIMNODE? "no_primnode ":"",
               ldd->ldd_flags & LDD_F_UPGRADE14  ? "upgrade1.4 ":"");
        printf("Persistent mount opts: %s\n", ldd->ldd_mount_opts);
        printf("Parameters:%s\n", ldd->ldd_params);
        if (ldd->ldd_userdata[0])
                printf("Comment: %s\n", ldd->ldd_userdata);
        printf("\n");
}
Esempio n. 2
0
void register_service_tags(char *usource, char *source, char *target)
{
        struct lustre_disk_data mo_ldd;
        struct utsname utsname_buf;
        struct stat stat_buf;
        char stclient_loc[] = "/opt/sun/servicetag/bin/stclient";
        int rc;

        rc = stat(stclient_loc, &stat_buf);

        if (rc) {
                if (errno != ENOENT && verbose) {
                        fprintf(stderr,
                                "%s: trying to stat stclient failed: %s\n",
                                progname, strerror(errno));
                }

                return;
        }

        /* call service tags stclient to show Lustre is in use on this system */
        rc = uname(&utsname_buf);
        if (rc) {
                if (verbose)
                        fprintf(stderr,
                                "%s: trying to get uname failed: %s, "
                                "inventory tags will not be created\n",
                                progname, strerror(errno));
                return;
        }

        /* client or server? */
        if (strchr(usource, ':')) {
                stclient("Client", utsname_buf.machine);
        } else {
                /* first figure what type of device it is */
                rc = get_mountdata(source, &mo_ldd);
                if (rc) {
                        if (verbose)
                                fprintf(stderr,
                                        "%s: trying to read mountdata from %s "
                                        "failed: %s, inventory tags will not "
                                        "be created\n",
                                        progname, target, strerror(errno));
                        return;
                }

                if (IS_MDT(&mo_ldd))
                        stclient("MDS", utsname_buf.machine);

                if (IS_MGS(&mo_ldd))
                        stclient("MGS", utsname_buf.machine);

                if (IS_OST(&mo_ldd))
                        stclient("OSS", utsname_buf.machine);
        }
}
int ldiskfs_prepare_lustre(struct mkfs_opts *mop,
			   char *wanted_mountopts, size_t len)
{
	struct lustre_disk_data *ldd = &mop->mo_ldd;
	int ret;

	/* Set MO_IS_LOOP to indicate a loopback device is needed */
	ret = is_block(mop->mo_device);
	if (ret < 0) {
		return errno;
	} else if (ret == 0) {
		mop->mo_flags |= MO_IS_LOOP;
	}

	if (IS_MDT(ldd) || IS_MGS(ldd))
		strscat(wanted_mountopts, ",user_xattr", len);

	return 0;
}
Esempio n. 4
0
/** Set up a mgc obd to process startup logs
 *
 * \param sb [in] super block of the mgc obd
 *
 * \retval 0 success, otherwise error code
 */
int lustre_start_mgc(struct super_block *sb)
{
	struct obd_connect_data *data = NULL;
	struct lustre_sb_info *lsi = s2lsi(sb);
	struct obd_device *obd;
	struct obd_export *exp;
	struct obd_uuid *uuid;
	class_uuid_t uuidc;
	lnet_nid_t nid;
	char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
	char *ptr;
	int recov_bk;
	int rc = 0, i = 0, j, len;

	LASSERT(lsi->lsi_lmd);

	/* 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;
		if (lsi->lsi_lmd->lmd_mgs &&
		    (class_parse_nid(lsi->lsi_lmd->lmd_mgs, &nid, &ptr) == 0)) {
			i++;
		} else if (IS_MGS(lsi)) {
			lnet_process_id_t id;
			while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
				if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND)
					continue;
				nid = id.nid;
				i++;
				break;
			}
		}
	} else { /* client */
		/* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
		ptr = lsi->lsi_lmd->lmd_dev;
		if (class_parse_nid(ptr, &nid, &ptr) == 0)
			i++;
	}
	if (i == 0) {
		CERROR("No valid MGS nids found.\n");
		return -EINVAL;
	}

	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));

	mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";

	OBD_ALLOC_PTR(data);
	if (data == NULL)
		GOTO(out_free, rc = -ENOMEM);

	obd = class_name2obd(mgcname);
	if (obd && !obd->obd_stopping) {
		rc = obd_set_info_async(NULL, obd->obd_self_export,
					strlen(KEY_MGSSEC), KEY_MGSSEC,
					strlen(mgssec), mgssec, NULL);
		if (rc)
			GOTO(out_free, rc);

		/* Re-using an existing MGC */
		atomic_inc(&obd->u.cli.cl_mgc_refcount);

		/* IR compatibility check, only for clients */
		if (lmd_is_client(lsi->lsi_lmd)) {
			int has_ir;
			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);
			LASSERT(rc == 0);
			has_ir = OCD_HAS_FLAG(data, IMP_RECOV);
			if (has_ir ^ !(*flags & LMD_FLG_NOIR)) {
				/* LMD_FLG_NOIR is for test purpose only */
				LCONSOLE_WARN(
				    "Trying to mount a client with IR setting "
				    "not compatible with current mgc. "
				    "Force to use current mgc setting that is "
				    "IR %s.\n",
				    has_ir ? "enabled" : "disabled");
				if (has_ir)
					*flags &= ~LMD_FLG_NOIR;
				else
					*flags |= LMD_FLG_NOIR;
			}
		}

		recov_bk = 0;
		/* If we are restarting the MGS, don't try to keep the MGC's
		   old connection, or registration will fail. */
		if (IS_MGS(lsi)) {
			CDEBUG(D_MOUNT, "New MGS with live MGC\n");
			recov_bk = 1;
		}

		/* Try all connections, but only once (again).
		   We don't want to block another target from starting
		   (using its local copy of the log), but we do want to connect
		   if at all possible. */
		recov_bk++;
		CDEBUG(D_MOUNT, "%s: Set MGC reconnect %d\n", mgcname,recov_bk);
		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);
		GOTO(out, rc = 0);
	}

	CDEBUG(D_MOUNT, "Start MGC '%s'\n", mgcname);

	/* Add the primary nids for the MGS */
	i = 0;
	sprintf(niduuid, "%s_%x", mgcname, i);
	if (IS_SERVER(lsi)) {
		ptr = lsi->lsi_lmd->lmd_mgs;
		if (IS_MGS(lsi)) {
			/* Use local nids (including LO) */
			lnet_process_id_t id;
			while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
				rc = do_lcfg(mgcname, id.nid,
					     LCFG_ADD_UUID, niduuid, 0,0,0);
			}
		} else {
			/* Use mgsnode= nids */
			/* mount -o mgsnode=nid */
			if (lsi->lsi_lmd->lmd_mgs) {
				ptr = lsi->lsi_lmd->lmd_mgs;
			} else if (class_find_param(ptr, PARAM_MGSNODE,
						    &ptr) != 0) {
				CERROR("No MGS nids given.\n");
				GOTO(out_free, rc = -EINVAL);
			}
			while (class_parse_nid(ptr, &nid, &ptr) == 0) {
				rc = do_lcfg(mgcname, nid,
					     LCFG_ADD_UUID, niduuid, 0,0,0);
				i++;
			}
		}
	} else { /* client */
		/* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
		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);
			i++;
			/* Stop at the first failover nid */
			if (*ptr == ':')
				break;
		}
	}
	if (i == 0) {
		CERROR("No valid MGS nids found.\n");
		GOTO(out_free, rc = -EINVAL);
	}
	lsi->lsi_lmd->lmd_mgs_failnodes = 1;

	/* Random uuid for MGC allows easier reconnects */
	OBD_ALLOC_PTR(uuid);
	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);
	OBD_FREE_PTR(uuid);
	if (rc)
		GOTO(out_free, rc);

	/* Add any failover MGS nids */
	i = 1;
	while (ptr && ((*ptr == ':' ||
	       class_find_param(ptr, PARAM_MGSNODE, &ptr) == 0))) {
		/* New failover node */
		sprintf(niduuid, "%s_%x", mgcname, i);
		j = 0;
		while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) {
			j++;
			rc = do_lcfg(mgcname, nid,
				     LCFG_ADD_UUID, niduuid, 0,0,0);
			if (*ptr == ':')
				break;
		}
		if (j > 0) {
			rc = do_lcfg(mgcname, 0, LCFG_ADD_CONN,
				     niduuid, 0, 0, 0);
			i++;
		} else {
			/* at ":/fsname" */
			break;
		}
	}
	lsi->lsi_lmd->lmd_mgs_failnodes = i;

	obd = class_name2obd(mgcname);
	if (!obd) {
		CERROR("Can't find mgcobd %s\n", mgcname);
		GOTO(out_free, rc = -ENOTCONN);
	}

	rc = obd_set_info_async(NULL, obd->obd_self_export,
				strlen(KEY_MGSSEC), KEY_MGSSEC,
				strlen(mgssec), mgssec, NULL);
	if (rc)
		GOTO(out_free, rc);

	/* Keep a refcount of servers/clients who started with "mount",
	   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;

#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 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) &&
	    lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR)
		data->ocd_connect_flags &= ~OBD_CONNECT_IMP_RECOV;
	data->ocd_version = LUSTRE_VERSION_CODE;
	rc = obd_connect(NULL, &exp, obd, &(obd->obd_uuid), data, NULL);
	if (rc) {
		CERROR("connect failed %d\n", rc);
		GOTO(out, rc);
	}

	obd->u.cli.cl_mgc_mgsexp = exp;

out:
	/* Keep the mgc info in the sb. Note that many lsi's can point
	   to the same mgc.*/
	lsi->lsi_mgc = obd;
out_free:
	mutex_unlock(&mgc_start_lock);

	if (data)
		OBD_FREE_PTR(data);
	if (mgcname)
		OBD_FREE(mgcname, len);
	if (niduuid)
		OBD_FREE(niduuid, len + 2);
	return rc;
}
Esempio n. 5
0
int main(int argc, char *const argv[])
{
	struct mkfs_opts mop;
	struct lustre_disk_data *ldd = &mop.mo_ldd;
	char *mountopts = NULL;
	char wanted_mountopts[512] = "";
	unsigned mount_type;
	int ret = 0;
	int ret2 = 0;

	progname = strrchr(argv[0], '/');
	if (progname != NULL)
		progname++;
	else
		progname = argv[0];

	if ((argc < 2) || (argv[argc - 1][0] == '-')) {
		usage(stderr);
		return EINVAL;
	}

	memset(&mop, 0, sizeof(mop));
	set_defaults(&mop);

	/* device is last arg */
	strscpy(mop.mo_device, argv[argc - 1], sizeof(mop.mo_device));

	ret = osd_init();
	if (ret != 0)
		return ret;

#ifdef TUNEFS
	/* For tunefs, we must read in the old values before parsing any
	   new ones. */

	/* Check whether the disk has already been formatted by mkfs.lustre */
	ret = osd_is_lustre(mop.mo_device, &mount_type);
	if (ret == 0) {
		fatal();
		fprintf(stderr, "Device %s has not been formatted with "
			"mkfs.lustre\n", mop.mo_device);
		ret = ENODEV;
		goto out;
	}
	ldd->ldd_mount_type = mount_type;

	ret = osd_read_ldd(mop.mo_device, ldd);
	if (ret != 0) {
		fatal();
		fprintf(stderr, "Failed to read previous Lustre data from %s "
			"(%d)\n", mop.mo_device, ret);
		goto out;
	}

	ldd->ldd_flags &= ~(LDD_F_WRITECONF | LDD_F_VIRGIN);

	/* svname of the form lustre:OST1234 means never registered */
	ret = strlen(ldd->ldd_svname);
	if (ldd->ldd_svname[ret - 8] == ':') {
		ldd->ldd_svname[ret - 8] = '-';
		ldd->ldd_flags |= LDD_F_VIRGIN;
	} else if (ldd->ldd_svname[ret - 8] == '=') {
		ldd->ldd_svname[ret - 8] = '-';
		ldd->ldd_flags |= LDD_F_WRITECONF;
	}

	if (strstr(ldd->ldd_params, PARAM_MGSNODE))
		mop.mo_mgs_failnodes++;

	if (verbose > 0)
		print_ldd("Read previous values", ldd);
#endif /* TUNEFS */

	ret = parse_opts(argc, argv, &mop, &mountopts);
	if (ret != 0 || version)
		goto out;

	if (!IS_MDT(ldd) && !IS_OST(ldd) && !IS_MGS(ldd)) {
		fatal();
		fprintf(stderr, "must set target type: MDT,OST,MGS\n");
		ret = EINVAL;
		goto out;
	}

	if (((IS_MDT(ldd) || IS_MGS(ldd))) && IS_OST(ldd)) {
		fatal();
		fprintf(stderr, "OST type is exclusive with MDT,MGS\n");
		ret = EINVAL;
		goto out;
	}

	/* Stand alone MGS doesn't need an index */
	if (!IS_MDT(ldd) && IS_MGS(ldd)) {
#ifndef TUNEFS
		/* But if --index was specified flag an error */
		if (!(ldd->ldd_flags & LDD_F_NEED_INDEX)) {
			badopt("index", "MDT,OST");
			goto out;
		}
#endif
		ldd->ldd_flags &= ~LDD_F_NEED_INDEX;
	}

	if ((ldd->ldd_flags & (LDD_F_NEED_INDEX | LDD_F_UPGRADE14)) ==
	    (LDD_F_NEED_INDEX | LDD_F_UPGRADE14)) {
		fatal();
		fprintf(stderr, "Can't find the target index, "
		"specify with --index\n");
		ret = EINVAL;
		goto out;
	}

	if (ldd->ldd_flags & LDD_F_NEED_INDEX)
		fprintf(stderr, "warning: %s: for Lustre 2.4 and later, the "
			"target index must be specified with --index\n",
			mop.mo_device);

	/* If no index is supplied for MDT by default set index to zero */
	if (IS_MDT(ldd) && (ldd->ldd_svindex == INDEX_UNASSIGNED)) {
		ldd->ldd_flags &= ~LDD_F_NEED_INDEX;
		ldd->ldd_svindex = 0;
	}
	if (!IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) {
		fatal();
		if (IS_MDT(ldd))
			fprintf(stderr, "Must specify --mgs or --mgsnode\n");
		else
			fprintf(stderr, "Must specify --mgsnode\n");
		ret = EINVAL;
		goto out;
	}
	if ((IS_MDT(ldd) || IS_OST(ldd)) && ldd->ldd_fsname[0] == '\0') {
		fatal();
		fprintf(stderr, "Must specify --fsname for MDT/OST device\n");
		ret = EINVAL;
		goto out;
	}

	/* These are the permanent mount options (always included) */
	ret = osd_prepare_lustre(&mop,
				 wanted_mountopts, sizeof(wanted_mountopts));
	if (ret != 0) {
		fatal();
		fprintf(stderr, "unable to prepare backend (%d)\n", ret);
		goto out;
	}

	if (mountopts) {
		trim_mountfsoptions(mountopts);
		if (check_mountfsoptions(mountopts, wanted_mountopts)) {
			ret = EINVAL;
			goto out;
		}
		snprintf(ldd->ldd_mount_opts, sizeof(ldd->ldd_mount_opts),
			 "%s", mountopts);
	} else {
#ifdef TUNEFS
		if (ldd->ldd_mount_opts[0] == 0)
		/* use the defaults unless old opts exist */
#endif
		{
			snprintf(ldd->ldd_mount_opts,
				 sizeof(ldd->ldd_mount_opts),
				 "%s", wanted_mountopts);
			trim_mountfsoptions(ldd->ldd_mount_opts);
		}
	}

	ret = osd_fix_mountopts(&mop, ldd->ldd_mount_opts,
				sizeof(ldd->ldd_mount_opts));
	if (ret != 0) {
		fatal();
		fprintf(stderr, "unable to fix mountfsoptions (%d)\n", ret);
		goto out;
	}

	server_make_name(ldd->ldd_flags, ldd->ldd_svindex,
			 ldd->ldd_fsname, ldd->ldd_svname);

	if (verbose >= 0)
		print_ldd("Permanent disk data", ldd);

	if (print_only) {
		printf("exiting before disk write.\n");
		goto out;
	}

	if (check_mtab_entry(mop.mo_device, mop.mo_device, NULL, NULL))
		return(EEXIST);

	/* Create the loopback file */
	if (mop.mo_flags & MO_IS_LOOP) {
		ret = access(mop.mo_device, F_OK);
		if (ret != 0)
			ret = errno;

#ifndef TUNEFS
		/* Reformat the loopback file */
		if (ret != 0 || (mop.mo_flags & MO_FORCEFORMAT)) {
			ret = loop_format(&mop);
			if (ret != 0)
				goto out;
		}
#endif
		if (ret == 0)
			ret = loop_setup(&mop);
		if (ret != 0) {
			fatal();
			fprintf(stderr, "Loop device setup for %s failed: %s\n",
					mop.mo_device, strerror(ret));
			goto out;
		}
	}

#ifndef TUNEFS
	/* Check whether the disk has already been formatted by mkfs.lustre */
	if (!(mop.mo_flags & MO_FORCEFORMAT)) {
		ret = osd_is_lustre(mop.mo_device, &mount_type);
		if (ret != 0) {
			fatal();
			fprintf(stderr, "Device %s was previously formatted "
				"for lustre. Use --reformat to reformat it, "
				"or tunefs.lustre to modify.\n",
				mop.mo_device);
			goto out;
		}
	}

	/* Format the backing filesystem */
	ret = osd_make_lustre(&mop);
	if (ret != 0) {
		fatal();
		fprintf(stderr, "mkfs failed %d\n", ret);
		goto out;
	}
#else /* !TUNEFS */
	/* update svname with '=' to refresh config */
	if (ldd->ldd_flags & LDD_F_WRITECONF) {
		struct mount_opts opts;
		opts.mo_ldd = *ldd;
		opts.mo_source = mop.mo_device;
		(void) osd_label_lustre(&opts);
	}

	/* Enable quota accounting */
	if (mop.mo_flags & MO_QUOTA) {
		ret = osd_enable_quota(&mop);
		goto out;
	}
#endif /* !TUNEFS */

	/* Write our config files */
	ret = osd_write_ldd(&mop);
	if (ret != 0) {
		fatal();
		fprintf(stderr, "failed to write local files\n");
		goto out;
	}

out:
	osd_fini();
	ret2 = loop_cleanup(&mop);
	if (ret == 0)
		ret = ret2;

	/* Fix any crazy return values from system() */
	if (ret != 0 && ((ret & 255) == 0))
		return 1;

	if (ret != 0)
		verrprint("%s: exiting with %d (%s)\n",
			  progname, ret, strerror(ret));
	return ret;
}
Esempio n. 6
0
/** Set up a mgc obd to process startup logs
 *
 * \param sb [in] super block of the mgc obd
 *
 * \retval 0 success, otherwise error code
 */
int lustre_start_mgc(struct super_block *sb)
{
	struct obd_connect_data *data = NULL;
	struct lustre_sb_info *lsi = s2lsi(sb);
	struct obd_device *obd;
	struct obd_export *exp;
	struct obd_uuid *uuid;
	class_uuid_t uuidc;
	lnet_nid_t nid;
	char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
	char *ptr;
	int rc = 0, i = 0, j, len;

	LASSERT(lsi->lsi_lmd);

	/* 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;
		if (lsi->lsi_lmd->lmd_mgs &&
		    (class_parse_nid(lsi->lsi_lmd->lmd_mgs, &nid, &ptr) == 0)) {
			i++;
		} else if (IS_MGS(lsi)) {
			lnet_process_id_t id;
			while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
				if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND)
					continue;
				nid = id.nid;
				i++;
				break;
			}
		}
	} else { /* client */
		/* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
		ptr = lsi->lsi_lmd->lmd_dev;
		if (class_parse_nid(ptr, &nid, &ptr) == 0)
			i++;
	}
	if (i == 0) {
		CERROR("No valid MGS nids found.\n");
		return -EINVAL;
	}

	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));

	mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";

	OBD_ALLOC_PTR(data);
	if (data == NULL)
		GOTO(out_free, rc = -ENOMEM);

	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);
		if (rc)
			GOTO(out_free, rc);

		/* Re-using an existing MGC */
		atomic_inc(&obd->u.cli.cl_mgc_refcount);

		/* IR compatibility check, only for clients */
		if (lmd_is_client(lsi->lsi_lmd)) {
			int has_ir;
			int vallen = sizeof(*data);