Unverified Commit 313c47f4 authored by Christian Brauner's avatar Christian Brauner
Browse files

fs: use nullfs unconditionally as the real rootfs



Remove the "nullfs_rootfs" boot parameter and simply always use nullfs.
The mutable rootfs will be mounted on top of it. Systems that don't use
pivot_root() to pivot away from the real rootfs will have an additional
mount stick around but that shouldn't be a problem at all. If it is
we'll rever this commit.

This also simplifies the boot process and removes the need for the
traditional switch_root workarounds.

Suggested-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 7416634f
Loading
Loading
Loading
Loading
+4 −20
Original line number Diff line number Diff line
@@ -76,13 +76,8 @@ What is rootfs?
---------------

Rootfs is a special instance of ramfs (or tmpfs, if that's enabled), which is
always present in 2.6 systems.  Traditionally, you can't unmount rootfs for
approximately the same reason you can't kill the init process; rather than
having special code to check for and handle an empty list, it's smaller and
simpler for the kernel to just make sure certain lists can't become empty.

However, if the kernel is booted with "nullfs_rootfs", an immutable empty
filesystem called nullfs is used as the true root, with the mutable rootfs
always present in Linux systems.  The kernel uses an immutable empty filesystem
called nullfs as the true root of the VFS hierarchy, with the mutable rootfs
(tmpfs/ramfs) mounted on top of it.  This allows pivot_root() and unmounting
of the initramfs to work normally.

@@ -126,25 +121,14 @@ All this differs from the old initrd in several ways:
    program.  See the switch_root utility, below.)

  - When switching another root device, initrd would pivot_root and then
    umount the ramdisk.  Traditionally, initramfs is rootfs: you can neither
    pivot_root rootfs, nor unmount it.  Instead delete everything out of
    rootfs to free up the space (find -xdev / -exec rm '{}' ';'), overmount
    rootfs with the new root (cd /newmount; mount --move . /; chroot .),
    attach stdin/stdout/stderr to the new /dev/console, and exec the new init.

    Since this is a remarkably persnickety process (and involves deleting
    commands before you can run them), the klibc package introduced a helper
    program (utils/run_init.c) to do all this for you.  Most other packages
    (such as busybox) have named this command "switch_root".

    However, if the kernel is booted with "nullfs_rootfs", pivot_root() works
    umount the ramdisk.  With nullfs as the true root, pivot_root() works
    normally from the initramfs.  Userspace can simply do::

      chdir(new_root);
      pivot_root(".", ".");
      umount2(".", MNT_DETACH);

    This is the preferred method when nullfs_rootfs is enabled.
    This is the preferred method for switching root filesystems.

Populating initramfs:
---------------------
+21 −43
Original line number Diff line number Diff line
@@ -75,17 +75,6 @@ static int __init initramfs_options_setup(char *str)

__setup("initramfs_options=", initramfs_options_setup);

bool nullfs_rootfs = false;

static int __init nullfs_rootfs_setup(char *str)
{
	if (*str)
		return 0;
	nullfs_rootfs = true;
	return 1;
}
__setup("nullfs_rootfs", nullfs_rootfs_setup);

static u64 event;
static DEFINE_XARRAY_FLAGS(mnt_id_xa, XA_FLAGS_ALLOC);
static DEFINE_IDA(mnt_group_ida);
@@ -4593,10 +4582,9 @@ int path_pivot_root(struct path *new, struct path *old)
 * pointed to by put_old must yield the same directory as new_root. No other
 * file system may be mounted on put_old. After all, new_root is a mountpoint.
 *
 * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem
 * unless the kernel was booted with "nullfs_rootfs". See
 * Documentation/filesystems/ramfs-rootfs-initramfs.rst for alternatives
 * in this situation.
 * The immutable nullfs filesystem is mounted as the true root of the VFS
 * hierarchy. The mutable rootfs (tmpfs/ramfs) is layered on top of this,
 * allowing pivot_root() to work normally from initramfs.
 *
 * Notes:
 *  - we don't move root/cwd if they are not at the root (reason: if something
@@ -5993,24 +5981,21 @@ static void __init init_mount_tree(void)
	struct path root;

	/*
	 * When nullfs is used, we create two mounts:
	 * We create two mounts:
	 *
	 * (1) nullfs with mount id 1
	 * (2) mutable rootfs with mount id 2
	 *
	 * with (2) mounted on top of (1).
	 */
	if (nullfs_rootfs) {
	nullfs_mnt = vfs_kern_mount(&nullfs_fs_type, 0, "nullfs", NULL);
	if (IS_ERR(nullfs_mnt))
		panic("VFS: Failed to create nullfs");
	}

	mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", initramfs_options);
	if (IS_ERR(mnt))
		panic("Can't create rootfs");

	if (nullfs_rootfs) {
	VFS_WARN_ON_ONCE(real_mount(nullfs_mnt)->mnt_id != 1);
	VFS_WARN_ON_ONCE(real_mount(mnt)->mnt_id != 2);

@@ -6029,13 +6014,6 @@ static void __init init_mount_tree(void)
		attach_mnt(real_mount(mnt), mp.parent, mp.mp);

	pr_info("VFS: Finished mounting rootfs on nullfs\n");
	} else {
		VFS_WARN_ON_ONCE(real_mount(mnt)->mnt_id != 1);

		/* The namespace root is the mutable rootfs. */
		mnt_root		= real_mount(mnt);
		init_mnt_ns.root	= mnt_root;
	}

	/*
	 * We've dropped all locks here but that's fine. Not just are we
+7 −13
Original line number Diff line number Diff line
@@ -493,7 +493,6 @@ void __init prepare_namespace(void)
out:
	devtmpfs_mount();

	if (nullfs_rootfs) {
	if (init_pivot_root(".", ".")) {
		pr_err("VFS: Failed to pivot into new rootfs\n");
		return;
@@ -503,11 +502,6 @@ void __init prepare_namespace(void)
		return;
	}
	pr_info("VFS: Pivoted into new rootfs\n");
		return;
	}

	init_mount(".", "/", NULL, MS_MOVE, NULL);
	init_chroot(".");
}

static bool is_tmpfs;
+0 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
void  mount_root_generic(char *name, char *pretty_name, int flags);
void  mount_root(char *root_device_name);
extern int root_mountflags;
extern bool nullfs_rootfs;

static inline __init int create_dev(char *name, dev_t dev)
{