(please cc me, I'm not subscribed) Hi,
On 07/05/2015 13:44, intrigeri wrote: > > May you please also provide a patch that applies on top of bilibop > 0.4.23? I need to build a Tails/Jessie ISO with a newer kernel (that > only supports overlayfs). 'git diff debian/0.4.23..451b58ad17c4ea4a lib/bilibop/common.sh' builds the attached patch. >> Unfortunately, bilibop-lockfs needs more work and tests, and is not >> ready for a new release. This means that there will not be a new bilibop >> package in debian repositories in the next (two) weeks. > > Any news on this front? Things work pretty good, and will probably be packaged next week. Cheers, quidame
diff --git a/lib/bilibop/common.sh b/lib/bilibop/common.sh index 1fbf549..18c1156 100644 --- a/lib/bilibop/common.sh +++ b/lib/bilibop/common.sh @@ -1,6 +1,6 @@ # /lib/bilibop/common.sh # -# Copyright (C) 2011-2014, Yann Amar <[email protected]> +# Copyright (C) 2011-2015, Yann Amar <[email protected]> # License GPL-3.0+ # # This program is free software: you can redistribute it and/or modify @@ -31,8 +31,9 @@ # and others), and then are replaced by grep and sed heuristics. #> We assume, even if it is not often, that /etc/udev/udev.conf can have been # modified and that 'udev_root' can be something else than '/dev'. -#> dm-crypt/LUKS, LVM, loopback and aufs root filesystems (and combinations -# of them) are now fully supported. +#> dm-crypt/LUKS, LVM, loopback, and aufs root filesystems (and combinations +# of them) are now fully supported. Btrfs and overlay filesystems are also +# partially supported (not fully tested). #> Functions that just output informations about devices/filesystems can be # called by any unprivileged user. @@ -211,56 +212,62 @@ EOF ### Here is the main function's dependency tree {{{ # # physical_hard_disk -# | # |__underlying_partition -# | # |__underlying_device -# | | # | |__underlying_device_from_device -# | | | # | | |__underlying_device_from_dm # | | |__underlying_device_from_loop -# | | | # | | |__backing_file_from_loop # | | |__device_id_of_file -# | | |__device_node_from_major_minor +# | | |__underlying_device_from_file __ see below +# | | |__device_node_from_major_minor vvvvvvvvv # | | -# | |__underlying_device_from_file +# | |__underlying_device_from_file _<<_<<_<<_ possible loop entry point +# | |__device_id_of_file | +# | |__find_mountpoint | +# | |__is_aufs_mountpoint | +# | | |__canonical | +# | | | +# | |__underlying_device_from_aufs | +# | | |__aufs_readonly_branch | +# | | | |__aufs_dirs_if_brs0 | +# | | | | |__is_aufs_mountpoint | +# | | | | |__canonical | +# | | | | | +# | | | |__aufs_si_directory | +# | | | |__is_aufs_mountpoint | +# | | | |__canonical | +# | | | | +# | | |__device_id_of_file | +# | | |__underlying_device_from_file _>>_| possible loop entry point +# | | |__device_node_from_major_minor | +# | | | +# | |__is_overlay_mountpoint | +# | | |__canonical | +# | | | +# | |__underlying_device_from_overlayfs | +# | | |__overlay_lowerdir | +# | | | |__is_overlay_mountpoint | +# | | | | |__canonical | +# | | | | | +# | | | |__canonpath | +# | | | | +# | | |__device_id_of_file | +# | | |__underlying_device_from_file _>>_| possible loop entry point +# | | |__device_node_from_major_minor # | | -# | |__device_node_from_major_minor -# | |__device_id_of_file -# | |__find_mountpoint -# | | | -# | | |__is_aufs_mountpoint -# | | | -# | | |__canonical +# | |__is_btrfs_mountpoint +# | | |__canonical # | | -# | |__underlying_device_from_aufs -# | | -# | |__aufs_dirs -# | | | -# | | |__aufs_dirs_if_brs0 -# | | | | -# | | | |__is_aufs_mountpoint -# | | | | -# | | | |_canonical -# | | | -# | | |__aufs_si_directory -# | | | -# | | |__is_aufs_mountpoint -# | | | -# | | |__canonical -# | | -# | |__device_id_of_file -# | |__device_node_from_major_minor +# | |__underlying_device_from_btrfs +# | |__device_node_from_major_minor # | # |__underlying_device_from_device -# | # |__underlying_device_from_dm # |__underlying_device_from_loop -# | # |__backing_file_from_loop -# |__device_id_of_file +# |__device_id_of_file ^^^^^^^^^ +# |__underlying_device_from_file __ see above # |__device_node_from_major_minor # # }}} @@ -279,14 +286,54 @@ canonical() { esac } # ===========================================================================}}} +# canonpath() ==============================================================={{{ +# What we want is: canonicalize a pathname even if the file (and even its +# parent directories) does not exist. Just do not try to resolve any part of +# the path; instead, rely only on path separators and specific patterns that +# allow us to logically shorten the path. +canonpath() { + ${DEBUG} && echo "> canonpath $@" >&2 + local pathname + case "${1}" in + "") return 0;; + /*) pathname="${1}";; + *) pathname="${PWD}/${1}";; + esac + while true; do + case "${pathname}" in + *//*|*/./*|*/../*|*/|*/.|*/..) + pathname="$(echo "${pathname}" | sed -re 's,(/+\.?)+/+,/,g; s,^(/+\.\.)+(/+|$),/,; s,[^/]+/+\.\.(/+|$),/,; s,/+,/,g; s,(/+\.?)+$,,')" + ;; + "") + echo "/" + break + ;; + *) + echo "${pathname}" + break + ;; + esac + done +} +# ===========================================================================}}} # find_mountpoint() ========================================================={{{ # What we want is: output the mountpoint of the filesystem the file or directory # given as argument depends is onto. Because it outputs the last field of the # last line of the 'df' output, df don't need the '-P' (POSIX format) option, # and so we are sure it works with all df commands or builtins (busybox). +# The use of directories is to work around overlayfs design (files and dirs are +# not treated the same way, see "stat inconsistency with overlayfs" thread in +# http://www.spinics.net/lists/linux-unionfs/index.html#00197). In my tests, +# the only one case where replacing a file path by its dirname may affect the +# result of df, stat... is for bind-mounted files (and when the two files are +# not on the same fs). find_mountpoint() { ${DEBUG} && echo "> find_mountpoint $@" >&2 - df "${1}" | sed -ne '$s,.* \([^[:blank:]]\+\)$,\1,p' + if [ -d "${1}" ] + then df "${1}" + else df "${1%/*}" + fi | + sed -ne '$s,.* \([^[:blank:]]\+\)$,\1,p' } # ===========================================================================}}} # device_node_from_major_minor() ============================================{{{ @@ -300,10 +347,30 @@ device_node_from_major_minor() { # ===========================================================================}}} # device_id_of_file() ======================================================={{{ # What we want is: output the major:minor of the filesystem containing the -# file or directory given as argument. +# file or directory given as argument. See the 'find_mountpoint()' function +# above, and its comments about "stat inconsistency with overlayfs". device_id_of_file() { ${DEBUG} && echo "> device_id_of_file $@" >&2 - udevadm info --device-id-of-file "${1}" + if [ -d "${1}" ] + then udevadm info --device-id-of-file "${1}" + else udevadm info --device-id-of-file "${1%/*}" + fi +} +# ===========================================================================}}} +# is_btrfs_mountpoint() ====================================================={{{ +# What we want is: check if a directory given as argument is a btrfs mountpoint +# and print the corresponding line from /proc/mounts. Accepts the '-q' (quiet) +# option: print nothing, but return a 0/1 exit value. This is due to the fact +# that btrfs mountpoints get 0 as their major device ID. +is_btrfs_mountpoint() { + ${DEBUG} && echo "> is_btrfs_mountpoint $@" >&2 + local opt= + case "${1}" in + -*) + opt="${1}" + shift ;; + esac + grep ${opt} "^[^ ]\+ $(canonical ${1}) btrfs " /proc/mounts } # ===========================================================================}}} # is_aufs_mountpoint() ======================================================{{{ @@ -338,28 +405,52 @@ aufs_dirs_if_brs0() { is_aufs_mountpoint "${1}" | sed -e 's@.*[ ,]br:\([^ ,]\+\).*@\1@ ; s@:@ @g' } # ===========================================================================}}} -# aufs_dirs() ==============================================================={{{ -# What we want is: output all the underlying mountpoints (called branches) an -# aufs filesystem given as argument is made of. -aufs_dirs() { - ${DEBUG} && echo "> aufs_dirs $@" >&2 +# aufs_readonly_branch() ===================================================={{{ +# What we want is: output the lower (readonly) branch of an aufs mount point +# given as argument. +aufs_readonly_branch() { + ${DEBUG} && echo "> aufs_readonly_branch $@" >&2 local br case "$(cat /sys/module/aufs/parameters/brs)" in 0) for br in $(aufs_dirs_if_brs0 "${1}") do - echo ${br} + echo ${br} | grep -q '=r[or]\(+wh\)\?$' && + echo ${br%\=r*} done ;; *) - for br in $(aufs_si_directory "${1}")/br* + for br in $(aufs_si_directory "${1}")/br? do - cat ${br} + grep '=r[or]\(+wh\)\?$' ${br} | sed -e 's,=r[or].*,,' done ;; esac } # ===========================================================================}}} +# is_overlay_mountpoint() ==================================================={{{ +# What we want is: check if a directory given as argument is an overlayfs +# mountpoint and print the corresponding line from /proc/mounts. Accepts the +# '-q' (quiet) option: print nothing, but return a 0/1 exit value. +is_overlay_mountpoint() { + ${DEBUG} && echo "> is_overlay_mountpoint $@" >&2 + local opt= + case "${1}" in + -*) + opt="${1}" + shift ;; + esac + grep ${opt} "^[^ ]\+ $(canonical ${1}) overlay " /proc/mounts +} +# ===========================================================================}}} +# overlay_lowerdir() ========================================================{{{ +# What we want is: output the lowerdir (readonly branch) of an overlayfs mount +# point given as argument. +overlay_lowerdir() { + ${DEBUG} && echo "> overlay_lowerdir $@" >&2 + canonpath $(is_overlay_mountpoint "${1}" | sed -e 's@.*[ ,]lowerdir=\([^ ,]\+\).*@\1@ ; s@/\+@/@g') +} +# ===========================================================================}}} # backing_file_from_loop() =================================================={{{ # What we want is: output the backing file of a loopback device given as # argument. This requires kernel >= 2.6.37. Great thing! Before that, it was @@ -387,16 +478,29 @@ underlying_device_from_loop() { local lofile="$(backing_file_from_loop ${1})" || return 1 if [ -b "${lofile}" ] then readlink -f "${lofile}" - elif [ -e "${lofile}" ] - then device_node_from_major_minor $(device_id_of_file "${lofile}") - elif [ -r "${1}" ] - then - # For some cases, when the loop device is set from inside the - # initramfs (Live Systems) - local dev="$(/sbin/losetup ${1} | sed "s;^${1}: \[\([0-9a-f]\{4\}\)\].*;\1;")" - device_node_from_major_minor "$((0x${dev}/256)):$((0x${dev}%256))" else - return 1 + local id + if [ -e "${lofile}" ] + then id=$(device_id_of_file "${lofile}") + elif [ -r "${1}" ] + then # For some cases, when the loop device is set from inside + # the initramfs (Live Systems) and /sys/*/loop/backing_file + # is out of sync + local dev="$(/sbin/losetup ${1} | sed "s;^${1}: \[\([0-9a-f]\{4\}\)\].*;\1;")" + id="$((0x${dev}/256)):$((0x${dev}%256))" + else return 1 + fi + case "${id}" in + "") + return 1 + ;; + 0:*) + underlying_device_from_file "${lofile}" + ;; + *) + device_node_from_major_minor "${id}" + ;; + esac fi } # ===========================================================================}}} @@ -408,24 +512,76 @@ underlying_device_from_loop() { # virtual fs. underlying_device_from_aufs() { ${DEBUG} && echo "> underlying_device_from_aufs $@" >&2 - local dir dev - for dir in $(aufs_dirs "${1}") - do - dev="$(device_id_of_file ${dir%\=r?*})" - case "${dev}" in - 0:*) - continue - ;; - *) - dev="$(device_node_from_major_minor "${dev}")" - ;; - esac - if [ -b "${dev}" ] - then readlink -f "${dev}" - return 0 + local dir="$(aufs_readonly_branch "${1}")" + local dev="$(device_id_of_file "${dir}")" + case "${dev}" in + "") + ;; + 0:*) + # aufs mounts can't be nested; but this may be btrfs + dev="$(underlying_device_from_file "${dir}")" + ;; + *) + dev="$(device_node_from_major_minor "${dev}")" + ;; + esac + + [ -b "${dev}" ] && readlink -f "${dev}" +} +# ===========================================================================}}} +# underlying_device_from_overlayfs() ========================================{{{ +# What we want is: output the underlying device of the (generally) readonly +# branch of an overlayfs mountpoint given as argument. We assume that there is +# only and at least one physical device used to build the overlayfs (but the +# directory is not necessarly the mountpoint of this device), other branch(es) +# being virtual fs. +underlying_device_from_overlayfs() { + ${DEBUG} && echo "> underlying_device_from_overlayfs $@" >&2 + local dev dir="$(overlay_lowerdir "${1}")" + + # First case: overlayfs mountpoint is set at runtime, so the lowerdir + # value is up-to-date. Think that when setting up overlayfs mountpoint + # from the initramdisk environment, using same pathnames than what they + # will be at runtime may ease the task. + if [ -d "${dir}" ] && grep -q "^/[^ ]\+ ${dir} " /proc/mounts; then + dev="$(device_id_of_file ${dir})" + else + # overlayfs mountpoint has been set at boottime (within the initrd env) + # and the value of 'lowerdir' found in /proc/mounts is obsolete. There + # is no safe way to know the current and actual lowerdir mountpoint. We + # have to assume some arbitrary conditions to take a chance to find the + # underlying device. This depends on arbtrary paths used in initrd + # scripts (tested with live-boot 5.0~a1-1 - experimental) + # First fallback: rely on the lowerdir's basename + dir="$(grep '^/' /proc/mounts | sed -e 's|^[^ ]\+ \([^ ]\+\) .*|\1|' | grep "/${dir##*/}$")" + if [ -d "${dir}" ]; then + dev="$(device_id_of_file ${dir})" fi - done - return 1 + fi + case "${dev}" in + "") + ;; + 0:*) + dev="$(underlying_device_from_file "${dir}")" + ;; + *) + dev="$(device_node_from_major_minor "${dev}")" + ;; + esac + + [ -b "${dev}" ] && readlink -f "${dev}" +} +# ===========================================================================}}} +# underlying_device_from_btrfs() ============================================{{{ +# What we want is: output the underlying device of a btrfs mountpoint given as +# argument. Such filesystems are not directly mapped to the block device they +# are written on: the device ID (major:minor) of a file on btrfs is not the +# same than the block device itself (say 8:1 for /dev/sda1), but a virtual one +# (with 0 as the major number). +underlying_device_from_btrfs() { + ${DEBUG} && echo "> underlying_device_from_btrfs $@" >&2 + local dev="$(grep "^/[^[:blank:]]\+\s${1}\sbtrfs\s" /proc/mounts | sed -e 's|^\([^ ]\+\)\s.*|\1|')" + [ -b "${dev}" ] && readlink -f "${dev}" } # ===========================================================================}}} # underlying_device_from_dm() ==============================================={{{ @@ -491,13 +647,16 @@ underlying_device_from_file() { then # 0 is the major number of all ramfs (tmpfs, devtmpfs, sysfs, proc # and others). If the file is hosted on a such virtual filesystem, - # we encounter an alternative: the file is on aufs and we continue - # after a jump on the real block device under the aufs, or we stop - # here. + # we encounter an alternative: the file is on aufs/overlay/btrfs + # and we continue after a jump on the real block device under the + # aufs/overlay/btrfs, or we stop there. mntpnt="$(find_mountpoint "${1}")" if is_aufs_mountpoint -q "${mntpnt}" then dev="$(underlying_device_from_aufs "${mntpnt}")" - else return 1 + elif is_overlay_mountpoint -q "${mntpnt}" + then dev="$(underlying_device_from_overlayfs "${mntpnt}")" + elif is_btrfs_mountpoint -q "${mntpnt}" + then dev="$(underlying_device_from_btrfs "${mntpnt}")" fi else dev="$(device_node_from_major_minor "${id}")" @@ -541,8 +700,7 @@ underlying_device() { # of mapped devices (LVM, dm-crypt), loopback devices and aufs filesystems. underlying_partition() { ${DEBUG} && echo "> underlying_partition $@" >&2 - local dev="$(underlying_device "${1}")" - local old new="${dev}" + local old new="$(underlying_device "${1}")" while true do @@ -680,37 +838,36 @@ get_aufs_variables() { } # ===========================================================================}}} -# aufs_mountpoints() ========================================================{{{ -# What we want is: output the mountpoints of all aufs filesystems. -aufs_mountpoints() { - ${DEBUG} && echo "> aufs_mountpoints $@" >&2 - grep '^[^ ]\+ /[^Â ]* aufs .*[, ]si=[0-9a-f]\+[, ].*' /proc/mounts | - sed -e 's,^[^ ]\+ \(/[^Â ]*\) aufs .*,\1,' -} -# ===========================================================================}}} -# aufs_readonly_branch() ===================================================={{{ -# What we want is: output the lower (readonly) branch of an aufs mount point -# given as argument. -aufs_readonly_branch() { - ${DEBUG} && echo "> aufs_readonly_branch $@" >&2 +# aufs_dirs() ==============================================================={{{ +# What we want is: output all the underlying mountpoints (called branches) an +# aufs filesystem given as argument is made of. +aufs_dirs() { + ${DEBUG} && echo "> aufs_dirs $@" >&2 local br case "$(cat /sys/module/aufs/parameters/brs)" in 0) for br in $(aufs_dirs_if_brs0 "${1}") do - echo ${br} | grep -q '=r[or]\(+wh\)\?$' && - echo ${br%\=r*} + echo ${br} done ;; *) - for br in $(aufs_si_directory "${1}")/br* + for br in $(aufs_si_directory "${1}")/br? do - grep '=r[or]\(+wh\)\?$' ${br} | sed -e 's,=r[or].*,,' + cat ${br} done ;; esac } # ===========================================================================}}} +# aufs_mountpoints() ========================================================{{{ +# What we want is: output the mountpoints of all aufs filesystems. +aufs_mountpoints() { + ${DEBUG} && echo "> aufs_mountpoints $@" >&2 + grep '^[^ ]\+ /[^Â ]* aufs .*[, ]si=[0-9a-f]\+[, ].*' /proc/mounts | + sed -e 's,^[^ ]\+ \(/[^Â ]*\) aufs .*,\1,' +} +# ===========================================================================}}} # aufs_writable_branch() ===================================================={{{ # What we want is: output the upper (read-write) branch of an aufs mount point # given as argument. @@ -726,7 +883,7 @@ aufs_writable_branch() { done ;; *) - for br in $(aufs_si_directory "${1}")/br* + for br in $(aufs_si_directory "${1}")/br? do grep '=rw\(+nolwh\)\?$' ${br} | sed -e 's,=rw.*,,' done @@ -735,6 +892,23 @@ aufs_writable_branch() { } # ===========================================================================}}} +# overlay_upperdir() ========================================================{{{ +# What we want is: output the upperdir (writable branch) of an overlayfs mount +# point given as argument. +overlay_upperdir() { + ${DEBUG} && echo "> overlay_upperdir $@" >&2 + canonpath $(is_overlay_mountpoint "${1}" | sed -e 's@.*[ ,]upperdir=\([^ ,]\+\).*@\1@ ; s@/\+@/@g') +} +# ===========================================================================}}} +# overlay_workdir() ========================================================={{{ +# What we want is: output the upperdir (writable branch) of an overlayfs mount +# point given as argument. +overlay_workdir() { + ${DEBUG} && echo "> overlay_workdir $@" >&2 + canonpath $(is_overlay_mountpoint "${1}" | sed -e 's@.*[ ,]workdir=\([^ ,]\+\).*@\1@ ; s@/\+@/@g') +} +# ===========================================================================}}} + # is_removable() ============================================================{{{ # What we want is: check if a whole disk node given as argument is seen as # removable from its sysfs attribute. If yes, this means the disk given as
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Tails-dev mailing list [email protected] https://mailman.boum.org/listinfo/tails-dev To unsubscribe from this list, send an empty email to [email protected].
