Zramswap 자동시작이 안되시는 분들을 위한 패치

아웅 말은 패치라고 했지만…
이미 파일을 변경해서 패치를 만들지 못했습니다.
어느순간부터 zramswap이 자동시작이 안되서 이상하다 싶어서 dmesg를 봤더니
코어2개인데 1개로만 등록하려고 하다가 에러가 나서 종료되는 듯 하더군요.
그래서 삽질로 찾아본 결과… initramfs에서 compcache란 놈이 zram을 사용하더군요.

/usr/share/initramfs-tools/hooks/compcache
이 파일인데… 원래 compcache로 ramzswap을 사용하게 되어 있던 넘인데…
zram까지 지원하게 스크립팅 되어 있더군요.

[code:3gvln54m]
#!/bin/sh
set -e

if [ "$1" = prereqs ]; then
exit 0
fi

. /usr/share/initramfs-tools/hook-functions

number=
suffix=
eval $(printf "%s" "$COMPCACHE_SIZE" |
sed -nre ‘s/^ ([1-9][0-9]) *([%KMGT]) *$/number="\1"; suffix="\2";/p’)

if [ -z "$number" ] || [ -z "$suffix" ]; then
exit 0
#변경사항 --------- 여기 부터 ---------
#설명 : /etc/initramfs-tools/initramfs.conf 파일에 COMPCACHE_SIZE=""라고 설정 되어 있습니다.
#캐시크기를 지정하는것으로 nnn{K|M|G|%}형태로 지정하게 되어있으며
#nnn이나 뒤의 Unit가 지정되지 않으면 종료됩니다.
#그래서 0{K|M|G|%}로 지정하면.. 자동으로 100%로 설정하게 바꾸었습니다.
elif [ $number -eq 0 ]; then
number=100
suffix="%"
#변경사항 --------- 여기 까지 ---------
fi

if have_module zram; then
name=zram
manual_add_modules zram
elif have_module ramzswap; then
name=ramzswap
manual_add_modules ramzswap
elif have_module compcache; then
name=compcache
manual_add_modules compcache
else
exit 0
fi

copy_exec /sbin/swapon
copy_exec /sbin/mkswap
copy_exec /usr/lib/initramfs-tools/bin/rzscontrol /sbin

#변경사항 --------- 여기 부터 ---------
mem_total="$(sed -nre ‘s/^MemTotal:\s*([0-9]+) kB$/\1/p’ /proc/meminfo)"
#변경사항 --------- 여기 까지 ---------

case "$suffix" in
#변경사항 --------- 여기 부터 ---------
%) kbytes="$(($mem_total * $number / 100))" ;;
#변경사항 --------- 여기 까지 ---------
K) kbytes=$(($number)) ;;
M) kbytes=$(($number * 1024)) ;;
G) kbytes=$(($number * 1024 * 1024)) ;;
T) kbytes=$(($number * 1024 * 1024 * 1024)) ;;
esac

#변경사항 --------- 여기 부터 ---------
#코어의 갯수만큼 zram을 만들기 위해 cpu갯수를 알아냅니다.
num_cpus="$(grep -c processor /proc/cpuinfo)"
[ "$num_cpus" != 0 ] || num_cpus=1
decr_num_cpus=$((num_cpus-1))
#변경사항 --------- 여기 까지 ---------
#아래 EOF까지는 initramfs안의 /sbin/compcache-enable이라는 스크립트를 만들어 주는것입니다.
cat >"$DESTDIR"/sbin/compcache-enable <<‘EOF’
#!/bin/sh
if [ "$#" != 3 ]; then
echo "Usage: $0 <type> <size> <device>" 1>&2
exit 1
fi
type="$1"
size="$2"
device="$3"

number=
suffix=
eval $(printf "%s" "$size" |
sed -nre ‘s/^ ([1-9][0-9]) *([%KMGT]) *$/number="\1"; suffix="\2";/p’)

mem_total="$(sed -nre ‘s/^MemTotal:\s*([0-9]+) kB$/\1/p’ /proc/meminfo)"

case "$suffix" in
%) kbytes="$(($mem_total * $number / 100))" ;;
K) kbytes=$(($number)) ;;
M) kbytes=$(($number * 1024)) ;;
G) kbytes=$(($number * 1024 * 1024)) ;;
T) kbytes=$(($number * 1024 * 1024 * 1024)) ;;
esac
bytes="$(($kbytes * 1024))"

if [ "$type" = zram ]; then
echo "$bytes" >/sys/block/$device/disksize &&
/sbin/mkswap "/dev/$device" >/dev/null

elif [ "$type" = ramzswap ]; then
/sbin/rzscontrol "/dev/$device" --disksize_kb="$kbytes" --init
fi
/sbin/swapon -p 100 "/dev/$device" 2>/dev/null

exit 0
EOF
chmod 0755 "$DESTDIR"/sbin/compcache-enable

mkdir -p "$DESTDIR"/etc/udev/rules.d
if [ "$name" = zram ]; then
#변경사항 --------- 여기 부터 ---------
#코어갯수로 나눈만큼으로 크기를 재조정합니다.
#이것은 initramfs내의 udev룰을 지정하는것으로
#본디 KERNEL==zram0라고 적혀 있던 건데 0을 로 바꾸었고,
#$COMPACHE_SIZE zram0라고 적혀 있던 것을 $COMPCACHE_SIZE_PER_CORE %k로 바꾸었습니다.
#udev룰에서 %k는 커널네임(커널에서 사용되는 이름)을 지칭합니다.
COMPCACHE_SIZE_PER_CORE="$((number/num_cpus))$suffix"
cat >"$DESTDIR"/etc/udev/rules.d/80-compcache.rules <<EOF
KERNEL=="zram
", ACTION=="add", \
RUN+="/sbin/compcache-enable zram $COMPCACHE_SIZE_PER_CORE %k"
EOF
#변경사항 --------- 여기 까지 ---------

done

elif [ "$name" = ramzswap ]; then
cat >"$DESTDIR"/etc/udev/rules.d/80-compcache.rules <<EOF
KERNEL=="ramzswap0", ACTION=="add", \
RUN+="/sbin/compcache-enable ramzswap $COMPCACHE_SIZE ramzswap0"
EOF
else
cat >"$DESTDIR"/etc/udev/rules.d/80-compcache.rules <<EOF
KERNEL=="ramzswap0", ACTION=="add", \
RUN+="/sbin/compcache-enable compcache $COMPCACHE_SIZE ramzswap0"
EOF
fi

cat >"$DESTDIR"/scripts/init-top/compcache <<EOF
#!/bin/sh

PREREQ=""
prereqs()
{
echo "$PREREQ"
}

case $1 in
prereqs)
prereqs
exit 0
;;
esac

find total amount of available ram

TOTAL_RAM=$( grep MemTotal /proc/meminfo |tr -d ‘: [A-Z][a-z]’)

Do not use compcache on the liveCD if we have more than 512M

if [ "${BOOT}" = "casper" ]; then
if [ "${TOTAL_RAM}" -gt 524288 ]; then
exit 0
fi
fi

for x in $(cat /proc/cmdline); do
case ${x} in
nocompcache)
exit 0
;;
esac
done

EOF

if [ "$name" = zram ]; then
#변경사항 --------- 여기 부터 ---------
#전에 적은 내용은 그냥 귀찮아서 modprobe zram num_device=xx||modprobe zram zram_num_device=xx이런 식으로 하였지만
#modinfo를 사용하서 모듈의 파라미터를 알내내어 해당 파라미터로 값을 넘기게 바꾸었습니다.
#원래코드에는 모듈파라미터가 지정되어 있지 않았었으므로
#1개의 zram디바이스(zram0)를 만들려고 시도 했었을 것입니다.
#이것은 core갯수만큼 zram디바이스를 만들면, udev에서 인식해서
#zramswap 디바이스당 할당 크기: 전체메모리/코어갯수
#zramswap 디바이스갯수 : 코어갯수
#로 만들어 질 것입니다.
modparm=$(modinfo zram|grep parm|sed -r ‘s/parm:\s+([^:]+).*/\1/ g’)
cat >>"$DESTDIR"/scripts/init-top/compcache <<EOF
modprobe -q --ignore-install zram $modparm=$num_cpus
EOF
#변경사항 --------- 여기 까지 ---------
elif [ "$name" = ramzswap ]; then
cat >>"$DESTDIR"/scripts/init-top/compcache <<EOF
modprobe -q --ignore-install ramzswap
EOF
else
cat >>"$DESTDIR"/scripts/init-top/compcache <<EOF
modprobe -q --ignore-install compcache compcache_size_kbytes="$kbytes"
EOF
fi

chmod 0755 "$DESTDIR"/scripts/init-top/compcache
[/code:3gvln54m]

아참 코드를 수정하신 후엔…
sudo update-initramfs -u 명령으로 리눅스이미지를 업데이트 해줘야 합니다.