From 58a01fd257b6f190d6a44662fbd78944fbc608aa Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 27 May 2019 16:58:01 +0200 Subject: Modularize --- modules/fs/path.inc | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 modules/fs/path.inc (limited to 'modules/fs') diff --git a/modules/fs/path.inc b/modules/fs/path.inc new file mode 100644 index 0000000..f3a041b --- /dev/null +++ b/modules/fs/path.inc @@ -0,0 +1,112 @@ +#!/bin/ash + +DM_STATE_FILE="/run/openslx/dmsetup.state" +readonly DM_STATE_FILE + +# Return the device corresponding to the given path, or +# empty if it's not mounted from a device (tmpfs, cifs, ...) +fs_path_getdev() { + local _dev + _dev="$( df -P "$1" | awk '$1 ~ "^/dev/" {print $1}' )" + [ -n "$_dev" ] || return 1 + [ -b "$_dev" ] || return 1 + printf "%s" "$_dev" +} + +# Return base mount point of given path +# eg. call with "/mnt/nfs/temp/data", returns "/mnt/nfs" +fs_path_getmountpoint() { + local _mp + _mp="$( df -P "$1" | awk '$6 ~ "^/" {print $6}' )" + [ -n "$_mp" ] || return 1 + [ -d "$_mp" ] || return 1 + printf "%s" "$_mp" +} + +# Get fstype of given directory +fs_path_gettype() { + local _mp + _mp="$( df -P "$1" | awk '$6 ~ "^/" {print $6}' )" + [ -n "$_mp" ] || return 1 + [ -d "$_mp" ] || return 1 + awk '$2 == "'"$_mp"'" {print $3}' '/proc/mounts' +} + +# Helper to check whether given directory resides in RAM, either +# by being mounted as tmpfs or not mounted at all in which case +# we assume the same. Returns 0 if so, 1 if otherwise backed, +# 2 when errors occur. +fs_path_isvolatile() { + [ -z "$1" ] && return 2 + local _dev _mp + _dev="$(fs_path_getdev "$1")" + [ -z "$_dev" ] && return 0 # No result, assume tmpfs + [ "$_dev" = "${_dev#/dev/zram}" ] || return 0 # zram is in RAM, like tmpfs + [ "$_dev" != "${_dev#/dev/mapper/}" ] || return 1 # Doesn't start with /dev/mapper, assume some kind of storage + [ -s "$DM_STATE_FILE" ] || return 2 # No point in continuing + _mp="$(fs_path_getmountpoint "$1")" + [ -z "$_mp" ] && return 2 + # it is a device mapper device, check if it was setup in dracut's initramfs. + grep -qE "^$( regex_escape "${_dev}" )\s+$( regex_escape "${_mp}" )\s+type=0" "$DM_STATE_FILE" +} + +# Return free/total space at given path, in KiB. +# If the given path is backed by a thin pool, snapshot, etc. +# it returns a conservative estimate, considering the remaining +# space of the backing device. +# Returns " " +fs_path_space() { + [ -z "$1" ] && return 1 + local _free _total _dev _type _id _name _bs _tmp _tfree _ttotal + _type="$( fs_path_gettype "$1" )" + [ -z "$_type" ] && return 1 + _free="$( df -P "$1" | awk '$6 ~ "^/" {print $4 " " $2}' )" + case "$_type" in # EASY! + tmpfs|nfs*|cifs) + printf "%s" "$_free" + return + esac + _dev="$( fs_path_getdev "$1" )" + if [ "$_dev" = "${_dev#/dev/mapper/}" ]; then # does *NOT* start with /dev/mapper, assume not device mapped + # In case we start using aufs again, check if it needs special handling... + printf "%s" "$_free" + return + fi + # Split, since we might need to do Min() + _total="${_free#* }" + _free="${_free% *}" + _type="$( dmsetup status "$_dev" | awk '{print $3}' )" + _tfree=0 + _ttotal=0 + case "$_type" in + snapshot) + # Field 4 is used/total in sectors of 512 byte, so divide by two for KiB + _tmp="$( dmsetup status "$_dev" | awk '{split($4, a, "/"); print (a[2] - a[1]) / 2 " " a[2] / 2}' )" + _tfree="${_tmp% *}" + _ttotal="${_tmp#* }" + ;; + thin) + # Determine matching pool + _id="$( dmsetup table "$_dev" | awk '{print $4}' )" + if [ -n "$_id" ]; then + _name="$( cat "/sys/dev/block/${_id}/dm/name" )" + if [ -n "$_name" ]; then + # Get data block size (in sectors of 512 byte) + _bs="$( dmsetup table "$_name" | awk '{print $6}' )" + if [ "$_bs" -gt 0 ]; then + # Field 6 is used/total (in data blocks), so transform into KiB + _tmp="$( dmsetup status "$_name" | awk -v "bs=$_bs" '{split($6, a, "/"); print ((a[2] - a[1]) / 2) * bs " " (a[2] / 2) * bs}' )" + _tfree="${_tmp% *}" + _ttotal="${_tmp#* }" + fi + fi + fi + ;; + esac + if [ "$_tfree" -ge 0 ] && [ "$_ttotal" -gt 0 ]; then + [ "$_tfree" -lt "$_free" ] && _free="$_tfree" + [ "$_ttotal" -lt "$_total" ] && _total="$_ttotal" + fi + printf "%s" "$_free $_total" +} + -- cgit v1.2.3-55-g7522