diff --git a/modules/filesystem/btrfs/btrfs.mod b/modules/filesystem/btrfs/btrfs.mod index af2ab32..0402ae9 100644 --- a/modules/filesystem/btrfs/btrfs.mod +++ b/modules/filesystem/btrfs/btrfs.mod @@ -7,15 +7,32 @@ module_load path # NOTE: set this for sudo # ALL ALL = (root) NOPASSWD:/bin/btrfs -is_subvol () { +is_subv () { if [[ $1 == "-r" ]]; then if ! btrfs subvolume show "$2" 2> /dev/null | grep readonly &> /dev/null; then return 1; fi else - btrfs subvolume show "$1" &> /dev/null + return $(btrfs subvolume show "$1" &> /dev/null) fi } -make_subvol() { + +is_subvv () { + if [[ $1 == "-r" ]]; then + if ! btrfs subvolume show "$2" 2> /dev/null | grep readonly &> /dev/null; then + echo not a readonly subvolume + else + echo readonly subvoluem + fi + else + if btrfs subvolume show "$1" &> /dev/null; then + echo subvolume + else + echo not a subvolume + fi + fi +} + +subv_make() { local usesudo local uid local gid @@ -29,7 +46,7 @@ make_subvol() { $usesudo chown "$uid":"$gid" "$1" } -del_subvol() { +subv_del() { local usesudo; local delete [[ $1 == "-d" ]] && delete=true && shift [[ $EUID -ne 0 ]] && usesudo=sudo @@ -49,29 +66,30 @@ del_subvol() { # BTRFSDATAROOT=${BTRFSDATAROOT:-/mnt/data} # # cd $BTRFSDATAROOT || exit # for svol in $svols; do -# make_subvol $BTRFSDATAROOT/$svol $@ +# subv_make $BTRFSDATAROOT/$svol $@ # done # } #ssudo mount -o subvol=opt /dev/sda4 /test -snapshot_restore () { - local src=$1 - local dest=$2 - local name=${3:-$(echo "$src"| rev | cut -f 2- -d '.' | rev)} - local usesudo - echo copying "$src" at "$PWD" to "$2" then renaming to "$name" - # TODO check for snapshot, strip volume from source path, remove extra snapshot when done - [[ $EUID -ne 0 ]] && usesudo=sudo - $usesudo "$BTRFS_BIN" send "$src" | $usesudo "$BTRFS_BIN" -q receive "$dest" - # cd $2 || return - $usesudo "$BTRFS_BIN" subvolume snapshot "$dest"/"$src" "$dest"/"$name" - # todo check for snapshot then delete transfered one -} +# FIXME: use subv_xfer +# snapshot_restore () { +# local src=$1 +# local dest=$2 +# local name=${3:-$(echo "$src"| rev | cut -f 2- -d '.' | rev)} +# local usesudo +# echo copying "$src" at "$PWD" to "$2" then renaming to "$name" +# # TODO check for snapshot, strip volume from source path, remove extra snapshot when done +# [[ $EUID -ne 0 ]] && usesudo=sudo +# $usesudo "$BTRFS_BIN" send "$src" | $usesudo "$BTRFS_BIN" -q receive "$dest" +# # cd $2 || return +# $usesudo "$BTRFS_BIN" subvolume snapshot "$dest"/"$src" "$dest"/"$name" +# # todo check for snapshot then delete transfered one +# } -subvolume_size () { +subv_size () { local all; [[ $1 == "-a" ]] && all=true if [[ $all ]]; then @@ -132,11 +150,11 @@ folder_snapshot() { } -snapshot_send() { +subv_xfer() { # Show usage and exit with status help () { - echo 'usage: snapshot_send -h,-r ' + echo 'usage: subv_xfer -h,-r ' } if [[ $1 == "-h" ]]; then help; return; fi @@ -151,7 +169,7 @@ snapshot_send() { if [[ $# -lt 2 ]]; then help; return 1; fi # Check for directories - if ! is_subvol "$1"; then + if ! is_subv "$1"; then echo source "$1" not a subvolume help return 2 @@ -173,7 +191,7 @@ snapshot_send() { [[ $3 ]] && ext=".$3" local tsnap - if ! is_subvol -r "$src"; then + if ! is_subv -r "$src"; then tsnap=$psrc/$name.tmp $dr sudo "$BTRFS_BIN" sub snap -r "$src" "$tsnap" fi @@ -182,18 +200,26 @@ snapshot_send() { echo "sudo $BTRFS_BIN send $([[ $tsnap ]] && echo "$tsnap" || echo "$src") | btrfs receive $dest" echo "sudo mv $dest/$name.tmp $dest/$name$ext" echo "[[ ""$tsnap"" ]] && sudo $BTRFS_BIN sub del $tsnap" + echo "sudo ""$BTRFS_BIN"" sub snap $dest/$name.tmp $dest/$name$ext" + echo "sudo ""$BTRFS_BIN"" sub del $dest/$name.tmp" else sudo "$BTRFS_BIN" send $([[ $tsnap ]] && echo "$tsnap" || echo "$src") | btrfs receive "$dest" - sudo mv "$dest"/"$name".tmp "$dest"/"$name"$ext + # FIXME: take a snapshot of the destination .tmp then remove .tmp, otherwise it will be readonly + # sudo mv "$dest"/"$name".tmp "$dest"/"$name"$ext + if is_subv -r "$dest"/"$name".tmp; then + sudo "$BTRFS_BIN" sub snap "$dest"/"$name".tmp "$dest"/"$name""$ext" + sudo "$BTRFS_BIN" sub del "$dest"/"$name".tmp + echo transfer is complete + fi [[ "$tsnap" ]] && sudo "$BTRFS_BIN" sub del "$tsnap" - echo transfer is complete + ls -la "$dest" - ls -la "$dest"/"$name"$ext + ls -la "$dest"/"$name""$ext" fi } -mount_subvolume () { +subv_mount () { # echo sudo mount $1 -o subvol=$2 $3 if mountpoint "$3" &> /dev/null; then echo "$3" already a mountpoint, aborting subvolume mount @@ -230,7 +256,7 @@ fi # finds device and subvolume of a mountpoint (or a mountpoint above the given path) -mp_subvol () { +subv_mp () { module_load filesystem local mp; local subvol mp=$(find_mountpoint "$1") @@ -257,10 +283,10 @@ btrfs_clone () { $usesudo umount /tmp/source &> /dev/null sudo mount "$src" /tmp/source # $usesudo umount /tmp/dest &> /dev/null - # if mount_subvolume $src $subvol /tmp/source; then - if ! make_subvol "$dest"/$(basename "$subvol") &> /dev/null; then echo unable to make subvolume "$1" at "$dest"; return 2; fi + # if subv_mount $src $subvol /tmp/source; then + if ! subv_make "$dest"/$(basename "$subvol") &> /dev/null; then echo unable to make subvolume "$1" at "$dest"; return 2; fi # $usesudo btrfs subvolume show $dest/$(basename $subvol) - # if mount_subvolume $(mp_subvol $dest/$(basename $subvol)) /tmp/dest; then + # if subv_mount $(subv_mp $dest/$(basename $subvol)) /tmp/dest; then # echo cloning now # # echo $usesudo btrfs-clone --toplevel $dr -v /tmp/source /tmp/dest cmd="$usesudo btrbk $dr archive /tmp/source/$1 $dest/$1" @@ -293,29 +319,61 @@ alias btsub="sudo $BTRFS_BIN subvolume" -dir2subvol () { +dir2subv () { # Directory to convert into BTRFS subvolume + dirPath="$1" +if [[ ! -d $dirPath ]]; then echo no directory at "$dirPath"; return 1; fi +dirSub="$2" +perms=/tmp/perms_$(basename "$dirPath") -getfacl -R "$dirPath" > /tmp/_perms -# Rename original dierctory -sudo mv "${dirPath}" "${dirPath}_original" +if is_subv "$dirPath"; then echo "$dirPath" is already a subvolume, exiting; return 0; fi -# Create btrfs subvolume -sudo "$BTRFS_BIN" subvolume create "${dirPath}" +if ! confirm transform "$dirPath" into a subvolume at "${dirSub:-$dirPath}"; then return 1; fi -# Copy as "reflink" for speed and save space -sudo cp --archive --one-file-system --reflink=always \ - "${dirPath}_original/." "${dirPath}" +pushd "$dirPath" &> /dev/null || return +echo saving permissions at "$PWD" to "$perms" +getfacl -R . | sudo tee "$perms" +cat "$perms" -# Remove old directory -sudo rm -rf --one-file-system "${dirPath}_original" +if [[ ! $dirSub ]]; then +echo moving "$dirPath" to "${dirPath}_temp" +sudo mv "${dirPath}" "${dirPath}_temp" +fi -setfacl --restore=/tmp/_perms +echo creating subvolume at "${dirSub:-$dirPath}" +sudo "$BTRFS_BIN" subvolume create "${dirSub:-$dirPath}" -rm -f /tmp/_perms +# Copy as reflink for speed and save space +if [[ $dirSub ]]; then +echo copying "$dirPath" to "$dirSub" +sudo cp --archive --one-file-system --reflink=always "${dirPath}/." "${dirSub}" +pushd "$dirSub" &> /dev/null || return 1 +else +echo copying "${dirPath}"_temp back to subvolume at "$dirPath" +sudo cp --archive --one-file-system --reflink=always "${dirPath}_temp/." "${dirPath}" +fi + +# echo for debugging changing permissions at "$PWD" +# sudo chmod -R 777 . +# sudo chown -R nobody:nobody . +# ls -la . +# echo "---------------------" + +echo restore saved permissions to "$perms" +sudo setfacl --restore="$perms" +sudo rm -f "$perms" + +echo "$dirPath" has been converted into a subvolume at "${dirSub:-$dirPath}" +if [[ -d ${dirPath}_temp ]];then + if confirm -s do you want to now delete the copy at "${dirPath}"_temp; then + sudo rm -rf --one-file-system "${dirPath}_temp" +fi +fi + +popd &> /dev/null || return 0 }