]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer.pm
clone_disk : cloudinit drive: don't clone snapname
[qemu-server.git] / PVE / QemuServer.pm
index 802315090c4327bf67b671daaed41cecfe831b61..1e9dec61ed6ddc284d23f507a2aa4bd29e23847f 100644 (file)
@@ -1202,8 +1202,7 @@ my $usbdesc = {
 };
 PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
 
-# NOTE: the match-groups of this regex are used in parse_hostpci
-my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
+my $PCIRE = qr/[a-f0-9]{2}:[a-f0-9]{2}(?:\.[a-f0-9])?/;
 my $hostpci_fmt = {
     host => {
        default_key => 1,
@@ -1244,6 +1243,17 @@ EODESCR
        optional => 1,
        default => 0,
     },
+    'mdev' => {
+       type => 'string',
+        format_description => 'string',
+       pattern => '[^/\.:]+',
+       optional => 1,
+       description => <<EODESCR
+The type of mediated device to use.
+An instance of this type will be created on startup of the VM and
+will be cleaned up when the VM stops.
+EODESCR
+    }
 };
 PVE::JSONSchema::register_format('pve-qm-hostpci', $hostpci_fmt);
 
@@ -2101,16 +2111,12 @@ sub parse_hostpci {
     my @idlist = split(/;/, $res->{host});
     delete $res->{host};
     foreach my $id (@idlist) {
-       if ($id =~ /^$PCIRE$/) {
-           if (defined($2)) {
-               push @{$res->{pciid}}, { id => $1, function => $2 };
-           } else {
-               my $pcidevices = PVE::SysFSTools::lspci($1);
-               $res->{pciid} = $pcidevices->{$1};
-           }
-       } else {
-           # should have been caught by parse_property_string already
-           die "failed to parse PCI id: $id\n";
+       if ($id =~ m/\./) { # full id 00:00.1
+           push @{$res->{pciid}}, {
+               id => $id,
+           };
+       } else { # partial id 00:00
+           $res->{pciid} = PVE::SysFSTools::lspci($id);
        }
     }
     return $res;
@@ -3539,6 +3545,14 @@ sub config_to_command {
        }
        my $pcidevices = $d->{pciid};
        my $multifunction = 1 if @$pcidevices > 1;
+       my $sysfspath;
+       if ($d->{mdev} && scalar(@$pcidevices) == 1) {
+           my $id = $pcidevices->[0]->{id};
+           my $uuid = PVE::SysFSTools::generate_mdev_uuid($vmid, $i);
+           $sysfspath = "/sys/bus/pci/devices/0000:$id/$uuid";
+       } elsif ($d->{mdev}) {
+           warn "ignoring mediated device with multifunction device\n";
+       }
 
        my $j=0;
         foreach my $pcidevice (@$pcidevices) {
@@ -3547,7 +3561,13 @@ sub config_to_command {
            $id .= ".$j" if $multifunction;
            my $addr = $pciaddr;
            $addr .= ".$j" if $multifunction;
-           my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
+           my $devicestr = "vfio-pci";
+           if ($sysfspath) {
+               $devicestr .= ",sysfsdev=$sysfspath";
+           } else {
+               $devicestr .= ",host=$pcidevice->{id}";
+           }
+           $devicestr .= ",id=$id$addr";
 
            if($j == 0){
                $devicestr .= "$rombar$xvga";
@@ -5137,15 +5157,21 @@ sub vm_start {
           next if !$d;
          my $pcidevices = $d->{pciid};
          foreach my $pcidevice (@$pcidevices) {
-               my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
+               my $pciid = $pcidevice->{id};
 
                my $info = PVE::SysFSTools::pci_device_info("0000:$pciid");
                die "IOMMU not present\n" if !PVE::SysFSTools::check_iommu_support();
                die "no pci device info for device '$pciid'\n" if !$info;
-               die "can't unbind/bind pci group to vfio '$pciid'\n"
-                   if !PVE::SysFSTools::pci_dev_group_bind_to_vfio($pciid);
-               die "can't reset pci device '$pciid'\n"
-                   if $info->{has_fl_reset} and !PVE::SysFSTools::pci_dev_reset($info);
+
+               if ($d->{mdev}) {
+                   my $uuid = PVE::SysFSTools::generate_mdev_uuid($vmid, $i);
+                   PVE::SysFSTools::pci_create_mdev_device($pciid, $uuid, $d->{mdev});
+               } else {
+                   die "can't unbind/bind pci group to vfio '$pciid'\n"
+                       if !PVE::SysFSTools::pci_dev_group_bind_to_vfio($pciid);
+                   die "can't reset pci device '$pciid'\n"
+                       if $info->{has_fl_reset} and !PVE::SysFSTools::pci_dev_reset($info);
+               }
          }
         }
 
@@ -5385,6 +5411,18 @@ sub vm_stop_cleanup {
            unlink "/var/run/qemu-server/${vmid}.$ext";
        }
 
+       foreach my $key (keys %$conf) {
+           next if $key !~ m/^hostpci(\d+)$/;
+           my $hostpciindex = $1;
+           my $d = parse_hostpci($conf->{$key});
+           my $uuid = PVE::SysFSTools::generate_mdev_uuid($vmid, $hostpciindex);
+
+           foreach my $pci (@{$d->{pciid}}) {
+               my $pciid = $pci->{id};
+               PVE::SysFSTools::pci_cleanup_mdev_device($pciid, $uuid);
+           }
+       }
+
        vmconfig_apply_pending($vmid, $conf, $storecfg) if $apply_pending_changes;
     };
     warn $@ if $@; # avoid errors - just warn
@@ -6617,6 +6655,7 @@ sub clone_disk {
        my $name = undef;
        if (drive_is_cloudinit($drive)) {
            $name = "vm-$newvmid-cloudinit";
+           $snapname = undef;
            # cloudinit only supports raw and qcow2 atm:
            if ($dst_format eq 'qcow2') {
                $name .= '.qcow2';