Skip to content
Permalink
a36efac996
Go to file
 
 
Cannot retrieve contributors at this time
executable file 288 lines (272 sloc) 9.59 KB
#!/bin/bash -e
################################################################################
# echo wrappers
INFO(){ echo -n "INFO: "; echo "$@" ;}
WARN(){ echo -n "WARN: "; echo "$@" ;}
ERRO(){ echo -n "ERRO: "; echo -n "$@" ; echo " Abort!"; exit 1;}
################################################################################
# helper function for see information about writing data
write(){
[ "$#" == "2" ] || return 0
val="$1" file="$2"
[ ! -z "$val" ] || return 0
[ ! -z "$file" ] || return 0
INFO "$val >> $file"
echo "$val" >> "$file" || \
WARN "Problem with writing $val >> $file"
}
zram_hot_add(){
WARN "zramctl can't find free device"
INFO "Use workaround hook for hot add"
if [ -f /sys/class/zram-control/hot_add ]; then
NEW_ZRAM=$(cat /sys/class/zram-control/hot_add)
INFO "Success: new device /dev/zram$NEW_ZRAM"
else
ERRO "This kernel not support hot add zram device, please use 4.2+ kernels or see modinfo zram and make modprobe rule"
fi
}
manage_zram(){
case $1 in
start)
[ -z "${zram[size]}" ] && return 0
zram[alg]=${zram[alg]:-lzo}
zram[streams]=${zram[streams]:-${sys[cpu_count]}}
zram[force]=${zram[force]:-true}
# Wrapper, for handling zram initialization problems
for (( i = 0; i < 10; i++ )); do
[ -d /sys/module/zram ] || modprobe zram
done
for (( i = 0; i < 10; i++ )); do
# zramctl is a external program -> return name of first free device
OUTPUT="$(zramctl -f -a ${zram[alg]} -t ${zram[streams]} -s ${zram[size]} 2>&1 || :)"
if echo "$OUTPUT" | grep -q "failed to reset: Device or resource busy"; then
sleep 1
continue
elif echo "$OUTPUT" | grep -q "zramctl: no free zram device found"; then
zram_hot_add
elif echo "$OUTPUT" | grep -q "/dev/zram"; then
[ -b "$OUTPUT" ] || continue
zram[dev]="$OUTPUT"
break
else
:
fi
done
mkswap "${zram[dev]}"
swapon -p 32767 "${zram[dev]}"
write "zram[dev]=${zram[dev]}" ${lock[zram]}
;;
stop)
# read info from zram lock file
. "${lock[zram]}"
swapoff "${zram[dev]}"
zramctl -r "${zram[dev]}"
rm "${lock[zram]}"
;;
esac
}
manage_swapf(){
case $1 in
start)
[ -z ${swapf[path]} ] && return 0
[ -z ${swapf[size]} ] && return 0
# Create sparse file for swap
truncate -s ${swapf[size]} ${swapf[path]} || return 0
# get first free loop device and
# use swap file through loop, for avoid error:
# skipping - it appears to have holes
swapf[loop]=`losetup -f --show ${swapf[path]}`
# loop use file descriptor, file still exist, but no have path
# When loop deatach file, file will be deleted.
rm ${swapf[path]}
mkswap ${swapf[loop]}
swapon -d ${swapf[loop]}
# set autoclear flag
losetup -d ${swapf[loop]}
write "swapf[loop]=${swapf[loop]}" ${lock[swapf]}
;;
stop)
. ${lock[swapf]}
if [ ! -z ${swapf[loop]} ]; then
swapoff ${swapf[loop]}
fi
rm ${lock[swapf]}
;;
esac
}
manage_swapdev(){
case $1 in
start)
[ -z "${swapd[devs]}" ] && return 0
for i in `echo ${swapd[devs]}`; do
if swapon -d -p 1 $i; then
write $i ${lock[dev]}
else
:
fi
done
;;
stop)
for i in `cat ${lock[dev]}`; do
swapoff $i || :
done
rm ${lock[dev]}
;;
esac
}
manage_zswap(){
ZSWAP_P=/sys/module/zswap/parameters/
case $1 in
start)
[ -f "${lock[zswap]}" ] && return 0
declare -A local
for param in enabled compressor max_pool_percent zpool; do
local["$param"]="$(cat $ZSWAP_P/$param)"
write "zswap[$param]=${local[$param]}" "${lock[zswap]}"
write "${zswap[$param]}" "$ZSWAP_P/$param"
done
;;
stop)
. "${lock[zswap]}"
for param in enabled compressor max_pool_percent zpool; do
write "${zswap[$param]}" "$ZSWAP_P/$param"
done
rm ${lock[zswap]}
;;
esac
}
read_line(){
FILE=$1 NUM=$2
head -n $NUM $FILE | tail -n 1
}
gen_vram_bounds(){
FILE_TMP="$(mktemp)"
lspci | grep VGA > $FILE_TMP
VGA_COUNT="$(cat -n $FILE_TMP | wc -l)"
for a in $(seq 1 $VGA_COUNT); do
PCI_SLOT=$(read_line $FILE_TMP $a| awk '{print $1}')
FILE_REGIONS_TMP="$(mktemp)"
lspci -v -s $PCI_SLOT | grep '(64-bit, prefetchable)' > $FILE_REGIONS_TMP
REGION_COUNT="$(cat -n $FILE_REGIONS_TMP | tail -n 1 | awk '{print $1}')"
for b in $(seq 1 $REGION_COUNT); do
LINE=$(read_line $FILE_REGIONS_TMP $b)
REGION_START=$( echo $LINE | awk '{print $3}' )
REGION_START_BYTE="$((16#$REGION_START))"
REGION_LENGHT=$( echo $LINE | awk '{print $6}' | cut -d'=' -f2 | tr -d ']' )
if echo $REGION_LENGHT | grep -q M; then
REGION_LENGHT_MB="$(echo $REGION_LENGHT | tr -d 'M')"
REGION_LENGHT_BYTE=$[$REGION_LENGHT_MB*1024*1024]
REGION_END=$[$REGION_START_BYTE+$REGION_LENGHT_BYTE]
vramswap_regions[${a}_${b}]="$REGION_START_BYTE $REGION_END"
else
ERRO "Can't compute VRAM Region size for $PCI_SLOT!"
fi
done
done
rm $FILE_TMP
}
manage_vramswap(){
case $1 in
start)
[ -f "${lock[vramswap]}" ] && return 0
[ -z "${vramswap[region_start]}" ] && return 0
[ -z "${vramswap[region_size]}" ] && return 0
if [ -b /dev/mtdblock0 ]; then
ERRO "Can't handle VRAM SWAP if /dev/mtdblock0 exist before first systemd-swap initialization!"
fi
gen_vram_bounds
U_REG_START="${vramswap[region_start]}"
U_REG_START="$((16#$U_REG_START))"
U_REG_END="${vramswap[region_size]}"
U_REG_END="$((16#$U_REG_END))"
U_REG_END="$[$U_REG_START+$U_REG_END]"
MEM_REGION_OKAY=false
for region in "${vramswap_regions[@]}"; do
break
START=$(echo $region | cut -d' ' -f1)
END=$(echo $region | cut -d' ' -f2)
if (( $U_REG_START >= $START )) && (( $U_REG_START < $END )); then
if (( $U_REG_END <= $END )); then
MEM_REGION_OKAY=true
else
continue
fi
else
continue
fi
done
if $MEM_REGION_OKAY; then
modprobe slram map=VRAM,0x${vramswap[region_start]},+0x${vramswap[region_size]}
modprobe mtdblock
if [ -b /dev/mtdblock0 ]; then
mkswap -L VRAM /dev/mtdblock0
swapon -p 32767 /dev/mtdblock0
fi
write /dev/mtdblock0 ${lock[vramswap]}
else
ERRO "No one parsed region is acceptable for VRAM!"
fi
;;
stop)
swapoff "$(cat ${lock[vramswap]})"
rmmod slram mtdblock
;;
esac
}
###############################################################################
# Script body
# Create associative arrays
declare -A sys zram lock swapf swapd zswap vramswap vramswap_regions
parse_config(){
# get cpu count from cpuinfo
sys[cpu_count]=$(nproc)
# get total ram size for meminfo
sys[ram_size]=$(awk '/MemTotal:/ { print $2 }' /proc/meminfo)
# get values from /etc/systemd-swap.conf
. $config
# Parse fstab for swap mounts
[ -z ${swapf[fstab]} ] || \
if [ ! -z "`grep '^[^#]*swap' /etc/fstab || :`" ]; then
unset swapf
INFO "Swap already specified in fstab, so disable swap file creation"
fi
# Try to auto found swap partitions
if [ ! -z ${swapd[parse]} ]; then
swapd[devs]=" `blkid -t TYPE=swap -o device | grep -vE '(zram|loop)' || :`
${swapd[devs]}"
[ ! -z ${swapf[Poff]} ] && [ ! -z "${swapd[devs]}" ] && unset swapf || :
fi
}
manage_config(){
config=/etc/systemd-swap.conf
if [ -f $config ]; then
parse_config
else
ERRO "Config $config deleted, reinstall package"
fi
}
###############################################################################
lock[zram]=/run/.systemd-swap.zram
lock[dev]=/run/.systemd-swap.dev
lock[swapf]=/run/.systemd-swap.swapf
lock[zswap]=/run/.systemd-swap.zswap
lock[vramswap]=/run/.systemd-swap.vramswap
case $1 in
start)
manage_config
# start several independent threads
[ -f ${lock[zram]} ] || manage_zram $1 &
[ -f ${lock[dev]} ] || manage_swapdev $1 &
[ -f ${lock[swapf]} ] || manage_swapf $1 &
[ -f ${lock[zswap]} ] || manage_zswap $1 &
[ -f ${lock[vramswap]} ] || manage_vramswap $1 &
;;
stop)
[ -f ${lock[zram]} ] && manage_zram $1 &
[ -f ${lock[dev]} ] && manage_swapdev $1 &
[ -f ${lock[swapf]} ] && manage_swapf $1 &
[ -f ${lock[zswap]} ] && manage_zswap $1 &
[ -f ${lock[vramswap]} ] && manage_vramswap $1 &
;;
esac
wait
You can’t perform that action at this time.