Having only one of subvol= and subvolid= is enough for mounting a btrfs subvolume
And having subvolid= set prevents things like 'snapper rollback' to work, as it
updates the subvolume in-place, leaving subvol= unchanged with a different subvolid.
btrfs doesn't need nor use a regular fsck utility.
This was wrongly added in b31a5d9f94 and made `genfstab` generate btrfs entries with `fs_passno` not
set to `0`.
As described in 2be79c6 ("run the chroot in a new PID namespace"), child
processes can hang around and keep various files open. This may prevent
filesystems from being unmounted (as they are still in-use).
When adding unshare mode, I did not quite understand this distinction
(and I wasn't testing with e.g. gnupg) so I didn't catch this. Fix this
by always using unshare to create a second pid namespace for "worker"
processes. This ensures that all children are dead when we start
unmounting things. As the top-level unshare is no longer always
necessary, convert the unshare variable to a binary value.
Fixes: ee9db7d ("Add unshare mode to pacstrap")
Closes: #21
This is effectively the same transformation as in the previous patch.
We move the mountpoint warning later to avoid warning when we are about
to bind-mount the chroot dir ourselves.
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
In an unshare environment, /etc/pacman.d/gnupg is owned by the original
root, who is now "nobody". cp will warn about this, since we can't
create files owned by the original root, and it instead creates them as
the unshare'd root (the original user). This is benign, so ignore it.
Avoid e.g. systemd-tmpfiles from tampering /run (of the host):
fchownat() of /run/systemd/netif failed: Read-only file system
fchownat() of /run/systemd/netif/links failed: Read-only file system
fchownat() of /run/systemd/netif/leases failed: Read-only file system
fchownat() of /run/systemd/netif/lldp failed: Read-only file system
In this particular case, it could cause unexpected (and unnecessary)
change of ownership to these directories (because of automatic uid/gid
allocation), which could prevent systemd-networkd from working.
Besides, the chroot should under no circumstances (actually) need any
(read-)write access to /run. If there's such need, we should not bind
mount.
Ref.: https://bugs.archlinux.org/task/61808