]> git.proxmox.com Git - qemu-server.git/commitdiff
implement virtio-scsi-pci controller
authorAlexandre Derumier <aderumier@odiso.com>
Mon, 30 Jul 2012 12:58:40 +0000 (14:58 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 31 Jul 2012 09:11:19 +0000 (11:11 +0200)
This add the new virtio-scsi controller support.
http://wiki.qemu.org/Features/VirtioSCSI

Guest need kernel >= 3.4 to support. Windows drivers are also available in last virtio-win

Advantages :

- true scsi controller.(like lsi but a lot faster, around 5% slower than virtio-blk)
- multiples disk by controller (256 for now)
- scsi passthrough
- discard support (great for ssd or thinp storages)
- bootable

Hotplug is not yet available in 1.1. (already available in git)

to define lsi or virtio-scsi-pci controller for scsi disk:

scsihw: lsi|virtio-scsi-pci

default is lsi if not defined.
A megasas controller is comming form qemu 1.2, so we'll able to simply add it in the list of scsi controllers

lsi0 and lsi1 controllers have been renamed to generic scsihw0 and scsihw1,
so we can use them for both lsi or virtio-scsi controller type. (and use same pci slot addr).

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
PVE/QemuServer.pm

index af03bf43162554273f1749134ea9a14ee528afe9..64996ba6eb5e95af4be50fca6a2ec95f75123f58 100644 (file)
@@ -213,6 +213,13 @@ my $confdesc = {
        type => 'string', format => 'dns-name',
        description => "Set a name for the VM. Only used on the configuration web interface.",
     },
+    scsihw => {
+       optional => 1,
+       type => 'string',
+       description => "scsi controller model",
+       enum => [qw(lsi virtio-scsi-pci)],
+       default => 'lsi',
+    },
     description => {
        optional => 1,
        type => 'string',
@@ -962,7 +969,7 @@ sub path_is_scsi {
 }
 
 sub print_drivedevice_full {
-    my ($storecfg, $vmid, $drive) = @_;
+    my ($storecfg, $conf, $vmid, $drive) = @_;
 
     my $device = '';
     my $maxdev = 0;
@@ -971,7 +978,7 @@ sub print_drivedevice_full {
        my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}");
        $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
     } elsif ($drive->{interface} eq 'scsi') {
-       $maxdev = 7;
+       $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7;
        my $controller = int($drive->{index} / $maxdev);
        my $unit = $drive->{index} % $maxdev;
        my $devicetype = 'hd';
@@ -987,7 +994,12 @@ sub print_drivedevice_full {
              $devicetype = 'block' if path_is_scsi($path);
          }
 
-       $device = "scsi-$devicetype,bus=lsi$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
+        if (!$conf->{scsihw} || $conf->{scsihw} eq 'lsi'){
+            $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}" if !$conf->{scsihw} || $conf->{scsihw} eq 'lsi';
+        } else {
+            $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
+        }
+
     } elsif ($drive->{interface} eq 'ide'){
        $maxdev = 2;
        my $controller = int($drive->{index} / $maxdev);
@@ -2266,6 +2278,7 @@ sub config_to_command {
     my $vollist = [];
     my $scsicontroller = {};
     my $ahcicontroller = {};
+    my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
 
     foreach_drive($conf, sub {
        my ($ds, $drive) = @_;
@@ -2289,11 +2302,12 @@ sub config_to_command {
        }
 
         if ($drive->{interface} eq 'scsi') {
-           my $maxdev = 7;
-           my $controller = int($drive->{index} / $maxdev);
-           $pciaddr = print_pci_addr("lsi$controller");
-           push @$cmd, '-device', "lsi,id=lsi$controller$pciaddr" if !$scsicontroller->{$controller};
-           $scsicontroller->{$controller}=1;
+
+           my $maxdev = ($scsihw ne 'lsi') ? 256 : 7;
+           my $controller = int($drive->{index} / $maxdev);
+           $pciaddr = print_pci_addr("scsihw$controller");
+           push @$cmd, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
+           $scsicontroller->{$controller}=1;
         }
 
         if ($drive->{interface} eq 'sata') {
@@ -2304,7 +2318,7 @@ sub config_to_command {
         }
 
        push @$cmd, '-drive',print_drive_full($storecfg, $vmid, $drive);
-       push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
+       push @$cmd, '-device',print_drivedevice_full($storecfg, $conf, $vmid, $drive);
     });
 
     push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
@@ -2411,7 +2425,7 @@ sub vm_deviceplug {
 
     if ($deviceid =~ m/^(virtio)(\d+)$/) {
         return undef if !qemu_driveadd($storecfg, $vmid, $device);
-        my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
+        my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
         qemu_deviceadd($vmid, $devicefull);
         if(!qemu_deviceaddverify($vmid, $deviceid)) {
            qemu_drivedel($vmid, $deviceid);
@@ -2419,17 +2433,19 @@ sub vm_deviceplug {
         }
     }
 
-    if ($deviceid =~ m/^(lsi)(\d+)$/) {
+    if ($deviceid =~ m/^(scsihw)(\d+)$/) {
+        my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
         my $pciaddr = print_pci_addr($deviceid);
-        my $devicefull = "lsi,id=$deviceid$pciaddr";
+        my $devicefull = "$scsihw,id=$deviceid$pciaddr";
         qemu_deviceadd($vmid, $devicefull);
         return undef if(!qemu_deviceaddverify($vmid, $deviceid));
     }
 
     if ($deviceid =~ m/^(scsi)(\d+)$/) {
-        return undef if !qemu_findorcreatelsi($storecfg,$conf, $vmid, $device);
+        return 1 if ($conf->{scsihw} && $conf->{scsihw} ne 'lsi'); #virtio-scsi not yet support hotplug
+        return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
         return undef if !qemu_driveadd($storecfg, $vmid, $device);
-        my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
+        my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
         if(!qemu_deviceadd($vmid, $devicefull)) {
            qemu_drivedel($vmid, $deviceid);
            return undef;
@@ -2559,16 +2575,16 @@ sub qemu_devicedelverify {
     return undef;
 }
 
-sub qemu_findorcreatelsi {
+sub qemu_findorcreatescsihw {
     my ($storecfg, $conf, $vmid, $device) = @_;
 
-    my $maxdev = 7;
+    my $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7;
     my $controller = int($device->{index} / $maxdev);
-    my $lsiid="lsi$controller";
+    my $scsihwid="scsihw$controller";
     my $devices_list = vm_devices_list($vmid);
 
-    if(!defined($devices_list->{$lsiid})) {
-       return undef if !vm_deviceplug($storecfg, $conf, $vmid, $lsiid);
+    if(!defined($devices_list->{$scsihwid})) {
+       return undef if !vm_deviceplug($storecfg, $conf, $vmid, $scsihwid);
     }
     return 1;
 }
@@ -3023,8 +3039,8 @@ sub print_pci_addr {
        #addr2 : first videocard
        balloon0 => { bus => 0, addr => 3 },
        watchdog => { bus => 0, addr => 4 },
-       lsi0 => { bus => 0, addr => 5 },
-       lsi1 => { bus => 0, addr => 6 },
+       scsihw0 => { bus => 0, addr => 5 },
+       scsihw1 => { bus => 0, addr => 6 },
        ahci0 => { bus => 0, addr => 7 },
        virtio0 => { bus => 0, addr => 10 },
        virtio1 => { bus => 0, addr => 11 },