mirror of https://github.com/digint/btrbk
btrbk: add action "ls": list all btrfs subvolumes below path
Features: - get mounted filesystems from /proc/self/mountinfo - fetch subvolumes using "btrfs subvolume list" (fast, needs root) - filter and print subvolumes below mount pointpull/293/head
parent
d88221e8bc
commit
7271732f9e
88
btrbk
88
btrbk
|
@ -216,6 +216,12 @@ my %table_formats = (
|
||||||
long => [ qw( tree uuid parent_uuid received_uuid recursion ) ],
|
long => [ qw( tree uuid parent_uuid received_uuid recursion ) ],
|
||||||
raw => [ qw( tree uuid parent_uuid received_uuid recursion ) ],
|
raw => [ qw( tree uuid parent_uuid received_uuid recursion ) ],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fs_list => { table => [ qw( mount_point id flags path ) ],
|
||||||
|
rel => [ qw( mount_point mount_source path subvolume_path subvolume_rel_path ) ],
|
||||||
|
long => [ qw( mount_point mount_source id top_level cgen gen uuid parent_uuid received_uuid flags path ) ],
|
||||||
|
raw => [ qw( mount_point mount_source mount_subvolid id top_level cgen gen uuid parent_uuid received_uuid readonly path subvolume_path ) ],
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
my %backend_cmd_map = (
|
my %backend_cmd_map = (
|
||||||
|
@ -353,6 +359,7 @@ commands:
|
||||||
usage print filesystem usage
|
usage print filesystem usage
|
||||||
origin <subvol> print origin information for subvolume
|
origin <subvol> print origin information for subvolume
|
||||||
diff <from> <to> shows new files between related subvolumes
|
diff <from> <to> shows new files between related subvolumes
|
||||||
|
ls <path> list all btrfs subvolumes below path
|
||||||
|
|
||||||
For additional information, see $PROJECT_HOME
|
For additional information, see $PROJECT_HOME
|
||||||
END_HELP
|
END_HELP
|
||||||
|
@ -4873,7 +4880,7 @@ MAIN:
|
||||||
WARN 'Found option "--progress", but required executable "mbuffer" does not exist on your system. Please install "mbuffer".';
|
WARN 'Found option "--progress", but required executable "mbuffer" does not exist on your system. Please install "mbuffer".';
|
||||||
$show_progress = 0;
|
$show_progress = 0;
|
||||||
}
|
}
|
||||||
my ($action_run, $action_usage, $action_resolve, $action_diff, $action_origin, $action_config_print, $action_list, $action_clean, $action_archive);
|
my ($action_run, $action_usage, $action_resolve, $action_diff, $action_origin, $action_config_print, $action_list, $action_clean, $action_archive, $action_ls);
|
||||||
my @filter_args;
|
my @filter_args;
|
||||||
my @subvol_args;
|
my @subvol_args;
|
||||||
my @dir_args;
|
my @dir_args;
|
||||||
|
@ -4915,6 +4922,12 @@ MAIN:
|
||||||
$action_usage = 1;
|
$action_usage = 1;
|
||||||
@filter_args = @ARGV;
|
@filter_args = @ARGV;
|
||||||
}
|
}
|
||||||
|
elsif ($command eq "ls") {
|
||||||
|
$action_ls = 1;
|
||||||
|
$fallback_default_config = 1;
|
||||||
|
$args_expected_min = $args_expected_max = 1;
|
||||||
|
@dir_args = @ARGV;
|
||||||
|
}
|
||||||
elsif ($command eq "diff") {
|
elsif ($command eq "diff") {
|
||||||
$action_diff = 1;
|
$action_diff = 1;
|
||||||
$fallback_default_config = 1;
|
$fallback_default_config = 1;
|
||||||
|
@ -5156,6 +5169,79 @@ MAIN:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if($action_ls)
|
||||||
|
{
|
||||||
|
#
|
||||||
|
# print accessible subvolumes for local path
|
||||||
|
#
|
||||||
|
my $path = $dir_args[0] || die;
|
||||||
|
my $root_vol = vinfo($path, $config);
|
||||||
|
|
||||||
|
# map url to real path (we need to match against mount points below)
|
||||||
|
my $root_path = system_realpath($root_vol);
|
||||||
|
unless($root_path) {
|
||||||
|
ERROR "Cannot find real path for: $root_vol->{PATH}";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
$root_vol = vinfo($root_path, $config);
|
||||||
|
$root_path .= '/' unless($root_path =~ /\/$/); # append trailing slash
|
||||||
|
|
||||||
|
my $mountinfo = system_list_mountinfo($root_vol) || die;
|
||||||
|
$mountinfo_cache{$root_vol->{MACHINE_ID}} = $mountinfo;
|
||||||
|
|
||||||
|
my @data;
|
||||||
|
my @path_hidden;
|
||||||
|
foreach my $mnt (reverse @$mountinfo) {
|
||||||
|
my $mnt_path = $mnt->{mount_point};
|
||||||
|
$mnt_path .= '/' unless($mnt_path =~ /\/$/); # append trailing slash
|
||||||
|
|
||||||
|
if(($mnt->{fs_type} eq "btrfs") &&
|
||||||
|
(($root_path =~ /^\Q$mnt_path\E/) || ($mnt_path =~ /^\Q$root_path\E/)))
|
||||||
|
{
|
||||||
|
$realpath_cache{$mnt->{mount_point}} = $mnt->{mount_point}; # we know those are real paths, prevents calling readlink in btrfs_mountpoint
|
||||||
|
my $vol = vinfo($mnt->{mount_point}, $config);
|
||||||
|
unless(vinfo_init_root($vol)) {
|
||||||
|
ERROR "Failed to fetch subvolume detail for: $vol->{PRINT}" . ($err ? ": $err" : "");
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $subvol_list = vinfo_subvol_list($vol);
|
||||||
|
foreach my $svol ($vol, @$subvol_list) {
|
||||||
|
my $svol_path = $svol->{PATH};
|
||||||
|
$svol_path .= '/' unless($svol_path =~ /\/$/); # append trailing slash
|
||||||
|
|
||||||
|
next unless($svol_path =~ /^\Q$root_path\E/);
|
||||||
|
|
||||||
|
if(grep { $svol_path =~ /^\Q$_\E/ } @path_hidden) {
|
||||||
|
DEBUG "subvolume is hidden by another mount point: $svol->{PRINT}";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
push @data, {
|
||||||
|
%{$svol->{node}}, # copy node
|
||||||
|
mount_point => $svol->{VINFO_MOUNTPOINT}{PATH},
|
||||||
|
mount_source => $svol->{node}{TREE_ROOT}{host_mount_source},
|
||||||
|
mount_subvolid => $mnt->{MNTOPS}{subvolid},
|
||||||
|
subvolume_path => $svol->{node}{path},
|
||||||
|
subvolume_rel_path => $svol->{node}{REL_PATH},
|
||||||
|
path => $svol->{PATH},
|
||||||
|
flags => ($svol->{node}{readonly} ? "readonly" : undef),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last if($root_path =~ /^\Q$mnt_path\E/);
|
||||||
|
push @path_hidden, ($mnt->{mount_point} . '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
my @sorted = sort { $a->{path} cmp $b->{path} } @data;
|
||||||
|
if($output_format) {
|
||||||
|
print_formatted("fs_list", \@sorted);
|
||||||
|
} else {
|
||||||
|
print join("\n", map { $_->{path} } @sorted) . "\n";
|
||||||
|
}
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# try exclusive lock if set in config or command-line option
|
# try exclusive lock if set in config or command-line option
|
||||||
|
|
Loading…
Reference in New Issue