Module Name: src Committed By: christos Date: Tue Jan 15 21:04:41 UTC 2013
Modified Files: src/distrib/utils/embedded: mkimage Log Message: Make autosizing really work: - Use newfs to compute the actual filesystem required size. - Fix the computation of set sizes to account for blocks and fragments. This results into a 95% full filesystem for my test (Total 566MB, 24MB free) from which 8MB is my requested overhead. Not perfect, but good enough. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/distrib/utils/embedded/mkimage Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/utils/embedded/mkimage diff -u src/distrib/utils/embedded/mkimage:1.10 src/distrib/utils/embedded/mkimage:1.11 --- src/distrib/utils/embedded/mkimage:1.10 Mon Jan 14 22:26:27 2013 +++ src/distrib/utils/embedded/mkimage Tue Jan 15 16:04:41 2013 @@ -1,6 +1,6 @@ #! /bin/sh -# $NetBSD: mkimage,v 1.10 2013/01/15 03:26:27 christos Exp $ +# $NetBSD: mkimage,v 1.11 2013/01/15 21:04:41 christos Exp $ # Copyright (c) 2012 Alistair Crooks <a...@netbsd.org> # All rights reserved. @@ -69,6 +69,8 @@ next_avail () } # find the size of the gzipped files in a .tgz archive +# Directories appear as 0, so count them as one block +# and round up files to a fragment. sizeone() { if [ ! -f "$1" ] then @@ -77,11 +79,18 @@ sizeone() { return; fi case "$1" in - *.tgz|*.tar.gz) - tar tvzf "$1" | awk '{ tot += $5 } END { print tot }' - ;; - *.tbz|*.tar.bz2) - tar tvjf "$1" | awk '{ tot += $5 } END { print tot }' + *.tgz|*.tar.gz|*.tbz|*.tar.bz2|*.txz|*.tar.xz) + tar tvzf "$1" | + awk -v fsize=${fsize} -v bsize=${bsize} ' + { + if ($5 == 0) + tot += bsize; + else + tot += ((int)(($5 + fsize - 1) / fsize)) * fsize; + } + END { + printf("%d\n", tot); + }' ;; *) echo 0 @@ -96,12 +105,70 @@ EOF exit 1 } +# Return the usable filesystem size in bytes, given the total size in bytes, +# and optionally block and fragment sizes +getffssize() { + local bytes="$1" + local barg + local farg + local overhead + + if [ -n "$2" ] + then + barg="-b $2" + if [ -n "$3" ] + then + farg="-f $3" + fi + fi + + overhead=$(newfs -N ${farg} ${barg} -s "${bytes}b" -F /dev/null | + awk '/using/ { + printf("%d\n", substr($6, 1, length($6) - 3) * 1024 * 1024); + }' + ) + echo $(( ${bytes} - ${overhead} )) +} + +# Compute the size of an ffs filesystem that can fit x bytes. +# Instead of duplicating the newfs calculations here we let +# it do the job, using binary search. +makeffssize() { + local bytes=$1 + local bsize=$2 + local fsize=$3 + local max=$(( 2 * ${bytes} )) + local min="${bytes}" + local cur + local res + while true; do + cur="$(( ( ${max} + ${min} ) / 2 ))" + res="$(getffssize "${cur}" ${bsize} ${fsize})" +# echo ${min} ${cur} ${max} ${res} ${bytes} 1>&2 + if [ "${res}" -eq "${bytes}" ] + then + break + elif [ "$(( ${min} + 1 ))" -ge "${max}" ] + then + break + elif [ "${res}" -lt "${bytes}" ] + then + min="${cur}" + elif [ "${res}" -gt "${bytes}" ] + then + max="${cur}" + fi + done + echo "${cur}" +} + finish() { cleanup ${sudo} umount ${mnt} ${sudo} vnconfig -u ${vnddev} } + DIR="$(dirname "$0")" PROG="$(basename "$0")" bar="===" @@ -110,6 +177,11 @@ mnt="${TMPDIR:-/tmp}/image.$$" src="/usr/src" obj="/usr/obj" + +# Presumable block and fragment size. +bsize=16384 +fsize=2048 + # First pass for options to get the host OPTS="S:c:h:s:x" while getopts "$OPTS" f @@ -155,17 +227,35 @@ if [ -n "$1" ]; then shift fi -total=0 +# calculate the set bytes +setbytes=0 +echo -n "${bar} computing set sizes (" for s in ${sets}; do one="$(sizeone ${setsdir}/${s}.tgz)" - total=$(( ${total} + ${one} )) + echo -n " $s=$(( ${one} / 1024 / 1024 ))MB" + setbytes=$(( ${setbytes} + ${one} )) done +echo "): $(( ${setbytes} / 1024 / 1024 ))MB ${bar}" + # calculate size of custom files -custsize=0 +custbytes=0 if [ -d "${custom}" ]; then - custsize=$(ls -lR "${custom}" | awk 'NF == 9 { tot += $5 } END { print tot }') + custbytes=$(ls -lR "${custom}" | + awk 'NF == 9 { tot += $5 } END { print tot }') fi -total=$(( ( ( ${total} + ${custsize} ) / 1000000 ) + ${overhead} )) +echo "${bar} computing custom sizes: $(( ${custbytes} / 1024 / 1024 ))MB ${bar}" + +# how many bytes +rawbytes="$(( ${setbytes} + ${custbytes} ))" +echo -n "${bar} computing ffs filesystem size for $(( ${rawbytes} / 1024 / 1024 ))MB: " +ffsbytes="$(makeffssize "${rawbytes}")" +ffsmb=$(( ${ffsbytes} / 1024 / 1024 )) +echo " ${ffsmb}MB ${bar}" + +# total in MB +total=$(( ${ffsmb} + ${overhead} )) +echo "${bar} overhead: ${overhead}MB ${bar}" + if [ $size -eq 0 ]; then # auto-size the pkgs fs newsize=${total}