diff options
-rw-r--r-- | block.c | 15 | ||||
-rw-r--r-- | block.h | 1 | ||||
-rw-r--r-- | block_int.h | 3 | ||||
-rw-r--r-- | hw/ide/core.c | 7 | ||||
-rw-r--r-- | hw/scsi-disk.c | 4 |
5 files changed, 27 insertions, 3 deletions
@@ -408,6 +408,16 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, } bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); + + /* + * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a + * write cache to the guest. We do need the fdatasync to flush + * out transactions for block allocations, and we maybe have a + * volatile write cache in our backing device to deal with. + */ + if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) + bs->enable_write_cache = 1; + /* Note: for compatibility, we open disk image files as RDWR, and RDONLY as fallback */ if (!(flags & BDRV_O_FILE)) @@ -918,6 +928,11 @@ int bdrv_is_sg(BlockDriverState *bs) return bs->sg; } +int bdrv_enable_write_cache(BlockDriverState *bs) +{ + return bs->enable_write_cache; +} + /* XXX: no longer used */ void bdrv_set_change_cb(BlockDriverState *bs, void (*change_cb)(void *opaque), void *opaque) @@ -135,6 +135,7 @@ int bdrv_get_translation_hint(BlockDriverState *bs); int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); +int bdrv_enable_write_cache(BlockDriverState *bs); int bdrv_is_inserted(BlockDriverState *bs); int bdrv_media_changed(BlockDriverState *bs); int bdrv_is_locked(BlockDriverState *bs); diff --git a/block_int.h b/block_int.h index 3e4b4a387b..f95c80b906 100644 --- a/block_int.h +++ b/block_int.h @@ -158,6 +158,9 @@ struct BlockDriverState { /* the memory alignment required for the buffers handled by this driver */ int buffer_alignment; + /* do we need to tell the quest if we have a volatile write cache? */ + int enable_write_cache; + /* NOTE: the following infos are only hints for real hardware drivers. They are not used by the block driver */ int cyls, heads, secs, translation; diff --git a/hw/ide/core.c b/hw/ide/core.c index fe5bd172af..6fd6dc2477 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -148,8 +148,11 @@ static void ide_identify(IDEState *s) put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10)); /* 14=set to 1, 1=SMART self test, 0=SMART error logging */ put_le16(p + 84, (1 << 14) | 0); - /* 14 = NOP supported, 0=SMART feature set enabled */ - put_le16(p + 85, (1 << 14) | 1); + /* 14 = NOP supported, 5=WCACHE enabled, 0=SMART feature set enabled */ + if (bdrv_enable_write_cache(s->bs)) + put_le16(p + 85, (1 << 14) | (1 << 5) | 1); + else + put_le16(p + 85, (1 << 14) | 1); /* 13=flush_cache_ext,12=flush_cache,10=lba48 */ put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10)); /* 14=set to 1, 1=smart self test, 0=smart error logging */ diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index ffc2654bf9..de8e314b15 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -709,7 +709,9 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, memset(p,0,20); p[0] = 8; p[1] = 0x12; - p[2] = 4; /* WCE */ + if (bdrv_enable_write_cache(s->dinfo->bdrv)) { + p[2] = 4; /* WCE */ + } p += 20; } if ((page == 0x3f || page == 0x2a) |