File: //bin/fstrim-blocks
#!/bin/bash
#
# Call fstrim on mounted partitions to maintain write performance.
# This is only relevant for SSD drives, see
# http://wiki.ubuntuusers.de/SSD/TRIM
export PATH=usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
set -e
declare -i interval=10
declare -i timeout=600
declare -i block_size=1073741824
function printUsage() {
cat <<EOF
Synopsis
$0 [-t timeout] [-i interval] [-b block size]
Trim device per block, with interval.
-t timeout
Number of seconds to wait trim per device.
Default value: $timeout seconds.
-i interval
Interval between trim next block.
Default value: $interval seconds.
-b block size
lenght trim byte
Default value: $block_size bytes.
EOF
}
# Options.
while getopts ":t:i:b:" option; do
case "$option" in
t) timeout=$OPTARG ;;
i) interval=$OPTARG ;;
b) block_size=$OPTARG ;;
*) printUsage; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# needs /proc
[ -r /proc/mounts ] || exit 0
# these file systems support trimming
SUPPORTED_FS="ext3 ext4 xfs btrfs"
# arguments: <haystack> <needle>
contains() {
[ "${1#*$2}" != "$1" ]
}
# As long as there are bugs like https://launchpad.net/bugs/1259829 we only run
# fstrim on Intel and Samsung drives; with --no-model-check it will run on all
# drives instead.
if [ "$1" = "--no-model-check" ]; then
NO_MODEL_CHECK=1
fi
DONE=''
while read DEV MOUNT FSTYPE OPTIONS REST; do
# only consider /dev/*
[ "${DEV#/dev}" != "$DEV" ] || continue
# ignore mounts with "discard", they TRIM already
if contains "$OPTIONS" discard; then continue; fi
# only consider supported file systems
if ! contains "$SUPPORTED_FS" "$FSTYPE"; then continue; fi
# ignore temporary devices which already went away
[ -e "$DEV" ] || continue
# did we see this already? we need to resolve symlinks
# for/dev/disks/by-{label,uuid}, etc.; ignore if the device does not exist
# any more
REALDEV=`readlink -f $DEV` || continue
if contains "$DONE" " $REALDEV "; then continue; fi
DONE="$DONE $REALDEV "
#echo "device $DEV real $REALDEV mountpoint $MOUNT fstype $FSTYPE"
# check if that device supports trim; this does not work for devmapper or
# mdadm, though, so just call fstrim on those without the extra check and
# ignore errors; for cryptsetup and LVM you also need extra configuration
# options to propagate discards, which the admin might have turned off
unset SILENT_FAILURE
if [ "${REALDEV#/dev/dm-}" != "$REALDEV" ]; then
#echo "device $DEV is on devmapper, skipping TRIM feature check"
SILENT_FAILURE=1
elif [ "${REALDEV#/dev/md}" != "$REALDEV" ]; then
#echo "device $DEV is on mdadm, skipping TRIM feature check"
SILENT_FAILURE=1
elif ! type hdparm >/dev/null 2>&1; then
#echo "hdparm not available, cannot TRIM"
exit 0
fi
lenght=$(df $REALDEV --block-size=$block_size | grep -v "blocks" | awk '{print $2}')
fstrim_cmd="ionice -c 2 -n 7 nice -n 19 fstrim $MOUNT"
dev_timeout=$timeout
# echo $lenght
for ((i=0; i<$lenght ; i++ ))
do
dev_timeout=$(bc <<< $dev_timeout-$interval)
if (( dev_timeout < 0 ));then
break
fi
offset=$(($i * $block_size))
fstrim_arg="-o $offset -l $block_size"
$fstrim_cmd $fstrim_arg 2>/dev/null || true
sleep $interval
done
done < /proc/mounts