|
|
#!/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'
}
# Returns true if the given path is the root of a mount point
# Does not normalize!
fs_path_ismountpoint() {
grep -Fq " $1 " /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")"
if [ -z "$_dev" ]; then
# not backed by a device in /dev, check for network shares
local _mtype="$(fs_path_gettype "$1")"
if [ -n "$_mtype" ] && regex_imatch "$_mtype" '^(nfs.?|cifs)$'; then
return 1
fi
# Neither backed by a device nor a cifs/nfs share, assume tmpfs
return 0
fi
[ "$_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 "<free> <total>"
fs_path_space() {
[ -z "$1" ] && return 1
local _free _total _dev _type _id _name _bs _tmp _tused _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[1] " " a[2]}' )"
_tused="${_tmp% *}"
_ttotal="${_tmp#* }"
_tfree=$( echo "($_ttotal - $_tused) / 2" | bc )
_ttotal=$( echo "$_ttotal / 2" | bc )
;;
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 '{split($6, a, "/"); print a[1] " " a[2]}' )"
_tused="${_tmp% *}"
_ttotal="${_tmp#* }"
_tfree=$( echo "(($_ttotal - $_tused) / 2) * $_bs" | bc )
_ttotal=$( echo "($_ttotal / 2) * $_bs" | bc )
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"
}
|