15

Is there a convenient way to get information on all btrfs filesystems subvolumes without resorting to C, i.e. in POSIX shell ?

/sys/fs/btrfs contains info only on filesystems, nothing on subvolumes, so currently i end up mounting all filesystems in a temp folder, scanning them with btrfs subvol list, then parsing the resulting output. Needless to say, that is fairly ugly.

This is with a 3.16.x kernel and btrfs-progs v3.14.1 (from stock Ubuntu 14.10).

Below is the (ugly) script I'm currently using. I know I could get the info I need using pure C, and that's probably what I'll end up doing, but I was wondering if there was a simpler, more elegant way.

#!/bin/bash

for i in /sys/fs/btrfs/*[!features]; do 

  device="/dev/$(basename $i/devices/*)"
  mountpoint=/var/lib/btrfs/tmp/mnt/$(basename "$i")

  [ -d "$mountpoint" ] || mkdir "$mountpoint"

  grep -qs $mountpoint /proc/mounts
  [ $? -ne 0 ] && mount -v "$device" "$mountpoint"

  while read -r subvol; do
    # whatever you want
  done < <(btrfs subvolume list "$mountpoint")

  umount $mountpoint
  rmdir $mountpoint
done
2
  • Did you end up writing a C program for this? I'm sure other people would find it useful if you're willing to share.
    – etskinner
    May 5, 2017 at 12:43
  • If fails for me: line 15: syntax error near unexpected token `done' and line 15: ` done < <(btrfs subvolume list "$mountpoint")'
    – Smeterlink
    May 12, 2020 at 4:14

1 Answer 1

6

/sys/fs/btrfs does't list all btrfs filesystem (e.g not mounted one), tested on Debian / Ubuntu (4.14.0-1 / 4.10.0-42).
I would use btrfs progs to search them:

btrfs filesystem show | awk '/ path /{print $NF}'

And since btrfs progs can list subvolumes only of mounted fs, your script is not far from what I would use:

#!/bin/bash

readarray -t btdev < <(sudo btrfs filesystem show | awk '/ path /{print $NF}' )

for i in "${btdev[@]}"; do 

  device="${i}"
  mountpoint=/var/lib/btrfs/tmp/mnt/$(basename "$i")

  [ -d "$mountpoint" ] || mkdir "$mountpoint"

  grep -qs $mountpoint /proc/mounts
  [ $? -ne 0 ] && mount -v "$device" "$mountpoint"

  while read -r subvol; do
    # whatever you want
  done < <(btrfs subvolume list "$mountpoint")

  umount $mountpoint
  rmdir $mountpoint
done

Not tested against multi-device filesystem (raid-0/1/10/5/6)

3
  • Fails for me: line 17: syntax error near unexpected token `done' and line 17: ` done < <(btrfs subvolume list "$mountpoint")'
    – Smeterlink
    May 12, 2020 at 21:24
  • @Smeterlink that's probably because your script got interpreted by another sh than bash, try chmod +x the-script.sh && ./the-script.sh or worst-case bash the-script.sh Aug 10, 2020 at 15:39
  • I have to use sudo to do see some outpur from commands like: btrfs filesystem show <path>. Maybe??
    – will
    May 29, 2021 at 15:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .