Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically configure bind directory #126

Merged
merged 6 commits into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,7 @@ Don't make it much higher than the compression algorithm (and the additional zra
`swappiness` 150 because the improved performance of zram allows more usage without any adverse affects from the default of 60.
It can be raised up to 200 which will improve performance in high memory pressure situations.

`target_dir` is the directory you wish to hold in zram, and the original will be moved to a bind mount `bind_dir` and is synchronized on start, stop, and write commands.

`bind_dir` is the directory where the original directory will be mounted for sync purposes.
Usually in `/opt` or `/var`, name optional.
`target_dir` is the directory you wish to hold in zram, and the original will be moved to a bind mount and is synchronized on start, stop, and write commands.

`oldlog_dir` will enable log-rotation to an off device directory while retaining only live logs in zram.
Usually in `/opt` or `/var`, name optional.
Expand All @@ -108,11 +105,11 @@ Once finished, start zram using `sudo systemctl start zram-config.service` or `s
# swap alg mem_limit disk_size swap_priority page-cluster swappiness
swap lzo-rle 250M 750M 75 0 150

# dir alg mem_limit disk_size target_dir bind_dir
#dir lzo-rle 50M 150M /home/pi /pi.bind
# dir alg mem_limit disk_size target_dir
#dir lzo-rle 50M 150M /home/pi

# log alg mem_limit disk_size target_dir bind_dir oldlog_dir
log lzo-rle 50M 150M /var/log /log.bind /opt/zram/oldlog
# log alg mem_limit disk_size target_dir oldlog_dir
log lzo-rle 50M 150M /var/log /opt/zram/oldlog
```

### Is it working?
Expand Down Expand Up @@ -193,6 +190,14 @@ It is also common for VMs to not have implemented emulation in their kernel for
If you experience issues, it may be better to not use zram-config in your VM environment.
It is recommended to thoroughly test zram-config in your specific VM setup to ensure it meets your needs.

#### Removal of `bind_dir` in `ztab`

Older versions of zram-config included the option to manually configure a `bind_dir` in the `ztab`.
This functionality was removed in favor of automatically creating a bind mount as it is less confusing and more consistent with the rest of the code.

Checks are in place to automatically convert `ztab` to this new format.
If errors occur, you may need to manually edit `ztab` to fix any issues.

### Performance

LZO-RLE offers the best performance and is probably the best choice, and from kernel 5.1 and onward it is the default.
Expand Down
1 change: 1 addition & 0 deletions update.bash
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ install -m 755 "$BASEDIR"/uninstall.bash /usr/local/share/zram-config/uninstall.
if ! [[ -f /etc/ztab ]]; then
install -m 644 "$BASEDIR"/ztab /etc/ztab
fi
sed -i -E 's/(\tbind_dir|\t\/\w*\.bind)//g' /etc/ztab # Remove bind_dir and /path.bind from ztab
if ! [[ -d /usr/local/share/zram-config/log ]]; then
mkdir -p /usr/local/share/zram-config/log
fi
Expand Down
94 changes: 49 additions & 45 deletions zram-config
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ createZdevice() {
fi

if ! echo "$ALG" > "/sys/block/zram${RAM_DEV}/comp_algorithm"; then
log "ERROR" "Failed to set compression algorithm for zram${RAM_DEV}."
log "ERROR" "Failed to set compression algorithm for /dev/zram${RAM_DEV}."
retVal=1
fi
if ! echo "$DISK_SIZE" > "/sys/block/zram${RAM_DEV}/disksize"; then
log "ERROR" "Failed to set disk size for zram${RAM_DEV}."
log "ERROR" "Failed to set disk size for /dev/zram${RAM_DEV}."
retVal=1
fi
if ! echo "$MEM_SIZE" > "/sys/block/zram${RAM_DEV}/mem_limit"; then
log "ERROR" "Failed to set memory limit for zram${RAM_DEV}."
log "ERROR" "Failed to set memory limit for /dev/zram${RAM_DEV}."
retVal=1
fi
if [[ $retVal -ne 0 ]]; then
Expand All @@ -52,7 +52,7 @@ createZdevice() {
fi

if [[ $MEM_SIZE == 0 ]]; then
log "INFO" "No memory limit set for zram${RAM_DEV}."
log "INFO" "No memory limit set for /dev/zram${RAM_DEV}."
fi

log "INFO" "zram${RAM_DEV} created comp_algorithm=${ALG} mem_limit=${MEM_SIZE} disksize=${DISK_SIZE}."
Expand All @@ -62,39 +62,39 @@ createZswap() {
log "INFO" "Beginning creation of swap device."
createZdevice || return 1
if ! mkswap --label "zram-config${RAM_DEV}" "/dev/zram${RAM_DEV}" &> /dev/null; then
log "ERROR" "Failed to create swap on zram${RAM_DEV}."
log "ERROR" "Failed to create swap on /dev/zram${RAM_DEV}."
return 1
fi

if [[ -n $PRIORITY ]]; then
if ! swapon -p "$PRIORITY" "/dev/zram${RAM_DEV}" &> /dev/null; then
log "ERROR" "Failed to swapon on zram${RAM_DEV}."
log "ERROR" "Failed to swapon on /dev/zram${RAM_DEV}."
return 1
fi
else
log "ERROR" "No swap priority provided for zram${RAM_DEV}."
log "ERROR" "No swap priority provided for /dev/zram${RAM_DEV}."
return 1
fi

if [[ -n $PAGE_CLUSTER ]]; then
if ! sysctl vm.page-cluster="$PAGE_CLUSTER"; then
log "ERROR" "Failed to set page_cluster for zram${RAM_DEV}."
log "ERROR" "Failed to set page_cluster for /dev/zram${RAM_DEV}."
return 1
fi
else
log "INFO" "No page cluster provided for zram${RAM_DEV}."
log "INFO" "No page cluster provided for /dev/zram${RAM_DEV}."
fi

if [[ -n $SWAPPINESS ]]; then
if ! sysctl vm.swappiness="$SWAPPINESS"; then
log "ERROR" "Failed to set swappiness for zram${RAM_DEV}."
log "ERROR" "Failed to set swappiness for /dev/zram${RAM_DEV}."
return 1
fi
else
log "INFO" "No swappiness provided for zram${RAM_DEV}."
log "INFO" "No swappiness provided for /dev/zram${RAM_DEV}."
fi

echo "swap /zram${RAM_DEV} zram-config${RAM_DEV}" >> "$TMPDIR"/zram-device-list
echo "swap zram${RAM_DEV}" >> "$TMPDIR"/zram-device-list
log "INFO" "Completed swap device creation."
}

Expand All @@ -115,45 +115,45 @@ createZdir() {
return 1
fi

mkdir -p "${ZDIR}${BIND_DIR}"
mkdir -p "${ZDIR}/${BIND_DIR}"

dirPerm="$(stat -c "%a" "$TARGET_DIR")"
dirUser="$(stat -c "%u" "$TARGET_DIR")"
dirGroup="$(stat -c "%g" "$TARGET_DIR")"
log "DEBUG" "File permissions for $TARGET_DIR - $dirPerm ${dirUser}:${dirGroup}"

if ! mount --bind "${TARGET_DIR}/" "${ZDIR}${BIND_DIR}/" &> /dev/null; then
log "ERROR" "Failed to bind mount ${TARGET_DIR} to ${ZDIR}${BIND_DIR}."
if ! mount --bind "${TARGET_DIR}/" "${ZDIR}/${BIND_DIR}/" &> /dev/null; then
log "ERROR" "Failed to bind mount ${TARGET_DIR} to ${ZDIR}/${BIND_DIR}."
return 1
fi
if ! mount --make-private "${ZDIR}${BIND_DIR}/" &> /dev/null; then
log "ERROR" "Failed to make ${ZDIR}${BIND_DIR} private."
if ! mount --make-private "${ZDIR}/${BIND_DIR}/" &> /dev/null; then
log "ERROR" "Failed to make ${ZDIR}/${BIND_DIR} private."
return 1
fi

dirMountOpt="$(awk -v a="${ZDIR}${BIND_DIR}" '$2 == a {print $4}' /proc/mounts | head -1)"
dirFSType="$(awk -v a="${ZDIR}${BIND_DIR}" '$2 == a {print $3}' /proc/mounts | head -1)"
dirMountOpt="$(awk -v a="${ZDIR}/${BIND_DIR}" '$2 == a {print $4}' /proc/mounts | head -1)"
dirFSType="$(awk -v a="${ZDIR}/${BIND_DIR}" '$2 == a {print $3}' /proc/mounts | head -1)"
log "DEBUG" "Directory settings - ${dirMountOpt} ${dirFSType}."

createZdevice || return 1

# shellcheck disable=SC2086
if ! ([[ -x $(command -v mkfs.$dirFSType) ]] && mkfs.$dirFSType "/dev/zram${RAM_DEV}" &> /dev/null); then
log "ERROR" "Failed to create filesystem on zram${RAM_DEV}."
log "ERROR" "Failed to create filesystem on /dev/zram${RAM_DEV}."
return 1
fi
mkdir -p "${ZDIR}/zram${RAM_DEV}"
mount --types "$dirFSType" -o "$dirMountOpt" "/dev/zram${RAM_DEV}" "${ZDIR}/zram${RAM_DEV}/" &> /dev/null || retVal=1
mkdir -p "${ZDIR}/zram${RAM_DEV}/upper" "${ZDIR}/zram${RAM_DEV}/workdir" "$TARGET_DIR"
mount --types overlay -o "redirect_dir=on,metacopy=on,lowerdir=${ZDIR}${BIND_DIR},upperdir=${ZDIR}/zram${RAM_DEV}/upper,workdir=${ZDIR}/zram${RAM_DEV}/workdir" "overlay${RAM_DEV}" "$TARGET_DIR" &> /dev/null || retVal=1
mount --types overlay -o "redirect_dir=on,metacopy=on,lowerdir=${ZDIR}/${BIND_DIR},upperdir=${ZDIR}/zram${RAM_DEV}/upper,workdir=${ZDIR}/zram${RAM_DEV}/workdir" "overlay${RAM_DEV}" "$TARGET_DIR" &> /dev/null || retVal=1
chown "${dirUser}:${dirGroup}" "${ZDIR}/zram${RAM_DEV}/upper" "${ZDIR}/zram${RAM_DEV}/workdir" "$TARGET_DIR" &> /dev/null || retVal=1
chmod "$dirPerm" "${ZDIR}/zram${RAM_DEV}/upper" "${ZDIR}/zram${RAM_DEV}/workdir" "$TARGET_DIR" &> /dev/null || retVal=1
if [[ $retVal -ne 0 ]]; then
log "ERROR" "Failed to setup and mount ${ZDIR}/zram${RAM_DEV}."
return 1
fi

echo "${ZTYPE} /zram${RAM_DEV} ${TARGET_DIR} ${BIND_DIR}" >> "$TMPDIR"/zram-device-list
echo "${ZTYPE} zram${RAM_DEV} ${TARGET_DIR}" >> "$TMPDIR"/zram-device-list

if [[ $ZTYPE == "log" ]] && [[ -n $OLDLOG_DIR ]]; then
echo -e "olddir ${OLDLOG_DIR}\\ncreateolddir 755 root root\\nrenamecopy" > /etc/logrotate.d/00_oldlog
Expand All @@ -164,18 +164,18 @@ createZdir() {
}

mergeOverlay() {
log "INFO" "Beginning merge of ${ZDIR}${BIND_DIR}."
if ! overlay merge --force-execution --ignore-mounted --lowerdir="${ZDIR}${BIND_DIR}" --upperdir="${ZDIR}${ZRAM_DEV}/upper" &> /dev/null; then
log "ERROR" "Failed to merge ${ZDIR}${BIND_DIR}."
log "INFO" "Beginning merge of ${ZDIR}/${BIND_DIR}."
if ! overlay merge --force-execution --ignore-mounted --lowerdir="${ZDIR}/${BIND_DIR}" --upperdir="${ZDIR}/${ZRAM_DEV}/upper" &> /dev/null; then
log "ERROR" "Failed to merge ${ZDIR}/${BIND_DIR}."
return 1
fi
log "INFO" "Merge of ${ZDIR}${BIND_DIR} complete."
log "INFO" "Merge of ${ZDIR}/${BIND_DIR} complete."
}

removeZdevice() {
local count=0

log "INFO" "Beginning removal of device /dev${ZRAM_DEV}."
log "INFO" "Beginning removal of device /dev/${ZRAM_DEV}."

if [[ -z $ZRAM_DEV ]]; then
log "ERROR" "Failed to remove zram device, missing required variables."
Expand All @@ -194,7 +194,7 @@ removeZdevice() {
done
fi

log "INFO" "Completed removal of device /dev${ZRAM_DEV}."
log "INFO" "Completed removal of device /dev/${ZRAM_DEV}."
}

umountTarget() {
Expand All @@ -210,7 +210,7 @@ umountTarget() {
removeZdir() {
local retVal=0

log "INFO" "Beginning merge of device /dev${ZRAM_DEV}."
log "INFO" "Beginning merge of device /dev/${ZRAM_DEV}."

[[ -n $OLDLOG_DIR ]] && rm -f /etc/logrotate.d/00_oldlog
[[ -z $TARGET_DIR ]] && retVal=1
Expand All @@ -225,22 +225,22 @@ removeZdir() {

mergeOverlay || return 1

umountTarget "${ZDIR}${ZRAM_DEV}" || return 1
rm -rf "${ZDIR}${ZRAM_DEV}"
umountTarget "${ZDIR}/${ZRAM_DEV}" || return 1
rm -rf "${ZDIR:?}/${ZRAM_DEV}"

umountTarget "${ZDIR}${BIND_DIR}" || return 1
rm -rf "${ZDIR}${BIND_DIR}"
umountTarget "${ZDIR}/${BIND_DIR}" || return 1
rm -rf "${ZDIR:?}/${BIND_DIR}"

log "INFO" "Completed merge of device /dev${ZRAM_DEV}."
log "INFO" "Completed merge of device /dev/${ZRAM_DEV}."

removeZdevice || return 1
}

removeZswap() {
log "INFO" "Beginning removal of swap device."

if [[ -z $SHUTDOWN ]] && ! swapoff "/dev${ZRAM_DEV}" &> /dev/null; then
log "ERROR" "Failed to swapoff /dev${ZRAM_DEV}."
if [[ -z $SHUTDOWN ]] && ! swapoff "/dev/${ZRAM_DEV}" &> /dev/null; then
log "ERROR" "Failed to swapoff /dev/${ZRAM_DEV}."
return 1
fi

Expand All @@ -250,19 +250,19 @@ removeZswap() {
}

syncZdir() {
log "INFO" "Beginning sync of device /dev${ZRAM_DEV}."
log "INFO" "Beginning sync of device /dev/${ZRAM_DEV}."

umountTarget "$TARGET_DIR" || return 1

mergeOverlay || return 1

mkdir -p "${ZDIR}${ZRAM_DEV}/upper" "${ZDIR}${ZRAM_DEV}/workdir" "$TARGET_DIR"
if ! mount --types overlay -o "redirect_dir=on,lowerdir=${ZDIR}${BIND_DIR},upperdir=${ZDIR}${ZRAM_DEV}/upper,workdir=${ZDIR}${ZRAM_DEV}/workdir" "overlay${ZRAM_DEV//[!0-9]/}" "$TARGET_DIR" &> /dev/null; then
log "ERROR" "Failed to remount overlay for ${ZDIR}${BIND_DIR}."
mkdir -p "${ZDIR}/${ZRAM_DEV}/upper" "${ZDIR}/${ZRAM_DEV}/workdir" "$TARGET_DIR"
if ! mount --types overlay -o "redirect_dir=on,lowerdir=${ZDIR}/${BIND_DIR},upperdir=${ZDIR}/${ZRAM_DEV}/upper,workdir=${ZDIR}/${ZRAM_DEV}/workdir" "overlay${ZRAM_DEV//[!0-9]/}" "$TARGET_DIR" &> /dev/null; then
log "ERROR" "Failed to remount overlay for ${ZDIR}/${BIND_DIR}."
return 1
fi

log "INFO" "Completed sync of device /dev${ZRAM_DEV}."
log "INFO" "Completed sync of device /dev/${ZRAM_DEV}."
}

serviceConfiguration() {
Expand Down Expand Up @@ -327,6 +327,10 @@ if systemctl list-jobs | grep -q 'shutdown.target.*start' || systemctl list-jobs
SHUTDOWN="1"
fi

# Remove `bind_dir` and `/path.bind` from ztab for breaking changes
# See https://github.com/ecdye/zram-config/pull/126 for more information
sed -i -E 's/(\tbind_dir|\t\/\w*\.bind)//g' /etc/ztab

case "$1" in
start)
log "INFO" "Starting services."
Expand Down Expand Up @@ -373,8 +377,8 @@ case "$1" in

dir|log)
TARGET_DIR="$5"
BIND_DIR="$6"
OLDLOG_DIR="$7"
BIND_DIR="$(basename "$TARGET_DIR").bind"
OLDLOG_DIR="$6"
serviceConfiguration "stop"
createZdir
;;
Expand Down Expand Up @@ -419,7 +423,7 @@ case "$1" in
dir|log)
ZRAM_DEV="$2"
TARGET_DIR="$3"
BIND_DIR="$4"
BIND_DIR="$(basename "$TARGET_DIR").bind"
serviceConfiguration "stop"
removeZdir
;;
Expand Down Expand Up @@ -456,7 +460,7 @@ case "$1" in
dir|log)
ZRAM_DEV="$2"
TARGET_DIR="$3"
BIND_DIR="$4"
BIND_DIR="$(basename "$TARGET_DIR").bind"
[[ -z $SHUTDOWN ]] && serviceConfiguration "stop"
syncZdir
;;
Expand Down
14 changes: 5 additions & 9 deletions ztab
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@
# which will improve performance in high memory pressure situations.
#
# target_dir is the directory you wish to hold in zram, and the original will be
# moved to a bind mount 'bind_dir' and is synchronized on start, stop, and write
# commands.
#
# bind_dir is the directory where the original directory will be mounted for
# sync purposes. Usually in '/opt' or '/var', name optional.
# moved to a bind mount and is synchronized on start, stop, and write commands.
#
# oldlog_dir will enable log-rotation to an off device directory while retaining
# only live logs in zram. Usually in '/opt' or '/var', name optional.
Expand All @@ -46,8 +42,8 @@
# swap alg mem_limit disk_size swap_priority page-cluster swappiness
swap lzo-rle 250M 750M 75 0 150

# dir alg mem_limit disk_size target_dir bind_dir
#dir lzo-rle 50M 150M /home/pi /pi.bind
# dir alg mem_limit disk_size target_dir
#dir lzo-rle 50M 150M /home/pi

# log alg mem_limit disk_size target_dir bind_dir oldlog_dir
log lzo-rle 50M 150M /var/log /log.bind /opt/zram/oldlog
# log alg mem_limit disk_size target_dir oldlog_dir
log lzo-rle 50M 150M /var/log /opt/zram/oldlog