#!/bin/sh # usage: snapshot.lvm2 vg/lv executable [args] if test $# -lt 2; then echo 'usage: snap.lvm2 vg/lv executable [args]' exit fi SRC="$1" shift S_VOL="${SRC}.snaprep" S_DEV="/dev/mapper/${SRC//\//-}.snaprep" SNAPSHOT="/mnt/snaprep/${SRC//\//-}" export SNAPSHOT LOCKDIR=/var/lock/snaprep test -d "$LOCKDIR" || mkdir -p "$LOCKDIR" || exit $? LOCKFILE="$LOCKDIR/lvm2.${SRC//\//-}" # since LVM implies Linux, I'm assuming the presence of the flock utility if ! flock -n "$LOCKFILE" true; then echo >&2 "locked: $SRC" exit 1 fi ( flock -n 3 || exit $? echo $$ >&3 if test -b "$S_DEV"; then echo >&2 "removing stale snapshot" if grep -qF "$S_DEV" /proc/mounts; then # TODO match only on start of line umount $S_DEV || exit $? fi lvremove -f "$S_DEV" || exit $? fi if test -d "$SNAPSHOT"; then # make sure it's empty and unused rmdir "$SNAPSHOT" || exit $? fi mkdir -p "$SNAPSHOT" || exit $? lvcreate -n "${SRC##*/}.snaprep" -L "${SNAPSHOT_SIZE:-10G}" -s "$SRC" || exit $? die_lvremove() { lvremove -f "$S_VOL" exit $? } magic="$(file -b -s "$(realpath "$S_DEV")")" case "$magic" in (*XFS*) mount -t xfs -o nouuid "$S_DEV" "$SNAPSHOT" || die_lvremove $?;; (*) mount "$S_DEV" "$SNAPSHOT" || die_lvremove $?;; esac SNAP_SRC=$SNAPSHOT export SNAP_SRC touch $SNAP_SRC/.snapshot.$(date +%s) "$@" RETCODE=$? umount "$SNAPSHOT" lvremove -f "$S_VOL" ) 3> "$LOCKFILE" exit $RETCODE