qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/3] proper support of FLUSH_CACHE and FLUSH_CACHE_E


From: Jens Axboe
Subject: [Qemu-devel] [PATCH 3/3] proper support of FLUSH_CACHE and FLUSH_CACHE_EXT
Date: Wed, 4 Jan 2006 13:16:53 +0100

Subject: [PATCH] Properly support the ide flush cache commands
From: Jens Axboe <address@hidden>
Date: 1136376567 +0100

Add a ->bdrv_sync() hook to the BlockDriver, as it should know how to
sync the cached state with what is on disk. I updated the raw and dmg
drivers, they just need to fsync() the file descriptor.

This is needed for correctness reasons, as the OS expects drive cached
data to be on platter when FLUSH_CACHE has completed successfully. At
least Linux uses this extensively for journalled file systems, if they
are mounted with the barrier= option.

---

 block-dmg.c |   11 +++++++++++
 block.c     |   19 +++++++++++++++++++
 block_int.h |    1 +
 hw/ide.c    |   18 +++++++++++++++---
 vl.h        |    1 +
 5 files changed, 47 insertions(+), 3 deletions(-)

5a8639e3c23e7e312c5213c15dd40a24eee9b416
diff --git a/block-dmg.c b/block-dmg.c
index 5df7235..486a938 100644
--- a/block-dmg.c
+++ b/block-dmg.c
@@ -269,6 +269,12 @@ static int dmg_read(BlockDriverState *bs
     return 0;
 }
 
+static int dmg_sync(BlockDriverState *bs)
+{
+    BDRVDMGState *s = bs->opaque;
+    return fsync(s->fd);
+}
+
 static void dmg_close(BlockDriverState *bs)
 {
     BDRVDMGState *s = bs->opaque;
@@ -293,5 +299,10 @@ BlockDriver bdrv_dmg = {
     dmg_read,
     NULL,
     dmg_close,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    dmg_sync,
 };
 
diff --git a/block.c b/block.c
index 6924cee..c37f29a 100644
--- a/block.c
+++ b/block.c
@@ -460,6 +460,14 @@ int bdrv_write(BlockDriverState *bs, int
     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
 }
 
+int bdrv_sync(BlockDriverState *bs)
+{
+    if (bs->drv->bdrv_sync)
+       return bs->drv->bdrv_sync(bs);
+
+    return -EIO;
+}
+
 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
 {
     *nb_sectors_ptr = bs->total_sectors;
@@ -752,6 +760,13 @@ static int raw_create(const char *filena
     return 0;
 }
 
+static int raw_sync(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    return fsync(s->fd);
+}
+
+
 BlockDriver bdrv_raw = {
     "raw",
     sizeof(BDRVRawState),
@@ -761,6 +776,10 @@ BlockDriver bdrv_raw = {
     raw_write,
     raw_close,
     raw_create,
+    NULL,
+    NULL,
+    NULL,
+    raw_sync,
 };
 
 void bdrv_init(void)
diff --git a/block_int.h b/block_int.h
index e303816..30e830a 100644
--- a/block_int.h
+++ b/block_int.h
@@ -40,6 +40,7 @@ struct BlockDriver {
                              int nb_sectors, int *pnum);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
+    int (*bdrv_sync)(BlockDriverState *bs);
     struct BlockDriver *next;
 };
 
diff --git a/hw/ide.c b/hw/ide.c
index 6a52347..3aadd9e 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "block_int.h"
 
 /* debug IDE devices */
 //#define DEBUG_IDE
@@ -422,7 +423,7 @@ static void put_le16(uint16_t *p, unsign
 
 static void ide_identify(IDEState *s)
 {
-    uint16_t *p;
+    uint16_t *p, flush_flags = 0;
     unsigned int oldsize;
     char buf[20];
 
@@ -431,6 +432,10 @@ static void ide_identify(IDEState *s)
        return;
     }
 
+    /* flush_cache_ext is bit 13, flush_cache is bit 12 */
+    if (s->bs->drv->bdrv_sync)
+       flush_flags = (1 << 13) | (1 << 12);
+
     memset(s->io_buffer, 0, 512);
     p = (uint16_t *)s->io_buffer;
     put_le16(p + 0, 0x0040);
@@ -473,11 +478,11 @@ static void ide_identify(IDEState *s)
     put_le16(p + 81, 0x16); /* conforms to ata5 */
     put_le16(p + 82, (1 << 14));
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
-    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
+    put_le16(p + 83, (1 << 14) | (1 << 10) | flush_flags);
     put_le16(p + 84, (1 << 14));
     put_le16(p + 85, (1 << 14));
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
-    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
+    put_le16(p + 86, (1 << 14) | (1 << 10) | flush_flags);
     put_le16(p + 87, (1 << 14));
     put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
     put_le16(p + 93, 1 | (1 << 14) | 0x2000);
@@ -1755,6 +1760,13 @@ static void ide_ioport_write(void *opaqu
             break;
         case WIN_FLUSH_CACHE:
         case WIN_FLUSH_CACHE_EXT:
+           if (s->is_cdrom)
+               goto abort_cmd;
+           if (bdrv_sync(s->bs))
+               goto abort_cmd;
+           s->status = READY_STAT;
+            ide_set_irq(s);
+            break;
        case WIN_STANDBYNOW1:
         case WIN_IDLEIMMEDIATE:
            s->status = READY_STAT;
diff --git a/vl.h b/vl.h
index 7a10728..01a1985 100644
--- a/vl.h
+++ b/vl.h
@@ -460,6 +460,7 @@ int bdrv_write(BlockDriverState *bs, int
 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
 int bdrv_commit(BlockDriverState *bs);
 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
+int bdrv_sync(BlockDriverState *bs);
 
 #define BDRV_TYPE_HD     0
 #define BDRV_TYPE_CDROM  1
-- 
1.0.GIT

-- 
Jens Axboe





reply via email to

[Prev in Thread] Current Thread [Next in Thread]