dracutdevs / dracut

dracut the event driven initramfs infrastructure
https://github.com/dracutdevs/dracut/wiki
GNU General Public License v2.0
597 stars 396 forks source link

rd.live.ram=1 may fill up /run if tmpfs is too small #2550

Open cbs228 opened 10 months ago

cbs228 commented 10 months ago

Describe the bug Many distros now cap the total size of the /run filesystem at a relatively small percentage of RAM. For example, Fedora Security Live F38 on a VM with 4 GB of RAM caps /run at only 779.89 MB. This is not enough to contain the complete ISO when rd.live.ram=1 is requested. When dracut writes the rootfs image to /run/initramfs/squashed.img, it fills up /run and fails the boot.

Distribution used Fedora Security Live F38

Dracut version 059-2.fc38

Init system systemd-253.2-1.fc38

To Reproduce

  1. Obtain Fedora-Security-Live-x86_64-38-1.6.iso
  2. Configure a VM in GNOME Boxes or libvirt with 4000 MB of RAM
  3. At the GRUB2 menu, choose a normal boot option like "Start Fedora-Security Live 38." Press e to edit the boot options. Add rd.live.ram=1 rd.break rd.shell to the end of the linux options line. Press ctrl-x to boot.
  4. Observe that dracut fails to mount the rootfs because mount can't recognize the filesystem.
  5. Run
    echo "something something something" >/run/initramfs/testfile

    and verify that a no space left on device error occurs. Also verify that /run/initramfs/squashed.img is smaller than it should be.

  6. tmpfs size may be queried with
    cat /proc/self/mountinfo

Expected behavior I believe that dracut dmsquash-live and livenet should either:

Without changes to dracut, distros that want to support rd.live.ram will need to ensure that /run/initramfs is large enough.

Additional context Requesting rd.live.ram=1 on a system with not enough memory may put the system under severe memory pressure. #2344 adds the capability to check for this, and we probably don't need to second-guess this check.

The tmpfs(5) default size is 50% of memory. The default size should be large enough on most modern hardware to contain a live image of "reasonable" size. It is clear that some distos opt for a lower size limit for /run.

See also downstream bug RH-2035641

Athwale commented 4 months ago

This is also a problem when you have rd.writable.fsimg=1 This option copies the rootfs.img into /run, this image can be very large.

It used to run fine on f38 but no longer works on f39. The /run should be resized automatically to fit the image when writable.fsimg is used otherwise you get "no space left on device"

Athwale commented 4 months ago

If you are experiencing this issue and need to temporarily fix it until dracut has a more permanent solution, you can create a custom dracut module, that remounts /run at the size you need like this:

File: module-setup.sh, executable:

#!/bin/bash

check() {
    return 0
}

depends() {
    return 0
}

install() {
    inst_hook pre-udev 10 "$moddir/run-remount.sh" 
}

File run-remount.sh, executable:

#!/bin/sh
# Append emergency_shell to debug.

SIZE="16000M"
echo "Mounting /run with $SIZE" > /dev/kmsg
mount -t tmpfs -o remount,mode=755,rw,nosuid,nodev,size="$SIZE",nr_inodes=819200,inode64 tmpfs /run
mkdir /usr/lib/dracut/modules.d/90dmsquash-a
mv run-remount.sh /usr/lib/dracut/modules.d/90dmsquash-a
mv module-setup.sh /usr/lib/dracut/modules.d/90dmsquash-a
echo 'add_dracutmodules+=dmsquash-a' >> /etc/dracut.conf.d/remount.conf

Then when dracut runs it will pick up the new module and during boot remount /run with the size of 16GB.

LaszloGombos commented 4 months ago

Perhaps https://github.com/dracutdevs/dracut/pull/2551

Athwale commented 4 months ago

I tested the https://github.com/dracutdevs/dracut/pull/2551 and it does not solve the problem with rd.writable.fsimg=1

In 90dmsquash-live module in dmsquash-live-root.sh The code that uses the new function is:

fi
if [ -e "$SQUASHED" ]; then
    if [ -n "$live_ram" ]; then
        imgsize=$(($(stat -c %s -- $SQUASHED) / (1024 * 1024)))
        check_live_ram $imgsize
        echo 'Copying live image to RAM...' > /dev/kmsg
        echo ' (this may take a minute)' > /dev/kmsg
        dd if=$SQUASHED of=/run/initramfs/squashed.img bs=512 2> /dev/null
        echo 'Done copying live image to RAM.' > /dev/kmsg
        SQUASHED="/run/initramfs/squashed.img"
    fi
...

This only takes care of the squashfs.img

But writable.fsimg which is a little lower in the file does not use it and the cp command will fail:

if [ -n "$FSIMG" ]; then
    if [ -n "$writable_fsimg" ]; then
        # mount the provided filesystem read/write
        echo "Unpacking live filesystem (may take some time)" > /dev/kmsg
        mkdir -m 0755 -p /run/initramfs/fsimg/
        if [ -n "$SQUASHED" ]; then
            cp -v $FSIMG /run/initramfs/fsimg/rootfs.img
        else
            unpack_archive $FSIMG /run/initramfs/fsimg/
        fi
        FSIMG=/run/initramfs/fsimg/rootfs.img
    fi
LaszloGombos commented 4 months ago

Thanks for helping. I misspoke earlier, this is the one I wanted to point out - https://github.com/dracutdevs/dracut/pull/2604

CC @FGrose