qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] ide.c make write cacheing controllable by guest
@ 2008-02-25 18:13 Ian Jackson
  2008-02-25 20:50 ` Jamie Lokier
  0 siblings, 1 reply; 12+ messages in thread
From: Ian Jackson @ 2008-02-25 18:13 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: message body text --]
[-- Type: text/plain, Size: 598 bytes --]

The attached patch implements the ATA write cache feature.  This
enables a guest to control, in the standard way, whether disk writes
are immediately committed to disk before the IDE command completes, or
may be buffered in the host.

In this patch, by default buffering is off, which provides better
reliability but may have a performance impact.  It would be
straightforward to change the default, or perhaps offer a command-line
option, if that would be preferred.

This patch is derived from one which was originally submitted to the
Xen tree by Rik van Riel <riel@redhat.com>.

Regards,
Ian.


[-- Attachment #2: IDE write caching configurability --]
[-- Type: text/plain, Size: 2563 bytes --]

diff --git a/hw/ide.c b/hw/ide.c
index 56a1cda..6668cc9 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -377,6 +377,7 @@ typedef struct IDEState {
     PCIDevice *pci_dev;
     struct BMDMAState *bmdma;
     int drive_serial;
+    int write_cache;
     /* ide regs */
     uint8_t feature;
     uint8_t error;
@@ -553,7 +554,8 @@ static void ide_identify(IDEState *s)
     put_le16(p + 68, 120);
     put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
     put_le16(p + 81, 0x16); /* conforms to ata5 */
-    put_le16(p + 82, (1 << 14));
+    /* 14=nop 5=write_cache */
+    put_le16(p + 82, (1 << 14) | (1 << 5));
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
     put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
     put_le16(p + 84, (1 << 14));
@@ -959,6 +961,9 @@ static void ide_sector_write(IDEState *s)
     if (n > s->req_nb_sectors)
         n = s->req_nb_sectors;
     ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+    if (ret == 0 && !s->write_cache) {
+	ret = bdrv_flush(s->bs);
+    }
     if (ret != 0) {
 	ide_rw_error(s);
 	return;
@@ -1015,6 +1020,13 @@ static void ide_write_dma_cb(void *opaque, int ret)
 
     /* end of transfer ? */
     if (s->nsector == 0) {
+	if (!s->write_cache) {
+	    ret = bdrv_flush(s->bs);
+	    if (ret != 0) {
+		ide_dma_error(s);
+		return;
+	    }
+	}
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s);
     eot:
@@ -2097,7 +2109,17 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             case 0xcc: /* reverting to power-on defaults enable */
             case 0x66: /* reverting to power-on defaults disable */
             case 0x02: /* write cache enable */
+                s->write_cache = 1;
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
             case 0x82: /* write cache disable */
+                s->write_cache = 0;
+                ret = bdrv_flush(s->bs);
+		if (ret != 0) goto abort_cmd;
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
             case 0xaa: /* read look-ahead enable */
             case 0x55: /* read look-ahead disable */
             case 0x05: /* set advanced power management mode */
@@ -2623,6 +2645,7 @@ static void ide_init2(IDEState *ide_state,
         s->irq = irq;
         s->sector_write_timer = qemu_new_timer(vm_clock,
                                                ide_sector_write_timer_cb, s);
+	s->write_cache = 0;
         ide_reset(s);
     }
 }

^ permalink raw reply related	[flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH] ide.c make write cacheing controllable by guest
@ 2008-03-27 18:02 Ian Jackson
  2008-03-27 18:16 ` Paul Brook
  0 siblings, 1 reply; 12+ messages in thread
From: Ian Jackson @ 2008-03-27 18:02 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: message body text --]
[-- Type: text/plain, Size: 269 bytes --]

I submitted this patch earlier but it seems to have been dropped,
perhaps due to the surrounding discussion of fsync vs. fdatasync.

I think this should be applied now and then I'll follow up with
another change to make all of the flushes use fdatasync.

Thanks,
Ian.


[-- Attachment #2: make write cacheing controllable by guest --]
[-- Type: text/plain, Size: 5496 bytes --]

>From 88ec110495c5c837562ceed4171d286bd4f7f470 Mon Sep 17 00:00:00 2001
From: Ian Jackson <iwj@mariner.uk.xensource.com>
Date: Thu, 27 Mar 2008 17:58:45 +0000
Subject: [PATCH] make write cacheing controllable by guest

This patch implements the ATA write cache feature.  This enables a
guest to control, in the standard way, whether disk writes are
immediately committed to disk before the IDE command completes, or may
be buffered in the host.

In this patch, by default buffering is off, which provides better
reliability but may have a performance impact.  It would be
straightforward to change the default, or perhaps offer a command-line
option, if that would be preferred.

This patch is derived from one which was originally submitted to the
Xen tree by Rik van Riel <riel@redhat.com> and includes code to save
the write_cache setting from Samuel Thibault.

From: Rik van Riel <riel@redhat.com>
Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
 hw/ide.c |   34 ++++++++++++++++++++++++++++++----
 1 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/hw/ide.c b/hw/ide.c
index b73dba2..acb2139 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -383,6 +383,7 @@ typedef struct IDEState {
     PCIDevice *pci_dev;
     struct BMDMAState *bmdma;
     int drive_serial;
+    int write_cache;
     /* ide regs */
     uint8_t feature;
     uint8_t error;
@@ -559,7 +560,8 @@ static void ide_identify(IDEState *s)
     put_le16(p + 68, 120);
     put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
     put_le16(p + 81, 0x16); /* conforms to ata5 */
-    put_le16(p + 82, (1 << 14));
+    /* 14=nop 5=write_cache */
+    put_le16(p + 82, (1 << 14) | (1 << 5));
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
     put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
     put_le16(p + 84, (1 << 14));
@@ -965,6 +967,9 @@ static void ide_sector_write(IDEState *s)
     if (n > s->req_nb_sectors)
         n = s->req_nb_sectors;
     ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+    if (ret == 0 && !s->write_cache) {
+	ret = bdrv_flush(s->bs);
+    }
     if (ret != 0) {
 	ide_rw_error(s);
 	return;
@@ -1021,6 +1026,13 @@ static void ide_write_dma_cb(void *opaque, int ret)
 
     /* end of transfer ? */
     if (s->nsector == 0) {
+	if (!s->write_cache) {
+	    ret = bdrv_flush(s->bs);
+	    if (ret != 0) {
+		ide_dma_error(s);
+		return;
+	    }
+	}
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s);
     eot:
@@ -2103,7 +2115,17 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             case 0xcc: /* reverting to power-on defaults enable */
             case 0x66: /* reverting to power-on defaults disable */
             case 0x02: /* write cache enable */
+                s->write_cache = 1;
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
             case 0x82: /* write cache disable */
+                s->write_cache = 0;
+                ret = bdrv_flush(s->bs);
+		if (ret != 0) goto abort_cmd;
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
             case 0xaa: /* read look-ahead enable */
             case 0x55: /* read look-ahead disable */
             case 0x05: /* set advanced power management mode */
@@ -2629,6 +2651,7 @@ static void ide_init2(IDEState *ide_state,
         s->irq = irq;
         s->sector_write_timer = qemu_new_timer(vm_clock,
                                                ide_sector_write_timer_cb, s);
+	s->write_cache = 0;
         ide_reset(s);
     }
 }
@@ -2657,6 +2680,7 @@ static void ide_save(QEMUFile* f, IDEState *s)
     if (s->identify_set) {
         qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
     }
+    qemu_put_8s(f, &s->write_cache);
     qemu_put_8s(f, &s->feature);
     qemu_put_8s(f, &s->error);
     qemu_put_be32s(f, &s->nsector);
@@ -2685,6 +2709,8 @@ static void ide_load(QEMUFile* f, IDEState *s)
     if (s->identify_set) {
         qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
     }
+    if (version_id >= 2)
+	qemu_get_8s(f, &s->write_cache);
     qemu_get_8s(f, &s->feature);
     qemu_get_8s(f, &s->error);
     qemu_get_be32s(f, &s->nsector);
@@ -3029,7 +3055,7 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
     PCIIDEState *d = opaque;
     int ret, i;
 
-    if (version_id != 1)
+    if (version_id != 1 && version_id != 2)
         return -EINVAL;
     ret = pci_device_load(&d->dev, f);
     if (ret < 0)
@@ -3105,7 +3131,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
-    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+    register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
 }
 
 /* hd_table must contain 4 block drivers */
@@ -3143,7 +3169,7 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
-    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+    register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
 }
 
 /***********************************************************/
-- 
1.4.4.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-03-28  9:39 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-25 18:13 [Qemu-devel] [PATCH] ide.c make write cacheing controllable by guest Ian Jackson
2008-02-25 20:50 ` Jamie Lokier
2008-02-26  1:16   ` Chris Wedgwood
2008-02-26  7:32     ` Jamie Lokier
2008-02-26 12:15   ` Ian Jackson
2008-02-26 12:49     ` Jamie Lokier
2008-02-26 16:57       ` Ian Jackson
2008-02-26 17:25         ` Jamie Lokier
2008-02-26 18:11           ` Ian Jackson
  -- strict thread matches above, loose matches on Subject: below --
2008-03-27 18:02 Ian Jackson
2008-03-27 18:16 ` Paul Brook
2008-03-28  9:38   ` Ian Jackson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).