Subject: Re: port-sparc64/25764: kernel doesn't make large enough MFS device for /dev
To: None <gnats-bugs@gnats.NetBSD.org>
From: Christian Biere <christianbiere@gmx.de>
List: netbsd-bugs
Date: 06/01/2004 01:11:57
--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

This more or less a duplicate of the following PRs:

bin/15235: init's mount_mfs call fails to reserve sufficient inodes
bin/24104: /sbin/init can't create mfs /dev
port-macppc/25735: init: mfs /dev: out of inodes

This problem has also been reported repeatedly on the mailing lists.
I suggest moving the mount_mfs call to MAKEDEV so that it's much easier
to bump the number of inodes i.e., it's not necessary to recompile /sbin/init.
Maybe it's possible to modify MAKEDEV to support a dry run to determine
the necessary number of inodes. This way there would be no need for a
hardcoded number.

The attached patch takes care of the first suggestion i.e., /sbin/init
calls "/etc/MAKEDEV mfs_dev" which takes care of mounting /dev on a memory
filesystem and creating the devices.

I've modified MAKEDEV so that "makedev()" contains a target "mfs_dev".
For simplicity and because this isn't a complete solution anyway, MFS_SIZE
isn't calculated but hardcoded:

mfs_dev)
	MFS_INODES=2048
	MFS_SIZE=2048

	mount_mfs -u 0 -g 0 -p 0755 \
		-b 4096 -f 512 -s $MFS_SIZE -n $MFS_INODES \
		swap /dev || exit
	cd /dev || exit
	makedev init
	;;
[...]

This works but I don't claim it's correct.

-- 
Christian

--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="init.udif"

Index: init.c
===================================================================
RCS file: /cvsroot/src/sbin/init/init.c,v
retrieving revision 1.63
diff -u -r1.63 init.c
--- init.c	3 Oct 2003 13:31:32 -0000	1.63
+++ init.c	31 May 2004 22:37:20 -0000
@@ -183,14 +183,6 @@
 
 #ifdef MFS_DEV_IF_NO_CONSOLE
 
-#define NINODE 896
-#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;
@@ -201,8 +193,11 @@
 };
 
 static int mfs_dev(void);
+
+#if 0
 static void mapfile(struct mappedfile *);
 static void writefile(struct mappedfile *);
+#endif
 
 #endif
 
@@ -1358,6 +1353,7 @@
 
 #ifdef MFS_DEV_IF_NO_CONSOLE
 
+#if 0
 static void
 mapfile(struct mappedfile *mf)
 {
@@ -1406,6 +1402,7 @@
 	(void)munmap(mf->buf, mf->len);
 	(void)close(fd);
 }
+#endif
 
 static int
 mfs_dev(void)
@@ -1415,74 +1412,18 @@
 	 */
 	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;
-#endif
 
 	/* If we have /dev/console, assume all is OK  */
 	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]);
-
-	/* Mount an mfs 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),
-		    "swap", "/dev", NULL);
-		_exit(1);
-		/*NOTREACHED*/
-
-	case -1:
-		return(-1);
-
-	default:
-		if (waitpid(pid, &status, 0) == -1)
-			return(-1);
-		if (status != 0)
-			return(-1);
-		break;
-	}
-
-#ifdef CPU_CONSDEV
-	olen = sizeof(dev);
-	if (sysctl(name, sizeof(name) / sizeof(name[0]), &dev, &olen,
-	    NULL, 0) == -1)
-#endif
-		dev = makedev(0, 0);
-
-	/* Make a console for us, so we can see things happening */
-	if (mknod(_PATH_CONSOLE, 0666 | S_IFCHR, dev) == -1)
-		return(-1);
-
-	(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]);
-
 	/* 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",
-			    "init", NULL); 
+			(void)execl(INIT_BSHELL, "sh", "/etc/MAKEDEV",
+			    "mfs_dev", NULL); 
 		_exit(1);
 
 	case -1:
@@ -1495,6 +1436,7 @@
 			errno = EINVAL;
 			break;
 		}
+		(void)freopen(_PATH_CONSOLE, "a", stderr);
 		return 0;
 	}
 	warn("Unable to run MAKEDEV");

--liOOAslEiF7prFVr--