[systemd-devel] [HEADS-UP] Discoverable Partitions Spec
Goffredo Baroncelli
kreijack at libero.it
Wed Mar 12 15:18:09 PDT 2014
On 03/12/2014 08:12 PM, Goffredo Baroncelli wrote:
[...]
> I am working to prototype something like that. A "mount.btrfs" command which
> 1) handles the rollback (i.e. the user make a snapshot which is a rollback; if something goes wrong and the machine reboot before ending the process, during the subvolume mounting phase the rollback replaces the "original" subvolume)
>
> 2) handles the automount (i.e. if a subvolume has the right xattr it is automatically mounted in the right place)
>
> My idea is that the subvolume are grouped so:
>
> @<name> simple subvolume
> @<name>.<timestamp> snapshot of subvolume <name>
> @<name>.rollback rollback subvolume
>
> If @<name>.rollback exists, then it replace @<name> (something went wrong, the machine rebooted so the rollback have to take place of the original subvolume)
>
> For each @<name> subvolume the following xattrs are considered:
> user.btrfs.automount=1|0 the subvolume has to be automounted
> user.btrfs.mountpoint=<path> subvolume mount point
>
>
> So this "mount.btrfs" command should:
>
> 1) mount the root btrfs filesystem (subvolid=5) in a temporary directory
> 2) performing the auto rollback (this behaviour can be controlled by another xattr)
> 3) mount the subvolume "@" as "root" (like the default one) in the right mount point
> 4) for each subvolume which has user.btrfs.automount=1, it should be mounted under the path stored in the "user.btrfs.mntpoint" xattr (relative to "@" or absolute)
> 5) umount the btrfs filesystem mounted at #1, or better move it to a new position in order
> to allow managing (snapshot) of the different subvolumes.
>
Below my POC.
$ sudo mount /dev/loop0 t
$ sudo getfattr -d t/{@*,.}
# file: t/@
user.btrfs.automount="1"
# file: t/@__boot__
user.btrfs.automount="1"
user.btrfs.mountpoint="/boot"
# file: t/@.broken-0
user.btrfs.automount="1"
# file: t/@.broken-1
user.btrfs.automount="1"
# file: t/@__home__
user.btrfs.automount="1"
user.btrfs.mountpoint="/home"
# file: t/@__root__.12345
user.btrfs.automount="0"
# file: t/@space space
user.btrfs.automount="0"
# file: t/@__srv__
user.btrfs.automount="0"
# file: t/.
user.btrfs.automount="1"
user.btrfs.autorollback="1"
user.btrfs.mountpoint="/var/btrfs"
$ sudo umount t
$ sudo sh mount.btrfs /dev/loop0 t
Mount /dev/loop0/@ -> t
Mount /dev/loop0/@__boot__ -> t//boot
Mount /dev/loop0/@__home__ -> t//home
Mount /dev/loop0 -> t//var/btrfs
ghigo at venice:~/btrfs/mount-btrfs$ find t
t
t/var
t/var/btrfs
t/var/btrfs/@__boot__
t/var/btrfs/@__home__
t/var/btrfs/@__srv__
t/var/btrfs/@__root__.12345
t/var/btrfs/@space space
t/var/btrfs/@.broken-0
t/var/btrfs/@.broken-0/var
t/var/btrfs/@.broken-0/var/btrfs
t/var/btrfs/@.broken-0/@__boot__
t/var/btrfs/@.broken-0/@__home__
t/var/btrfs/@.broken-0/boot
t/var/btrfs/@.broken-0/home
t/var/btrfs/@.broken-0/non-rollback-subvol
t/var/btrfs/@.broken-1
t/var/btrfs/@.broken-1/var
t/var/btrfs/@.broken-1/var/btrfs
t/var/btrfs/@.broken-1/@__boot__
t/var/btrfs/@.broken-1/@__home__
t/var/btrfs/@.broken-1/boot
t/var/btrfs/@.broken-1/home
t/var/btrfs/@.broken-1/rollback-subvol
find: File system loop detected; ‘t/var/btrfs/@’ is part of the same file system loop as ‘t’.
t/@__boot__
t/@__home__
t/boot
t/home
t/non-rollback-subvol
$cat mount.btrfs
#!/bin/sh
XAAMOUNT="user.btrfs.automount"
XAAMNTPNT="user.btrfs.mountpoint"
XAAROLLBACK="user.btrfs.autorollback"
xdebug() {
[ -z "$DEBUG" ] && return
echo "$@"
}
autorollback() {
( cd "$tmpdir"; ls -d @*.rollback 2>/dev/null) | while read drb; do
rbfullpath="$tmpdir/$drb"
[ ! -d "$rbfullpath" ] && continue
is_btrfs_subvol "$rbfullpath" || continue
f="$(get_fattr $XAAROLLBACK "$rbfullpath" )"
[ "x$f" = "x0" ] && continue
d="$(echo $drb | sed -e "s/.rollback$//")"
fullpath="$tmpdir/$d"
if [ -d "$fullpath" ]; then
f="$(get_fattr $XAAROLLBACK "$fullpath" )"
[ "x$f" = "x0" ] && continue
i=0
while true; do
newfullpath="$fullpath.broken-$i"
if [ ! -e "$newfullpath" ]; then
mv "$fullpath" "$newfullpath"
break
fi
i=$(($i+1))
done
fi
echo "Rollback $d"
mv "$rbfullpath" "$fullpath"
done
}
is_btrfs_subvol() {
[ "$(stat -c "%i" "$1")" -eq "256" ]
}
get_fattr() {
name="$1"
file="$2"
getfattr --only-values -n "$name" "$file" 2>/dev/null || echo -n ""
}
automount() {
tmpdir="$1"
srcdev="$2"
mntpnt="$3"
fullpath="$tmpdir/@"
[ ! -d "$fullpath" ] && return 1
is_btrfs_subvol "$fullpath" || return 1
b="$(get_fattr $XAAMOUNT "$fullpath" )"
[ "x$b" = "x0" ] && return 1
path="$(get_fattr $XAAMNTPNT "$fullpath" )"
if [ -n "$path" ] ; then
mntpnt="$path"
fi
xdebug mount -o "subvol=@" "$srcdev" "$mntpnt/"
echo "Mount $srcdev/@ -> $mntpnt"
mount -o "subvol=@" "$srcdev" "$mntpnt/" || return 1
( cd "$tmpdir"; ls -d @* 2>/dev/null) | grep -v "\." | while read d; do
[ "x$d" = "x./@" ] && continue
fullpath="$tmpdir/$d"
[ ! -d "$fullpath" ] && continue
is_btrfs_subvol "$fullpath" || continue
path="$(get_fattr $XAAMNTPNT "$fullpath" )"
[ -z "$path" ] && continue
b="$(get_fattr $XAAMOUNT "$fullpath" )"
[ "x$b" = "x0" ] && continue
echo "Mount $srcdev/$d -> $mntpnt/$path"
xdebug mount -o "subvol=$d" "$srcdev" "$mntpnt/$path"
mkdir -p "$mntpnt/$path"
mount -o "subvol=$d" "$srcdev" "$mntpnt/$path"
done
return 0
}
main() {
#create tempdir
tmpdir=$(mktemp --directory)
srcdev="$1"
mntpnt="$2"
xdebug mount -t btrfs "$srcdev" "$tmpdir"
mount -o subvolid=5 -t btrfs "$srcdev" "$tmpdir" || exit
# get the global value
GLOBALAMOUNT=$(get_fattr $XAAMOUNT "$tmpdir/.")
GLOBALAROLLBACK=$(get_fattr $XAAROLLBACK "$tmpdir/.")
BTRFSROOT="$(get_fattr $XAAMNTPNT "$tmpdir/." )"
xdebug "GLOBALAMOUNT=$GLOBALAMOUNT, GLOBALAROLLBACK=$GLOBALAROLLBACK"
if [ "x$GLOBALAROLLBACK" = "x1" ]; then
autorollback "$tmpdir"
fi
if [ "x$GLOBALAMOUNT" = "x1" ]; then
if ! automount "$tmpdir" "$srcdev" "$mntpnt"; then
echo 1>&2 "ERROR: unable to mount the filesystem"
exit 10
fi
umount "$tmpdir"
if [ -n "$BTRFSROOT" ]; then
mkdir -p "$mntpnt/$BTRFSROOT"
echo "Mount $srcdev -> $mntpnt/$BTRFSROOT"
mount -o subvolid=5 "$srcdev" "$mntpnt/$BTRFSROOT"
fi
else
mount --move "$tmpdir" "$mntpnt"
fi
}
#FIXME: allow options
if [ $# -ne 2 ]; then
echo "usage: $0 <srcdev> <mount-point>"
exit 1
fi
main "$@"
--
gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it>
Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5
More information about the systemd-devel
mailing list