+sub foreach_volid {
+ my ($conf, $func, @param) = @_;
+
+ my $volhash = {};
+
+ my $test_volid = sub {
+ my ($volid, $is_cdrom, $replicate, $shared, $snapname, $size) = @_;
+
+ return if !$volid;
+
+ $volhash->{$volid}->{cdrom} //= 1;
+ $volhash->{$volid}->{cdrom} = 0 if !$is_cdrom;
+
+ $volhash->{$volid}->{replicate} //= 0;
+ $volhash->{$volid}->{replicate} = 1 if $replicate;
+
+ $volhash->{$volid}->{shared} //= 0;
+ $volhash->{$volid}->{shared} = 1 if $shared;
+
+ $volhash->{$volid}->{referenced_in_config} //= 0;
+ $volhash->{$volid}->{referenced_in_config} = 1 if !defined($snapname);
+
+ $volhash->{$volid}->{referenced_in_snapshot}->{$snapname} = 1
+ if defined($snapname);
+ $volhash->{$volid}->{size} = $size if $size;
+ };
+
+ PVE::QemuConfig->foreach_volume($conf, sub {
+ my ($ds, $drive) = @_;
+ $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $drive->{shared}, undef, $drive->{size});
+ });
+
+ foreach my $snapname (keys %{$conf->{snapshots}}) {
+ my $snap = $conf->{snapshots}->{$snapname};
+ $test_volid->($snap->{vmstate}, 0, 1, $snapname);
+ $volhash->{$snap->{vmstate}}->{is_vmstate} = 1 if $snap->{vmstate};
+ PVE::QemuConfig->foreach_volume($snap, sub {
+ my ($ds, $drive) = @_;
+ $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $drive->{shared}, $snapname);
+ });
+ }
+
+ foreach my $volid (keys %$volhash) {
+ &$func($volid, $volhash->{$volid}, @param);
+ }
+}
+