diff --git a/README.md b/README.md index 333c516..e03c4e3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,46 @@ # zfs-inplace-rebalancing Simple bash script to rebalance pool data between all mirrors when adding vdevs to a pool. + +## How it works + +This script simply copies all files, deletes the original and renames the copy back to the original name. The given root directory is traversed recursively (using `find`) and each file is processed individually. At no point in time are both versions of the original file deleted. + +## Prerequisites + +### Balance Status + +To check the current balance of a pool use: + +``` +zpool list -v +``` + +### No Deduplication + +Due to the working principle of this script, which essentially creates a duplicate file on purpose, deduplication will most definitely prevent it from working as intended. If you use deduplication you probably have to resort to a more expensive rebalancing method that involves additional drives. + +### Data selection + +Due to the working principle of this script, it is crucial that you **only run it on data that is not actively accessed**, since the original file will be deleted. + +## Usage + +**ALWAYS HAVE A BACKUP OF YOUR DATA!** + +``` +chmod +x ./zfs-in-place-mirror-rebalance.sh +./zfs-in-place-mirror-rebalance.sh /pool/path/to/rebalance +``` + +Note that this script does **not** have any kind of progress bar (yet), so it might be a good idea to try a small subfolder first, or process your pool folder layout in manually selected badges. + +When aborting the script midway through, be sure to check the last lines of its output. When cancelling before or during the renaming process a ".rebalance" file might be left and you have to rename it manually. + +## Attributions + +This script was inspired by [zfs-balancer](https://github.com/programster/zfs-balancer). + +## Disclaimer + +This software is provided "as is" and "as available", without any warranty. +**ALWAYS HAVE A BACKUP OF YOUR DATA!** diff --git a/zfs-in-place-mirror-rebalance.sh b/zfs-in-place-mirror-rebalance.sh new file mode 100755 index 0000000..6feb184 --- /dev/null +++ b/zfs-in-place-mirror-rebalance.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# exit script on error +set -e +# exit on undeclared variable +set -u + +function rebalance () { + file_path=$1 + + tmp_extension=".balance" + + echo "${file_path}" + echo "Copying '${file_path}' to '${file_path}${tmp_extension}'..." + # -a -- keep attributes + # -d -- keep symlinks (dont copy target) + # -x -- stay on one system + # -p -- preserve ACLs too + cp -adxp "${file_path}" "${file_path}${tmp_extension}" + + echo "Removing original '${file_path}'..." + rm "${file_path}" + + echo "Renaming temporary copy to original '${file_path}'..." + mv "${file_path}${tmp_extension}" "${file_path}" +} + +root_path=$1 +# recursively scan through files and execute "rebalance" procedure +find "$root_path" -type f -print0 | while IFS= read -r -d '' file; do rebalance "$file"; done +echo Done!