Subject: Re: problem with MFS and init
To: Jachym Holecek <freza@liberouter.org>
From: Jachym Holecek <freza@liberouter.org>
List: tech-embed
Date: 11/03/2005 20:19:02
> Cool. We could further have /dev union mounted to avoid
> the mmap() dance + saving a few bytes of code. I'll test it
> this night.

Patch below (modified version of Dave's one).

> [Steven M. Bellovin]
> Last time I tried it, I couldn't union-mount a tmpfs over anything.  It
> would be nice if that worked.

Some naive tests seem to work for me (tmpfs union-over ffs2). Do you
see the problem in fresh -current as well?

> [David Laight]
> Beware that the install kernels don't have tmpfs and maybe not
> union mounts, but rely on init to create a /dev.

We could trade mfs for union+tmpfs -- I'll take a look how much
size difference it makes when I'm back home.

> Also note that there is code in init to handle MAKEDEV being a symlink
> (probably to /etc/MAKEDEV because it is an editabel file - or maybe
> because MAKEDEV.local is and has to be in the same place).

Symlinks on the bottom of an union mount work correctly. Am I missing
something here?

	-- Jachym

Index: init.c
===================================================================
RCS file: /cvsroot/src/sbin/init/init.c,v
retrieving revision 1.70
diff -u -r1.70 init.c
--- init.c	27 Jun 2005 01:00:05 -0000	1.70
+++ init.c	3 Nov 2005 18:59:26 -0000
@@ -93,15 +93,17 @@
 const struct timespec dtrtime = {.tv_sec = 0, .tv_nsec = 250000};
 
 #if defined(RESCUEDIR)
-#define	INIT_BSHELL	RESCUEDIR "/sh"
-#define	INIT_MOUNT_MFS	RESCUEDIR "/mount_mfs"
-#define	INIT_PATH	RESCUEDIR ":" _PATH_STDPATH
+#define	INIT_BSHELL		RESCUEDIR "/sh"
+#define	INIT_MOUNT_TMPFS	RESCUEDIR "/mount_tmpfs"
+#define	INIT_PATH		RESCUEDIR ":" _PATH_STDPATH
 #else
-#define	INIT_BSHELL	_PATH_BSHELL
-#define	INIT_MOUNT_MFS	"/sbin/mount_mfs"
-#define	INIT_PATH	_PATH_STDPATH
+#define	INIT_BSHELL		_PATH_BSHELL
+#define	INIT_MOUNT_TMPFS	"/sbin/mount_tmpfs"
+#define	INIT_PATH		_PATH_STDPATH
 #endif
 
+#define INIT_MAKEDEV 	"/dev/MAKEDEV"
+
 int main(int, char *[]);
 
 void handle(sig_t, ...);
@@ -185,28 +187,7 @@
 DB *session_db;
 
 #ifdef MFS_DEV_IF_NO_CONSOLE
-
-#define NINODE 1024
-#define FSSIZE ((8192		/* boot area */				\
-	+ 2 * 8192		/* two copies of superblock */		\
-	+ 4096			/* cylinder group info */		\
-	+ NINODE * (128 + 18)	/* inode and directory entry */		\
-	+ mfile[0].len		/* size of MAKEDEV file */		\
-	+ 2 * 4096) / 512)	/* some slack */
-
-struct mappedfile {
-	const char *path;
-	char	*buf;
-	int	len;
-} mfile[] = {
-	{ "/dev/MAKEDEV",	NULL,	0 },
-	{ "/dev/MAKEDEV.local",	NULL,	0 }
-};
-
-static int mfs_dev(void);
-static void mapfile(struct mappedfile *);
-static void writefile(struct mappedfile *);
-
+static int tmpfs_dev(void);
 #endif
 
 /*
@@ -246,7 +227,7 @@
 
 
 #ifdef MFS_DEV_IF_NO_CONSOLE
-	if (mfs_dev() == -1)
+	if (tmpfs_dev() == -1)
 		requested_transition = single_user;
 #endif
 
@@ -1364,58 +1345,12 @@
 #endif /* LETS_GET_SMALL */
 
 #ifdef MFS_DEV_IF_NO_CONSOLE
-
-static void
-mapfile(struct mappedfile *mf)
-{
-	int fd;
-	struct stat st;
-
-	if (lstat(mf->path, &st) == -1)
-		return;
-
-	if ((st.st_mode & S_IFMT) == S_IFLNK) {
-		mf->buf = malloc(st.st_size + 1);
-		mf->buf[st.st_size] = 0;
-		if (readlink(mf->path, mf->buf, st.st_size) != st.st_size)
-			return;
-		mf->len = -1;
-		return;
-	}
-
-	if ((fd = open(mf->path, O_RDONLY)) == -1)
-		return;
-	mf->buf = mmap(0, (size_t)st.st_size, PROT_READ,
-			MAP_FILE|MAP_SHARED, fd, (off_t)0);
-	(void)close(fd);
-	if (mf->buf == MAP_FAILED)
-		return;
-	mf->len = st.st_size;
-}
-
-static void
-writefile(struct mappedfile *mf)
-{
-	int fd;
-
-	if (mf->len == -1) {
-		symlink(mf->buf, mf->path);
-		free(mf->buf);
-		return;
-	}
-
-	if (mf->len == 0)
-		return;
-	fd = open(mf->path, O_WRONLY | O_CREAT | O_TRUNC, 0755);
-	if (fd == -1)
-		return;
-	(void)write(fd, mf->buf, mf->len);
-	(void)munmap(mf->buf, mf->len);
-	(void)close(fd);
-}
-
+/*
+ * Missing /dev/console and supposing /dev/MAKEDEV exists,
+ * populate /dev in tmpfs.
+ */
 static int
-mfs_dev(void)
+tmpfs_dev(void)
 {
 	/*
 	 * We cannot print errors so we bail out silently...
@@ -1423,7 +1358,6 @@
 	pid_t pid;
 	int status;
 	dev_t dev;
-	char *fs_size;
 #ifdef CPU_CONSDEV
 	static int name[2] = { CTL_MACHDEP, CPU_CONSDEV };
 	size_t olen;
@@ -1433,20 +1367,16 @@
 	if (access(_PATH_CONSOLE, F_OK) != -1)
 		return(0);
 
-	/* Grab the contents of MAKEDEV */
-	mapfile(&mfile[0]);
-
-	/* Grab the contents of MAKEDEV.local */
-	mapfile(&mfile[1]);
+	/* If we don't have MAKEDEV, all is lost */
+	if (access(INIT_MAKEDEV, F_OK) == -1)
+		return(-1);
 
-	/* Mount an mfs over /dev so we can create devices */
+	/* Mount an tmpfs over /dev so we can create devices */
 	switch ((pid = fork())) {
 	case 0:
-		asprintf(&fs_size, "%d", FSSIZE);
-		(void)execl(INIT_MOUNT_MFS, "mount_mfs",
-		    "-b", "4096", "-f", "512",
-		    "-s", fs_size, "-n", STR(NINODE),
-		    "-p", "0755",
+		(void)execl(INIT_MOUNT_TMPFS, "mount_tmpfs",
+		    "-m", "0755",
+		    "-o", "union",
 		    "swap", "/dev", NULL);
 		_exit(1);
 		/*NOTREACHED*/
@@ -1475,21 +1405,14 @@
 
 	(void)freopen(_PATH_CONSOLE, "a", stderr);
 
-	warnx("Creating mfs /dev (%d blocks, %d inodes)", FSSIZE, NINODE);
-
-	/* Create a MAKEDEV script in the mfs /dev */
-	writefile(&mfile[0]);
-
-	/* Create a MAKEDEV.local script in the mfs /dev */
-	writefile(&mfile[1]);
+	warnx("Creating tmpfs /dev");
 
 	/* Run the makedev script to create devices */
 	switch ((pid = fork())) {
 	case 0:
 		dup2(2, 1);	/* Give the script stdout */
 		if (chdir("/dev") == 0)
-			(void)execl(INIT_BSHELL, "sh",
-			    mfile[0].len ? "./MAKEDEV" : "/etc/MAKEDEV",
+			(void)execl(INIT_BSHELL, "sh", INIT_MAKEDEV,
 			    "init", NULL); 
 		_exit(1);