diff --git a/debian/changelog b/debian/changelog index 433d4798..6ee9a917 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,10 @@ livecd-rootfs (23.10.8) UNRELEASED; urgency=medium for the StarFive VisionFive 2 board. As it is larger than U-Boot we need to increase the size of the loader 2 partition to accommodate it. + [ Michael Hudson-Doyle ] + * lb_chroot_layered: use rsync to make more minimal overlay layers. + (LP: #2028213) + -- Michael Hudson-Doyle Wed, 02 Aug 2023 13:12:09 +1200 livecd-rootfs (23.10.7) mantic; urgency=medium diff --git a/live-build/lb_chroot_layered b/live-build/lb_chroot_layered index 6529ef2e..d3173755 100755 --- a/live-build/lb_chroot_layered +++ b/live-build/lb_chroot_layered @@ -107,57 +107,6 @@ lb_chroot_includes () { cd "${OLDPWD}" } -reduce_pass_size () { - # Remove duplicated files between parent and current pass - # Note the empty directories created in a child pass are not removed - local pass=$1 - local parent="$(get_parent_pass $pass)" - - $(is_root_layer $pass) && return - - pass_dir="overlay.${pass}" - parent_pass_dir="overlay.${parent}" - - local list_pass=$(mktemp) - local list_parent=$(mktemp) - - (cd $pass_dir && find . ! -type d -printf "%h/%f|%s|%y|%U|%G|%m\n"|sort > $list_pass) - (cd $parent_pass_dir && find . ! -type d -printf "%h/%f|%s|%y|%U|%G|%m\n"|sort > $list_parent) - - # Only iterate on common files with same type, owner, permission and size - comm -12 $list_pass $list_parent|cut -d'|' -f1|while read f; do - # If file contents are different, keep it - if ! diff --brief --no-dereference "$pass_dir/$f" "$parent_pass_dir/$f" >/dev/null; then - continue - fi - p="$(dirname "$f")" - while [ "$p" != . ]; do - # As explained in the overlayfs documentation - # https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#whiteouts-and-opaque-directories - # an xattr of trusted.overlay.opaque indicates an 'opaque' directory - # that was deleted from the overlay. Removing files from within the - # directory, even if identical with one in the lower layer, will result - # in it going missing from the combined filesystem. - # - # It would be possible to be more clever, e.g. if the two directories - # are still similar, we could the delete the attribute and convert any - # still-needed deletions to whiteouts but it doesn't seem worth it in - # the cases seen so far. - if [ -n "$(getfattr -n trusted.overlay.opaque -h --only-values -- "$pass_dir/$p" 2>/dev/null)" ]; then - Echo_message "reduce_pass_size: '%s' would be removed from overlay but for trusted.overlay.opaque on '%s'" "$f" "$p" - continue 2 - fi - p="$(dirname "$p")" - done - # Files are strictly identical between the 2 passes (only mod or access times differs). No need for unused delta. - Echo_message "reduce_pass_size: '%s' is strictly identical between %s and %s. Removing." "$f" "$pass" "$parent" - rm "$pass_dir/$f" - done - - rm $list_pass - rm $list_parent -} - create_chroot_pass () { local pass=$1 shift 1 # restore ${*} @@ -182,8 +131,8 @@ create_chroot_pass () { mkdir -p "$overlay_dir/" lowerdirs=$(get_lowerdirs_for_pass $pass) if [ -n "$lowerdirs" ]; then - mkdir -p chroot/ - mount_overlay "$lowerdirs" "$overlay_dir" chroot/ + mkdir -p chroot "${overlay_dir}-initial" + mount_overlay "$lowerdirs" "${overlay_dir}-initial" chroot/ else ln -s "$overlay_dir/" chroot fi @@ -319,13 +268,22 @@ create_chroot_pass () { lb chroot_devpts remove ${*} if [ -n "$lowerdirs" ]; then - umount chroot - rmdir chroot + # Although the current chroot was created as an overlay over + # the previous layer, many operations can result in redundant + # files in the upperdir. Rather than trying to minimize the + # overlay by hand, we rsync the chroot into a fresh overlay, + # rely on rsyncs ability to avoid redundant file operations, + # and take _that_ overlay's upperdir as the content of the + # layer. + mkdir chroot-2 + mount_overlay "$lowerdirs" "$overlay_dir" chroot-2/ + rsync -aXHAS --del chroot/ chroot-2/ + umount chroot chroot-2 + rmdir chroot chroot-2 + rm -rf ${overlay_dir}-initial else rm chroot fi - - reduce_pass_size $pass } if [ ! -d chroot.bootstrap/ ]; then