Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jun 2001 00:39:47 -0700
From:      Dima Dorfman <dima@unixfreak.org>
To:        hackers@freebsd.org
Cc:        dougb@freebsd.org
Subject:   mount_mfs-like program for md
Message-ID:  <20010612073947.51AD73E28@bazooka.unixfreak.org>

next in thread | raw e-mail | index | archive | help
Hi folks,

Would anybody have a tantrum if a program with a mount_mfs-like
interface to create an md disk and put a UFS filesystem on it was
imported into the base system?  This has been suggested in the past,
and the only real objection was that it shouldn't be named mount_*.
At this time, I am *not* proposing to name it mount_*.

More specifically, the program exec's mdconfig, disklabel, newfs, and
mount, in that order, to set up the disk and filesystem.  It supports
all the options mount_mfs did, passing them to the correct program(s).
It can theoretically be renamed to mount_<something> to handle
corresponding /etc/fstab entries; however, I would like to make it
clear that I am *not* proposing that.

Furthermore, dougb@ says that something similar would have to be used
in /etc/rc to make filesystems on md disks for, e.g., /tmp, anyway,
and this just factors out the code into something that can be used
separately.  So, is there any reason not to do this?  I've attached a
sharball of the sources.

Regards,

					Dima Dorfman
					dima@unixfreak.org

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	mdmfs
#	mdmfs/Makefile
#	mdmfs/pathnames.h
#	mdmfs/mdmfs.c
#	mdmfs/mdmfs.8
#
echo c - mdmfs
mkdir -p mdmfs > /dev/null 2>&1
echo x - mdmfs/Makefile
sed 's/^X//' >mdmfs/Makefile << 'END-of-mdmfs/Makefile'
X# $FreeBSD$
X
XPROG=		mdmfs
XMAN=		mdmfs.8
XWARNS?=		2
X
X.include <bsd.prog.mk>
END-of-mdmfs/Makefile
echo x - mdmfs/pathnames.h
sed 's/^X//' >mdmfs/pathnames.h << 'END-of-mdmfs/pathnames.h'
X/* $FreeBSD$ */
X#ifndef	MDMFS_PATHNAMES_H
X#define	MDMFS_PATHNAMES_H
X
X#define	PATH_MDCONFIG	"/sbin/mdconfig"
X#define	PATH_DISKLABEL	"/sbin/disklabel"
X#define	PATH_NEWFS	"/sbin/newfs"
X#define	PATH_MOUNT	"/sbin/mount"
X
X#endif	/* !MDMFS_PATHNAMES_H */
END-of-mdmfs/pathnames.h
echo x - mdmfs/mdmfs.c
sed 's/^X//' >mdmfs/mdmfs.c << 'END-of-mdmfs/mdmfs.c'
X/*
X * Copyright (c) 2001 Dima Dorfman <dima@unixfreak.org>.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X/*
X * mdmfs (md/MFS) is a wrapper around mdconfig(8), disklabel(8),
X * newfs(8), and mount(8) that mimics the command line option set of
X * the deprecated mount_mfs(8).  As the name suggests, it creates an
X * md(4) disk, labels it, newfs's it, and mounts it.
X */
X
X#ifndef lint
Xstatic const char rcsid[] =
X  "$FreeBSD$";
X#endif /* not lint */
X
X#include <sys/param.h>
X#include <sys/mdioctl.h>
X#include <sys/stat.h>
X#include <sys/wait.h>
X
X#include <assert.h>
X#include <err.h>
X#include <fcntl.h>
X#include <grp.h>
X#include <paths.h>
X#include <pwd.h>
X#include <stdarg.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X
X#include "pathnames.h"
X
X/* XXX variable args in macros is a GCCism! */
X#define ARGAPPEND(d, s...)	(argappend(d, sizeof(d), " " ##s))
X#define debugprintf(s...)	if (debug) (void)fprintf(stderr, "DEBUG: " ##s)
X
Xtypedef enum { false, true } bool;
X
Xstruct mtpt_info {
X	uid_t		 mi_uid;
X	bool		 mi_have_uid;
X	gid_t		 mi_gid;
X	bool		 mi_have_gid;
X	mode_t		 mi_mode;
X	bool		 mi_have_mode;
X};
X
Xbool debug, loudsubs, norun;	/* Global options. */
Xint unit;			/* The unit we're working with. */
Xconst char *mdname;		/* Name of memory disk device (e.g., "md"). */
Xsize_t mdnamelen;		/* Length of mdname. */
X
Xint	 main(int, char **);
Xvoid	 argappend(char *, size_t, const char *, ...);
Xvoid	 do_disklabel(void);
Xvoid	 do_mdconfig_attach(const char *, const enum md_types);
Xvoid	 do_mdconfig_attach_au(const char *, const enum md_types);
Xvoid	 do_mdconfig_detach(void);
Xvoid	 do_mount(const char *, const char *);
Xvoid	 do_mtptsetup(const char *, struct mtpt_info *);
Xvoid	 do_newfs(const char *);
Xvoid	 extract_ugid(const char *, struct mtpt_info *);
Xint	 run(int *, const char *, ...);
Xvoid	 usage(void);
X
Xint
Xmain(int ac, char **av)
X{
X	char mdconfig_arg[MAXPATHLEN], newfs_arg[MAXPATHLEN],
X	    mount_arg[MAXPATHLEN];
X	char ch, *mtpoint, *unitstr;
X	struct mtpt_info mi;
X	bool nodetach = false, softdep = true, autounit = false;
X	bool have_mdtype = false;
X	enum md_types mdtype;
X
X	(void)memset(&mi, '\0', sizeof(mi));
X	(void)memset(mdconfig_arg, '\0', sizeof(mdconfig_arg));
X	(void)memset(newfs_arg, '\0', sizeof(newfs_arg));
X	(void)memset(mount_arg, '\0', sizeof(mount_arg));
X	mdname = MD_NAME;
X	mdnamelen = strlen(MD_NAME);
X
X	while ((ch = getopt(ac, av,
X	    "a:b:c:Dd:e:F:f:hi:LMm:Nn:O:o:p:Ss:t:w:X")) != -1)
X		switch (ch) {
X		case 'a':
X			ARGAPPEND(newfs_arg, "-a %s", optarg);
X			break;
X		case 'b':
X			ARGAPPEND(newfs_arg, "-b %s", optarg);
X			break;
X		case 'c':
X			ARGAPPEND(newfs_arg, "-c %s", optarg);
X			break;
X		case 'D':
X			nodetach = true;
X			break;
X		case 'd':
X			ARGAPPEND(newfs_arg, "-d %s", optarg);
X			break;
X		case 'e':
X			ARGAPPEND(newfs_arg, "-e %s", optarg);
X			break;
X		case 'F':
X			if (have_mdtype)
X				usage();
X			mdtype = MD_VNODE;
X			have_mdtype = true;
X			ARGAPPEND(mdconfig_arg, "-f %s", optarg);
X			break;
X		case 'f':
X			ARGAPPEND(newfs_arg, "-f %s", optarg);
X			break;
X		case 'h':
X			usage();
X			break;
X		case 'i':
X			ARGAPPEND(newfs_arg, "-i %s", optarg);
X			break;
X		case 'L':
X			loudsubs = true;
X			break;
X		case 'M':
X			if (have_mdtype)
X				usage();
X			mdtype = MD_MALLOC;
X			have_mdtype = true;
X			break;
X		case 'm':
X			ARGAPPEND(newfs_arg, "-m %s", optarg);
X			break;
X		case 'N':
X			norun = true;
X			break;
X		case 'n':
X			ARGAPPEND(newfs_arg, "-n %s", optarg);
X			break;
X		case 'O':
X			ARGAPPEND(newfs_arg, "-o %s", optarg);
X			break;
X		case 'o':
X			ARGAPPEND(mount_arg, "-o %s", optarg);
X			break;
X		case 'p':
X			if (*optarg >= '0' && *optarg <= '7')
X				mi.mi_mode = strtol(optarg, NULL, 8);
X			if ((mi.mi_mode & ~07777) != 0)
X				usage();
X			mi.mi_have_mode = true;
X			break;
X		case 'S':
X			softdep = false;
X			break;
X		case 's':
X			ARGAPPEND(mdconfig_arg, "-s %s", optarg);
X			break;
X		case 't':
X			ARGAPPEND(mount_arg, "-t %s", optarg);
X			break;
X		case 'w':
X			extract_ugid(optarg, &mi);
X			break;
X		case 'X':
X			debug = true;
X			break;
X		default:
X			usage();
X		}
X	ac -= optind;
X	av += optind;
X	if (ac < 2)
X		usage();
X	unitstr = av[0];
X	if (strncmp(unitstr, "/dev/", 5) == 0)
X		unitstr += 5;
X	if (strncmp(unitstr, mdname, mdnamelen) == 0)
X		unitstr += mdnamelen;
X	if (*unitstr == '\0') {
X		autounit = true;
X		unit = -1;
X	} else {
X		unit = strtoul(unitstr, NULL, 10);
X		if ((unsigned)unit == ULONG_MAX)
X			errx(1, "bad device unit: %s", unitstr);
X	}
X	mtpoint = av[1];
X	if (!have_mdtype)
X		mdtype = MD_SWAP;
X
X	if (softdep)
X		ARGAPPEND(newfs_arg, "-U");
X
X	if (!nodetach && !autounit)
X		do_mdconfig_detach();
X	if (autounit)
X		do_mdconfig_attach_au(mdconfig_arg, mdtype);
X	else
X		do_mdconfig_attach(mdconfig_arg, mdtype);
X	do_disklabel();
X	do_newfs(newfs_arg);
X	do_mount(mount_arg, mtpoint);
X	do_mtptsetup(mtpoint, &mi);
X
X	return (0);
X}
X
X/*
X * Append the formatted string pointed to by 'fmt' to 'dst'.
X */
Xvoid
Xargappend(char *dst, size_t dstlen, const char *fmt, ...)
X{
X	va_list ap;
X	char tb[256];
X	size_t rv;
X	
X	va_start(ap, fmt);
X	rv = vsnprintf(tb, sizeof(tb), fmt, ap);
X	va_end(ap);
X	assert(rv < sizeof(tb));
X	rv = strlcat(dst, tb, dstlen);
X	assert(rv < dstlen);
X}
X
Xvoid
Xdo_disklabel(void)
X{
X	int rv;
X
X	rv = run(NULL, "%s -r -w %s%d auto", PATH_DISKLABEL, mdname, unit);
X	if (rv)
X		errx(1, "disklabel exited with error code %d", rv);
X}
X
Xvoid
Xdo_mdconfig_attach(const char *args, const enum md_types mdtype)
X{
X	int rv;
X	const char *ta;		/* Type arg. */
X
X	switch (mdtype) {
X	case MD_SWAP:
X		ta = "-t swap";
X		break;
X	case MD_VNODE:
X		ta = "-t vnode";
X		break;
X	case MD_MALLOC:
X		ta = "-t malloc";
X		break;
X	default:
X		abort();
X	}
X	rv = run(NULL, "%s -a %s%s -u %s%d", PATH_MDCONFIG, ta, args,
X	    mdname, unit);
X	if (rv)
X		errx(1, "mdconfig (attach) exited with error code %d", rv);
X}
X
Xvoid
Xdo_mdconfig_attach_au(const char *args, const enum md_types mdtype)
X{
X	int rv, fd;
X	const char *ta;		/* Type arg. */
X	char tb[10];
X	char *linep;
X	size_t linelen;
X	FILE *sfd;		/* FILE version of fd. */
X
X	switch (mdtype) {
X	case MD_SWAP:
X		ta = "-t swap";
X		break;
X	case MD_VNODE:
X		ta = "-t vnode";
X		break;
X	case MD_MALLOC:
X		ta = "-t malloc";
X		break;
X	default:
X		abort();
X	}
X	rv = run(&fd, "%s -a %s%s", PATH_MDCONFIG, ta, args);
X	if (rv)
X		errx(1, "mdconfig (attach) exited with error code %d", rv);
X	if (norun) {	/* Since we didn't run, we can't read.  Fake it. */
X		unit = -1;
X		return;
X	}
X	sfd = fdopen(fd, "r");
X	if (sfd == NULL)
X		err(1, "fdopen");
X	linep = fgetln(sfd, &linelen);
X	if (linep == NULL && linelen < mdnamelen + 1)
X		errx(1, "unexpected output from mdconfig (attach)");
X	if (strncmp(linep, mdname, mdnamelen) == 0)
X		linep += mdnamelen;
X	assert(linelen + mdnamelen < sizeof(tb));
X	strncpy(tb, linep, linelen);
X	tb[linelen] = '\0';
X	unit = strtoul(tb, NULL, 10);
X	if ((unsigned)unit == ULONG_MAX)
X		errx(1, "unexpected output from mdconfig (attach)");
X
X	fclose(sfd);
X	close(fd);
X}
X
Xvoid
Xdo_mdconfig_detach(void)
X{
X	int rv;
X
X	rv = run(NULL, "%s -d -u %s%d", PATH_MDCONFIG, mdname, unit);
X	if (rv && debug)	/* This is allowed to fail. */
X		warnx("mdconfig (detach) exited with error code %d (ignored)",
X		      rv);
X}
X
Xvoid
Xdo_mount(const char *args, const char *mtpoint)
X{
X	int rv;
X
X	rv = run(NULL, "%s%s /dev/%s%dc %s", PATH_MOUNT, args,
X	    mdname, unit, mtpoint);
X	if (rv)
X		errx(1, "mount exited with error code %d", rv);
X}
X
Xvoid
Xdo_mtptsetup(const char *mtpoint, struct mtpt_info *mip)
X{
X
X	if (mip->mi_have_mode) {
X		debugprintf("changing mode of %s to %o.\n", mtpoint,
X		    mip->mi_mode);
X		if (!norun)
X			if (chmod(mtpoint, mip->mi_mode) == -1)
X				err(1, "chmod: %s", mtpoint);
X	}
X	if (mip->mi_have_uid) {
X		debugprintf("changing owner (user) or %s to %u.\n", mtpoint,
X		    mip->mi_uid);
X		if (!norun)
X			if (chown(mtpoint, mip->mi_uid, -1) == -1)
X				err(1, "chown %s to %u (user)", mtpoint,
X				    mip->mi_uid);
X	}
X	if (mip->mi_have_gid) {
X		debugprintf("changing owner (group) or %s to %u.\n", mtpoint,
X		    mip->mi_gid);
X		if (!norun)
X			if (chown(mtpoint, -1, mip->mi_gid) == -1)
X				err(1, "chown %s to %u (group)", mtpoint,
X				    mip->mi_gid);
X	}
X}
X
Xvoid
Xdo_newfs(const char *args)
X{
X	int rv;
X
X	rv = run(NULL, "%s%s /dev/%s%dc", PATH_NEWFS, args, mdname, unit);
X	if (rv)
X		errx(1, "newfs exited with error code %d", rv);
X}
X
X/*
X * 'str' should be a user and group name similar to the last argument
X * to chown(1); i.e., a user, followed by a colon or period, followed
X * by a group.  The user and group in 'str' may be either a [ug]id or
X * a name.  Upon return, the uid and gid fields in 'mip' will contain
X * the uid and gid of the user and group name in 'str', respectively.
X *
X * In other words, this derives a user and group id from a string
X * formatted like the last argument to chown(1).
X */
Xvoid
Xextract_ugid(const char *str, struct mtpt_info *mip)
X{
X	struct passwd *pw;
X	struct group *gr;
X	char ug[MAXLOGNAME * 2 + 2];
X	char *user, *group;
X	char *p;
X	uid_t *uid;
X	gid_t *gid;
X
X	uid = &mip->mi_uid;
X	gid = &mip->mi_gid;
X	mip->mi_have_uid = mip->mi_have_gid = false;
X
X	(void)strlcpy(ug, str, sizeof(ug));
X	group = ug;
X	user = strsep(&group, ":.");
X	if (user == NULL || group == NULL || *user == '\0' || *group == '\0')
X		usage();
X
X	*uid = strtoul(user, &p, 10);
X	if ((unsigned)*uid == ULONG_MAX)
X		usage();
X	if (*p != '\0') {
X		pw = getpwnam(user);
X		if (pw == NULL)
X			errx(1, "invalid user: %s", user);
X		*uid = pw->pw_uid;
X		mip->mi_have_uid = true;
X	}
X	*gid = strtoul(group, &p, 10);
X	if ((unsigned)*gid == ULONG_MAX)
X		usage();
X	if (*p != '\0') {
X		gr = getgrnam(group);
X		if (gr == NULL)
X			errx(1, "invalid group: %s", group);
X		*gid = gr->gr_gid;
X		mip->mi_have_gid = true;
X	}
X
X	assert(mip->mi_have_uid);
X	assert(mip->mi_have_gid);
X}
X
X/*
X * Run a process with command name and arguments pointed to by the
X * formatted string 'cmdline'.  Since system(3) is not used, the first
X * space-delimited token of 'cmdline' must be the full pathname of the
X * program to run.  The return value is the return code of the process
X * spawned.  If 'ofd' is non-NULL, it is set to the standard output of
X * the program spawned (i.e., you can read from ofd and get the output
X * of the program).
X */
Xint
Xrun(int *ofd, const char *cmdline, ...)
X{
X	va_list ap;
X	char cmd[MAXPATHLEN], **av, **avp, *p;
X	int i, pid, status, ac, pfd[2], nfd;
X	bool dup2dn = true;	/* Dup /dev/null to stdout? */
X
X	va_start(ap, cmdline);
X	(void)vsnprintf(cmd, sizeof(cmd), cmdline, ap);
X	va_end(ap);
X
X	for (ac = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++)
X		ac++;		/* 'ac' generation loop. */
X	av = (char **)malloc(sizeof(*av) * (ac + 1));
X	if (av == NULL)
X		err(1, "malloc");
X	for (p = cmd, avp = av; (*avp = strsep(&p, " ")) != NULL;)
X		if (**av != '\0')
X			if (++avp >= &av[ac]) {
X				*avp = NULL;
X				break;
X			}
X	assert(*av);
X	if (debug) {
X		(void)fprintf(stderr, "DEBUG: running:");
X		/* Should be equivilent to 'cmd' (before strsep, of course). */
X		for (i = 0; av[i] != NULL; i++)
X			(void)fprintf(stderr, " %s", av[i]);
X		(void)fprintf(stderr, "\n");
X	}
X	if (ofd != NULL) {
X		if (pipe(&pfd[0]) == -1)
X			err(1, "pipe");
X		*ofd = pfd[0];
X		dup2dn = false;
X	}
X	pid = fork();
X	switch (pid) {
X	case 0:
X		if (norun)
X			_exit(0);
X		if (ofd != NULL)
X			if (dup2(pfd[1], STDOUT_FILENO) < 0)
X				err(1, "dup2");
X		if (!loudsubs) {
X			nfd = open(_PATH_DEVNULL, O_RDWR);
X			if (nfd < 0)
X				err(1, "open: %s", _PATH_DEVNULL);
X			if (dup2(nfd, STDIN_FILENO) < 0)
X				err(1, "dup2");
X			if (dup2dn)
X				if (dup2(nfd, STDOUT_FILENO) < 0)
X				   err(1, "dup2");
X			if (dup2(nfd, STDERR_FILENO) < 0)
X				err(1, "dup2");
X		}
X
X		(void)execv(av[0], av);
X		warn("exec: %s", av[0]);
X		_exit(-1);
X	case -1:
X		err(1, "fork");
X	}
X	while (waitpid(pid, &status, 0) != pid)
X		;
X	free(av);
X	return (WEXITSTATUS(status));
X}
X
Xvoid
Xusage(void)
X{
X
X	fprintf(stderr,
X"usage: %s [-DLMNSX] [-a maxcontig] [-b block-size] [-c cylinders]\n"
X"\t[-d rotdelay] [-e maxbpg] [-F file] [-f frag-size] [-i bytes]\n"
X"\t[-m percent-free] [-n rotational-positions] [-O optimization]\n"
X"\t[-o mount-options] [-p permissions] [-s size] [-w user:group]\n"
X"\tmd-device mount-point\n", getprogname());
X	exit(1);
X}
END-of-mdmfs/mdmfs.c
echo x - mdmfs/mdmfs.8
sed 's/^X//' >mdmfs/mdmfs.8 << 'END-of-mdmfs/mdmfs.8'
X.\"
X.\" Copyright (c) 2001 Dima Dorfman <dima@unixfreak.org>
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X.\" SUCH DAMAGE.
X.\"
X.\" $FreeBSD$
X.\"
X.Dd May 26, 2001
X.Dt MDMFS 8
X.Os
X.Sh NAME
X.Nm mdmfs
X.Nd configure and mount an in-memory filesystem using the
X.Xr md 4
Xdriver
X.Sh SYNOPSIS
X.Nm
X.Op Fl DLMNSX
X.Op Fl a Ar maxcontig
X.Op Fl b Ar block-size
X.Op Fl c Ar cylinders
X.Op Fl d Ar rotdelay
X.Op Fl e Ar maxbpg
X.Op Fl F Ar file
X.Op Fl f Ar frag-size
X.Op Fl i Ar bytes
X.Op Fl m Ar percent-free
X.Op Fl n Ar rotational-positions
X.Op Fl O Ar optimization
X.Op Fl o Ar mount-options
X.Op Fl p Ar permissions
X.Op Fl s Ar size
X.Op Fl w Ar user Ns | Ns Ar group
X.Ar md-device
X.Ar mount-point
X.Sh DESCRIPTION
XThe
X.Nm
Xprogram is designed to be a work-alike and look-alike of the deprecated
X.Xr mount_mfs 8 .
XThe end result is essentially the same,
Xbut is accomplished in a completely different way.
X.Nm
Xconfigures an
X.Xr md 4
Xdisk using
X.Xr mdconfig 8 ,
Xlabels it using
X.Xr disklabel 8 ,
Xputs a UFS filesystem on it using
X.Xr newfs 8 ,
Xand mounts it using
X.Xr mount 8 .
XAll the command line options are passed to the appropriate program
Xat the appropriate stage in order to achieve the desired effect.
X.Pp
XBy default,
X.Nm
Xcreates a swap-based
X.Pq Dv MD_SWAP
Xdisk with soft-updates enabled
Xand mounts it on
X.Ar mount-point .
XIt uses the
X.Xr md 4
Xdevice specified by
X.Ar md-device .
XIf
X.Ar md-device
Xis
X.Ql md
X(no unit number),
Xit will use
X.Xr md 4 Ns 's
Xauto-unit feature to automatically select an unused device.
XUnless otherwise specified with one of the options below,
Xit uses the default arguments to all the helper programs.
X.Pp
XThe following options are available.
XWhere possible,
Xthe option letter matches the one used by
X.Xr mount_mfs 8
Xfor the same thing.
X.Bl -tag -width Ds
X.It Fl a Ar maxcontig
XSpecify the maximum number of contiguous blocks that will be laid
Xout before forcing a rotational delay
X(see the
X.Fl d
Xoption).
X.It Fl b Ar block-size
XThe block size of the filesystem, in bytes.
X.It Fl c Ar cylinders
XThe number of cylinders per cylinder group in the filesystem.
X.It Fl D
XIf not using auto-unit,
Xdon't run
X.Xr mdconfig 8
Xto try to detach the unit before attaching it.
X.It Fl d Ar rotdelay
XSpecify the mininum time in milliseconds required to initiate another
Xdisk transfer on the same cylinder.
XModern disks with read/write-behind achieve higher performance without
Xthis feature,
Xso it is best to leave it at 0 milliseconds.
X.It Fl e Ar maxbpg
XIndicate the maximum number of blocks any single file can allocate
Xout of a cylinder group before it is forced to begin allocating
Xblocks from another cylinder group.
X.It Fl F Ar file
XCreate a vnode-backed
X.Pq Dv MD_VNODE
Xmemory disk backed by
X.Ar file .
X.It Fl f Ar frag-size
XThe fragment size of the filesystem in bytes.
X.It Fl i Ar bytes
XNumber of bytes per inode.
X.It Fl L
XShow the output of the helper programs.
XBy default,
Xit is sent to
X.Pa /dev/null .
X.It Fl M
XCreate a
X.Xr malloc 9
Xbacked disk
X.Pq Dv MD_MALLOC
Xinstead of a swap-backed disk.
X.It Fl m Ar percent-free
XThe percentage of space reserved for the superuser.
X.It Fl N
XDon't actually run the helper programs.
XThis is most useful in conjunction with
X.Fl X .
X.It Fl n Ar rotational-positions
XThe default number of rotational positions to distinguish.
X.It Fl O Ar optimization
XSelect the optimization preference;
Xvalid choices are
X.Ar space
Xand
X.Ar time ,
Xwhich will optimize for minimum space fragmentation and
Xminimum time spent allocating blocks,
Xrespectively.
X.It Fl o Ar mount-options
XSpecify the mount options with which to mount the filesystem.
XSee
X.Xr mount 8
Xfor more information.
X.It Fl p Ar permissions
XSet the file (directory) permissions of the mount point
X.Ar mount-point
Xto
X.Ar permissions .
X.It Fl S
XDon't enable soft-updates on the filesystem.
X.It Fl s Ar size
XSpecify the size of the disk to create.
XThis only makes sense if
X.Fl F
Xis
X.Em not
Xspecified.
XThat is,
Xthis will work for the default swap-backed
X.Pq Dv MD_SWAP
Xdisks,
Xand the optional
X.Pq Fl M
X.Xr malloc 9
Xbacked disks
X.Pq Dv MD_MALLOC .
X.It Fl w Ar user Ns | Ns Ar group
XSet the owner user and group to
X.Ar user
Xand
X.Ar group ,
Xrespectively.
XThe arguments have the same semantics as with
X.Xr chown 8 ,
Xbut specifying just a user or just a group is not supported.
X.El
X.Pp
XThe
X.Fl F
Xand
X.Fl s
Xoptions are passed to
X.Xr mdconfig 8
Xas
X.Fl f
Xand
X.Fl s ,
Xrespectively.
XThe
X.Fl a ,
X.Fl b ,
X.Fl c ,
X.Fl d ,
X.Fl e ,
X.Fl f ,
X.Fl i ,
X.FL m
Xand
X.Fl n
Xoptions are passed to
X.Xr newfs 8
Xwith the same letter;
Xthe
X.Fl O
Xoption is passed to
X.Xr newfs 8
Xas
X.Fl o .
XThe
X.Fl o
Xand
X.Fl t
Xoptions are passed to
X.Xr mount 8
Xwith the same letter.
XSee the programs that the options are passed to for more information
Xon their semantics.
X.Sh EXAMPLES
XCreate and mount a 32 megabyte swap-backed filesystem on
X.Pa /tmp :
X.Pp
X.Dl mdmfs -s 32m md /tmp
X.Pp
XCreate and mount a 16 megabyte malloc-backed filesystem on
X.Pa /tmp
Xusing the
X.Pa /dev/md1
Xdevice;
Xfurthermore,
Xdon't use soft-updates it and mount it
X.Cm async :
X.Pp
X.Dl mdmfs -M -S -o async -s 16m md1 /tmp
X.Sh AUTHORS
X.An Dima Dorfman
X.Aq dima@unixfreak.org
END-of-mdmfs/mdmfs.8
exit


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010612073947.51AD73E28>