4

In GNU/Linux how is the best way to tell the difference between a directory and a btrfs subvolume?

I know they are suppose to look the same, and that's cool. But for maintenance purposes, when I look at a directory, I want to know if its just a directory, or if its instead a subvolume. (For that matter it would also be nice to know if it's mounted or not, and if so how and from where.)

Purpose: I want to revise how my sub-volumes are structured, as suggested for example here. I need a way to see what I'm doing, in order to check what I'm doing. Thanks. :-)


What I've looked at:

The output of ls -d or tree -d show folders, but don't distinguish between directories and btrfs subvolumes. Using ls -l they in-fact look identical.

Even ls --classify and ls --file-type don't seem to clarify this distinction.


Possible solution:

I found that I could check the inode number of a folder, and if it was 256 that would say it's a subvolume. (Refs 1, 2, 3)


So is using inode=256 the best heuristic to distinguish between directories and subvolumes? (I'm assuming that in some underlying file system there might be another reason for an inode to be =256. So to do a definitive check, you would also have to be sure the directory in question was part of a btrfs file system.)

Another approach might be via the command btrfs subversion list . and then parsing the output. You would have to add to this mount | grep /\, or something like that to handle the root mount of a btrfs disk, disks, partition or partitions as the case may be.


Future: I think it would be great if there was some new option on ls that would give information about sub-volumes and mount points, possibly in a format similar to how soft links are displayed, i.e.

$ ls --show-mounts
/ <-- mounted from /dev/sdc
.snapshots <-- subvolume of /
shapshot <-- subvolume of .snapshots mounted to it's folder /2

Background:

  • Directories and subvolumes are vastly different things to manage.

  • You can't use rmdir or rm -rf to remove a subvolume, but instead must use btrfs subvolume delete.

  • And you can't hard link directories or files unless you are within one specific subvolume.

  • Subvolumes appear as being auto-mounted, although they can also be mounted manually to different mount points.

  • If you use snapper or take snapshots, snapshots are actually subvolumes, at least a special type of subvolume.

    For example, your root tree might look partly like this:

    /  
    /.snapshots  
    /.snapshots/1  
    /.snapshots/1/snapshot  
    /.snapshots/2  
    /.snapshots/2/snapshot  
    ...
    

    Only /1 and /2 are normal directories here, while /, /.snapshots, and /snapshot appear to be btrfs subvolumes.

2
btrfs subvolume show /directory/in/question

Most likely you need sudo. The command will succeed if it's a subvolume; it will fail otherwise. You can redirect output to /dev/null and rely solely on the exit status.

This will test every directory available in the directory tree:

sudo find / -type d -exec sh -c '
   for d do
      btrfs subvolume show "$d" >/dev/null 2>&1 && printf "%s\n" "$d"
   done' find-sh {} +

You may want to exclude paths that are beyond suspicion. The following code excludes /proc, /sys and /dev:

sudo find / -type d \( \
     \( -path /proc -prune \) -o \
     \( -path /sys -prune \) -o \
     \( -path /dev -prune \) -o \
     \( -exec sh -c '
        for d do
           btrfs subvolume show "$d" >/dev/null 2>&1 && printf "%s\n" "$d"
        done
     ' find-sh {} + \) \)
| improve this answer | |
1

The st_dev field returned by stat(2), called ID of device containing file, is different across BTRFS subvolumes as well as across filesystems. Using the command line, that is

if [ btrfs != "$(findmnt -noFSTYPE --target=.)" ]
then
    echo "not btrfs"
elif findmnt . >/dev/null
then
    echo "btrfs mountpoint"
elif [ "$(stat -c%d .)" -ne "$(stat -c%d ..)" ]
then
    echo "btrfs subvolume"
else
    echo "btrfs directory"
fi
| improve this answer | |
  • 1
    Sorry, but doesn't work. Shows what 'device', not if the device is a btrfs, or if btrfs subvolume. – Elliptical view Feb 17 at 6:09
  • Compare st_dev against that of the parent directory. They're different for subvolumes. See my edit. – izmw1cfg Feb 18 at 2:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.