#!/bin/bash

# This is the Linux version, adapted from OSX version
# This needs to be run AS ROOT either directly or with sudo / similar

# NOTE this only works on MIRROR pools, NOT RAIDZ

# REF: https://askubuntu.com/questions/1231355/how-can-i-shrink-a-zfs-volume-on-ubuntu-18-04
# NOTE - UNTested with zfs on Linux but should work with ~ZFS 0.8.6 and newer

# REQUIRES: truncate, awk, grep, working ZFS installation v0.8.6 or newer
# REQUIRES: an ISO to copy to the test pool

#source ~/bin/failexit.mrg
# REF: https://sharats.me/posts/shell-script-best-practices/
function failexit () {
  echo '! Something failed! Code: '"$1 $2" >&2 # code (and optional description)
  exit $1
}

# TODO EDITME xxx
dest=/media/sgtera2 
# Preferably should not be a ZFS target, shoot for ext4 / XFS, etc
# You could use /home here if enough free space

# TODO EDITME
iso2cp=/media/toshtera10/ISO/systemrescue-9.06-amd64.iso
[ -e $iso2cp ] || failexit 128 "ISO $iso2cp not found"

cd $dest || failexit 44 "Cant cd to $dest"

echo "$(date) - Creating virtual zfs disks"
size2=4096
size1=2048

# NOTE not all filesystems support sparse files; if they do this should be quicker than dd
time truncate -s ${size1}M zd1                               
truncate -s ${size1}M zd2
truncate -s ${size1}M zd3
truncate -s ${size1}M zd4

time truncate -s ${size2}M zd5
truncate -s ${size2}M zd6
truncate -s ${size2}M zd7
time truncate -s ${size2}M zd8

ls -lh zd*
date

[ -e zd1 ] || failexit 45 "Cant find zd disks in $dest"

zp=zshrinky
echo "$(date) - Creating zpool $zp"

zpool create -f -o ashift=12 -O atime=off -O compression=lz4 $zp mirror \
 $PWD/zd5 $PWD/zd6 || failexit 64 "Failed to create $zp"
zpool set autoexpand=on $zp

df -hT /$zp
echo "$(date) - Copying ISO to $zp"
time cp -v $iso2cp /$zp
ls -lh /$zp

function zps () {
 zpool status -v $zp |awk 'NF>0'
}

zps
zpool list $zp

echo "Press Enter to shrink $zp - existing pool is ~ ${size2}M - or ^C to stop"
read

echo "$(date) - Adding smaller mirror disks"
zpool add $zp mirror $PWD/zd1 $PWD/zd2
zps

echo "$(date) - Shrinkydink $zp"

# Show how much before committing
time zpool remove -n $zp mirror-0
time zpool remove $zp mirror-0

date

# do forever
while :; do
  [ $(zps |grep -c "Evacuation of mirror in progress") -eq 0 ] && break
  zps
  zpool iostat -y -T d -v $zp
  sleep 5
done

echo "- DONE -"
zps 
echo ''
zpool list $zp
echo ''
df -hT /$zp
date
echo "Dont forget to zpool destroy $zp before running this again"

exit;


# Example output
  pool: zshrinky
 state: ONLINE
  scan: none requested
remove: Removal of vdev 0 copied 744M in 0h0m, completed on Wed Apr 26 00:08:13 2023
    18.2K memory used for removed device mappings
config:
        NAME                      STATE     READ WRITE CKSUM
        zshrinky                  ONLINE       0     0     0
          mirror-1                ONLINE       0     0     0
            /Volumes/sgtera2/zd1  ONLINE       0     0     0
            /Volumes/sgtera2/zd2  ONLINE       0     0     0
errors: No known data errors

NAME       SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zshrinky  1.88G   745M  1.15G        -         -     5%    38%  1.00x  ONLINE  -

Filesystem     Type  Size  Used Avail Use% Mounted on
zshrinky       zfs   1.8G  744M  1.1G  42% /Volumes/zshrinky
