Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Need help setting initramfs to hibernate.
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Kernel & Hardware
View previous topic :: View next topic  
Author Message
Rockman8
n00b
n00b


Joined: 19 Sep 2023
Posts: 36

PostPosted: Wed Jul 10, 2024 7:32 pm    Post subject: Need help setting initramfs to hibernate. Reply with quote

Hello guys,

I got this init where I mount all the lvm partitions and I whish to set it to hibernate (elogind) I used this init as model

https://wiki.gentoo.org/wiki/Custom_Initramfs/Examples

This code in particular

Code:

for p in \$(cat /proc/cmdline); do
   case "\${p}" in
      crypt_root=*)
         crypt_root="\${p#*=}"
         ;;
      root=*)
         root="\${p#*=}"
         ;;
      resume=*)
         resume="\${p#*=}"
         ;;
      ro|rw)
         mount_ro_rw="\${p}"
         ;;
   esac
done

# enable resume from hibernate
if [ -n "\${resume}" ]; then
   # copy the major:minor of the swap block device into /sys/power/resume
   printf '%u:%u\\n' \$(stat -L -c '0x%t 0x%T' "\${resume}") > /sys/power/resume || \
     rescue_shell "Activating resume failed."
fi


and changed it into

Code:

resume_hibernate() {

        # set hardcoded default values
        resume="/dev/vg0/swap"

        # parse kernel command line
        for p in $(cat /proc/cmdline); do

                if ["${p}"=resume]; then
                        resume="${p#*=}"
                fi

        done

        # enable resume from hibernate
        if [ -n "${resume}" ]; then

                # copy the major:minor of the swap block device into /sys/power/resume

                printf '%u:%u\n' $(stat -L -c '0x%t 0x%T' "${resume}") > /sys/power/resume || rescue_shell "Activating resume failed."

        fi

}


Is this code safe to run?

This is my current init

Code:

#!/bin/busybox sh

rescue_shell() {
    #load keymap
        loadkmap < /keymap.bmap

    echo "$@"
    echo "Something went wrong. Dropping you to a shell."
    module_usb_install
    busybox --install -s /usr/local/bin
    setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1'

    #exec /bin/sh
}

uuidlabel_root() {
    for cmd in $(cat /proc/cmdline) ; do
        case $cmd in
        root=*)
            type=$(echo $cmd | cut -d= -f2)
            echo "Mounting rootfs"
            if [ $type == "LABEL" ] || [ $type == "UUID" ] ; then
                uuid=$(echo $cmd | cut -d= -f3)
                mount -o ro $(findfs "$type"="$uuid") /mnt/root
            else
                mount -o ro $(echo $cmd | cut -d= -f2) /mnt/root
            fi
            ;;
        esac
    done
}

check_filesystem() {
    # most of code coming from /etc/init.d/fsck

    local fsck_opts= check_extra= RC_UNAME=$(uname -s)

    # FIXME : get_bootparam forcefsck
    if [ -e /forcefsck ]; then
        fsck_opts="$fsck_opts -f"
        check_extra="(check forced)"
    fi

    echo "Checking local filesystem $check_extra : $1"

    if [ "$RC_UNAME" = Linux ]; then
        fsck_opts="$fsck_opts -C0 -T"
    fi

    trap : INT QUIT

    # using our own fsck, not the builtin one from busybox
    /bin/fsck -p $fsck_opts $1

    case $? in
        0)      return 0;;
        1)      echo "Filesystem repaired"; return 0;;
        2|3)    if [ "$RC_UNAME" = Linux ]; then
                        echo "Filesystem repaired, but reboot needed"
                        reboot -f
                else
                        rescue_shell "Filesystem still have errors; manual fsck required"
                fi;;
        4)      if [ "$RC_UNAME" = Linux ]; then
                        rescue_shell "Fileystem errors left uncorrected, aborting"
                else
                        echo "Filesystem repaired, but reboot needed"
                        reboot
                fi;;
        8)      echo "Operational error"; return 0;;
        12)     echo "fsck interrupted";;
        *)      echo "Filesystem couldn't be fixed";;
    esac
    rescue_shell
}

module_install() {
   #This function must be called AFTER the lvm partitions have been mounted

   #export FIRMWARE_DIR=/mnt/root/lib/firmware/

   # Loading r8169 (ethernet) and amdgpu (graphic card) firmware and modules

   #ln -st /lib/modules/ /mnt/root/usr/lib/modules/$(uname -r)/
   #(busybox's ln does not support -t option, must move into desired directory and then the target directory symlink is created.)
   
        #creating modules' directory lin
   cd /lib/
   ln -s /mnt/root/usr/lib/modules/

        #creating link firmware's directory link
   cd /lib/
   ln -s /mnt/root/lib/firmware/

        #moving out from the directory
   cd

   /bin/modprobe -av realtek 8169 #drm amdgpu

}

module_usb_install() {
   #load usb support
   insmod /modules/xhci-hcd.ko       || echo "Failed to load xhci-hcd"
   insmod /modules/ehci-hcd.ko        || echo "Failed to load eci-hcd"
   insmod /modules/ohci-hcd.ko        || echo "Failed to load ohci-hcd"
   insmod /modules/usb-storage.ko     || echo "Failed to load usb-storage"
   insmod /modules/uas.ko        || echo "Failed to load uas"

}

resume_hibernate() {

        # set hardcoded default values
        resume="${RESUME}"

        # parse kernel command line
        for p in \$(cat /proc/cmdline); do
                if ["\${p}"=resume]; then
                        resume="\${p#*=}"
                fi
        done

        # enable resume from hibernate
        if [ -n "\${resume}" ]; then
                # copy the major:minor of the swap block device into /sys/power/resume
                printf '%u:%u\\n' \$(stat -L -c '0x%t 0x%T' "\${resume}") > /sys/power/resume || \
                rescue_shell "Activating resume failed."
        fi

}


# temporarily mount proc and sys
#module_usb_install
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev

# disable kernel messages from popping onto the screen
echo 0 > /proc/sys/kernel/printk

# clear the screen
clear

# mounting rootfs on /mnt/root
lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control

lvm lvchange -a ly vg0/root      || rescue_shell
lvm lvchange -a ly vg0/boot      || rescue_shell
lvm lvchange -a ly vg0/usr       || rescue_shell
lvm lvchange -a ly vg0/var       || rescue_shell
lvm lvchange -a ly vg0/var_tmp   || rescue_shell
lvm lvchange -a ly vg0/var_log    || rescue_shell
lvm lvchange -a ly vg0/swap    || rescue_shell

lvm vgscan --mknodes || rescue_shell   # creates /dev/mapper/vg0-root /dev/vg0/root

uuidlabel_root || rescue_shell "Error with uuidlabel_root"

# space separated list of mountpoints that ...
mountpoints="/boot /usr /var /var/tmp /var/log" #note: you can add more than just usr, but make sure they are declared in /usr/src/initramfs/initramfs_list

# ... we want to find in /etc/fstab ...
ln -s /mnt/root/etc/fstab /etc/fstab

# ... to check filesystems and mount our devices.
for m in $mountpoints ; do
    check_filesystem $m

    echo "Mounting $m"
    # mount the device and ...
    mount $m || rescue_shell "Error while mounting $m"

    # ... move the tree to its final location
    mount --move $m "/mnt/root"$m || rescue_shell "Error while moving $m"
done

   # install modules
        # currently not installing any early modules
   #module_install || rescue_shell "Error while installing modules"

=========================================================================================

#Resuming after lvm partitions have been started and mounted

#resume_hibernate || rescue_shell

=========================================================================================

echo "All done. Switching to real root."

# clean up. The init process will remount proc sys and dev later
umount /proc
umount /sys
umount /dev

# switch to the real root and execute init
exec switch_root /mnt/root /sbin/init


and grub.conf

Code:

GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/vg0/swap"


Is this OK? Can I hibernate safely and wake up without messing with my system?

Thanks in advance!
Back to top
View user's profile Send private message
sublogic
Apprentice
Apprentice


Joined: 21 Mar 2022
Posts: 269
Location: Pennsylvania, USA

PostPosted: Thu Jul 11, 2024 1:48 am    Post subject: Re: Need help setting initramfs to hibernate. Reply with quote

Rockman8 wrote:
Is this OK? Can I hibernate safely and wake up without messing with my system?
NO !

Your script mounts root before attempting to resume. The kernel docs say:
Documentation/power/swsusp.rst wrote:
**BIG FAT WARNING**

If you touch anything on disk between suspend and resume...
...kiss your data goodbye.

If you do resume from initrd after your filesystems are mounted...
...bye bye root partition.

[this is actually same case as above]


You should attempt to resume as soon as you have /dev/vg0/swap.

(Also there is no need for a rescue shell if the resume fails. That's normal after a shutdown instead of a hibernate: there is no hibernation signature. Your script just continues. Now you can mount root and do the switch_root.)

I didn't check deeply. I assume this /init boots correctly with the resume_hibernate commented out ?
Back to top
View user's profile Send private message
Rockman8
n00b
n00b


Joined: 19 Sep 2023
Posts: 36

PostPosted: Thu Jul 11, 2024 5:09 am    Post subject: Reply with quote

Thank you for answering.

Quote:


I didn't check deeply. I assume this /init boots correctly with the resume_hibernate commented out ?



It does although my rescue shell does not allow keyboard input somehow, tried to load usb kernel modules or call mdev to detect keyboard or install modules before mounting devtmpfs but it did not work, after trying for some days and not getting anywhere I moved on and just left it alone.

Also tried to load early some kernel modules by linking the firmware and modules directory into the initramfs after mounting the partitions but that did not work either, so again I left it alone after tweaked the kernel to somewhat how it was working before I got stuck in the boot process. kinda satisfied now but puzzled as to why i could not load the ethernet driver or the amdgpu module, because if the time comes to when i need to load something early I might not be able to do it.

So leaving the modules out it does load the lvm partitions and checks every partition without any issue.

And how about now?

Code:


...

# mounting rootfs on /mnt/root
lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control

lvm lvchange -a ly vg0/root      || rescue_shell
lvm lvchange -a ly vg0/boot      || rescue_shell
lvm lvchange -a ly vg0/usr       || rescue_shell
lvm lvchange -a ly vg0/var       || rescue_shell
lvm lvchange -a ly vg0/var_tmp   || rescue_shell
lvm lvchange -a ly vg0/var_log    || rescue_shell
lvm lvchange -a ly vg0/swap    || rescue_shell

lvm vgscan --mknodes || rescue_shell   # creates /dev/mapper/vg0-root /dev/vg0/root

#resume_hibernate

...



or perhaps like this?
and call it before all the other partitions are mounted maybe right after devtmpfs is mounted?

Code:


resume_hibernate() {

        # set hardcoded default values
        resume="/dev/vg0/swap"

        # parse kernel command line
        for p in $(cat /proc/cmdline); do

                if ["${p}"=resume]; then
                        resume="${p#*=}"
                fi

        done

        # enable resume from hibernate
        if [ -n "${resume}" ]; then

                 lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control
                 lvm lvchange -a ly vg0/swap    || rescue_shell
                 lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control

                # copy the major:minor of the swap block device into /sys/power/resume

                printf '%u:%u\n' $(stat -L -c '0x%t 0x%T' "${resume}") > /sys/power/resume || rescue_shell "Activating resume failed."

        fi

}

Back to top
View user's profile Send private message
pietinger
Moderator
Moderator


Joined: 17 Oct 2006
Posts: 5050
Location: Bavaria

PostPosted: Thu Jul 11, 2024 10:35 am    Post subject: Reply with quote

Rockman8 wrote:
It does although my rescue shell does not allow keyboard input somehow, tried to load usb kernel modules or call mdev to detect keyboard [...]

Maybe try to find the reason for this ... and then you dont need trying to load modules. I see you configure your kernel yourself; that is a big advantage: Enable all for the keyboard as built-in; especially:
Code:
Device Drivers  --->
    Input device support  --->
        [*] Keyboards  --->
            [*] AT keyboard

(See also: https://wiki.gentoo.org/wiki/User:Pietinger/Tutorials/Manual_Configuring_Kernel_Version_6.6 )
_________________
https://wiki.gentoo.org/wiki/User:Pietinger
Back to top
View user's profile Send private message
Hu
Administrator
Administrator


Joined: 06 Mar 2007
Posts: 22598

PostPosted: Thu Jul 11, 2024 2:08 pm    Post subject: Reply with quote

The main value of modules is to defer loading them until they are needed. If you need them so early that the initramfs always loads them, it seems like you are not getting any value from using a module, and are instead going through extra trouble that would be avoided if those features were built in. If it were my system, I would set as =y any kernel features that I always want enabled in every boot. Use modules only for those things that I might reasonably go hours or days without loading.
Back to top
View user's profile Send private message
sublogic
Apprentice
Apprentice


Joined: 21 Mar 2022
Posts: 269
Location: Pennsylvania, USA

PostPosted: Fri Jul 12, 2024 2:34 am    Post subject: Reply with quote

Rockman8 wrote:
And how about now?

Code:


...

# mounting rootfs on /mnt/root
lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control

lvm lvchange -a ly vg0/root      || rescue_shell
lvm lvchange -a ly vg0/boot      || rescue_shell
lvm lvchange -a ly vg0/usr       || rescue_shell
lvm lvchange -a ly vg0/var       || rescue_shell
lvm lvchange -a ly vg0/var_tmp   || rescue_shell
lvm lvchange -a ly vg0/var_log    || rescue_shell
lvm lvchange -a ly vg0/swap    || rescue_shell

lvm vgscan --mknodes || rescue_shell   # creates /dev/mapper/vg0-root /dev/vg0/root

#resume_hibernate

...


Better. Back up your system before you try.

You have a lot of lvm commands. My initramfs runs just these two:
Code:
lvm vgscan
lvm vgchange -ay --sysinit
(Created by genkernel, I confess, I'll write my own clean /init any day now. It's only been three years.)


Quote:
or perhaps like this?
and call it before all the other partitions are mounted maybe right after devtmpfs is mounted?

Code:
resume_hibernate() {

        # set hardcoded default values
        resume="/dev/vg0/swap"

        # parse kernel command line
        for p in $(cat /proc/cmdline); do

                if ["${p}"=resume]; then
                        resume="${p#*=}"
                fi

        done

        # enable resume from hibernate
        if [ -n "${resume}" ]; then

                 lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control
                 lvm lvchange -a ly vg0/swap    || rescue_shell
                 lvm vgscan --mknodes || rescue_shell    # creates /dev/mapper/control

                # copy the major:minor of the swap block device into /sys/power/resume

                printf '%u:%u\n' $(stat -L -c '0x%t 0x%T' "${resume}") > /sys/power/resume || rescue_shell "Activating resume failed."

        fi

}


Personally I prefer the first solution, where it is clear that you attempt to resume as soon as the swap volume is available and before you touch anything else.
(There is something to be said for inline code, within reason; why write a function that is called only once ?)

Second Hu on compiling keyboard/usb drivers built-in. Run lsmod when fully booted to see what's loaded and convert the important ones to =y.
Also if you kernel has CONFIG_DEVTMPFS_MOUNT=y you shouldn't have to mount /dev yourself.
Back to top
View user's profile Send private message
pietinger
Moderator
Moderator


Joined: 17 Oct 2006
Posts: 5050
Location: Bavaria

PostPosted: Fri Jul 12, 2024 9:40 am    Post subject: Reply with quote

sublogic wrote:
Also if you kernel has CONFIG_DEVTMPFS_MOUNT=y you shouldn't have to mount /dev yourself.

Be aware: This is only true IF the kernel mounts the root partition ... :lol:

When using an initramfs, the kernel will not mount the root partition, because it is now the job of the initramfs. This means: This kernel option has no effect when using an initramfs AND you must always have this line in your initramfs (if you have no manual defined devices): mount -t devtmpfs none /dev
_________________
https://wiki.gentoo.org/wiki/User:Pietinger
Back to top
View user's profile Send private message
Rockman8
n00b
n00b


Joined: 19 Sep 2023
Posts: 36

PostPosted: Fri Jul 12, 2024 3:32 pm    Post subject: Reply with quote

Thanks guys for answering!

Quote:


Maybe try to find the reason for this ... and then you dont need trying to load modules. I see you configure your kernel yourself; that is a big advantage: Enable all for the keyboard as built-in; especially:
Code:
Code:
Device Drivers  --->
    Input device support  --->
        [*] Keyboards  --->
            [*] AT keyboard




I did find out while following your wiki that atkb is actually set to built in and that I got ps/2 ports in the back of my motherboard, I don't have the adapter ps/2 to usb on me now, but I'm pretty sure that's where the shell is looking to receive input? And Ironically I only got the atkb set as built in in there but all the others are deactivated.

Ah and one more thing, setting this atkb option will automatically set the serial i/o support.

Maybe that explains why it's expecting a ps/2 input instead of usb one?

Code:
Say Yes here if you have any input device that uses serial I/O to
 communicate with the system. This includes the
 * standard AT keyboard and PS/2 mouse *
 well as serial mice, Sun keyboards, some joysticks and 6dof
 devices and more.

Location:
-> Device Drivers
     -> Input device support
         -> Hardware I/O ports
             -> Serial I/O support (SERIO [=y]) 
Selected by [y]:
KEYBOARD_ATKBD [=y] && INPUT [=y] && INPUT_KEYBOARD [=y]





Quote:


The main value of modules is to defer loading them until they are needed. If you need them so early that the initramfs always loads them, it seems like you are not getting any value from using a module, and are instead going through extra trouble that would be avoided if those features were built in. If it were my system, I would set as =y any kernel features that I always want enabled in every boot. Use modules only for those things that I might reasonably go hours or days without loading.



I wanted to keep the amdgpu and ethernet driver as modules to make updates easier or any case I need to kill video, ethernet or sound without rebooting? But I don't think any of these reasons make any sense anymore, is there really a reason that I should be compiling any module as not built in besides for testing puposes?

Ah and yes if keep something this much time just hanging around without loading I just might forget completely about them and maybe even not using at all? Just found a few modules compiled that I found out that were never used but were there just in case and only remebered because I stumbled upon them when I was tweaking the kernel. So I might just leave them off perhaps and compile as module when I really need them?

Quote:
Better. Back up your system before you try.

You have a lot of lvm commands. My initramfs runs just these two:
Code:
Code:
lvm vgscan
lvm vgchange -ay --sysinit

(Created by genkernel, I confess, I'll write my own clean /init any day now. It's only been three years.)


I think that I must activated 1 by 1 just in case need any of them deactivated and also be aware of their presence I think that's why went for lvchange instead of vgchange

It might take a while to properly back up my system, I'm thinking of setting up a second system perhaps another gentoo, maybe a lighter one to run on 250gb external drive to run fsarchiver when this one is offline.

By the way I'm following pietinger wiki and I'm considering really go monolithic just seems to be easier and maybe even put initramfs inside it, been running gen_initramfs.sh so much that I don't mind running it again and compiling kernel all together and the grub file will be close to its default setting, although I'll just comment the line and leave there for reference
Back to top
View user's profile Send private message
sublogic
Apprentice
Apprentice


Joined: 21 Mar 2022
Posts: 269
Location: Pennsylvania, USA

PostPosted: Fri Jul 12, 2024 9:50 pm    Post subject: Reply with quote

pietinger wrote:
sublogic wrote:
Also if you kernel has CONFIG_DEVTMPFS_MOUNT=y you shouldn't have to mount /dev yourself.

Be aware: This is only true IF the kernel mounts the root partition ... :lol:

When using an initramfs, the kernel will not mount the root partition, because it is now the job of the initramfs. This means: This kernel option has no effect when using an initramfs AND you must always have this line in your initramfs (if you have no manual defined devices): mount -t devtmpfs none /dev
Thank you. Another gentoo learning experience, done the easy way :wink:
Back to top
View user's profile Send private message
sublogic
Apprentice
Apprentice


Joined: 21 Mar 2022
Posts: 269
Location: Pennsylvania, USA

PostPosted: Fri Jul 12, 2024 9:58 pm    Post subject: Reply with quote

Rockman8 wrote:
is there really a reason that I should be compiling any module as not built in besides for testing puposes?

Not having to maintain a in-kernel firmware list; unloading and reloading buggy drivers (I had to do that with my previous wireless card). If your built-in drivers can mount the root and finish booting, you have enough.
Back to top
View user's profile Send private message
Rockman8
n00b
n00b


Joined: 19 Sep 2023
Posts: 36

PostPosted: Thu Jul 18, 2024 3:56 am    Post subject: Reply with quote

Quote:

Not having to maintain a in-kernel firmware list; unloading and reloading buggy drivers (I had to do that with my previous wireless card). If your built-in drivers can mount the root and finish booting, you have enough.


Luckily, mine is just some dated desktop, I guess there's a lot well tested drivers for me, got no issues that i know of so far.
]
Although I didn't try to hibernate yet I did follow pietinger's guide and spent some time trying to make it work with current configuration, I tried to go monolithic but turns out I do have some itens that I'm not sure if should have then built in or as module, so I ended up following hu's advice, at very least the number of modules went down by a great amount. Maybe even sped up my boot time.

Now I'll have to set up the back up machine before I try to pull this up.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Kernel & Hardware All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum