Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 Jan 2018 19:12:37 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r327592 - in stable/11: etc etc/defaults sbin/mdmfs
Message-ID:  <201801051912.w05JCb9g038703@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Fri Jan  5 19:12:36 2018
New Revision: 327592
URL: https://svnweb.freebsd.org/changeset/base/327592

Log:
  MFC r319987, r324107-r324108
  
  r319987 (MFC'd just to make following changes apply cleanly):
  Replace md(4) usage in diskless(8) script rc.initdiskless with tmpfs(5).
  Need to multiply the size of the disk passed to mount_md by 512 as mdmfs
  expects number of 512-byte blocks while tmpfs size option wants number of
  bytes.
  
  r324107:
  Enhance mdmfs(8) to work with tmpfs(5).
  
  Existing scripts and associated config such as rc.initdiskless, rc.d/var,
  and others, use mdmfs to create memory filesystems. That program accepts a
  size argument which allows SI suffixes and treats an unsuffixed number as a
  count of 512 byte sectors. That makes it difficult to convert existing
  scripts to use tmpfs instead of mdmfs, because tmpfs treats unsuffixed
  numbers as a count of bytes. The script logic to deal with existing user
  config that might include suffixed and unsuffixed numbers is... unpleasant.
  
  Also, there is no g'tee that tmpfs will be available. It is sometimes
  configured out of small-resource embedded systems to save memory and flash
  storage space.
  
  These changes enhance mdmfs(8) so that it accepts two new values for the
  'md-device' arg: 'tmpfs' and 'auto'. With tmpfs, the program always uses
  tmpfs(5) (and fails if it's not available). With 'auto' the program prefers
  tmpfs, but falls back to using md(4) if tmpfs isn't available. It also
  handles the -s <size> argument so that the mdconfig interpetation of
  unsuffixed numbers applies when tmpfs is used as well, so that existing user
  config keeps working after a switch to tmpfs.
  
  A new rc setting, mfs_type, is added to etc/defaults/rc.conf to let users
  force the use of tmpfs or md; the default value is "auto".
  
  Differential Revision:	https://reviews.freebsd.org/D12301
  
  r324108:
  Remove spurious $flags; it's a paste-o from copying the line from rc.subr.
  Also, add a comment documenting the args passed to mount_md().

Modified:
  stable/11/etc/defaults/rc.conf
  stable/11/etc/rc.initdiskless
  stable/11/etc/rc.subr
  stable/11/sbin/mdmfs/mdmfs.8
  stable/11/sbin/mdmfs/mdmfs.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/etc/defaults/rc.conf
==============================================================================
--- stable/11/etc/defaults/rc.conf	Fri Jan  5 18:32:46 2018	(r327591)
+++ stable/11/etc/defaults/rc.conf	Fri Jan  5 19:12:36 2018	(r327592)
@@ -51,6 +51,7 @@ tmpmfs_flags="-S"	# Extra mdmfs options for the mfs /t
 varmfs="AUTO"		# Set to YES to always create an mfs /var, NO to never
 varsize="32m"		# Size of mfs /var if created
 varmfs_flags="-S"	# Extra mount options for the mfs /var
+mfs_type="auto"		# "md", "tmpfs", "auto" to prefer tmpfs with md as fallback
 populate_var="AUTO"	# Set to YES to always (re)populate /var, NO to never
 cleanvar_enable="YES" 	# Clean the /var directory
 local_startup="/usr/local/etc/rc.d" # startup script dirs.

Modified: stable/11/etc/rc.initdiskless
==============================================================================
--- stable/11/etc/rc.initdiskless	Fri Jan  5 18:32:46 2018	(r327591)
+++ stable/11/etc/rc.initdiskless	Fri Jan  5 19:12:36 2018	(r327592)
@@ -195,10 +195,11 @@ handle_remount() { # $1 = mount point
     to_umount="$b ${to_umount}"
 }
 
-# Create a generic memory disk
-#
+# Create a generic memory disk.
+# The 'auto' parameter will attempt to use tmpfs(5), falls back to md(4).
+# $1 is size in 512-byte sectors, $2 is the mount point.
 mount_md() {
-    /sbin/mdmfs -S -i 4096 -s $1 -M md $2
+    /sbin/mdmfs -s $1 auto $2
 }
 
 # Create the memory filesystem if it has not already been created

Modified: stable/11/etc/rc.subr
==============================================================================
--- stable/11/etc/rc.subr	Fri Jan  5 18:32:46 2018	(r327591)
+++ stable/11/etc/rc.subr	Fri Jan  5 19:12:36 2018	(r327592)
@@ -1834,7 +1834,7 @@ mount_md()
 	if [ -n "$3" ]; then
 		flags="$3"
 	fi
-	/sbin/mdmfs $flags -s $1 md $2
+	/sbin/mdmfs $flags -s $1 ${mfs_type} $2
 }
 
 # Code common to scripts that need to load a kernel module

Modified: stable/11/sbin/mdmfs/mdmfs.8
==============================================================================
--- stable/11/sbin/mdmfs/mdmfs.8	Fri Jan  5 18:32:46 2018	(r327591)
+++ stable/11/sbin/mdmfs/mdmfs.8	Fri Jan  5 19:12:36 2018	(r327592)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 9, 2016
+.Dd September 9, 2017
 .Dt MDMFS 8
 .Os
 .Sh NAME
@@ -33,7 +33,9 @@
 .Nm mount_mfs
 .Nd configure and mount an in-memory file system using the
 .Xr md 4
-driver
+driver or the
+.Xr tmpfs 5
+filesystem
 .Sh SYNOPSIS
 .Nm
 .Op Fl DLlMNnPStTUX
@@ -63,9 +65,13 @@ utility is designed to be a work-alike and look-alike 
 .Xr mount_mfs 8 .
 The end result is essentially the same,
 but is accomplished in a completely different way.
-The
+Based on
+.Ar md-device ,
+the
 .Nm
-utility configures an
+utility either creates a 
+.Xr tmpfs 5
+filesystem, or it configures an
 .Xr md 4
 disk using
 .Xr mdconfig 8 ,
@@ -81,6 +87,44 @@ compressed disk images, as long as the kernel supports
 All the command line options are passed to the appropriate program
 at the appropriate stage in order to achieve the desired effect.
 .Pp
+When
+.Ar md-device
+is `auto',
+.Nm
+uses
+.Xr tmpfs 5
+if it is present in the kernel or can be loaded as a module,
+otherwise it falls back to using
+.Xr md 4
+auto-unit as if `md' had been specified.
+.Pp
+When
+.Ar md-device
+is `tmpfs',
+.Nm
+mounts a
+.Xr tmpfs 5
+filesystem, translating the
+.Fl s
+size option, if present, into a `-o size=' mount option.
+Any
+.Fl o
+options on the command line are passed through to the
+.Xr tmpfs 5
+mount.
+Options specific to
+.Xr mdconfig 8
+or
+.Xr newfs 8
+are ignored.
+.Pp
+When
+.Ar md-device
+does not result in
+.Xr tmpfs 5
+being used, then an
+.Xr md 4
+device is configured instead.
 By default,
 .Nm
 creates a swap-based
@@ -218,14 +262,10 @@ is
 .Em not
 specified.
 That is,
-this will work for the default swap-backed
-.Pq Dv MD_SWAP
-disks,
-and the optional
-.Pq Fl M
-.Xr malloc 9
-backed disks
-.Pq Dv MD_MALLOC .
+this will work when the backing storage is some form of
+memory, as opposed to a fixed-size file.
+The size may include the usual SI suffixes (k, m, g, t, p).
+A number without a suffix is interpreted as a count of 512-byte sectors.
 .It Fl t
 Turn on the TRIM enable flag for
 .Xr newfs 8 .
@@ -391,6 +431,7 @@ was given on the command line.
 .Sh SEE ALSO
 .Xr md 4 ,
 .Xr fstab 5 ,
+.Xr tmpfs 5 ,
 .Xr mdconfig 8 ,
 .Xr mount 8 ,
 .Xr newfs 8

Modified: stable/11/sbin/mdmfs/mdmfs.c
==============================================================================
--- stable/11/sbin/mdmfs/mdmfs.c	Fri Jan  5 18:32:46 2018	(r327591)
+++ stable/11/sbin/mdmfs/mdmfs.c	Fri Jan  5 19:12:36 2018	(r327592)
@@ -34,15 +34,19 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/linker.h>
 #include <sys/mdioctl.h>
+#include <sys/module.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 
 #include <assert.h>
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <inttypes.h>
 #include <paths.h>
 #include <pwd.h>
 #include <stdarg.h>
@@ -78,7 +82,8 @@ static void	 debugprintf(const char *, ...) __printfli
 static void	 do_mdconfig_attach(const char *, const enum md_types);
 static void	 do_mdconfig_attach_au(const char *, const enum md_types);
 static void	 do_mdconfig_detach(void);
-static void	 do_mount(const char *, const char *);
+static void	 do_mount_md(const char *, const char *);
+static void	 do_mount_tmpfs(const char *, const char *);
 static void	 do_mtptsetup(const char *, struct mtpt_info *);
 static void	 do_newfs(const char *);
 static void	 extract_ugid(const char *, struct mtpt_info *);
@@ -89,14 +94,15 @@ int
 main(int argc, char **argv)
 {
 	struct mtpt_info mi;		/* Mountpoint info. */
+	intmax_t mdsize;
 	char *mdconfig_arg, *newfs_arg,	/* Args to helper programs. */
 	    *mount_arg;
 	enum md_types mdtype;		/* The type of our memory disk. */
-	bool have_mdtype;
+	bool have_mdtype, mlmac;
 	bool detach, softdep, autounit, newfs;
-	char *mtpoint, *unitstr;
+	const char *mtpoint, *size_arg, *unitstr;
 	char *p;
-	int ch;
+	int ch, idx;
 	void *set;
 	unsigned long ul;
 
@@ -105,6 +111,7 @@ main(int argc, char **argv)
 	detach = true;
 	softdep = true;
 	autounit = false;
+	mlmac = false;
 	newfs = true;
 	have_mdtype = false;
 	mdtype = MD_SWAP;
@@ -119,6 +126,7 @@ main(int argc, char **argv)
 	mdconfig_arg = strdup("");
 	newfs_arg = strdup("");
 	mount_arg = strdup("");
+	size_arg = NULL;
 
 	/* If we were started as mount_mfs or mfs, imply -C. */
 	if (strcmp(getprogname(), "mount_mfs") == 0 ||
@@ -175,6 +183,7 @@ main(int argc, char **argv)
 			loudsubs = true;
 			break;
 		case 'l':
+			mlmac = true;
 			argappend(&newfs_arg, "-l");
 			break;
 		case 'M':
@@ -213,7 +222,7 @@ main(int argc, char **argv)
 			softdep = false;
 			break;
 		case 's':
-			argappend(&mdconfig_arg, "-s %s", optarg);
+			size_arg = optarg;
 			break;
 		case 't':
 			argappend(&newfs_arg, "-t");
@@ -242,42 +251,107 @@ main(int argc, char **argv)
 	if (argc < 2)
 		usage();
 
-	/* Derive 'unit' (global). */
-	unitstr = argv[0];
-	if (strncmp(unitstr, "/dev/", 5) == 0)
-		unitstr += 5;
-	if (strncmp(unitstr, mdname, mdnamelen) == 0)
-		unitstr += mdnamelen;
-	if (!isdigit(*unitstr)) {
-		autounit = true;
-		unit = -1;
-		mdsuffix = unitstr;
-	} else {
-		ul = strtoul(unitstr, &p, 10);
-		if (ul == ULONG_MAX)
-			errx(1, "bad device unit: %s", unitstr);
-		unit = ul;
-		mdsuffix = p;	/* can be empty */
+	/*
+	 * Historically our size arg was passed directly to mdconfig, which
+	 * treats a number without a suffix as a count of 512-byte sectors;
+	 * tmpfs would treat it as a count of bytes.  To get predictable
+	 * behavior for 'auto' we document that the size always uses mdconfig
+	 * rules.  To make that work, decode the size here so it can be passed
+	 * to either tmpfs or mdconfig as a count of bytes.
+	 */
+	if (size_arg != NULL) {
+		mdsize = (intmax_t)strtoumax(size_arg, &p, 0);
+		if (p == size_arg || (p[0] != 0 && p[1] != 0) || mdsize < 0)
+			errx(1, "invalid size '%s'", size_arg);
+		switch (*p) {
+		case 'p':
+		case 'P':
+			mdsize *= 1024;
+		case 't':
+		case 'T':
+			mdsize *= 1024;
+		case 'g':
+		case 'G':
+			mdsize *= 1024;
+		case 'm':
+		case 'M':
+			mdsize *= 1024;
+		case 'k':
+		case 'K':
+			mdsize *= 1024;
+		case 'b':
+		case 'B':
+			break;
+		case '\0':
+			mdsize *= 512;
+			break;
+		default:
+			errx(1, "invalid size suffix on '%s'", size_arg);
+		}
 	}
 
+	/*
+	 * Based on the command line 'md-device' either mount a tmpfs filesystem
+	 * or configure the md device then format and mount a filesystem on it.
+	 * If the device is 'auto' use tmpfs if it is available and there is no
+	 * request for multilabel MAC (which tmpfs does not support).
+	 */
+	unitstr = argv[0];
 	mtpoint = argv[1];
-	if (!have_mdtype)
-		mdtype = MD_SWAP;
-	if (softdep)
-		argappend(&newfs_arg, "-U");
-	if (mdtype != MD_VNODE && !newfs)
-		errx(1, "-P requires a vnode-backed disk");
 
-	/* Do the work. */
-	if (detach && !autounit)
-		do_mdconfig_detach();
-	if (autounit)
-		do_mdconfig_attach_au(mdconfig_arg, mdtype);
-	else
-		do_mdconfig_attach(mdconfig_arg, mdtype);
-	if (newfs)
-		do_newfs(newfs_arg);
-	do_mount(mount_arg, mtpoint);
+	if (strcmp(unitstr, "auto") == 0) {
+		if (mlmac)
+			idx = -1; /* Must use md for mlmac. */
+		else if ((idx = modfind("tmpfs")) == -1)
+			idx = kldload("tmpfs");
+		if (idx == -1)
+			unitstr = "md";
+		else
+			unitstr = "tmpfs";
+	}
+
+	if (strcmp(unitstr, "tmpfs") == 0) {
+		if (size_arg != NULL && mdsize != 0)
+			argappend(&mount_arg, "-o size=%jd", mdsize);
+		do_mount_tmpfs(mount_arg, mtpoint); 
+	} else {
+		if (size_arg != NULL)
+			argappend(&mdconfig_arg, "-s %jdB", mdsize);
+		if (strncmp(unitstr, "/dev/", 5) == 0)
+			unitstr += 5;
+		if (strncmp(unitstr, mdname, mdnamelen) == 0)
+			unitstr += mdnamelen;
+		if (!isdigit(*unitstr)) {
+			autounit = true;
+			unit = -1;
+			mdsuffix = unitstr;
+		} else {
+			ul = strtoul(unitstr, &p, 10);
+			if (ul == ULONG_MAX)
+				errx(1, "bad device unit: %s", unitstr);
+			unit = ul;
+			mdsuffix = p;	/* can be empty */
+		}
+	
+		if (!have_mdtype)
+			mdtype = MD_SWAP;
+		if (softdep)
+			argappend(&newfs_arg, "-U");
+		if (mdtype != MD_VNODE && !newfs)
+			errx(1, "-P requires a vnode-backed disk");
+	
+		/* Do the work. */
+		if (detach && !autounit)
+			do_mdconfig_detach();
+		if (autounit)
+			do_mdconfig_attach_au(mdconfig_arg, mdtype);
+		else
+			do_mdconfig_attach(mdconfig_arg, mdtype);
+		if (newfs)
+			do_newfs(newfs_arg);
+		do_mount_md(mount_arg, mtpoint);
+	}
+
 	do_mtptsetup(mtpoint, &mi);
 
 	return (0);
@@ -434,7 +508,7 @@ do_mdconfig_detach(void)
  * Mount the configured memory disk.
  */
 static void
-do_mount(const char *args, const char *mtpoint)
+do_mount_md(const char *args, const char *mtpoint)
 {
 	int rv;
 
@@ -442,6 +516,19 @@ do_mount(const char *args, const char *mtpoint)
 	    mdname, unit, mdsuffix, mtpoint);
 	if (rv)
 		errx(1, "mount exited with error code %d", rv);
+}
+
+/*
+ * Mount the configured tmpfs.
+ */
+static void
+do_mount_tmpfs(const char *args, const char *mtpoint)
+{
+	int rv;
+
+	rv = run(NULL, "%s -t tmpfs %s tmp %s", _PATH_MOUNT, args, mtpoint);
+	if (rv)
+		errx(1, "tmpfs mount exited with error code %d", rv);
 }
 
 /*



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