diff --git a/openrc/dmcache.confd b/openrc/dmcache.confd new file mode 100644 index 0000000..deea0db --- /dev/null +++ b/openrc/dmcache.confd @@ -0,0 +1,74 @@ +# configuration file for dm-cache +# +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright 2023 Forza +# +# Linux Cache admin documentation: +# https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/cache.html +# + +# Mandatory options are: +# dmname, cachedev, metadev, origindev + +# The assembled dm-cache device name +# This will be available in /dev/mapper/ +dmname="dmcache1" + +# The device to use as cache. Usually a fast +# SSad or NVME device +cachedev="/dev/disk/by-partlabel/cache" + +# A small device used to store dm-cache metadata +metadev="/dev/disk/by-partlabel/meta" + +# The origin block device. This is the slow device +# that should be accelerated with dm-cache. +# DO NOT use a filesystem uuid here, but a device ID. +# example: +# origindev="/dev/disk/by-partuuid/ac0ae9b1-8e32-4e33-b641-998bc0298d14" +# origindev="/dev/disk/by-id/ata-WDC_WD10JFCX-68N6GN0_WD-WX52A60PS33D-part1" +origindev="/dev/disk/by-partlabel/data" + +# The following section has optional settings to tune the +# device-mapper options for assembling the cache. +# These are advanced options. Make sure to read the Linux Cache +# documentation before changing these. + +# dm-cache requires the origindev size in 512 byte sectors. +originsize="$(/sbin/blockdev --getsz ${origindev})" + +# Set read-ahead sectors for the mapped device. +# This does not change the read-ahead for the underlying +# devices. +#readahead=256 + +# Cache block size in 512 byte sectors. +# 256 sectors = 128KiB size cache blocks +#cacheblock=256 + +# Write cache mode: writeback, writethrough or passthrough. +#cachemode="1 writethrough" + +# Migration policy decides when to migrate data to/from cache +# and origin device. +#cachepolicy="default" + +# Additional policy arguments. +#cachepolicyargs="0" + + +# 'writethrough' cache (default): +# Write through caching prohibits cachedev content from being +# different from origindev content. This mode only accelerates +# reads, but should allow the origin device to be used without the +# cache dev after a crash. +# +# 'writeback' cache: +# When write back cache is used. Writes are written to the +# cachedev first, before being synced in the background to the +# origindev. +# If the system crashes, the dm-cache must be assembled again +# before use to avoid serious filesystem damage. +# If the cachedev fails, the filesystem can be irrevokably damaged! + + diff --git a/openrc/dmcache.initd b/openrc/dmcache.initd new file mode 100644 index 0000000..4a2f8d4 --- /dev/null +++ b/openrc/dmcache.initd @@ -0,0 +1,115 @@ +#!/sbin/openrc-run +# shellcheck shell=sh + +# dm-cache +# A helper program to setup and manage device-mapper +# cache devices. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright 2023 Forza + +name="dm-cache ${dmname}" +description="Activates dm-cache devices" +extra_started_commands="suspend resume cleaner" +: "${cacheblock:=256}" +: "${cachemode:="1 writethrough"}" +: "${cachepolicy:="default"}" +: "${cachepolicyargs:=0}" +: "${readahead:="auto"}" +# dm-cache requires the origindev size in sectors. +: "${originsize:="$(/sbin/blockdev --getsz "${origindev}")"}" + +depend() { + need dev modules + use lvm + before localmount +} + +checkconfig() { + if [ -z "${origindev}" ]; then + eerror "origindev not set!" + return 1 + fi + if [ -z "${metadev}" ]; then + eerror "metadev not set!" + return 1 + fi + if [ -z "${cachedev}" ]; then + eerror "cachedev not set!" + return 1 + fi + if [ -z "${dmname}" ]; then + eerror "dmname not set!" + return 1 + fi +} + +start() { + checkconfig || return 1 + ebegin "Creating dm-cache ${dmname}" + + if findmnt "${origindev}" > /dev/null; then + eerror "Origin device is already mounted. Aborting." + exit 1 + fi + + dmsetup create "${dmname}" --table "0 ${originsize} cache ${metadev} ${cachedev} ${origindev} ${cacheblock} ${cachemode} ${cachepolicy} ${cachepolicyargs}" --readahead "${readahead}" + eend $? +} + +stop() { + if [ "$RC_RUNLEVEL" = "shutdown" ]; then + if findmnt "/dev/mapper/${dmname}" > /dev/null; then + ewarn "System is shutting down and \"${dmname}\" is still mounted!" + ewarn "Attempting to unmount holders..." + umount --all-targets "/dev/mapper/${dmname}" || eerror "Could not unmount!" + fi + else + if findmnt "/dev/mapper/${dmname}" > /dev/null; then + eerror "Cannot stop dm-cache. \"${dmname}\" is mounted!" + exit 1 + fi + fi + ebegin "Stopping dm-cache ${dmname}" + # Cannot flush or stop a suapended device. + dmsetup resume "${dmname}" + blockdev --flushbufs "/dev/mapper/${dmname}" + einfo "Waiting for flush. This can take a while with large caches..." + dmsetup remove "${dmname}" + exit $? +} + +cleaner() { + # The Cleaner policy attempts to write out cached data + # to the origin device at a higher rate. This is useful + # if you want to remove or decomission the dm-cache. + # Cleaner only makes sense for the 'writeback' mode. + + checkconfig || return 1 + ebegin "Enabling the Cleaner write cache policy." + dmsetup suspend "${dmname}" + dmsetup reload -r --table "0 ${originsize} cache ${metadev} ${cachedev} ${origindev} ${cacheblock} ${cachemode} cleaner 0" "${dmname}" + errorlevel=$? + if [ ! $errorlevel = 0 ]; then + ewarn "Could not change to Cleaner policy" + fi + dmsetup resume "${dmname}" + eend $? +} + +suspend() { + checkconfig || return 1 + if findmnt "/dev/mapper/${dmname}" > /dev/null; then + ewarn "Warning, \"${dmname}\" is mounted!" + fi + ebegin "Suspending \"${dmname}\"" + dmsetup suspend "${dmname}" + eend $? +} + +resume() { + checkconfig || return 1 + ebegin "Resuming \"${dmname}\"" + dmsetup resume "${dmname}" + eend $? +}