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);