Exemple #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");
}
Exemple #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;
}
Exemple #4
0
static int parse_ldd(char *source, struct mount_opts *mop, char *options)
{
	struct lustre_disk_data *ldd = &mop->mo_ldd;
	char *cur, *start;
	int rc;

	rc = osd_is_lustre(source, &ldd->ldd_mount_type);
	if (rc == 0) {
		fprintf(stderr, "%s: %s has not been formatted with mkfs.lustre"
			" or the backend filesystem type is not supported by "
			"this tool\n", progname, source);
		return ENODEV;
	}

	rc = osd_read_ldd(source, ldd);
	if (rc) {
		fprintf(stderr, "%s: %s failed to read permanent mount"
			" data: %s\n", progname, source,
			rc >= 0 ? strerror(rc) : "");
		return rc;
	}

	if ((IS_MDT(ldd) || IS_OST(ldd)) &&
	    (ldd->ldd_flags & LDD_F_NEED_INDEX)) {
		fprintf(stderr, "%s: %s has no index assigned "
			"(probably formatted with old mkfs)\n",
			progname, source);
		return EINVAL;
	}

	if (ldd->ldd_flags & LDD_F_UPGRADE14) {
		fprintf(stderr, "%s: we cannot upgrade %s from this (very old) "
			"Lustre version\n", progname, source);
		return EINVAL;
	}

	if (ldd->ldd_flags & LDD_F_UPDATE)
		clear_update_ondisk(source, ldd);

	/* Since we never rewrite ldd, ignore temp flags */
	ldd->ldd_flags &= ~(LDD_F_VIRGIN | LDD_F_WRITECONF);

	/* svname of the form lustre:OST1234 means never registered */
	rc = strlen(ldd->ldd_svname);
	if (strcmp(ldd->ldd_svname, "MGS") != 0) {
		if (rc < 8) {
			fprintf(stderr, "%s: invalid name '%s'\n",
				progname, ldd->ldd_svname);
			return EINVAL;
		} else if (ldd->ldd_svname[rc - 8] == ':') {
			ldd->ldd_svname[rc - 8] = '-';
			ldd->ldd_flags |= LDD_F_VIRGIN;
		} else if (ldd->ldd_svname[rc - 8] == '=') {
			ldd->ldd_svname[rc - 8] = '-';
			ldd->ldd_flags |= LDD_F_WRITECONF;
		}
	}
	/* backend osd type */
	append_option(options, "osd=");
	strcat(options, mt_type(ldd->ldd_mount_type));

	append_option(options, ldd->ldd_mount_opts);

	if (!mop->mo_have_mgsnid) {
		/* Only use disk data if mount -o mgsnode=nid wasn't
		 * specified */
		if (ldd->ldd_flags & LDD_F_SV_TYPE_MGS) {
			append_option(options, "mgs");
			mop->mo_have_mgsnid++;
		} else {
			add_mgsnids(mop, options, ldd->ldd_params);
		}
	}
	/* Better have an mgsnid by now */
	if (!mop->mo_have_mgsnid) {
		fprintf(stderr, "%s: missing option mgsnode=<nid>\n",
			progname);
		return EINVAL;
	}

	if (ldd->ldd_flags & LDD_F_VIRGIN)
		append_option(options, "virgin");
	if (ldd->ldd_flags & LDD_F_UPDATE)
		append_option(options, "update");
	if (ldd->ldd_flags & LDD_F_WRITECONF)
		append_option(options, "writeconf");
	if (ldd->ldd_flags & LDD_F_NO_PRIMNODE)
		append_option(options, "noprimnode");

	/* prefix every lustre parameter with param= so that in-kernel
	 * mount can recognize them properly and send to MGS at registration */
	start = ldd->ldd_params;
	while (start && *start != '\0') {
		while (*start == ' ') start++;
		if (*start == '\0')
			break;
		cur = start;
		start = strchr(cur, ' ');
		if (start) {
			*start = '\0';
			start++;
		}
		append_option(options, "param=");
		strcat(options, cur);
	}

	/* svname must be last option */
	append_option(options, "svname=");
	strcat(options, ldd->ldd_svname);

	return 0;
}
/* Build fs according to type */
int ldiskfs_make_lustre(struct mkfs_opts *mop)
{
	char mkfs_cmd[PATH_MAX];
	char buf[64];
	char *start;
	char *dev;
	int ret = 0, ext_opts = 0;
	bool enable_64bit = false;
	long inode_size = 0;
	size_t maxbuflen;

	mop->mo_blocksize_kb = 4;

	start = strstr(mop->mo_mkfsopts, "-b");
	if (start) {
		char *end = NULL;
		long blocksize;

		blocksize = strtol(start + 2, &end, 0);
		if (end && (*end == 'k' || *end == 'K'))
			blocksize *= 1024;
		/* EXT4_MIN_BLOCK_SIZE || EXT4_MAX_BLOCK_SIZE */
		if (blocksize < 1024 || blocksize > 65536) {
			fprintf(stderr,
				"%s: blocksize %lu not in 1024-65536 bytes, normally 4096 bytes\n",
				progname, blocksize);
			return EINVAL;
		}

		if ((blocksize & (blocksize - 1)) != 0) {
			fprintf(stderr,
				"%s: blocksize %lu not a power-of-two value\n",
				progname, blocksize);
			return EINVAL;
		}
		mop->mo_blocksize_kb = blocksize >> 10;
	}

	if (!(mop->mo_flags & MO_IS_LOOP)) {
		__u64 device_kb = get_device_size(mop->mo_device);

		if (device_kb == 0)
			return ENODEV;

		/* Compare to real size */
		if (mop->mo_device_kb == 0 || device_kb < mop->mo_device_kb)
			mop->mo_device_kb = device_kb;
	}

	if (mop->mo_device_kb != 0) {
		__u64 block_count;

		if (mop->mo_device_kb < 32384) {
			fprintf(stderr, "%s: size of filesystem must be larger "
				"than 32MB, but is set to %lldKB\n",
				progname, (long long)mop->mo_device_kb);
			return EINVAL;
		}
		block_count = mop->mo_device_kb / mop->mo_blocksize_kb;
		if (block_count > 0xffffffffULL) {
			/* If the LUN size is just over 2^32 blocks, limit the
			 * filesystem size to 2^32-1 blocks to avoid problems
			 * with ldiskfs/mkfs not handling this well. b=22906
			 */
			if (block_count < 0x100002000ULL)
				mop->mo_device_kb =
					0xffffffffULL * mop->mo_blocksize_kb;
			else
				enable_64bit = true;
		}
	}

	if ((mop->mo_ldd.ldd_mount_type != LDD_MT_EXT3) &&
	    (mop->mo_ldd.ldd_mount_type != LDD_MT_LDISKFS) &&
	    (mop->mo_ldd.ldd_mount_type != LDD_MT_LDISKFS2)) {
		fprintf(stderr, "%s: unsupported fs type: %d (%s)\n",
			progname, mop->mo_ldd.ldd_mount_type,
			MT_STR(&mop->mo_ldd));

		return EINVAL;
	}

	/* Journal size in MB */
	if (strstr(mop->mo_mkfsopts, "-J") == NULL &&
	    mop->mo_device_kb > 1024 * 1024) {
		/* Choose our own default journal size */
		long journal_mb = 0, max_mb;

		/* cap journal size at 4GB for MDT, leave at 1GB for OSTs */
		if (IS_MDT(&mop->mo_ldd))
			max_mb = 4096;
		else if (IS_OST(&mop->mo_ldd))
			max_mb = 1024;
		else /* Use mke2fs default size for MGS */
			max_mb = 0;

		/* Use at most 4% of device for journal */
		journal_mb = mop->mo_device_kb * 4 / (1024 * 100);
		if (journal_mb > max_mb)
			journal_mb = max_mb;

		if (journal_mb) {
			snprintf(buf, sizeof(buf), " -J size=%ld", journal_mb);
			strscat(mop->mo_mkfsopts, buf,
				sizeof(mop->mo_mkfsopts));
		}
	}

	/*
	 * The inode size is constituted by following elements
	 * (assuming all files are in composite layout and has
	 * 3 components):
	 *
	 *   ldiskfs inode size: 160
	 *   MDT extended attributes size, including:
	 *	ext4_xattr_header: 32
	 *	LOV EA size: 32(lov_comp_md_v1) +
	 *		     3 * 40(lov_comp_md_entry_v1) +
	 *		     3 * 32(lov_mds_md) +
	 *		     stripes * 24(lov_ost_data) +
	 *		     16(xattr_entry) + 4("lov")
	 *	LMA EA size: 24(lustre_mdt_attrs) +
	 *		     16(xattr_entry) + 4("lma")
	 *	SOM EA size: 24(lustre_som_attrs) +
	 *		     16(xattr_entry) + 4("som")
	 *	link EA size: 24(link_ea_header) + 18(link_ea_entry) +
	 *		      16(filename) + 16(xattr_entry) + 4("link")
	 *   and some margin for 4-byte alignment, ACLs and other EAs.
	 *
	 * If we say the average filename length is about 32 bytes,
	 * the calculation looks like:
	 * 160 + 32 + (32+3*(40+32)+24*stripes+20) + (24+20) + (24+20) +
	 *  (24+20) + (~42+16+20) + other <= 512*2^m, {m=0,1,2,3}
	 */
	if (strstr(mop->mo_mkfsopts, "-I") == NULL) {
		if (IS_MDT(&mop->mo_ldd)) {
			if (mop->mo_stripe_count > 59)
				inode_size = 512; /* bz 7241 */
			/* see also "-i" below for EA blocks */
			else if (mop->mo_stripe_count > 16)
				inode_size = 2048;
			else
				inode_size = 1024;
		} else if (IS_OST(&mop->mo_ldd)) {
			/* We store MDS FID and necessary composite
			 * layout information in the OST object EA:
			 *   ldiskfs inode size: 160
			 *   OST extended attributes size, including:
			 *	ext4_xattr_header: 32
			 *	LMA EA size: 24(lustre_mdt_attrs) +
			 *		     16(xattr_entry) + 4("lma")
			 *	FID EA size: 52(filter_fid) +
			 *		     16(xattr_entry) + 4("fid")
			 * 160 + 32 + (24+20) + (52+20) = 308
			 */
			inode_size = 512;
		}

		if (inode_size > 0) {
			snprintf(buf, sizeof(buf), " -I %ld", inode_size);
			strscat(mop->mo_mkfsopts, buf,
				sizeof(mop->mo_mkfsopts));
		}
	}

	/* Bytes_per_inode: disk size / num inodes */
	if (strstr(mop->mo_mkfsopts, "-i") == NULL &&
	    strstr(mop->mo_mkfsopts, "-N") == NULL) {
		long bytes_per_inode = 0;

		/* Allocate more inodes on MDT devices.  There is
		 * no data stored on the MDT, and very little extra
		 * metadata beyond the inode.  It could go down as
		 * low as 1024 bytes, but this is conservative.
		 * Account for external EA blocks for wide striping.
		 */
		if (IS_MDT(&mop->mo_ldd)) {
			bytes_per_inode = inode_size + 1536;

			if (mop->mo_stripe_count > 59) {
				int extra = mop->mo_stripe_count * 24;

				extra = ((extra - 1) | 4095) + 1;
				bytes_per_inode += extra;
			}
		}

		/* Allocate fewer inodes on large OST devices.  Most
		 * filesystems can be much more aggressive than even
		 * this, but it is impossible to know in advance.
		 */
		if (IS_OST(&mop->mo_ldd)) {
			/* OST > 16TB assume average file size 1MB */
			if (mop->mo_device_kb > (16ULL << 30))
				bytes_per_inode = 1024 * 1024;
			/* OST > 4TB assume average file size 512kB */
			else if (mop->mo_device_kb > (4ULL << 30))
				bytes_per_inode = 512 * 1024;
			/* OST > 1TB assume average file size 256kB */
			else if (mop->mo_device_kb > (1ULL << 30))
				bytes_per_inode = 256 * 1024;
			/* OST > 10GB assume average file size 64kB,
			 * plus a bit so that inodes will fit into a
			 * 256x flex_bg without overflowing.
			 */
			else if (mop->mo_device_kb > (10ULL << 20))
				bytes_per_inode = 69905;
		}

		if (bytes_per_inode > 0) {
			snprintf(buf, sizeof(buf), " -i %ld", bytes_per_inode);
			strscat(mop->mo_mkfsopts, buf,
				sizeof(mop->mo_mkfsopts));
			mop->mo_inode_size = bytes_per_inode;
		}
	}

	if (verbose < 2)
		strscat(mop->mo_mkfsopts, " -q", sizeof(mop->mo_mkfsopts));

	/* start handle -O mkfs options */
	start = strstr(mop->mo_mkfsopts, "-O");
	if (start) {
		if (strstr(start + 2, "-O") != NULL) {
			fprintf(stderr,
				"%s: don't specify multiple -O options\n",
				progname);
			return EINVAL;
		}
		start = moveopts_to_end(start);
		maxbuflen = sizeof(mop->mo_mkfsopts) -
			(start - mop->mo_mkfsopts) - strlen(start);
		ret = enable_default_ext4_features(mop, start, maxbuflen, 1);
	} else {
		start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts);
		maxbuflen = sizeof(mop->mo_mkfsopts) - strlen(mop->mo_mkfsopts);
		ret = enable_default_ext4_features(mop, start, maxbuflen, 0);
	}
	if (ret)
		return ret;
	/* end handle -O mkfs options */

	/* start handle -E mkfs options */
	start = strstr(mop->mo_mkfsopts, "-E");
	if (start) {
		if (strstr(start + 2, "-E") != NULL) {
			fprintf(stderr,
				"%s: don't specify multiple -E options\n",
				progname);
			return EINVAL;
		}
		start = moveopts_to_end(start);
		maxbuflen = sizeof(mop->mo_mkfsopts) -
			(start - mop->mo_mkfsopts) - strlen(start);
		ext_opts = 1;
	} else {
		start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts);
		maxbuflen = sizeof(mop->mo_mkfsopts) - strlen(mop->mo_mkfsopts);
	}

	/* In order to align the filesystem metadata on 1MB boundaries,
	 * give a resize value that will reserve a power-of-two group
	 * descriptor blocks, but leave one block for the superblock.
	 * Only useful for filesystems with < 2^32 blocks due to resize
	 * limitations.
	 */
	if (!enable_64bit && strstr(mop->mo_mkfsopts, "meta_bg") == NULL &&
	    IS_OST(&mop->mo_ldd) && mop->mo_device_kb > 100 * 1024) {
		unsigned int group_blocks = mop->mo_blocksize_kb * 8192;
		unsigned int desc_per_block = mop->mo_blocksize_kb * 1024 / 32;
		unsigned int resize_blks;

		resize_blks = (1ULL<<32) - desc_per_block*group_blocks;
		snprintf(buf, sizeof(buf), "%u", resize_blks);
		append_unique(start, ext_opts ? "," : " -E ",
			      "resize", buf, maxbuflen);
		ext_opts = 1;
	}

	/* Avoid zeroing out the full journal - speeds up mkfs */
	if (is_e2fsprogs_feature_supp("-E lazy_journal_init"))
		append_unique(start, ext_opts ? "," : " -E ",
			      "lazy_journal_init", NULL, maxbuflen);
	/* end handle -E mkfs options */

	/* Allow reformat of full devices (as opposed to partitions).
	 * We already checked for mounted dev.
	 */
	strscat(mop->mo_mkfsopts, " -F", sizeof(mop->mo_mkfsopts));

	snprintf(mkfs_cmd, sizeof(mkfs_cmd), "%s -j -b %d -L %s ", MKE2FS,
		 mop->mo_blocksize_kb * 1024, mop->mo_ldd.ldd_svname);

	/* For loop device format the dev, not the filename */
	dev = mop->mo_device;
	if (mop->mo_flags & MO_IS_LOOP)
		dev = mop->mo_loopdev;

	vprint("formatting backing filesystem %s on %s\n",
	       MT_STR(&mop->mo_ldd), dev);
	vprint("\ttarget name   %s\n", mop->mo_ldd.ldd_svname);
	vprint("\tkilobytes     %llu\n", mop->mo_device_kb);
	vprint("\toptions       %s\n", mop->mo_mkfsopts);

	/* mkfs_cmd's trailing space is important! */
	strscat(mkfs_cmd, mop->mo_mkfsopts, sizeof(mkfs_cmd));
	strscat(mkfs_cmd, " ", sizeof(mkfs_cmd));
	strscat(mkfs_cmd, dev, sizeof(mkfs_cmd));
	if (mop->mo_device_kb != 0) {
		snprintf(buf, sizeof(buf), " %lluk",
			 (unsigned long long)mop->mo_device_kb);
		strscat(mkfs_cmd, buf, sizeof(mkfs_cmd));
	}

	vprint("mkfs_cmd = %s\n", mkfs_cmd);
	ret = run_command(mkfs_cmd, sizeof(mkfs_cmd));
	if (ret) {
		fatal();
		fprintf(stderr, "Unable to build fs %s (%d)\n", dev, ret);
	}
	return ret;
}
static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
					size_t maxbuflen, bool user_spec)
{
	unsigned long long blocks = mop->mo_device_kb / mop->mo_blocksize_kb;
	bool enable_64bit = false;

	/* Enable large block addresses if the LUN is over 2^32 blocks. */
	if (blocks > 0xffffffffULL && is_e2fsprogs_feature_supp("-O 64bit"))
		enable_64bit = true;

	if (IS_OST(&mop->mo_ldd)) {
		append_unique(anchor, user_spec ? "," : " -O ",
			      "extents", NULL, maxbuflen);
		append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen);
	} else if (IS_MDT(&mop->mo_ldd)) {
		append_unique(anchor, user_spec ? "," : " -O ",
			      "dirdata", NULL, maxbuflen);
		append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen);
		if (enable_64bit)
			append_unique(anchor, ",", "extents", NULL, maxbuflen);
		else
			append_unique(anchor, ",", "^extents", NULL, maxbuflen);
	} else {
		append_unique(anchor, user_spec ? "," : " -O ",
			      "uninit_bg", NULL, maxbuflen);
	}

	/* Multiple mount protection enabled only if failover node specified */
	if (mop->mo_flags & MO_FAILOVER) {
		if (is_e2fsprogs_feature_supp("-O mmp"))
			append_unique(anchor, ",", "mmp", NULL, maxbuflen);
		else
			disp_old_e2fsprogs_msg("mmp", 1);
	}

	/* Allow more than 65000 subdirectories */
	if (is_e2fsprogs_feature_supp("-O dir_nlink"))
		append_unique(anchor, ",", "dir_nlink", NULL, maxbuflen);

	/* The following options are only valid for ext4-based ldiskfs.
	 * If --backfstype=ext3 is specified, do not enable them. */
	if (mop->mo_ldd.ldd_mount_type == LDD_MT_EXT3)
		return 0;

	/* Enable quota by default */
	if (is_e2fsprogs_feature_supp("-O quota")) {
		append_unique(anchor, ",", "quota", NULL, maxbuflen);
	} else {
		fatal();
		fprintf(stderr, "\"-O quota\" must be supported by "
			"e2fsprogs, please upgrade your e2fsprogs.\n");
		return EINVAL;
	}

	/* Allow files larger than 2TB.  Also needs LU-16, but not harmful. */
	if (is_e2fsprogs_feature_supp("-O huge_file"))
		append_unique(anchor, ",", "huge_file", NULL, maxbuflen);

	if (enable_64bit)
		append_unique(anchor, ",", "64bit", NULL, maxbuflen);

	if (blocks >= 0x1000000000 && is_e2fsprogs_feature_supp("-O meta_bg"))
		append_unique(anchor, ",", "meta_bg", NULL, maxbuflen);

	if (enable_64bit || strstr(mop->mo_mkfsopts, "meta_bg"))
		append_unique(anchor, ",", "^resize_inode", NULL, maxbuflen);

	/* Cluster inode/block bitmaps and inode table for more efficient IO.
	 * Align the flex groups on a 1MB boundary for better performance. */
	/* This -O feature needs to go last, since it adds the "-G" option. */
	if (is_e2fsprogs_feature_supp("-O flex_bg")) {
		char tmp_buf[64];

		append_unique(anchor, ",", "flex_bg", NULL, maxbuflen);

		if (IS_OST(&mop->mo_ldd) &&
		    strstr(mop->mo_mkfsopts, "-G") == NULL) {
			snprintf(tmp_buf, sizeof(tmp_buf), " -G %u",
				 1024 / mop->mo_blocksize_kb);
			strscat(anchor, tmp_buf, maxbuflen);
		}
	}
	/* Don't add any more "-O" options here, see last comment above */
	return 0;
}
Exemple #7
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;
}
Exemple #8
0
int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
	       char **mountopts)
{
	static struct option long_opt[] = {
		{ "backfs-mount-opts",  required_argument,	NULL, 'B' },
		{ "failnode",		required_argument,	NULL, 'f' },
		{ "failover",		required_argument,	NULL, 'f' },
		{ "help",		no_argument,		NULL, 'h' },
		{ "index",		required_argument,	NULL, 'i' },
		{ "fsname",		required_argument,	NULL, 'L' },
		{ "mgsnode",		required_argument,	NULL, 'm' },
		{ "mgsnid",		required_argument,	NULL, 'm' },
		{ "dryrun",		no_argument,		NULL, 'n' },
		{ "mountfsoptions",	required_argument,	NULL, 'o' },
		{ "param",		required_argument,	NULL, 'p' },
		{ "quiet",		no_argument,		NULL, 'q' },
		{ "servicenode",	required_argument,	NULL, 's' },
		{ "network",		required_argument,	NULL, 't' },
		{ "comment",		required_argument,	NULL, 'u' },
		{ "force-nohostid",	no_argument,		NULL, 'U' },
		{ "verbose",		no_argument,		NULL, 'v' },
		{ "version",		no_argument,		NULL, 'V' },
#ifndef TUNEFS
		{ "backfstype",		required_argument,	NULL, 'b' },
		{ "stripe-count-hint",	required_argument,	NULL, 'c' },
		{ "device-size",	required_argument,	NULL, 'd' },
		{ "mgs",		no_argument,		NULL, 'G' },
		{ "mkfsoptions",	required_argument,	NULL, 'k' },
		{ "mdt",		no_argument,		NULL, 'M' },
		{ "nomgs",		no_argument,		NULL, 'N' },
		{ "ost",		no_argument,		NULL, 'O' },
		{ "reformat",		no_argument,		NULL, 'r' },
		{ "replace",		no_argument,		NULL, 'R' },
#else
		{ "erase-params",	no_argument,		NULL, 'e' },
		{ "quota",		no_argument,		NULL, 'Q' },
		{ "writeconf",		no_argument,		NULL, 'w' },
#endif
		{ 0,			0,			NULL,  0  }
	};
	char *optstring = "B:f:hi:L:m:no:p:qs:t:u:vV"
#ifndef TUNEFS
			  "b:c:d:Gk:MNOrR";
#else
			  "eQw";
#endif
	struct lustre_disk_data *ldd = &mop->mo_ldd;
	char new_fsname[16] = { 0 };
	int opt;
	int rc, longidx;
	int failnode_set = 0, servicenode_set = 0;
	int replace = 0;
	bool index_option = false;

	while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) !=
	       EOF) {
		switch (opt) {
		case 'B':
			mop->mo_mountopts = optarg;
			break;
		case 'f':
		case 's': {
			char *nids;

			if ((opt == 'f' && servicenode_set) ||
			    (opt == 's' && failnode_set)) {
				fprintf(stderr, "%s: %s cannot use with --%s\n",
					progname, long_opt[longidx].name,
					opt == 'f' ? "servicenode" :
					"failnode");
				return 1;
			}

			nids = convert_hostnames(optarg);
			if (nids == NULL)
				return 1;

			rc = append_param(ldd->ldd_params, PARAM_FAILNODE,
					  nids, ':');
			free(nids);
			if (rc != 0)
				return rc;

			/* Must update the mgs logs */
			ldd->ldd_flags |= LDD_F_UPDATE;
			if (opt == 'f') {
				failnode_set = 1;
			} else {
				ldd->ldd_flags |= LDD_F_NO_PRIMNODE;
				servicenode_set = 1;
			}
			mop->mo_flags |= MO_FAILOVER;
			break;
		}
		case 'h':
			usage(stdout);
			return 1;
		case 'i': {
			char *endptr = NULL;
			int base;
			index_option = true;
			/* LU-2374: check whether it is OST/MDT later */
			base = (strlen(optarg) > 1 &&
				!strncmp(optarg, "0x", 2)) ? 16 : 10;
			/* Allowed input are base 16 and base 10 numbers only */
			mop->mo_ldd.ldd_svindex = strtoul(optarg,
							  &endptr, base);
			if (*endptr != '\0') {
				fprintf(stderr, "%s: wrong index %s. "
					"Target index must be decimal or "
					"hexadecimal.\n",
					progname, optarg);
				return 1;
			}
			if (ldd->ldd_svindex >= INDEX_UNASSIGNED) {
				fprintf(stderr, "%s: wrong index %u. "
					"Target index must be less than %u.\n",
					progname, ldd->ldd_svindex,
					INDEX_UNASSIGNED);
				return 1;
			}

			ldd->ldd_flags &= ~LDD_F_NEED_INDEX;
			break;
		}
		case 'L': {
			rc = lustre_is_fsname_valid(optarg, 1,
						    LUSTRE_MAXFSNAME);
			if (rc < 0) {
				fprintf(stderr, "%s: filesystem name must be "
					"1-%d chars\n", progname,
					LUSTRE_MAXFSNAME);
				return 1;
			} else if (rc > 0) {
				fprintf(stderr, "%s: char '%c' not allowed in "
					"filesystem name\n", progname, rc);
				return 1;
			}

			strscpy(new_fsname, optarg, sizeof(new_fsname));
			break;
		}
		case 'm': {
			char *nids = convert_hostnames(optarg);

			if (nids == NULL)
				return 1;

			rc = append_param(ldd->ldd_params, PARAM_MGSNODE,
					  nids, ':');
			free(nids);
			if (rc != 0)
				return rc;

			mop->mo_mgs_failnodes++;
			break;
		}
		case 'n':
			print_only++;
			break;
		case 'o':
			*mountopts = optarg;
			break;
		case 'p':
			rc = add_param(ldd->ldd_params, NULL, optarg);
			if (rc != 0)
				return rc;

			/* Must update the mgs logs */
			ldd->ldd_flags |= LDD_F_UPDATE;
			break;
		case 'q':
			verbose--;
			break;
		case 't':
			if (!IS_MDT(ldd) && !IS_OST(ldd)) {
				badopt(long_opt[longidx].name, "MDT,OST");
				return 1;
			}

			if (optarg == NULL)
				return 1;

			rc = add_param(ldd->ldd_params, PARAM_NETWORK, optarg);
			if (rc != 0)
				return rc;

			/* Must update the mgs logs */
			ldd->ldd_flags |= LDD_F_UPDATE;
			break;
		case 'u':
			strscpy(ldd->ldd_userdata, optarg,
				sizeof(ldd->ldd_userdata));
			break;
		case 'U':
			mop->mo_flags |= MO_NOHOSTID_CHECK;
			break;
		case 'v':
			verbose++;
			break;
		case 'V':
			++version;
			fprintf(stdout, "%s %s\n", progname,
				LUSTRE_VERSION_STRING);
			return 0;
#ifndef TUNEFS
		case 'b': {
			int i = 0;

			do {
				if (strcmp(optarg, mt_str(i)) == 0) {
					ldd->ldd_mount_type = i;
					break;
				}
			} while (++i < LDD_MT_LAST);

			if (i == LDD_MT_LAST) {
				fprintf(stderr, "%s: invalid backend filesystem"
					" type %s\n", progname, optarg);
				return 1;
			}
			break;
		}
		case 'c':
			if (IS_MDT(ldd)) {
				int stripe_count = atol(optarg);

				if (stripe_count <= 0) {
					fprintf(stderr, "%s: bad stripe count "
						"%d\n", progname, stripe_count);
					return 1;
				}
				mop->mo_stripe_count = stripe_count;
			} else {
				badopt(long_opt[longidx].name, "MDT");
				return 1;
			}
			break;
		case 'd':
			mop->mo_device_kb = atol(optarg);
			break;
		case 'G':
			ldd->ldd_flags |= LDD_F_SV_TYPE_MGS;
			break;
		case 'k':
			strscpy(mop->mo_mkfsopts, optarg,
				sizeof(mop->mo_mkfsopts));
			break;
		case 'M':
			ldd->ldd_flags |= LDD_F_SV_TYPE_MDT;
			break;
		case 'N':
			ldd->ldd_flags &= ~LDD_F_SV_TYPE_MGS;
			break;
		case 'O':
			ldd->ldd_flags |= LDD_F_SV_TYPE_OST;
			break;
		case 'r':
			mop->mo_flags |= MO_FORCEFORMAT;
			break;
		case 'R':
			replace = 1;
			break;
#else /* !TUNEFS */
		case 'e':
			ldd->ldd_params[0] = '\0';
			/* Must update the mgs logs */
			ldd->ldd_flags |= LDD_F_UPDATE;
			break;
		case 'Q':
			mop->mo_flags |= MO_QUOTA;
			break;
		case 'w':
			ldd->ldd_flags |= LDD_F_WRITECONF;
			break;
#endif /* !TUNEFS */
		default:
			if (opt != '?') {
				fatal();
				fprintf(stderr, "Unknown option '%c'\n", opt);
			}
			return EINVAL;
		}
	}

	if (strlen(new_fsname) > 0) {
		if (!(mop->mo_flags & MO_FORCEFORMAT) &&
		     (!(ldd->ldd_flags &
			(LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF)))) {
			fprintf(stderr, "%s: cannot change the name "
				"of a registered target\n", progname);
			return 1;
		}

		strscpy(ldd->ldd_fsname, new_fsname, sizeof(ldd->ldd_fsname));
	}

	if (index_option && !(mop->mo_ldd.ldd_flags &
	      (LDD_F_UPGRADE14 | LDD_F_VIRGIN |
	       LDD_F_WRITECONF))) {
		fprintf(stderr, "%s: cannot change the index of"
			" a registered target\n", progname);
		return 1;
	}

	/* Need to clear this flag after parsing 'L' and 'i' options. */
	if (replace)
		ldd->ldd_flags &= ~LDD_F_VIRGIN;

	if (optind == argc) {
		/* The user didn't specify device name */
		fatal();
		fprintf(stderr, "Not enough arguments - device name or "
			"pool/dataset name not specified.\n");
		return EINVAL;
	} else {
		/*  The device or pool/filesystem name */
		strscpy(mop->mo_device, argv[optind], sizeof(mop->mo_device));

		/* Followed by optional vdevs */
		if (optind < argc - 1)
			mop->mo_pool_vdevs = (char **) &argv[optind + 1];
	}

	return 0;
}
Exemple #9
0
int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
               char **mountopts)
{
	static struct option long_opt[] = {
		{ "backfstype",		required_argument,	NULL, 'b' },
		{ "stripe-count-hint",	required_argument,	NULL, 'c' },
		{ "comment",		required_argument,	NULL, 'u' },
		{ "configdev",		required_argument,	NULL, 'C' },
		{ "device-size",	required_argument,	NULL, 'd' },
		{ "dryrun",		no_argument,		NULL, 'n' },
		{ "erase-params",	no_argument,		NULL, 'e' },
		{ "failnode",		required_argument,	NULL, 'f' },
		{ "failover",		required_argument,	NULL, 'f' },
		{ "mgs",		no_argument,		NULL, 'G' },
		{ "help",		no_argument,		NULL, 'h' },
		{ "index",		required_argument,	NULL, 'i' },
		{ "mkfsoptions",	required_argument,	NULL, 'k' },
		{ "mgsnode",		required_argument,	NULL, 'm' },
		{ "mgsnid",		required_argument,	NULL, 'm' },
		{ "mdt",		no_argument,		NULL, 'M' },
		{ "fsname",		required_argument,	NULL, 'L' },
		{ "noformat",		no_argument,		NULL, 'n' },
		{ "nomgs",		no_argument,		NULL, 'N' },
		{ "mountfsoptions",	required_argument,	NULL, 'o' },
		{ "ost",		no_argument,		NULL, 'O' },
		{ "param",		required_argument,	NULL, 'p' },
		{ "print",		no_argument,		NULL, 'n' },
		{ "quiet",		no_argument,		NULL, 'q' },
		{ "quota",		no_argument,		NULL, 'Q' },
		{ "reformat",		no_argument,		NULL, 'r' },
		{ "replace",		no_argument,		NULL, 'R' },
		{ "servicenode",	required_argument,	NULL, 's' },
		{ "network",		required_argument,	NULL, 't' },
		{ "verbose",		no_argument,		NULL, 'v' },
		{ "writeconf",		no_argument,		NULL, 'w' },
		{ 0,			0,			NULL,  0  }
	};
	char *optstring = "b:c:C:d:ef:Ghi:k:L:m:MnNo:Op:PqrRs:t:Uu:vw";
	int opt;
	int rc, longidx;
	int failnode_set = 0, servicenode_set = 0;
	int replace = 0;

        while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) !=
               EOF) {
                switch (opt) {
                case 'b': {
                        int i = 0;
                        while (i < LDD_MT_LAST) {
                                if (strcmp(optarg, mt_str(i)) == 0) {
                                        mop->mo_ldd.ldd_mount_type = i;
                                        break;
                                }
                                i++;
                        }
			if (i == LDD_MT_LAST) {
				fprintf(stderr, "%s: invalid backend filesystem"
					" type %s\n", progname, optarg);
				return 1;
			}
                        break;
                }
                case 'c':
                        if (IS_MDT(&mop->mo_ldd)) {
                                int stripe_count = atol(optarg);
                                if (stripe_count <= 0) {
                                        fprintf(stderr, "%s: bad stripe count "
                                                "%d\n", progname, stripe_count);
                                        return 1;
                                }
                                mop->mo_stripe_count = stripe_count;
                        } else {
                                badopt(long_opt[longidx].name, "MDT");
                                return 1;
                        }
                        break;
                case 'C': /* Configdev */
                        //FIXME
                        printf("Configdev not implemented\n");
                        return 1;
		case 'd':
			mop->mo_device_kb = atol(optarg);
			break;
                case 'e':
                        mop->mo_ldd.ldd_params[0] = '\0';
                        /* Must update the mgs logs */
                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                        break;
                case 'f':
                case 's': {
                        char *nids;

                        if ((opt == 'f' && servicenode_set)
                            || (opt == 's' && failnode_set)) {
                                fprintf(stderr, "%s: %s cannot use with --%s\n",
                                        progname, long_opt[longidx].name,
                                        opt == 'f' ? "servicenode" : "failnode");
                                return 1;
                        }

                        nids = convert_hostnames(optarg);
                        if (!nids)
                                return 1;
                        rc = add_param(mop->mo_ldd.ldd_params, PARAM_FAILNODE,
                                       nids);
                        free(nids);
                        if (rc)
                                return rc;
                        /* Must update the mgs logs */
                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                        if (opt == 'f') {
                                failnode_set = 1;
                        } else {
                                mop->mo_ldd.ldd_flags |= LDD_F_NO_PRIMNODE;
                                servicenode_set = 1;
                        }
			mop->mo_flags |= MO_FAILOVER;
                        break;
                }
                case 'G':
                        mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_MGS;
                        break;
                case 'h':
                        usage(stdout);
                        return 1;
                case 'i':
                        if (!(mop->mo_ldd.ldd_flags &
                              (LDD_F_UPGRADE14 | LDD_F_VIRGIN |
                               LDD_F_WRITECONF))) {
                                fprintf(stderr, "%s: cannot change the index of"
                                        " a registered target\n", progname);
                                return 1;
                        }
			/* LU-2374: check whether it is OST/MDT later */
			mop->mo_ldd.ldd_svindex = atol(optarg);
			mop->mo_ldd.ldd_flags &= ~LDD_F_NEED_INDEX;
                        break;
                case 'k':
                        strscpy(mop->mo_mkfsopts, optarg,
                                sizeof(mop->mo_mkfsopts));
                        break;
                case 'L': {
                        char *tmp;
                        if (!(mop->mo_flags & MO_FORCEFORMAT) &&
                            (!(mop->mo_ldd.ldd_flags &
                               (LDD_F_UPGRADE14 | LDD_F_VIRGIN |
                                LDD_F_WRITECONF)))) {
                                fprintf(stderr, "%s: cannot change the name of"
                                        " a registered target\n", progname);
                                return 1;
                        }
                        if ((strlen(optarg) < 1) || (strlen(optarg) > 8)) {
                                fprintf(stderr, "%s: filesystem name must be "
                                        "1-8 chars\n", progname);
                                return 1;
                        }
                        if ((tmp = strpbrk(optarg, "/:"))) {
                                fprintf(stderr, "%s: char '%c' not allowed in "
                                        "filesystem name\n", progname, *tmp);
                                return 1;
                        }
                        strscpy(mop->mo_ldd.ldd_fsname, optarg,
                                sizeof(mop->mo_ldd.ldd_fsname));
                        break;
                }
                case 'm': {
                        char *nids = convert_hostnames(optarg);
                        if (!nids)
                                return 1;
                        rc = add_param(mop->mo_ldd.ldd_params, PARAM_MGSNODE,
                                       nids);
                        free(nids);
                        if (rc)
                                return rc;
                        mop->mo_mgs_failnodes++;
                        break;
                }
                case 'M':
                        mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_MDT;
                        break;
                case 'n':
                        print_only++;
                        break;
                case 'N':
                        mop->mo_ldd.ldd_flags &= ~LDD_F_SV_TYPE_MGS;
                        break;
                case 'o':
                        *mountopts = optarg;
                        break;
                case 'O':
                        mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_OST;
                        break;
                case 'p':
                        rc = add_param(mop->mo_ldd.ldd_params, NULL, optarg);
                        if (rc)
                                return rc;
                        /* Must update the mgs logs */
                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                        break;
                case 'q':
                        verbose--;
                        break;
                case 'r':
                        mop->mo_flags |= MO_FORCEFORMAT;
                        break;
		case 'R':
			replace = 1;
			break;
                case 't':
                        if (!IS_MDT(&mop->mo_ldd) && !IS_OST(&mop->mo_ldd)) {
                                badopt(long_opt[longidx].name, "MDT,OST");
                                return 1;
                        }

                        if (!optarg)
                                return 1;

                        rc = add_param(mop->mo_ldd.ldd_params,
                                       PARAM_NETWORK, optarg);
                        if (rc != 0)
                                return rc;
                        /* Must update the mgs logs */
                        mop->mo_ldd.ldd_flags |= LDD_F_UPDATE;
                        break;
                case 'u':
                        strscpy(mop->mo_ldd.ldd_userdata, optarg,
                                sizeof(mop->mo_ldd.ldd_userdata));
                        break;
                case 'v':
                        verbose++;
                        break;
                case 'w':
                        mop->mo_ldd.ldd_flags |= LDD_F_WRITECONF;
                        break;
		case 'Q':
			mop->mo_flags |= MO_QUOTA;
			break;
                default:
                        if (opt != '?') {
                                fatal();
                                fprintf(stderr, "Unknown option '%c'\n", opt);
                        }
                        return EINVAL;
                }
        }//while

	/* Need to clear this flag after parsing 'L' and 'i' options. */
	if (replace)
		mop->mo_ldd.ldd_flags &= ~LDD_F_VIRGIN;

	if (optind == argc) {
		/* The user didn't specify device name */
		fatal();
		fprintf(stderr, "Not enough arguments - device name or "
			"pool/dataset name not specified.\n");
		return EINVAL;
	} else {
		/*  The device or pool/filesystem name */
		strscpy(mop->mo_device, argv[optind], sizeof(mop->mo_device));

		/* Followed by optional vdevs */
		if (optind < argc - 1)
			mop->mo_pool_vdevs = (char **) &argv[optind + 1];
	}

        return 0;
}