summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ball <nullspoon@oper.io>2021-09-26 20:19:50 -0600
committerAaron Ball <nullspoon@oper.io>2021-09-26 20:19:50 -0600
commit7fd96e4fffc25629653210a562e9077405e6fca0 (patch)
tree43d385fea2fd2ce9f494cc152a87f0e0354e01f6
parentfa5eaf860940060f61670a8e41eb58707c3e12c2 (diff)
downloadzmount-emulate-util-linux-mount.tar.gz
zmount-emulate-util-linux-mount.tar.xz
Further refactoring to emulate util-linux mount commandsemulate-util-linux-mount
Previously this script (zmount) worked like an init script, with start, stop, status commands. Now this behaves more like the util-linux mount commands, mount and umount. This provides the commands zmount and zumount. Currently it only supports the `-a` switch, which mounts all or unmounts all zram filesystems. This also provides a makefile for installing these scripts and the corresponding script library to their relevant directories.
-rw-r--r--Makefile15
-rw-r--r--lib/zmount.lib.sh127
-rwxr-xr-xzmount176
-rwxr-xr-xzmount.init11
-rwxr-xr-xzumount97
5 files changed, 288 insertions, 138 deletions
diff --git a/Makefile b/Makefile
index 8a53d46..9ace0dd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,14 @@
.DEFAULT: install
+PREFIX := /usr
+VERSION=1.0
-install:
- install -D -v -m 755 zmount $(DESTDIR)/bin/zmount
- install -D -v -m 755 ztab.example $(DESTDIR)/etc/ztab
+interpolate:
+ if [ ! -d tmp ]; then mkdir -p tmp; fi
+ sed 's/{{ VERSION }}/$(VERSION)/' < zmount > tmp/zmount
+ sed 's/{{ VERSION }}/$(VERSION)/' < zumount > tmp/zumount
+
+install: interpolate
+ install -D -v -m 755 tmp/zmount $(DESTDIR)$(PREFIX)/bin/zmount
+ install -D -v -m 755 tmp/zumount $(DESTDIR)$(PREFIX)/bin/zumount
+ install -D -v -m 644 lib/zmount.lib.sh $(DESTDIR)$(PREFIX)/lib/zmount.lib.sh
+ install -D -v -m 755 ztab.example $(DESTDIR)/etc/ztab
diff --git a/lib/zmount.lib.sh b/lib/zmount.lib.sh
new file mode 100644
index 0000000..5743032
--- /dev/null
+++ b/lib/zmount.lib.sh
@@ -0,0 +1,127 @@
+#!/usr/bin/env bash
+# Zmount automatically configures zram devices with the ztab config file
+# Copyright (C) 2021 Aaron Ball <nullspoon@oper.io>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -euo pipefail
+export IFS=$'\n\t'
+
+
+CONFIG='/etc/ztab'
+RUN='/var/run/zmount'
+
+writelog() { printf '%s\n' "${1}"; }
+error() { writelog "ERROR: ${1}" >&2; }
+
+require_root() {
+ if [ "${UID}" -ne 0 ]; then
+ printf 'Must be run as root\n' >&2
+ return 1
+ fi
+ return 0
+}
+
+zmount.ztab.parseline() {
+ local -a lineargs=()
+ lineargs=($(printf '%s\n' "${1:?}" | tr ' ' '\n'))
+ if [ "${#lineargs[@]}" -ne 5 ]; then
+ error "Line ${1} does not have correct columns"
+ return 1
+ fi
+ printf '%s\n' ${lineargs[@]}
+ return 0
+}
+
+zmount.swap.setup() {
+ local size="${1}"
+ local dev="$(zramctl -f)"
+
+ [ ! -d "${RUN}" ] && mkdir -p ${RUN}
+
+ # Check for existing mounts to avoid duplicates
+ if [ -f "${RUN}/swap" ]; then
+ error 'Zswap device already detected. Skipping duplicate.'
+ return 1
+ fi
+
+ # Create the zram device
+ zramctl "${dev}" -s "${size}" -t "$(( $(nproc) / 2 ))"
+
+ mkswap "${dev}" 2>&1 1>/dev/null
+ swapon "${dev}"
+ printf '%s\n' "${dev}" > "${RUN}/swap"
+}
+
+
+zmount.dir.setup() {
+ local fs="${1}"
+ local size="${2}"
+ local dir="${3}"
+ local opts="${4:-defaults}"
+ local perms="${5:-none}" # Default to 777 to emulate tmpfs
+ local dev="$(zramctl -f)"
+
+ [ ! -d "${RUN}" ] && mkdir -p ${RUN}
+
+ # Check for existing mounts to avoid duplicates
+ if [ -f "${RUN}/${dir//\//_}" ]; then
+ error "Skipping duplicate mount dir ${dir}"
+ return 1
+ fi
+
+ # Create the zram device
+ zramctl "${dev}" -s "${size}" -t "$(( $(nproc) / 2 ))"
+
+ if [ "${fs}" = 'btrfs' ]; then
+ mkfs.btrfs -q "${dev}"
+ elif [ "${fs}" = 'ext2' ]; then
+ mkfs.ext2 -q "${dev}"
+ elif [ "${fs}" = 'ext3' ]; then
+ mkfs.ext3 -q "${dev}"
+ elif [ "${fs}" = 'ext4' ]; then
+ mkfs.ext4 -q "${dev}"
+ elif [ "${fs}" = 'exfat' ]; then
+ mkfs.exfat -q "${dev}"
+ elif [ "${fs}" = 'vfat' ]; then
+ mkfs.vfat -q "${dev}"
+ elif [ "${fs}" = 'xfs' ]; then
+ mkfs.xfs -q "${dev}"
+ else
+ printf 'Unknown filesystem type %s\n' "${fs}"
+ return 1
+ fi
+ mount -o "${opts}" "${dev}" "${dir}"
+ printf '%s\n' "${dev}" > "${RUN}/${dir//\//_}"
+}
+
+zmount.dir.setperms() {
+ local dir="${1}"
+ local permstr="${2}"
+ local perm
+ local -a keyval=()
+
+ [ "${permstr}" = 'none' ] && return 0
+
+ for perm in $(printf '%s\n' ${permstr} | tr ',' '\n'); do
+ keyval=($(printf '%s\n' "${perm}" | tr '=' '\n'))
+ if [ "${keyval[0]}" = 'user' ]; then
+ chown "${keyval[1]}" "${dir}"
+ elif [ "${keyval[0]}" = 'group' ]; then
+ chgrp "${keyval[1]}" "${dir}"
+ elif [ "${keyval[0]}" = 'mode' ]; then
+ chmod "${keyval[1]}" "${dir}"
+ fi
+ done
+}
diff --git a/zmount b/zmount
index 42721f7..c12e73b 100755
--- a/zmount
+++ b/zmount
@@ -18,161 +18,67 @@
set -euo pipefail
export IFS=$'\n\t'
-CONFIG='/etc/ztab'
-RUN='/var/run/zmount'
-
-_parseline() {
- local -a lineargs=()
- lineargs=($(printf '%s\n' "${1:?}" | tr ' ' '\n'))
- if [ "${#lineargs[@]}" -ne 5 ]; then
- printf 'ERROR: Line "%s" does not have correct columns\n' >&2
- return 1
- fi
- printf '%s\n' ${lineargs[@]}
- return 0
-}
-
-_setperms() {
- local dir="${1}"
- local permstr="${2}"
- local perm
- local -a keyval=()
-
- [ "${permstr}" = 'none' ] && return 0
-
- for perm in $(printf '%s\n' ${permstr} | tr ',' '\n'); do
- keyval=($(printf '%s\n' "${perm}" | tr '=' '\n'))
- if [ "${keyval[0]}" = 'user' ]; then
- chown "${keyval[1]}" "${dir}"
- elif [ "${keyval[0]}" = 'group' ]; then
- chgrp "${keyval[1]}" "${dir}"
- elif [ "${keyval[0]}" = 'mode' ]; then
- chmod "${keyval[1]}" "${dir}"
- fi
- done
-}
-
-_setup_dev() {
- local fs="${1}"
- local size="${2}"
- local dir="${3}"
- local opts="${4:-defaults}"
- local perms="${5:-none}" # Default to 777 to emulate tmpfs
-
- local dev="$(zramctl -f)"
- local threads="$(( $(nproc) / 2 ))"
-
- [ ! -d "${RUN}" ] && mkdir -p ${RUN}
-
- # Check for existing mounts to avoid duplicates
- if [ "${fs}" = 'swap' ] && [ -f "${RUN}/swap" ]; then
- printf 'ERROR: Zswap device already detected. Skipping second.\n' >&2
- return 1
- elif [ -f "${RUN}/${dir//\//_}" ]; then
- printf 'ERROR: Skipping duplicate mount dir %s\n' "${dir}" >&2
- return 1
- fi
-
- # Create the zram device
- zramctl "${dev}" -s "${size}" -t "${threads}"
-
- if [ "${fs}" = 'swap' ]; then
- mkswap "${dev}" 2>&1 1>/dev/null
- swapon "${dev}"
- printf '%s\n' "${dev}" > "${RUN}/swap"
- else
- if [ "${fs}" = 'btrfs' ]; then
- mkfs.btrfs -q "${dev}"
- elif [ "${fs}" = 'ext2' ]; then
- mkfs.ext2 -q "${dev}"
- elif [ "${fs}" = 'ext3' ]; then
- mkfs.ext3 -q "${dev}"
- elif [ "${fs}" = 'ext4' ]; then
- mkfs.ext4 -q "${dev}"
- elif [ "${fs}" = 'exfat' ]; then
- mkfs.exfat -q "${dev}"
- elif [ "${fs}" = 'vfat' ]; then
- mkfs.vfat -q "${dev}"
- elif [ "${fs}" = 'xfs' ]; then
- mkfs.xfs -q "${dev}"
- else
- printf 'Unknown filesystem type %s\n' "${fs}"
- return 1
- fi
- mount -o "${opts}" "${dev}" "${dir}"
- printf '%s\n' "${dev}" > "${RUN}/${dir//\//_}"
- fi
-}
+LIBDIR="${LIBDIR:-/usr/lib}"
+source "${LIBDIR}/zmount.lib.sh"
status() { zramctl; }
-start() {
+mountall() {
local -a lineargs=()
- for line in $(grep -v '^#' /etc/ztab); do
- lineargs=($(_parseline "${line}"))
+ for line in $(grep -v '^ *#\|^$' "${CONFIG}"); do
+ lineargs=($(zmount.ztab.parseline "${line}"))
if [ "${lineargs[0]}" = 'swap' ]; then
- printf 'Setting up %s zswap\n' "${lineargs[1]}"
+ writelog "Setting up ${lineargs[1]} zswap"
+ zmount.swap.setup ${lineargs[1]} || continue
else
- printf 'Setting up %s zram dev on %s\n' "${lineargs[1]}" "${lineargs[2]}"
+ writelog "Setting up ${lineargs[1]} zram dev on ${lineargs[2]}"
+ zmount.dir.setup ${lineargs[@]} || continue
+ zmount.dir.setperms "${lineargs[2]}" "${lineargs[4]}"
fi
- _setup_dev ${lineargs[@]}
- _setperms "${lineargs[2]}" "${lineargs[4]}"
done
}
+gethelp() {
+ cat - <<EOF
-stop() {
- local -a lineargs=()
- local fs size dir
-
- for line in $(grep -v '^#' /etc/ztab); do
- lineargs=($(_parseline "${line}"))
- fs="${lineargs[0]}"
- size="${lineargs[1]}"
- dir="${lineargs[2]}"
- # Ignore opts and perms column
-
- if [ "${fs}" = 'swap' ] && [ -f "${RUN}/swap" ]; then
- dev="$(cat ${RUN}/swap)"
- printf 'Stopping %s (mounted as swap)\n' "${dev}"
- swapoff "${dev}"
- rm -f "${RUN}/swap"
- else
- if [ ! -f "${RUN}/${dir//\//_}" ]; then
- printf '%s is already unmounted from %s\n' "${fs}" "${dir}"
- continue
- fi
- dev="$(cat ${RUN}/${dir//\//_})"
- printf 'Stopping %s (mounted on %s)\n' "${dev}" "${dir}"
- umount "${dir}" || : # Ignore unmount failures
- rm -f "${RUN}/${dir//\//_}"
- fi
- zramctl "${dev}" -r
- done
-}
+Usage:
+ zmount [-hV]
+ zmount -a
+ zmount <path>
+Mount zram filesystems.
+
+Options:
+ -a, --all unmount all zram filesystems
+
+ -h, --help display this help
+ -V, --version display version
+
+EOF
+}
main() {
- if [ ${UID} -ne 0 ]; then
- printf 'Must be run as root\n' >&2
- return 1
- fi
+ local -a args=(${@})
# Make sure the zram module is loaded
modprobe zram
- if [ "${1:-}" = 'start' ]; then
- start
- elif [ "${1:-}" = 'stop' ]; then
- stop
- elif [ "${1:-}" = 'status' ]; then
- status
- else
- printf 'usage: %s [start|stop|status]\n' "${0}"
- return 1
- fi
+ # Print status if no args specified
+ [ "${#args[@]}" -eq 0 ] && status && return 0
+
+ for arg in ${args[@]}; do
+ if [ "${arg}" = '-h' ] || [ "${arg}" = '--help' ]; then
+ gethelp
+ elif [ "${arg}" = '-V' ] || [ "${arg}" = '--version' ]; then
+ writelog 'zmount {{ VERSION }}'
+ else
+ if [ "${arg}" = '-a' ]; then
+ require_root && mountall
+ fi
+ fi
+ done
}
main ${@}
diff --git a/zmount.init b/zmount.init
new file mode 100755
index 0000000..99972f1
--- /dev/null
+++ b/zmount.init
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+set -euo pipefail
+export IFS=$'\n\t'
+
+if [ "${1}" = 'start' ]; then
+ zmount -a
+elif [ "${1}" = 'stop' ]; then
+ zumount -a
+elif [ "${1}" = 'status' ]; then
+ zmount
+fi
diff --git a/zumount b/zumount
new file mode 100755
index 0000000..08ad6c5
--- /dev/null
+++ b/zumount
@@ -0,0 +1,97 @@
+#!/usr/bin/env bash
+# Zmount automatically configures zram devices with the ztab config file
+# Copyright (C) 2021 Aaron Ball <nullspoon@oper.io>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -euo pipefail
+export IFS=$'\n\t'
+
+LIBDIR="${LIBDIR:-/usr/lib}"
+source "${LIBDIR}/zmount.lib.sh"
+
+umountall() {
+ local -a lineargs=()
+ local fs size dir
+
+ for line in $(grep -v '^#' "${CONFIG}"); do
+ lineargs=($(zmount.ztab.parseline "${line}"))
+ fs="${lineargs[0]}"
+ size="${lineargs[1]}"
+ dir="${lineargs[2]}"
+ # Ignore opts and perms column
+
+ if [ "${fs}" = 'swap' ] && [ -f "${RUN}/swap" ]; then
+ dev="$(cat ${RUN}/swap)"
+ writelog "Stopping ${dev} (mounted as swap)"
+ swapoff "${dev}"
+ rm -f "${RUN}/swap"
+ else
+ if [ ! -f "${RUN}/${dir//\//_}" ]; then
+ writelog "${fs} is already unmounted from ${dir}"
+ continue
+ fi
+ dev="$(cat ${RUN}/${dir//\//_})"
+ writelog "Stopping ${dev} (mounted on ${dir})"
+ umount "${dir}" || : # Ignore unmount failures
+ rm -f "${RUN}/${dir//\//_}"
+ fi
+ zramctl "${dev}" -r
+ done
+}
+
+gethelp() {
+ cat - <<EOF
+
+Usage:
+ zumount [-hV]
+ zumount -a
+ zumount <path>
+
+Unmount zram filesystems.
+
+Options:
+ -a, --all unmount all zram filesystems
+
+ -h, --help display this help
+ -V, --version display version
+
+EOF
+}
+
+
+main() {
+ local -a args=(${@})
+
+ # Print status if no args specified
+ if [ "${#args[@]}" -eq 0 ]; then
+ printf 'zumount: bad usage\n' >&2
+ printf "Try 'zumount --help' for more information.\n" >&2
+ return 1
+ fi
+
+ for arg in ${args[@]}; do
+ if [ "${arg}" = '-h' ] || [ "${arg}" = '--help' ]; then
+ gethelp
+ elif [ "${arg}" = '-V' ] || [ "${arg}" = '--version' ]; then
+ writelog 'zumount {{ VERSION }}'
+ else
+ if [ "${arg}" = '-a' ]; then
+ require_root && umountall
+ fi
+ fi
+ done
+}
+
+main ${@}

Generated by cgit