In bash scripting, how could I check elegantly if a specific location is a btrfs subvolume?
I do NOT want to know if the given location is in a btrfs file system (or subvolume). I want to know if the given location is the head of a subvolume.
Ideally, the solution could be written in a bash function so I could write:
if is_btrfs_subvolume $LOCATION; then
# ... stuff ...
fi
An 'elegant' solution would be readable, small in code, small in resource consumption.
A BTRFS subvolume is a part of filesystem with its own independent file/directory hierarchy and inode number namespace. Subvolumes can share file extents. A snapshot is also subvolume, but with a given initial content of the original subvolume. A subvolume has always inode number 256. Note.
directories directly under your Btrfs / along with subvolumes like /timeshift-btrfs . In your OS all these entries would appear under / after mounting the Btrfs / to the OS / . By deriving your OS's root tree from Btrfs /@ you keep it tidy.
Btrfs—short for "B-Tree File System" and frequently pronounced "butter" or "butter eff ess"—is the most advanced filesystem present in the mainline Linux kernel. In some ways, btrfs simply seeks to supplant ext4, the default filesystem for most Linux distributions.
The snapshot feature of the Btrfs filesystem uses the Copy-on-Write (CoW) principle. So, it does not take much disk space, and you can take snapshots of a subvolume instantly. The Btrfs filesystem supports 2 types of snapshots.
As you can see, the test subvolume is created on the Btrfs filesystem mounted on the /data directory. To remove the test Btrfs subvolume, run the following command:
To mount a Btrfs subvolume, you need to know either its name or its ID. You can find the name or the ID of all the Btrfs subvolumes created on the Btrfs filesystem mounted on the /data directory as follows: Let’s mount the projects Btrfs subvolume. The projects Btrfs subvolume has the ID 261.
A Btrfs snapshot is a copy of an entire subvolume. This could be useful in a snapshot-based recovery or backup strategy. For instance, having / separate from /home means you can roll back a system update without affecting user data; conversely, you can back up user data without keeping system files.
The default subvolume (see btrfs subvolume set-default) cannot be deleted and returns error (EPERM) and this is logged to the system log. A subvolume that’s currently involved in send (see btrfs send) also cannot be deleted until the send is finished.
The subvolume is identified by inode number 256, so you can check it simply by
if [ `stat --format=%i /path` -eq 256 ]; then ...; fi
There's also a so called empty-subvolume, ie. if a nested subvolume is snapshotted, this entity will exist in place of the original subvolume. Its inode number is 2.
For a generally reliable check wheter any directory is a subvolume, the filesystem type should be verified as well
stat -f --format=%T /path
Solution1: Using @kdave suggestions:
is_btrfs_subvolume() {
local dir=$1
[ "$(stat -f --format="%T" "$dir")" == "btrfs" ] || return 1
inode="$(stat --format="%i" "$dir")"
case "$inode" in
2|256)
return 0;;
*)
return 1;;
esac
}
Solution2: What I used before (only one call, but probably brittle):
is_btrfs_subvolume() {
btrfs subvolume show "$1" >/dev/null 2>&1
}
EDIT: Corrected and replaced list
by show
as the behavior of list
would not answer correctly on any normal btrfs
directory.
EDIT2: as @kdave didn't post a full version of his superior answer, I added it to my answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With