From a49eaeb9f6c0c30252a09ba532401d1bf5aeb028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Tue, 16 Apr 2024 09:58:45 +0200 Subject: [PATCH 1/5] feat: detect and report buggy versions of btrfs-progs --- btrfs-list | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/btrfs-list b/btrfs-list index 54cc335..ed79359 100755 --- a/btrfs-list +++ b/btrfs-list @@ -452,6 +452,15 @@ if (version->declare($version)->numify lt version->declare("3.18")->numify && !$ exit 1; } ## end if (version->declare($version...)) +if ($version_verbatim eq '6.1' && !$opt_ignore_version_check) { + warning(2, + "the btrfs-progs version you're using, " . "v$version_verbatim, is known to be missing subvolume uuids."); +} +elsif ($version_verbatim eq '5.15' && !$opt_ignore_version_check) { + warning(2, + "the btrfs-progs version you're using, " . "v$version_verbatim, is known to report free fs space incorrectly."); +} + if ($< != 0 && !$opt_ignore_root_check) { print STDERR "FATAL: you must be root to use this command\n"; print STDERR "If you think this is in error, use --ignore-root-check\n"; From 1b6fd9d42efcbc50af8753adddbd400fca05c108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Tue, 16 Apr 2024 09:58:59 +0200 Subject: [PATCH 2/5] feat: add btrfs-progs v5.10.1 bug workaround --- btrfs-list | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/btrfs-list b/btrfs-list index ed79359..70222f6 100755 --- a/btrfs-list +++ b/btrfs-list @@ -140,6 +140,8 @@ GetOptions( 'd|deleted' => \my $opt_deleted, ) or die "FATAL: Error parsing arguments, aborting\n"; +$opt_quiet ||= 0; + sub debug { return if !$opt_debug; print STDERR $_ . "\n" for @_; @@ -557,6 +559,11 @@ foreach (@fishow) { if (not exists $filesystems{$fuuid}) { $filesystems{$fuuid} = {uuid => $fuuid, label => $label, devices => [], devinfo => {}}; } + # btrfs-progs v5.10.1 bug workaround: "dm-X" instead of "/dev/dm-X" + if ($dev && $dev =~ m{^dm-}) { + debug("Applying workaround $dev => /dev/$dev"); + $dev = "/dev/$dev"; + } if (-l $dev) { $dev = link2real($dev); } From 10a3e258ab4fbb121f87b33e40647e2dc6882ecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Tue, 16 Apr 2024 10:45:22 +0200 Subject: [PATCH 3/5] feat: add --used --- btrfs-list | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/btrfs-list b/btrfs-list index 70222f6..1036acc 100755 --- a/btrfs-list +++ b/btrfs-list @@ -73,6 +73,7 @@ If no mountpoints are specified, display info for all btrfs filesystems. --snap-max-excl SIZE hide snapshots whose exclusively allocated extents take up more space than SIZE -f, --free-space only show free space on the filesystem + -u, --used display used space instead of free space -p, --profile PROFILE override data profile detection and consider it as 'dup', 'single', 'raid0', 'raid1', @@ -138,6 +139,7 @@ GetOptions( 'r|raw' => \my $opt_raw, 'btrfs-binary=s' => \my $opt_btrfs_binary, 'd|deleted' => \my $opt_deleted, + 'u|used' => \my $opt_used, ) or die "FATAL: Error parsing arguments, aborting\n"; $opt_quiet ||= 0; @@ -1118,13 +1120,25 @@ foreach my $line (@orderedAll) { if (exists $line->{free}) { my $displayProfile = $line->{profile}; $displayProfile .= "/" . $line->{mprofile} if ($line->{profile} ne $line->{mprofile}); - $extra = sprintf( - "(%s, %s/%s free, %.02f%%", - $displayProfile, - pretty_print_str($line->{free}, 2), - pretty_print_str($line->{fssize}, 2), - $line->{free} * 100 / $line->{fssize} - ); + if (!$opt_used) { + $extra = sprintf( + "(%s, %s/%s free, %.02f%%", + $displayProfile, + pretty_print_str($line->{free}, 2), + pretty_print_str($line->{fssize}, 2), + $line->{free} * 100 / $line->{fssize} + ); + } ## end if (!$opt_used) + else { + my $used = $line->{fssize} - $line->{free}; + $extra = sprintf( + "(%s, %s/%s used, %.02f%%", + $displayProfile, + pretty_print_str($used, 2), + pretty_print_str($line->{fssize}, 2), + $used * 100 / $line->{fssize} + ); + } ## end else [ if (!$opt_used) ] if ($line->{unallocatable} && $line->{unallocatable} > MiB) { $extra .= sprintf(', %s unallocatable', pretty_print_str($line->{unallocatable}, 2)); } From f8bddd3b2cb41fee0359cab4334a7b76139ed9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Tue, 16 Apr 2024 09:57:37 +0200 Subject: [PATCH 4/5] chore: update README --- README.md | 6 ++++-- btrfs-list | 25 ++++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 5ed1053..c38f38f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Overview -Btrfs is a great filesystem, but its userland tools are not very user-frienfly yet. +Btrfs is a great filesystem, but its userland tools are not very user-friendly yet. As a long-time user, I've developed `btrfs-list` as a wrapper to make sense out of the `btrfs sub list` and `btrfs qgroup show` commands. You need `btrfs-list` if either: @@ -28,7 +28,8 @@ If no mountpoints are specified, display info for all btrfs filesystems. -h, --help display this message --debug enable debug output - -q, --quiet silence the quota disabled & quota rescan warnings + -q, --quiet silence quota disabled & quota rescan warnings, + repeat to silence all other warnings. --version display version info --color WHEN colorize the output; WHEN can be 'never', 'always', or 'auto' (default is: @@ -50,6 +51,7 @@ If no mountpoints are specified, display info for all btrfs filesystems. --snap-max-excl SIZE hide snapshots whose exclusively allocated extents take up more space than SIZE -f, --free-space only show free space on the filesystem + -u, --used display used space instead of free space -p, --profile PROFILE override data profile detection and consider it as 'dup', 'single', 'raid0', 'raid1', diff --git a/btrfs-list b/btrfs-list index 1036acc..edbe2c6 100755 --- a/btrfs-list +++ b/btrfs-list @@ -51,7 +51,8 @@ If no mountpoints are specified, display info for all btrfs filesystems. -h, --help display this message --debug enable debug output - -q, --quiet silence warnings + -q, --quiet silence quota disabled & quota rescan warnings, + repeat to silence all other warnings. --version display version info --color WHEN colorize the output; WHEN can be 'never', 'always', or 'auto' (default is: @@ -110,7 +111,7 @@ GetOptions( 'version' => \my $opt_version, 'ignore-version-check' => \my $opt_ignore_version_check, 'ignore-root-check' => \my $opt_ignore_root_check, - 'q|quiet' => \my $opt_quiet, + 'q|quiet+' => \my $opt_quiet, 's|hide-snap' => \my $opt_hide_snapshots, 'S|snap-only' => \my $opt_only_snapshots, 'f|free-space' => \my $opt_free_space, @@ -150,6 +151,13 @@ sub debug { return; } +sub warning { + my ($level, @lines) = @_; + return if ($level <= $opt_quiet); + print STDERR "WARNING: $_\n" for @lines; + return; +} ## end sub warning + sub run_cmd { my %params = @_; my $cmd = $params{'cmd'}; @@ -170,13 +178,13 @@ sub run_cmd { while (<$_stdout>) { chomp; debug("stdout: " . $_); - /WARNING:/ and print STDERR $_ . "\n"; + /WARNING: (.+)/ and warning(2, "btrfs-progs: $1"); push @stdout, $_; } ## end while (<$_stdout>) while (<$_stderr>) { chomp; debug("stderr: " . $_); - /WARNING: (?!RAID56 detected, not implemented)/ and print STDERR $_ . "\n"; + /WARNING: (RAID56 detected, not implemented)/ and warning(2, "btrfs-progs: $1"); if (!$silent_stderr) { print join(' ', @$cmd) . ": stderr: " . $_ . "\n"; } @@ -690,7 +698,7 @@ foreach my $fuuid (keys %filesystems) { $profile = $opt_profile if defined $opt_profile; if (!$profile) { - print STDERR "WARNING: No profile found, assuming single\n"; + warning(2, "No profile found, assuming single"); $profile = "single"; } @@ -838,7 +846,7 @@ foreach my $fuuid (keys %filesystems) { $cmd = run_cmd(silent_stderr => 1, cmd => [qw{ btrfs quota rescan -s }, $mp]); if ($cmd->{stdout}->[0] && $cmd->{stdout}->[0] =~ /operation running|current key/) { - print STDERR "WARNING: a quota rescan is running, size information is not correct yet\n" if not $opt_quiet; + warning(1, "a quota rescan is running, size information is not correct yet"); } $cmd = run_cmd(silent_stderr => 1, cmd => [qw{ btrfs qgroup show -pcre --raw }, $mp]); @@ -847,8 +855,7 @@ foreach my $fuuid (keys %filesystems) { # btrfs-progs v3.18 doesn't support --raw $cmd = run_cmd(silent_stderr => 1, cmd => [qw{ btrfs qgroup show -pcre }, $mp]); if ($cmd->{status} || !@{$cmd->{stdout}}) { - print STDERR "WARNING: to get refer/excl size information, please enable qgroups (btrfs quota enable $mp)\n" - if not $opt_quiet; + warning(1, "to get refer/excl size information, please enable qgroups (btrfs quota enable $mp)"); $vol{$fuuid}{df}{noquota} = 1; } } ## end if ($cmd->{status} || ...) @@ -1009,7 +1016,7 @@ foreach my $fuuid (sort keys %filesystems) { # do we still have unseen volumes? (we shouldn't) foreach my $vuuid (keys %{$vol{$fuuid}}) { next if $seen{$vuuid}; - print STDERR "WARN: we shouldn't have orphaned volumne $vuuid\n"; + warning(2, "we shouldn't have orphaned volumne $vuuid"); push @ordered, $vuuid; } From a09ec3816272883877b5396f086ccca2b8b7ec0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Tue, 16 Apr 2024 10:49:43 +0200 Subject: [PATCH 5/5] release v2.3 --- btrfs-list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btrfs-list b/btrfs-list index edbe2c6..6c61cfb 100755 --- a/btrfs-list +++ b/btrfs-list @@ -26,7 +26,7 @@ use Getopt::Long qw{ :config gnu_getopt no_ignore_case }; use Data::Dumper; use Term::ANSIColor; -my $VERSION = "2.2"; +my $VERSION = "2.3"; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Terse = 1;