]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_property: add a new tool to administer fs properties
authorDarrick J. Wong <djwong@kernel.org>
Fri, 26 Jul 2024 22:09:28 +0000 (15:09 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 31 Jul 2024 01:45:40 +0000 (18:45 -0700)
Create a tool to list, get, set, and remove filesystem properties.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
man/man8/xfs_property.8 [new file with mode: 0644]
spaceman/Makefile
spaceman/xfs_property [new file with mode: 0755]

diff --git a/man/man8/xfs_property.8 b/man/man8/xfs_property.8
new file mode 100644 (file)
index 0000000..6324533
--- /dev/null
@@ -0,0 +1,52 @@
+.TH xfs_property 8
+.SH NAME
+xfs_property \- examine and edit properties about an XFS filesystem
+.SH SYNOPSIS
+.B xfs_property
+.I target
+.B get
+.IR name ...
+.br
+.B xfs_property
+.I target
+.B list [ \-v ]
+.br
+.B xfs_property
+.I target
+.B set
+.IR name=value ...
+.br
+.B xfs_property
+.I target
+.B remove
+.IR name ...
+.br
+.B xfs_property \-V
+.SH DESCRIPTION
+.B xfs_property
+retrieves, lists, sets, or removes properties of an XFS filesystem.
+Filesystem properties are root-controlled attributes set on the root directory
+of the filesystem to enable the system administrator to coordinate with
+userspace programs.
+
+.SH COMMANDS
+.TP
+.B get
+.IR name ...
+Prints the values of the given filesystem properties.
+.TP
+.B list
+Lists the names of all filesystem properties.
+If the
+.B -v
+flag is specified, prints the values as well.
+.TP
+.B set
+.IR name = value ...
+Sets the given filesystem properties to the specified values and prints what
+was set.
+.TP
+.B
+remove
+.IR name ...
+Unsets the given filesystem properties.
index 2688b37c770ddd43ef75e98bde03345e8b5c6a61..e914b921de8b500d102e2973ae0809a8d725575e 100644 (file)
@@ -16,7 +16,7 @@ CFILES = \
        init.c \
        prealloc.c \
        trim.c
-LSRCFILES = xfs_info.sh
+LSRCFILES = xfs_info.sh xfs_property
 
 LLDLIBS = $(LIBHANDLE) $(LIBXCMD) $(LIBFROG)
 LTDEPENDENCIES = $(LIBHANDLE) $(LIBXCMD) $(LIBFROG)
@@ -42,6 +42,7 @@ install: default
        $(INSTALL) -m 755 -d $(PKG_SBIN_DIR)
        $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR)
        $(INSTALL) -m 755 xfs_info.sh $(PKG_SBIN_DIR)/xfs_info
+       $(INSTALL) -m 755 xfs_property $(PKG_SBIN_DIR)/xfs_property
 install-dev:
 
 -include .dep
diff --git a/spaceman/xfs_property b/spaceman/xfs_property
new file mode 100755 (executable)
index 0000000..57185fa
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/bash -f
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2024 Oracle.  All Rights Reserved.
+# Author: Darrick J. Wong <djwong@kernel.org>
+#
+
+OPTS=""
+USAGE="Usage: xfs_property [-V] [mountpoint|device|file] [list [-v]|get name...|set name=value...|remove name...]"
+
+# Try to find a loop device associated with a file.  We only want to return
+# one loopdev (multiple loop devices can attach to a single file) so we grab
+# the last line and return it if it's actually a block device.
+try_find_loop_dev_for_file() {
+       local x="$(losetup -O NAME -j "$1" 2> /dev/null | tail -n 1)"
+       test -b "${x}" && echo "${x}"
+}
+
+while getopts "V" c
+do
+       case $c in
+       V)      xfs_spaceman -p xfs_info -V
+               status=$?
+               exit ${status}
+               ;;
+       *)      echo "${USAGE}" 1>&2
+               exit 2
+               ;;
+       esac
+done
+set -- extra "$@"
+shift $OPTIND
+
+if [ $# -lt 2 ]; then
+       echo "${USAGE}" 1>&2
+       exit 2
+fi
+
+target="$1"
+shift
+subcommand="$1"
+shift
+
+db_args=()
+spaceman_args=()
+
+case "$subcommand" in
+"list")
+       vparam=
+       if [ $# -eq 1 ] && [ "$1" = "-v" ]; then
+               vparam=" -v"
+       fi
+       db_args+=('-c' "attr_list -Z${vparam}")
+       spaceman_args+=('-c' "listfsprops${vparam}")
+       ;;
+"get"|"remove"|"set")
+       for arg in "$@"; do
+               db_args+=('-c' "attr_${subcommand} -Z ${arg/=/ }")
+               spaceman_args+=('-c' "${subcommand}fsprops ${arg}")
+       done
+       ;;
+*)
+       echo "${USAGE}" 1>&2
+       exit 2
+esac
+
+# See if we can map the arg to a loop device
+loopdev="$(try_find_loop_dev_for_file "${target}")"
+test -n "${loopdev}" && target="${loopdev}"
+
+# If we find a mountpoint for the device, do a live query; otherwise try
+# reading the fs with xfs_db.
+if mountpt="$(findmnt -t xfs -f -n -o TARGET "${target}" 2> /dev/null)"; then
+       exec xfs_spaceman -p xfs_property "${spaceman_args[@]}" "${mountpt}"
+else
+       exec xfs_db -p xfs_property -x -c 'path /' "${db_args[@]}" "${target}"
+fi