From e900a7b748316b5b5a98e41dde36a0cb8e15be5f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Sep 2009 19:01:15 +0200 Subject: [PATCH] block: add enable_write_cache flag Add a enable_write_cache flag in the block driver state, and use it to decide if we claim to have a volatile write cache that needs controlled flushing from the guest. The flag is off if cache=writethrough is defined because O_DSYNC guarantees that every write goes to stable storage, and it is on for cache=none and cache=writeback. Both scsi-disk and ide now use the new flage, changing from their defaults of always off (ide) or always on (scsi-disk). Signed-off-by: Christoph Hellwig Signed-off-by: Anthony Liguori --- block.c | 15 +++++++++++++++ block.h | 1 + block_int.h | 3 +++ hw/ide/core.c | 7 +++++-- hw/scsi-disk.c | 4 +++- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index 45ad6fb4b9..da0930cbba 100644 --- a/block.c +++ b/block.c @@ -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) diff --git a/block.h b/block.h index ea6905291e..0ae2526531 100644 --- a/block.h +++ b/block.h @@ -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) -- GitLab