- $g->launch ();
-
- my @partitions = get_partitions ($g);
-
- # Think of a printable name for this domain. Just choose the
- # first parameter passed to this function, which will work for
- # most cases (it'll either be the domain name or the first disk
- # image name).
- my $domname = $_[0];
-
- # Mount each partition in turn, and if mountable, do a statvfs on it.
- foreach my $partition (@partitions) {
- my %stat;
- eval {
- $g->mount_ro ($partition, "/");
- %stat = $g->statvfs ("/");
- };
- if (!$@) {
- print_stat ($domname, $partition, \%stat);
+ # Code in Sys::Guestfs::Lib dies here if there are no disks at all.
+
+ return @disks;
+}
+
+# Sort the domains by name for display.
+@domains = sort { $a->{name} cmp $b->{name} } @domains;
+
+# Since we got this far, we're somewhat sure we're going to
+# get to print the result, so display the title.
+print_title ();
+
+# To minimize the number of times we have to launch the appliance,
+# shuffle as many domains together as we can, but not exceeding
+# MAX_DISKS per request. If --one-per-guest was requested then only
+# request disks from a single guest each time.
+if ($one_per_guest) {
+ foreach (@domains) {
+ my @request = ( $_ );
+ multi_df (@request);
+ }
+} else {
+ while (@domains) {
+ my $n = 0; # number of disks added so far
+ my @request = ();
+ while (@domains) {
+ my $c = @{$domains[0]->{disks}};
+ if ($c > $max_disks) {
+ warn __x("virt-df: ignoring {name}, it has too many disks ({c} > {max})",
+ name => $domains[0]->{name},
+ c => $c, max => $max_disks);
+ next;
+ }
+ last if $n + $c > $max_disks;
+ $n += $c;
+ push @request, shift (@domains);
+ }
+ multi_df (@request);
+ }
+}
+
+sub multi_df
+{
+ local $_;
+ eval {
+ my $g = Sys::Guestfs->new ();
+
+ my ($d, $disk);
+
+ foreach $d (@_) {
+ foreach $disk (@{$d->{disks}}) {
+ my $filename = $disk->[0];
+ my $format = $disk->[1];
+ my @args = ($filename);
+ push @args, readonly => 1;
+ push @args, format => $format if defined $format;
+ $g->add_drive_opts (@args);
+ }
+ }
+
+ $g->launch ();
+ my $has_lvm2 = feature_available ($g, "lvm2");
+
+ my @devices = $g->list_devices ();
+ my @partitions = $g->list_partitions ();
+
+ my $n = 0;
+ foreach $d (@_) {
+ my $name = $d->{name};
+ my $uuid = $d->{uuid};
+ my $nr_disks = @{$d->{disks}};
+
+ # Filter LVM to only the devices applying to the original domain.
+ my @devs = @devices[$n .. $n+$nr_disks-1];
+ $g->lvm_set_filter (\@devs) if $has_lvm2;
+
+ # Find which whole devices (RHBZ#590167), partitions and LVs
+ # contain mountable filesystems. Stat those which are
+ # mountable, and ignore the others.
+ foreach (@devs) {
+ try_df ($name, $uuid, $g, $_, canonical_dev ($_, $n));
+ }
+ foreach (filter_partitions (\@devs, @partitions)) {
+ try_df ($name, $uuid, $g, $_, canonical_dev ($_, $n));
+ }
+ if ($has_lvm2) {
+ foreach ($g->lvs ()) {
+ try_df ($name, $uuid, $g, $_);
+ }
+ }
+
+ $n += $nr_disks;