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. Commented 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")' Commented 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")' Commented 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 Commented Aug 10, 2020 at 15:39
  • I have to use sudo to do see some outpur from commands like: btrfs filesystem show <path>. Maybe?? Commented May 29, 2021 at 15:55

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.