From: Aaron LI Date: Fri, 30 Mar 2018 06:32:59 +0000 (+0800) Subject: mkinitrd(8): determine the initrd size from the contents size X-Git-Tag: v5.5.0~888 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/eeb035f875d0cb79c54938cc9ae8858344059cd1 mkinitrd(8): determine the initrd size from the contents size * Calculate the contents size to determine the required initrd size. The used initrd size is determined from the total contents size, rounded up to align with 1 MiB, added additional 1 MiB. The calculated initrd size is 12 MiB at the moment, so we have 3 MiB more usable memory now (compared to the fixed 15 MiB before). * Add options "-s" to specify the required initrd size as before. But a check against the above determined required initrd size is performance to avoid the out-of-space error, resulting in a broken initrd image. * Add option "-S" to constrain the allowed maximum initrd size, because a too big initrd image will also lead to boot failure, due to the boot loader limitation. * Some minor cleanups and improvements, better error handle and messages. * Update the mkinitrd.conf and man page accordingly. Reviewed-by: zrj --- diff --git a/etc/defaults/mkinitrd.conf b/etc/defaults/mkinitrd.conf index aa66f16292..ae3ac1e74f 100644 --- a/etc/defaults/mkinitrd.conf +++ b/etc/defaults/mkinitrd.conf @@ -2,6 +2,6 @@ # BOOT_DIR="/boot" CONTENT_DIRS="/usr/share/initrd" -INITRD_DIRS="bin boot dev etc mnt proc root sbin tmp var var/empty var/db new_root" -INITRD_SIZE="15m" +INITRD_DIRS="bin dev etc sbin tmp var new_root" +INITRD_SIZE_MAX="15" # [MiB] TMP_DIR="/tmp" diff --git a/sbin/mkinitrd/mkinitrd.8 b/sbin/mkinitrd/mkinitrd.8 index 028220a48f..eb28a48780 100644 --- a/sbin/mkinitrd/mkinitrd.8 +++ b/sbin/mkinitrd/mkinitrd.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2010 The DragonFly Project. All rights reserved. +.\" Copyright (c) 2010,2018 The DragonFly Project. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -28,7 +28,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 3, 2015 +.Dd March 30, 2018 .Dt MKINITRD 8 .Os .Sh NAME @@ -39,24 +39,53 @@ .Op Fl b Ar bootdir .Op Fl c Ar contentsdir .Op Fl t Ar tmpdir +.Op Fl s Ar size +.Op Fl S Ar max_size .Sh DESCRIPTION The .Nm script builds a ramdisk (md) image based on the UFS filesystem containing only the most basic tools, such as a minimal .Xr init 8 , -.Xr sh 1 -as well as many +.Xr sh 1 , +various .Xr mount 8 -utilities. +utilities, +.Xr lvm 8 , +.Xr cryptsetup 8 , +.Xr tcplay 8 , +as well as some basic networking tools. +And the ramdisk is required to help mount the encrypted root partition. .Pp -It will also copy the contents of +The contents of .Pa /usr/share/initrd -onto the ramdisk, maintaining the same hierarchy. +will be copied onto the ramdisk, maintaining the same hierarchy. This directory can be changed with the .Fl c option. .Pp +By default +.Nm +will calculate the contents size and create a ramdisk just big enough. +The +.Fl s +option accepting an integer (number of MiB) can specify the required +size of the ramdisk. +The special value of +.Pa 0 +can be given to ignore the +.Pa INITRD_SIZE +setting from the configuration file as described below. +The +.Fl S +option also accepts an integer (number of MiB) and constrains the maximum +allowed size of the ramdisk. +Specifying a value of +.Pa 0 +will ignore the +.Pa INITRD_SIZE_MAX +setting from the configuration file. +.Pp On completion, the final image will be copied to .Pa /boot/kernel/initrd.img.gz , ready to be used as an early userland. @@ -82,7 +111,7 @@ following variables (defaults are in .Pa /etc/defaults/mkinitrd.conf ) : .Bd -literal -offset indent BUILD_DIR -INITRD_SIZE +INITRD_SIZE_MAX INITRD_DIRS CONTENT_DIRS .Ed @@ -144,6 +173,9 @@ vfs.root.realroot="local:ufs:/dev/vg00/lv0[:OPTIONS]" .Bd -literal -offset indent vfs.root.realroot="crypt:ufs:/dev/ad0s0a:secvolume[:OPTIONS]" .Ed +.Bd -literal -offset indent +vfs.root.realroot="crypt:hammer2:serno/XXXXXX.s1d:root[:OPTIONS]" +.Ed .Sh SEE ALSO .Xr md 4 , .Xr loader.conf 5 diff --git a/sbin/mkinitrd/mkinitrd.sh b/sbin/mkinitrd/mkinitrd.sh index 38bc723087..714573fd3d 100644 --- a/sbin/mkinitrd/mkinitrd.sh +++ b/sbin/mkinitrd/mkinitrd.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2010 +# Copyright (c) 2010,2018 # The DragonFly Project. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,26 +40,59 @@ fi VN_DEV="" +# Calculate the total size of the given directory, taking care of the +# hard links. +calc_size() +{ + find "$1" -ls | \ + awk '{ print $7,$1 }' | \ + sort -n -k 2 | \ + uniq -f 1 | \ + awk '{ sum+=$1 } END { print sum }' # [byte] +} + +calc_initrd_size() +{ + echo "Contents directories:" >&2 + isize=0 + for dir in ${CONTENT_DIRS}; do + csize=$(calc_size ${dir}) + echo "* ${dir}: ${csize} bytes" >&2 + isize=$((${isize} + ${csize})) + done + # Round initrd size up by MiB + isize_mb=$(echo "${isize}" | awk ' + function ceil(x) { + y = int(x); + return (x>y ? y+1 : y); + } + { + mb = $1/1024/1024; + print ceil(mb); + }') + # Add additional 1 MiB + echo $((${isize_mb} + 1)) +} + create_vn() { - if [ ! -d $BUILD_DIR ]; then + if [ ! -d "$BUILD_DIR" ]; then mkdir -p $BUILD_DIR echo "Created build directory $BUILD_DIR" fi - vnconfig -c -S ${INITRD_SIZE} -Z -T vn ${TMP_DIR}/initrd.img \ - > ${TMP_DIR}/vndev.mkinitrd - if [ $? -ne 0 ]; then - echo "Failed to configure vn device" - exit 1 - fi + vnconfig -c -S ${INITRD_SIZE}m -Z -T vn ${TMP_DIR}/initrd.img \ + > ${TMP_DIR}/vndev.mkinitrd || { + echo "Failed to configure vn device" + exit 1 + } VN_DEV=`cat ${TMP_DIR}/vndev.mkinitrd | cut -f 2 -d ' '` - [ -f ${TMP_DIR}/vndev.mkinitrd ] && rm ${TMP_DIR}/vndev.mkinitrd + rm ${TMP_DIR}/vndev.mkinitrd echo "Configured $VN_DEV" newfs -i 131072 -m 0 /dev/${VN_DEV}s0 echo "Formatted initrd image with UFS" - mount /dev/${VN_DEV}s0 $BUILD_DIR + mount -t ufs /dev/${VN_DEV}s0 $BUILD_DIR echo "Mounted initrd image on ${BUILD_DIR}" } @@ -83,24 +116,27 @@ make_hier() copy_content() { for dir in ${CONTENT_DIRS}; do - cpdup ${dir}/ ${BUILD_DIR}/ + cpdup -o -u ${dir}/ ${BUILD_DIR}/ || { + echo "Failed to copy ${dir} to ${BUILD_DIR}" + exit 1 + } done } print_info() { lt ${BUILD_DIR} - df -h | head -n 1 - df -h | grep $VN_DEV + df -h ${BUILD_DIR} } usage() { - echo "usage: $0 [-b bootdir] [-c contentsdir] [-t tmpdir]" + echo "usage: ${0##*/} [-b bootdir] [-c contentsdir] [-t tmpdir]" \ + "[-s size] [-S max_size]" exit 2 } -args=`getopt b:c:t: $*` +args=`getopt b:c:s:S:t: $*` test $? -ne 0 && usage set -- $args @@ -108,20 +144,47 @@ for i; do case "$i" in -b) BOOT_DIR="$2"; shift; shift;; -c) CONTENT_DIR="$2"; shift; shift;; + -s) INITRD_SIZE="$2"; shift; shift;; + -S) INITRD_SIZE_MAX="$2"; shift; shift;; -t) TMP_DIR="$2"; shift; shift;; --) shift; break; esac done -test ! -d ${BOOT_DIR} && usage +test ! -d ${BOOT_DIR} && usage test ! -d ${CONTENT_DIR} && usage -test ! -d ${TMP_DIR} && usage -test ! -z $1 && usage +test ! -d ${TMP_DIR} && usage +test ! -z "$1" && usage + BUILD_DIR="${TMP_DIR}/initrd" +INITRD_SIZE=${INITRD_SIZE%[mM]} # [MiB] +INITRD_SIZE_MAX=${INITRD_SIZE_MAX%[mM]} # [MiB] + +CSIZE=$(calc_initrd_size) +echo "Required initrd image size: ${CSIZE} MiB" +if [ -n "${INITRD_SIZE}" -a "${INITRD_SIZE}" != "0" ]; then + if [ ${CSIZE} -gt ${INITRD_SIZE} ]; then + echo "Specified initrd size (${INITRD_SIZE} MiB) too small" + exit 1 + fi +else + INITRD_SIZE=${CSIZE} +fi +echo "Initrd size: ${INITRD_SIZE} MiB" + +if [ -n "${INITRD_SIZE_MAX}" -a "${INITRD_SIZE_MAX}" != "0" ] && \ + [ ${INITRD_SIZE} -gt ${INITRD_SIZE_MAX} ]; then + echo "Exceeded the specified maximum size (${INITRD_SIZE_MAX} MiB)" + exit 1 +fi create_vn copy_content make_hier print_info destroy_vn -/usr/bin/gzip -9 ${TMP_DIR}/initrd.img +echo -n "Compressing ${TMP_DIR}/initrd.img ..." +gzip -9 ${TMP_DIR}/initrd.img +echo " OK" +echo -n "Copying ${TMP_DIR}/initrd.img.gz to ${BOOT_DIR}/kernel/initrd.img.gz ..." mv ${TMP_DIR}/initrd.img.gz ${BOOT_DIR}/kernel/initrd.img.gz +echo " OK"