How to distinguish between a directory and a subvolume

btrfsmountsnapper

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.

Best Answer

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 {} + \) \)

Related: How to determine which subvolume a directory/file is on?

Related Question