+
+ $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 $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, $g, $_, canonical_dev ($_, $n));
+ }
+ foreach (filter_partitions (\@devs, @partitions)) {
+ try_df ($name, $g, $_, canonical_dev ($_, $n));
+ }
+ if ($has_lvm2) {
+ foreach ($g->lvs ()) {
+ try_df ($name, $g, $_);
+ }
+ }
+
+ $n += $nr_disks;
+ }
+ };
+ warn if $@;
+}
+
+sub filter_partitions
+{
+ my $devs = shift;
+ my @devs = @$devs;
+ my @r;
+
+ foreach my $p (@_) {
+ foreach my $d (@devs) {
+ if ($p =~ /^$d\d/) {
+ push @r, $p;
+ last;
+ }
+ }
+ }
+
+ return @r;
+}
+
+# Calculate the canonical name for a device.
+# eg: /dev/vdb1 when offset = 1
+# => canonical name is /dev/sda1
+sub canonical_dev
+{
+ local $_;
+ my $dev = shift;
+ my $offset = shift;
+
+ return $dev unless $dev =~ m{^/dev/.d([a-z])(\d*)$};
+ my $disk = $1;
+ my $partnum = $2;
+
+ $disk = chr (ord ($disk) - $offset);
+
+ return "/dev/sd$disk$partnum"
+}
+
+sub try_df
+{
+ local $_;
+ my $domname = shift;
+ my $g = shift;
+ my $dev = shift;
+ my $display = shift || $dev;
+
+ my %stat;
+ eval {
+ $g->mount_ro ($dev, "/");
+ %stat = $g->statvfs ("/");
+ };
+ if (!$@) {
+ print_stat ($domname, $display, \%stat);