]> git.proxmox.com Git - qemu-server.git/commitdiff
Add `ssd` property to IDE, SATA, and SCSI drives
authorNick Chevsky <nchevsky@gmail.com>
Sun, 28 Oct 2018 20:41:46 +0000 (16:41 -0400)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 30 Oct 2018 08:22:20 +0000 (09:22 +0100)
When enabled, the `ssd` property exposes drives as SSDs (rather than
rotational hard disks) by setting QEMU's `rotation_rate` property [1,
2] on `ide-hd`, `scsi-block`, and `scsi-hd` devices. This is required
to enable support for TRIM and SSD-specific optimizations in certain
guest operating systems that are limited to emulated controller types
(IDE, AHCI, and non-VirtIO SCSI).

This change also unifies the diverging IDE and SATA code paths in
QemuServer::print_drivedevice_full(), which suffered from:
* Code duplication: The only differences between IDE and SATA were in
bus-unit specification and maximum device counts.
* Inconsistent implementation: The IDE code used the new `ide-hd`
and `ide-cd` device types, whereas SATA still relied on the deprecated
`ide-drive` [3, 4] (which doesn't support `rotation_rate`).
* Different feature sets: The IDE code exposed a `model` property that
the SATA code didn't, even though QEMU supports it for both.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1498042
[2] https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg00698.html
[3] https://www.redhat.com/archives/libvir-list/2012-March/msg00684.html
[4] https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg02024.html

Signed-off-by: Nick Chevsky <nchevsky@gmail.com>
PVE/QemuServer.pm

index 933f54fceb3861db5c949be98f01e4bb6dd77ad6..82c9b9611b2fca16e2bb0da42b8a52ebf759ee38 100644 (file)
@@ -1000,6 +1000,14 @@ my %scsiblock_fmt = (
     },
 );
 
+my %ssd_fmt = (
+    ssd => {
+       type => 'boolean',
+       description => "Whether to expose this drive as an SSD, rather than a rotational hard disk.",
+       optional => 1,
+    },
+);
+
 my $add_throttle_desc = sub {
     my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
     my $d = {
@@ -1047,6 +1055,7 @@ $drivedesc_base{'iops_wr_length'} = { alias => 'iops_wr_max_length' };
 my $ide_fmt = {
     %drivedesc_base,
     %model_fmt,
+    %ssd_fmt,
 };
 PVE::JSONSchema::register_format("pve-qm-ide", $ide_fmt);
 
@@ -1062,6 +1071,7 @@ my $scsi_fmt = {
     %iothread_fmt,
     %queues_fmt,
     %scsiblock_fmt,
+    %ssd_fmt,
 };
 my $scsidesc = {
     optional => 1,
@@ -1072,6 +1082,7 @@ PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
 
 my $sata_fmt = {
     %drivedesc_base,
+    %ssd_fmt,
 };
 my $satadesc = {
     optional => 1,
@@ -1097,6 +1108,7 @@ my $alldrive_fmt = {
     %model_fmt,
     %queues_fmt,
     %scsiblock_fmt,
+    %ssd_fmt,
 };
 
 my $efidisk_fmt = {
@@ -1704,21 +1716,33 @@ sub print_drivedevice_full {
            $device = "scsi-$devicetype,bus=$controller_prefix$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;
+       if ($drive->{ssd} && ($devicetype eq 'block' || $devicetype eq 'hd')) {
+           $device .= ",rotation_rate=1";
+       }
+
+    } elsif ($drive->{interface} eq 'ide' || $drive->{interface} eq 'sata') {
+       my $maxdev = ($drive->{interface} eq 'sata') ? $MAX_SATA_DISKS : 2;
        my $controller = int($drive->{index} / $maxdev);
        my $unit = $drive->{index} % $maxdev;
        my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
 
-       $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
-       if ($devicetype eq 'hd' && (my $model = $drive->{model})) {
-           $model = URI::Escape::uri_unescape($model);
-           $device .= ",model=$model";
+       $device = "ide-$devicetype";
+       if ($drive->{interface} eq 'ide') {
+           $device .= ",bus=ide.$controller,unit=$unit";
+       } else {
+           $device .= ",bus=ahci$controller.$unit";
+       }
+       $device .= ",drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
+
+       if ($devicetype eq 'hd') {
+           if (my $model = $drive->{model}) {
+               $model = URI::Escape::uri_unescape($model);
+               $device .= ",model=$model";
+           }
+           if ($drive->{ssd}) {
+               $device .= ",rotation_rate=1";
+           }
        }
-    } elsif ($drive->{interface} eq 'sata'){
-       my $controller = int($drive->{index} / $MAX_SATA_DISKS);
-       my $unit = $drive->{index} % $MAX_SATA_DISKS;
-       $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
     } elsif ($drive->{interface} eq 'usb') {
        die "implement me";
        #  -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0