summaryrefslogtreecommitdiffstats
path: root/modules.d/99fs-lib
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/99fs-lib')
-rwxr-xr-xmodules.d/99fs-lib/fs-lib.sh262
-rwxr-xr-xmodules.d/99fs-lib/module-setup.sh89
2 files changed, 351 insertions, 0 deletions
diff --git a/modules.d/99fs-lib/fs-lib.sh b/modules.d/99fs-lib/fs-lib.sh
new file mode 100755
index 0000000..c4640fa
--- /dev/null
+++ b/modules.d/99fs-lib/fs-lib.sh
@@ -0,0 +1,262 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+fsck_ask_reboot() {
+ info "note - fsck suggests reboot, if you"
+ info "leave shell, booting will continue normally"
+ emergency_shell -n "(reboot ?)"
+}
+
+fsck_ask_err() {
+ warn "*** An error occurred during the file system check."
+ warn "*** Dropping you to a shell; the system will try"
+ warn "*** to mount the filesystem(s), when you leave the shell."
+ emergency_shell -n "(Repair filesystem)"
+}
+
+# inherits: _ret _drv _out
+fsck_tail() {
+ [ "$_ret" -gt 0 ] && warn "$_drv returned with $_ret"
+ if [ "$_ret" -ge 4 ]; then
+ [ -n "$_out" ] && echo "$_out" | vwarn
+ fsck_ask_err
+ else
+ [ -n "$_out" ] && echo "$_out" | vinfo
+ [ "$_ret" -ge 2 ] && fsck_ask_reboot
+ fi
+}
+
+# note: this function sets _drv of the caller
+fsck_able() {
+ case "$1" in
+ xfs)
+ # {
+ # type xfs_db &&
+ # type xfs_repair &&
+ # type xfs_check &&
+ # type mount &&
+ # type umount
+ # } >/dev/null 2>&1 &&
+ # _drv="_drv=none fsck_drv_xfs" &&
+ # return 0
+ return 1
+ ;;
+ ext?)
+ type e2fsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_com e2fsck" \
+ && return 0
+ ;;
+ f2fs)
+ type fsck.f2fs > /dev/null 2>&1 \
+ && _drv="fsck_drv_com fsck.f2fs" \
+ && return 0
+ ;;
+ jfs)
+ type jfs_fsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_com jfs_fsck" \
+ && return 0
+ ;;
+ reiserfs)
+ type reiserfsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_com reiserfsck" \
+ && return 0
+ ;;
+ btrfs)
+ # type btrfsck >/dev/null 2>&1 &&
+ # _drv="_drv=none fsck_drv_btrfs" &&
+ # return 0
+ return 1
+ ;;
+ nfs*)
+ # nfs can be a nop, returning success
+ _drv=":" \
+ && return 0
+ ;;
+ *)
+ type fsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_std fsck" \
+ && return 0
+ ;;
+ esac
+
+ return 1
+}
+
+# note: all drivers inherit: _drv _fop _dev
+
+fsck_drv_xfs() {
+ # xfs fsck is not necessary... Either it mounts or not
+ return 0
+}
+
+fsck_drv_btrfs() {
+ # btrfs fsck is not necessary... Either it mounts or not
+ return 0
+}
+
+# common code for checkers that follow usual subset of options and return codes
+fsck_drv_com() {
+ local _drv="$1"
+ local _ret
+ local _out
+
+ if ! strglobin "$_fop" "-[ynap]"; then
+ _fop="-a${_fop:+ "$_fop"}"
+ fi
+
+ info "issuing $_drv $_fop $_dev"
+ # we enforce non-interactive run, so $() is fine
+ # shellcheck disable=SC2086
+ _out=$($_drv $_fop "$_dev")
+ _ret=$?
+ fsck_tail
+
+ return $_ret
+}
+
+# code for generic fsck, if the filesystem checked is "unknown" to us
+fsck_drv_std() {
+ local _ret
+ local _out
+ unset _out
+
+ info "issuing fsck $_fop $_dev"
+ # note, we don't enforce -a here, thus fsck is being run (in theory)
+ # interactively; otherwise some tool might complain about lack of terminal
+ # (and using -a might not be safe)
+ # shellcheck disable=SC2086
+ fsck $_fop "$_dev" > /dev/console 2>&1
+ _ret=$?
+ fsck_tail
+
+ return $_ret
+}
+
+# checks single filesystem, relying on specific "driver"; we don't rely on
+# automatic checking based on fstab, so empty one is passed;
+# takes 4 arguments - device, filesystem, filesystem options, additional fsck options;
+# first 2 arguments are mandatory (fs may be auto or "")
+# returns 255 if filesystem wasn't checked at all (e.g. due to lack of
+# necessary tools or insufficient options)
+fsck_single() {
+ local FSTAB_FILE=/etc/fstab.empty
+ local _dev="$1"
+ local _fs="${2:-auto}"
+ local _fop="$4"
+ local _drv
+
+ [ $# -lt 2 ] && return 255
+ _dev=$(readlink -f "$(label_uuid_to_dev "$_dev")")
+ [ -e "$_dev" ] || return 255
+ _fs=$(det_fs "$_dev" "$_fs")
+ fsck_able "$_fs" || return 255
+
+ info "Checking $_fs: $_dev"
+ export FSTAB_FILE
+ eval "$_drv"
+ return $?
+}
+
+# takes list of filesystems to check in parallel; we don't rely on automatic
+# checking based on fstab, so empty one is passed
+fsck_batch() {
+ local FSTAB_FILE=/etc/fstab.empty
+ local _drv=fsck
+ local _dev
+ local _ret
+ local _out
+
+ [ $# -eq 0 ] || ! type fsck > /dev/null 2>&1 && return 255
+
+ info "Checking filesystems (fsck -M -T -a):"
+ for _dev in "$@"; do
+ info " $_dev"
+ done
+
+ export FSTAB_FILE
+ _out="$(fsck -M -T "$@" -- -a)"
+ _ret=$?
+
+ fsck_tail
+
+ return $_ret
+}
+
+# verify supplied filesystem type:
+# if user provided the fs and we couldn't find it, assume user is right
+# if we found the fs, assume we're right
+det_fs() {
+ local _dev="$1"
+ local _orig="${2:-auto}"
+ local _fs
+
+ _fs=$(udevadm info --query=property --name="$_dev" \
+ | while read -r line || [ -n "$line" ]; do
+ if str_starts "$line" "ID_FS_TYPE="; then
+ echo "${line#ID_FS_TYPE=}"
+ break
+ fi
+ done)
+ _fs=${_fs:-auto}
+
+ if [ "$_fs" = "auto" ]; then
+ _fs="$_orig"
+ fi
+ echo "$_fs"
+}
+
+write_fs_tab() {
+ local _o
+ local _rw
+ local _root
+ local _rootfstype
+ local _rootflags
+ local _fspassno
+
+ _fspassno="0"
+ _root="$1"
+ _rootfstype="$2"
+ _rootflags="$3"
+ [ -z "$_rootfstype" ] && _rootfstype=$(getarg rootfstype=)
+ [ -z "$_rootflags" ] && _rootflags=$(getarg rootflags=)
+
+ [ -z "$_rootfstype" ] && _rootfstype="auto"
+
+ if [ -z "$_rootflags" ]; then
+ _rootflags="ro,x-initrd.mount"
+ else
+ _rootflags="ro,$_rootflags,x-initrd.mount"
+ fi
+
+ _rw=0
+
+ CMDLINE=$(getcmdline)
+ for _o in $CMDLINE; do
+ case $_o in
+ rw)
+ _rw=1
+ ;;
+ ro)
+ _rw=0
+ ;;
+ esac
+ done
+ if [ "$_rw" = "1" ]; then
+ _rootflags="$_rootflags,rw"
+ if ! getargbool 0 rd.skipfsck; then
+ _fspassno="1"
+ fi
+ fi
+
+ if grep -q "$_root /sysroot" /etc/fstab; then
+ echo "$_root /sysroot $_rootfstype $_rootflags $_fspassno 0" >> /etc/fstab
+ else
+ return
+ fi
+
+ if type systemctl > /dev/null 2> /dev/null; then
+ systemctl daemon-reload
+ systemctl --no-block start initrd-root-fs.target
+ fi
+}
diff --git a/modules.d/99fs-lib/module-setup.sh b/modules.d/99fs-lib/module-setup.sh
new file mode 100755
index 0000000..2b81b0c
--- /dev/null
+++ b/modules.d/99fs-lib/module-setup.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+echo_fs_helper() {
+ local fs=$2
+ case "$fs" in
+ xfs)
+ echo -n " xfs_db xfs_repair xfs_check xfs_metadump "
+ ;;
+ ext?)
+ echo -n " e2fsck "
+ ;;
+ jfs)
+ echo -n " jfs_fsck "
+ ;;
+ reiserfs)
+ echo -n " reiserfsck "
+ ;;
+ btrfs)
+ echo -n " btrfsck "
+ ;;
+ esac
+
+ echo -n " fsck.$fs "
+ return 0
+}
+
+include_fs_helper_modules() {
+ local fs=$2
+ case "$fs" in
+ xfs | btrfs | ext4 | ext3)
+ instmods crc32c
+ ;;
+ f2fs)
+ instmods crc32
+ ;;
+ esac
+}
+
+# called by dracut
+installkernel() {
+ # xfs/btrfs/ext4 need crc32c, f2fs needs crc32
+ if [[ $hostonly ]]; then
+ for_each_host_dev_fs include_fs_helper_modules
+ :
+ else
+ instmods crc32c crc32
+ fi
+}
+
+# called by dracut
+install() {
+ local _helpers
+
+ inst "$moddir/fs-lib.sh" "/lib/fs-lib.sh"
+ : > "${initdir}"/etc/fstab.empty
+
+ [[ $nofscks == "yes" ]] && return
+
+ if [[ $fscks == "${fscks#*[^ ]*}" ]]; then
+ _helpers=(
+ /sbin/fsck* /usr/sbin/fsck*
+ xfs_db xfs_check xfs_repair xfs_metadump
+ e2fsck jfs_fsck reiserfsck btrfsck
+ )
+ if [[ $hostonly ]]; then
+ read -r -a _helpers < <(for_each_host_dev_fs echo_fs_helper)
+ fi
+ else
+ read -r -a _helpers <<< "$fscks"
+ fi
+
+ _helpers+=(umount mount)
+
+ if [[ ${_helpers[*]} == *e2fsck* ]] && [[ -e $dracutsysrootdir/etc/e2fsck.conf ]]; then
+ inst_simple /etc/e2fsck.conf
+ fi
+
+ inst_multiple -o "${_helpers[@]}" fsck
+}