allow guest control of the volatile write cache
Subsystems (3)
cover allow guest control of the volatile write cache
This series adds support for the guest to control the volatile write cache setting on disks exported by qemu for ide and virtio. For ide it just wires up the existing SETFEATURES calls, and for virtio it adds a new writeable config space field. SCSI is not supported at this point, as the convoluted callback mess in the SCSI stack doesn't allow commands except for plain WRITEs to read data from guest memory.
The backend is based on the code that Prerna posted a while ago, and not Stefan's /proc based variant. I'm open to either one, but the problem with the /proc based one is that it's Linux-specific.
PATCH 1/4 block: clarify the meaning of BDRV_O_NOCACHE
Change BDRV_O_NOCACHE to only imply bypassing the host OS file cache, but no writeback semantics. All existing callers are changed to also specify BDRV_O_CACHE_WB to give them writeback semantics.
block.c +1 -7
@@ -439,13 +439,7 @@ static int bdrv_open_common(BlockDriverS 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 )) +if (flags &BDRV_O_CACHE_WB ) bs->enable_write_cache =1 ;/*
block/raw-posix.c +1 -1
@@ -154,7 +154,7 @@ static int raw_open_common(BlockDriverSt* and O_DIRECT for no caching. */ if ((bdrv_flags &BDRV_O_NOCACHE )) s->open_flags |=O_DIRECT ; -else if (!(bdrv_flags &BDRV_O_CACHE_WB )) +if (!(bdrv_flags &BDRV_O_CACHE_WB )) s->open_flags |=O_DSYNC ; s->fd =-1 ;
block/raw-win32.c +6 -6
@@ -88,9 +88,9 @@ static int raw_open(BlockDriverState *bs } overlapped =FILE_ATTRIBUTE_NORMAL ; -if ((flags &BDRV_O_NOCACHE )) - overlapped |=FILE_FLAG_NO_BUFFERING |FILE_FLAG_WRITE_THROUGH ; -else if (!(flags &BDRV_O_CACHE_WB )) +if (flags &BDRV_O_NOCACHE ) + overlapped |=FILE_FLAG_NO_BUFFERING ; +if (!(flags &BDRV_O_CACHE_WB )) overlapped |=FILE_FLAG_WRITE_THROUGH ; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL,
@@ -349,9 +349,9 @@ static int hdev_open(BlockDriverState *b create_flags =OPEN_EXISTING ; overlapped =FILE_ATTRIBUTE_NORMAL ; -if ((flags &BDRV_O_NOCACHE )) - overlapped |=FILE_FLAG_NO_BUFFERING |FILE_FLAG_WRITE_THROUGH ; -else if (!(flags &BDRV_O_CACHE_WB )) +if (flags &BDRV_O_NOCACHE ) + overlapped |=FILE_FLAG_NO_BUFFERING ; +if (!(flags &BDRV_O_CACHE_WB )) overlapped |=FILE_FLAG_WRITE_THROUGH ; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL,
blockdev.c +1 -1
@@ -326,7 +326,7 @@ DriveInfo *drive_init(QemuOpts *opts, inif ((buf =qemu_opt_get (opts,"cache" )) !=NULL ) {if (!strcmp (buf,"off" ) || !strcmp (buf,"none" )) { - bdrv_flags |=BDRV_O_NOCACHE ; + bdrv_flags |=BDRV_O_NOCACHE |BDRV_O_CACHE_WB ; }else if (!strcmp (buf,"writeback" )) { bdrv_flags |=BDRV_O_CACHE_WB ; }else if (!strcmp (buf,"unsafe" )) {
qemu-io.c +2 -2
@@ -1655,7 +1655,7 @@ open_f(int argc, char **argv) flags |=BDRV_O_SNAPSHOT ;break ;case 'n' : - flags |=BDRV_O_NOCACHE ; + flags |=BDRV_O_NOCACHE |BDRV_O_CACHE_WB ;break ;case 'r' : readonly =1 ;
@@ -1751,7 +1751,7 @@ int main(int argc, char **argv) flags |=BDRV_O_SNAPSHOT ;break ;case 'n' : - flags |=BDRV_O_NOCACHE ; + flags |=BDRV_O_NOCACHE |BDRV_O_CACHE_WB ;break ;case 'c' :add_user_command (optarg);
qemu-nbd.c +1 -1
@@ -238,7 +238,7 @@ int main(int argc, char **argv) flags |=BDRV_O_SNAPSHOT ;break ;case 'n' : - flags |=BDRV_O_NOCACHE ; + flags |=BDRV_O_NOCACHE |BDRV_O_CACHE_WB ;break ;case 'b' : bindto = optarg;
[Qemu-devel] Re: [PATCH 1/4] block: clarify the meaning of BDRV_O_NOCACHE
Quoted 5 lines · Christoph Hellwig
Change
BDRV_O_NOCACHEto only imply bypassing the host OS file cache, but no writeback semantics. All existing callers are changed to also specifyBDRV_O_CACHE_WBto give them writeback semantics.Signed-off-by Christoph Hellwig <[email protected]>
I think there is one hunk missing:
block/qcow2.c +1 -1
@@ -229,7 +229,7 @@ static int qcow2_open(BlockDriverState *bs, int flags) }/* alloc L2 table/refcount block cache */ - writethrough = ((flags &BDRV_O_CACHE_MASK ) ==0 ); + writethrough = ((flags & (BDRV_O_CACHE_WB |BDRV_O_NO_FLUSH )) ==0 ); s->l2_table_cache =qcow2_cache_create (bs,L2_CACHE_SIZE , writethrough); s->refcount_block_cache =qcow2_cache_create (bs,REFCOUNT_CACHE_SIZE , writethrough);
Stefan
[Qemu-devel] Re: [PATCH 1/4] block: clarify the meaning of BDRV_O_NOCACHE
Am 16.03.2011 10:42, schrieb Stefan Hajnoczi:
Quoted 13 lines · Christoph Hellwig
Quoted 5 lines
Change
BDRV_O_NOCACHEto only imply bypassing the host OS file cache, but no writeback semantics. All existing callers are changed to also specifyBDRV_O_CACHE_WBto give them writeback semantics.Signed-off-by Christoph Hellwig <[email protected]>I think there is one hunk missing:
block/qcow2.c +0
-0
block/qcow2.c static int qcow2_open(BlockDriverState *bs, int flags) · line 235
Quoted 8 lines
block/qcow2.c +1
-1@@ -229,7 +229,7 @@ static int qcow2_open(BlockDriverState *bs, int flags) }/* alloc L2 table/refcount block cache */ - writethrough = ((flags &BDRV_O_CACHE_MASK ) ==0 ); + writethrough = ((flags & (BDRV_O_CACHE_WB |BDRV_O_NO_FLUSH )) ==0 ); s->l2_table_cache =qcow2_cache_create (bs,L2_CACHE_SIZE , writethrough); s->refcount_block_cache =qcow2_cache_create (bs,REFCOUNT_CACHE_SIZE , writethrough);
This one doesn't make a difference. But the intention could be made clearer now that all writeback modes have BDRV_O_CACHE_WB set:
writethrough = ((flags & BDRV_O_CACHE_WB) == 0);
Kevin
[Qemu-devel] Re: [PATCH 1/4] block: clarify the meaning of BDRV_O_NOCACHE
In reply to Stefan Hajnocziblock/qcow2.c static int qcow2_open(BlockDriverState *bs, int flags) · line 232
Quoted 2 lines · Stefan Hajnoczi
block/qcow2.c +1
-1- writethrough = ((flags &BDRV_O_CACHE_MASK ) ==0 ); + writethrough = ((flags & (BDRV_O_CACHE_WB |BDRV_O_NO_FLUSH )) ==0 );
or rather
writethrough = ((flags & (BDRV_O_CACHE_WB) != );
but yes, this code had sneaked in since my initial version.
[Qemu-devel] Re: [PATCH 1/4] block: clarify the meaning of BDRV_O_NOCACHE
Quoted 9 lines · Christoph Hellwig
Quoted 2 lines · Stefan Hajnoczi
- writethrough = ((flags &
BDRV_O_CACHE_MASK) == 0);
+ writethrough = ((flags & (BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH)) == 0);or rather
writethrough = ((flags & (
BDRV_O_CACHE_WB) != );but yes, this code had sneaked in since my initial version.
My intention was that if we don't care about honoring flushes then we might as well use Qcow2Cache. But yes, just checking for cache mode is the clearest.
Stefan
[Qemu-devel] Re: [PATCH 1/4] block: clarify the meaning of BDRV_O_NOCACHE
Am 16.03.2011 18:00, schrieb Stefan Hajnoczi:
Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Stefan Hajnoczi
block/qcow2.c static int qcow2_open(BlockDriverState *bs, int flags) · line 232
Quoted 2 lines
block/qcow2.c +1
-1- writethrough = ((flags &BDRV_O_CACHE_MASK ) ==0 ); + writethrough = ((flags & (BDRV_O_CACHE_WB |BDRV_O_NO_FLUSH )) ==0 );or rather
Quoted 7 lines
Quoted 3 lines
writethrough = ((flags & (BDRV_O_CACHE_WB) != );but yes, this code had sneaked in since my initial version.
My intention was that if we don't care about honoring flushes then we might as well use Qcow2Cache. But yes, just checking for cache mode is the clearest.
You mean for a possible writethrough mode with BDRV_O_NO_FLUSH set? Such a mode doesn't make a lot of sense to me.
Kevin
[Qemu-devel] Re: [PATCH 1/4] block: clarify the meaning of BDRV_O_NOCACHE
Quoted 10 lines · Kevin Wolf
Am 16.03.2011 18:00, schrieb Stefan Hajnoczi:
Quoted 9 lines · Christoph Hellwig
Quoted 8 lines · Stefan Hajnoczi
Quoted 2 lines
- writethrough = ((flags &
BDRV_O_CACHE_MASK) == 0);
+ writethrough = ((flags & (BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH)) == 0);or rather
writethrough = ((flags & (
BDRV_O_CACHE_WB) != );
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
but yes, this code had sneaked in since my initial version.
My intention was that if we don't care about honoring flushes then we might as well use Qcow2Cache. But yes, just checking for cache mode is the clearest.
You mean for a possible writethrough mode with
BDRV_O_NO_FLUSHset? Such a mode doesn't make a lot of sense to me.
Yeah, I guess you're right, we can never have BDRV_O_NO_FLUSH without BDRV_O_CACHE_WB today. I wasn't thinking end-to-end, just looking at the BDRV_O_* flag bits.
Stefan
PATCH 2/4 block: add a helper to change writeback mode on the fly
In reply to Christoph HellwigAdd a new bdrv_change_cache that can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.
All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
block.c +40 -0
@@ -441,6 +441,8 @@ static int bdrv_open_common(BlockDriverSif (flags &BDRV_O_CACHE_WB ) bs->enable_write_cache =1 ; +else + bs->enable_write_cache =0 ;/* * Clear flags that are internal to the block layer before opening the
@@ -651,6 +653,44 @@ unlink_and_fail:return ret; } +static int bdrv_reopen (BlockDriverState *bs,int bdrv_flags) +{ +BlockDriver *drv = bs->drv; +int ret; + +if (bdrv_flags == bs->open_flags) { +return 0 ; + } + +/* Quiesce IO for the given block device */ +qemu_aio_flush (); +bdrv_flush (bs); + +bdrv_close (bs); + ret =bdrv_open (bs, bs->filename, bdrv_flags, drv); + +/* +* A failed attempt to reopen the image file must lead to 'abort()' +*/ +if (ret !=0 ) { +abort (); + } + +return ret; +} + +int bdrv_change_cache (BlockDriverState *bs,bool enable) +{ +int bdrv_flags =0 ; + + bdrv_flags = bs->open_flags & ~BDRV_O_CACHE_WB ; +if (enable) { + bdrv_flags |=BDRV_O_CACHE_WB ; + } + +return bdrv_reopen (bs, bdrv_flags); +} +void bdrv_close (BlockDriverState *bs) {if (bs->drv) {
block.h +1 -0
@@ -87,6 +87,7 @@ int bdrv_pwrite_sync(BlockDriverState *bint bdrv_write_sync (BlockDriverState *bs,int64_t sector_num,const uint8_t *buf,int nb_sectors);int bdrv_truncate (BlockDriverState *bs,int64_t offset); +int bdrv_change_cache (BlockDriverState *bs,bool enable);int64_t bdrv_getlength (BlockDriverState *bs);void bdrv_get_geometry (BlockDriverState *bs,uint64_t *nb_sectors_ptr);void bdrv_guess_geometry (BlockDriverState *bs,int *pcyls,int *pheads,int *psecs);
PATCH 3/4 ide: wire up setfeatures cache control
Wire up the ATA SETFEATURES subcalls that control the volatile write cache to the new bdrv_change_cache helper.
hw/ide/core.c +17 -0
@@ -1700,6 +1700,19 @@ void ide_ioport_write(void *opaque, uint } } +static void ide_setcache (IDEState *s,bool enable) +{ +if (bdrv_change_cache (s->bs, enable)) { +ide_abort_command (s); +ide_set_irq (s->bus); +return ; + } + + s->identify_set =0 ; + + s->status =READY_STAT |SEEK_STAT ; +ide_set_irq (s->bus); +}void ide_exec_cmd (IDEBus *bus,uint32_t val) {
@@ -1855,7 +1868,11 @@ void ide_exec_cmd(IDEBus *bus, uint32_tcase 0xcc :/* reverting to power-on defaults enable */ case 0x66 :/* reverting to power-on defaults disable */ case 0x02 :/* write cache enable */ +ide_setcache (s, true); +break ;case 0x82 :/* write cache disable */ +ide_setcache (s, false); +break ;case 0xaa :/* read look-ahead enable */ case 0x55 :/* read look-ahead disable */ case 0x05 :/* set advanced power management mode */
PATCH 4/4 virtio-blk: add runtime cache control
In reply to Christoph HellwigAdd a new writeable features config space field, which allows the guest to communicate features it wants enabled/disabled at runtime. The only feature defined so far is the status of the volatile write cache.
Also rename the virtio_blk_update_config to virtio_blk_get_config to fit the method naming scheme.
hw/virtio-blk.c +21 -2
@@ -434,7 +434,7 @@ static void virtio_blk_reset(VirtIODevic/* coalesce internal state, copy to pci i/o region 0 */ -static void virtio_blk_update_config (VirtIODevice *vdev,uint8_t *config) +static void virtio_blk_get_config (VirtIODevice *vdev,uint8_t *config) {VirtIOBlock *s =to_virtio_blk (vdev);struct virtio_blk_config blkcfg;
@@ -455,9 +455,26 @@ static void virtio_blk_update_config(Vir blkcfg.alignment_offset =0 ; blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size; blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size; +if (bdrv_enable_write_cache (s->bs)) + blkcfg.features |=VIRTIO_BLK_RT_WCE ;memcpy (config, &blkcfg,sizeof (struct virtio_blk_config )); } +static void virtio_blk_set_config (VirtIODevice *vdev,const uint8_t *config) +{ +VirtIOBlock *s =to_virtio_blk (vdev); +struct virtio_blk_config blkcfg; +bool enable = false; + +memcpy (&blkcfg, config,sizeof (blkcfg)); + +if (blkcfg.features &VIRTIO_BLK_RT_WCE ) + enable = true; + +/* no error reporting, needs to be checked by a config re-read */ +bdrv_change_cache (s->bs, enable); +} +static uint32_t virtio_blk_get_features (VirtIODevice *vdev,uint32_t features) {VirtIOBlock *s =to_virtio_blk (vdev);
@@ -466,6 +483,7 @@ static uint32_t virtio_blk_get_features( features |= (1 <<VIRTIO_BLK_F_GEOMETRY ); features |= (1 <<VIRTIO_BLK_F_TOPOLOGY ); features |= (1 <<VIRTIO_BLK_F_BLK_SIZE ); + features |= (1 <<VIRTIO_BLK_F_DYNAMIC );if (bdrv_enable_write_cache (s->bs)) features |= (1 <<VIRTIO_BLK_F_WCACHE );
@@ -543,7 +561,8 @@ VirtIODevice *virtio_blk_init(DeviceStatsizeof (struct virtio_blk_config ), sizeof(VirtIOBlock)); - s->vdev.get_config = virtio_blk_update_config; + s->vdev.get_config = virtio_blk_get_config; + s->vdev.set_config = virtio_blk_set_config; s->vdev.get_features = virtio_blk_get_features; s->vdev.reset = virtio_blk_reset; s->bs = conf->bs;
hw/virtio-blk.h +3 -0
@@ -33,6 +33,7 @@/* #define VIRTIO_BLK_F_IDENTIFY 8 ATA IDENTIFY supported, DEPRECATED */ #define VIRTIO_BLK_F_WCACHE 9/* write cache enabled */ #define VIRTIO_BLK_F_TOPOLOGY 10/* Topology information is available */ +#define VIRTIO_BLK_F_DYNAMIC 11/* Dynamic features field */ struct virtio_blk_config {
@@ -47,6 +48,8 @@ struct virtio_blk_configuint8_t alignment_offset;uint16_t min_io_size;uint32_t opt_io_size; +uint32_t features; +#define VIRTIO_BLK_RT_WCE (1 << 0) } __attribute__((packed));/* These two define direction. */
[Qemu-devel] Re: [PATCH 2/4] block: add a helper to change writeback mode on the fly
In reply to Christoph HellwigQuoted 30 lines · Christoph Hellwig
Add a new
bdrv_change_cachethat can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
Signed-off-by Christoph Hellwig <[email protected]>Index:
qemu/block.c
===================================================================block.c 2011-03-15 14:57:03.680633093 +0100 renamed from block.c 2011-03-15 11:47:31.285634626 +0100 +7
-0@@ -441,6 +441,8 @@ static int bdrv_open_common(BlockDriverS if (flags & BDRV_O_CACHE_WB) bs->enable_write_cache = 1; + else + bs->enable_write_cache = 0; /* * Clear flags that are internal to the block layer before opening the@@ -651,6 +653,44 @@ unlink_and_fail: return ret; } +static int bdrv_reopen(BlockDriverState *bs, int bdrv_flags) +{ + BlockDriver *drv = bs->drv; + int ret; +
block.c 2011-03-15 14:57:03.680633093 +0100 unlink_and_fail: · line 670
Quoted 10 lines
block.c 2011-03-15 14:57:03.680633093 +0100 renamed from block.c 2011-03-15 11:47:31.285634626 +0100 +10
-0+ if (bdrv_flags == bs->open_flags) { + return 0; + } + + /* Quiesce IO for the given block device */ + qemu_aio_flush(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv);
This will fail for -snapshot disks since the on-disk file is deleted.
In general it would be more robust to keep the original file descriptor around in case the file cannot be opened with the new flags.
Stefan
[Qemu-devel] Re: [PATCH 2/4] block: add a helper to change writeback mode on the fly
Am 16.03.2011 10:49, schrieb Stefan Hajnoczi:
Quoted 44 lines · Christoph Hellwig
Quoted 30 lines
Add a new
bdrv_change_cachethat can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
Signed-off-by Christoph Hellwig <[email protected]>Index:
qemu/block.c
===================================================================block.c 2011-03-15 14:57:03.680633093 +0100 renamed from block.c 2011-03-15 11:47:31.285634626 +0100 +7
-0@@ -441,6 +441,8 @@ static int bdrv_open_common(BlockDriverS if (flags & BDRV_O_CACHE_WB) bs->enable_write_cache = 1; + else + bs->enable_write_cache = 0; /* * Clear flags that are internal to the block layer before opening the@@ -651,6 +653,44 @@ unlink_and_fail: return ret; } +static int bdrv_reopen(BlockDriverState *bs, int bdrv_flags) +{ + BlockDriver *drv = bs->drv; + int ret; +block.c 2011-03-15 14:57:03.680633093 +0100 unlink_and_fail: · line 670
Quoted 10 lines
block.c 2011-03-15 14:57:03.680633093 +0100 renamed from block.c 2011-03-15 11:47:31.285634626 +0100 +10
-0+ if (bdrv_flags == bs->open_flags) { + return 0; + } + + /* Quiesce IO for the given block device */ + qemu_aio_flush(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv);This will fail for -snapshot disks since the on-disk file is deleted.
Quoted 3 lines
In general it would be more robust to keep the original file descriptor around in case the file cannot be opened with the new flags.
Looks like we'll need a bdrv_reopen for protocols?
Kevin
Re: [Qemu-devel] [PATCH 2/4] block: add a helper to change writeback mode on the fly
In reply to Christoph HellwigQuoted 39 lines · Christoph Hellwig
Add a new
bdrv_change_cachethat can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
Signed-off-by Christoph Hellwig <[email protected]>block.c +27
-0+static int bdrv_reopen (BlockDriverState *bs,int bdrv_flags) +{ +BlockDriver *drv = bs->drv; +int ret; + +if (bdrv_flags == bs->open_flags) { +return 0 ; + } + +/* Quiesce IO for the given block device */ +qemu_aio_flush (); +bdrv_flush (bs); + +bdrv_close (bs); + ret =bdrv_open (bs, bs->filename, bdrv_flags, drv); + +/* +* A failed attempt to reopen the image file must lead to 'abort()' +*/ +if (ret !=0 ) { +abort (); + } + +return ret; +} + +int bdrv_change_cache (BlockDriverState *bs,bool enable)
block.c unlink_and_fail: · line 692
Quoted 10 lines
block.c +10
-0+{ +int bdrv_flags =0 ; + + bdrv_flags = bs->open_flags & ~BDRV_O_CACHE_WB ; +if (enable) { + bdrv_flags |=BDRV_O_CACHE_WB ; + } + +return bdrv_reopen (bs, bdrv_flags); +}
Is there any way we can manage todo this *without* closing and re-opening the file descriptor ?
One of the things we're considering for the future is to enable QEMU to be passed open FD(s) for its drives, from the management system, instead of having QEMU open the files itself. This will make it possible to have strong, per-VM selinux isolation for disks stored on NFS. It will also make it easier to let us run QEMU inside a private filesystem namespace (CLONE_NEWNS) and not have to expose any files in that namespace except the QEMU binary & a few device nodes (particularly useful for hotplug since we won't know what files need to be visible inside the private namespace ahead of time).
If QEMU expects to close+reopen any of its disks at any time the guest requests, this will complicate life somewhat
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Re: [Qemu-devel] [PATCH 2/4] block: add a helper to change writeback mode on the fly
Am 17.03.2011 15:44, schrieb Daniel P. Berrange:
Quoted 54 lines · Christoph Hellwig
Quoted 39 lines
Add a new
bdrv_change_cachethat can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
Signed-off-by Christoph Hellwig <[email protected]>block.c +27
-0+static int bdrv_reopen (BlockDriverState *bs,int bdrv_flags) +{ +BlockDriver *drv = bs->drv; +int ret; + +if (bdrv_flags == bs->open_flags) { +return 0 ; + } + +/* Quiesce IO for the given block device */ +qemu_aio_flush (); +bdrv_flush (bs); + +bdrv_close (bs); + ret =bdrv_open (bs, bs->filename, bdrv_flags, drv); + +/* +* A failed attempt to reopen the image file must lead to 'abort()' +*/ +if (ret !=0 ) { +abort (); + } + +return ret; +} + +int bdrv_change_cache (BlockDriverState *bs,bool enable)block.c unlink_and_fail: · line 692
Quoted 10 lines
block.c +10
-0+{ +int bdrv_flags =0 ; + + bdrv_flags = bs->open_flags & ~BDRV_O_CACHE_WB ; +if (enable) { + bdrv_flags |=BDRV_O_CACHE_WB ; + } + +return bdrv_reopen (bs, bdrv_flags); +}Is there any way we can manage todo this *without* closing and re-opening the file descriptor ?
Quoted 3 lines
One of the things we're considering for the future is to enable QEMU to be passed open FD(s) for its drives, from the management system, instead of having QEMU open the files itself.
What about cache mode, read-only flags etc. that are set with the right flags during the open? Must qemu just assume that the management has done the right thing?
And what about things like backing files or other information that depends on the content of the image file?
Quoted 2 lines
If QEMU expects to close+reopen any of its disks at any time the guest requests, this will complicate life somewhat
It does expect this. For example for making backing files temporarily read-write during a 'commit' monitor command, we already reopen the image. (Let's hope nobody uses -snapshot, live snapshots and commit, he would lose his disk...)
Kevin
Re: [Qemu-devel] [PATCH 2/4] block: add a helper to change writeback mode on the fly
Quoted 66 lines · Kevin Wolf
Am 17.03.2011 15:44, schrieb Daniel P. Berrange:
Quoted 54 lines · Christoph Hellwig
Quoted 39 lines
Add a new
bdrv_change_cachethat can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
Signed-off-by Christoph Hellwig <[email protected]>block.c +27
-0+static int bdrv_reopen (BlockDriverState *bs,int bdrv_flags) +{ + BlockDriver *drv = bs->drv; + int ret; + + if (bdrv_flags == bs->open_flags) { + return 0; + } + + /* Quiesce IO for the given block device */ + qemu_aio_flush(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv); + + /* + * A failed attempt to reopen the image file must lead to 'abort()' + */ + if (ret != 0) { + abort(); + } + + return ret; +} + +int bdrv_change_cache (BlockDriverState *bs,bool enable)block.c unlink_and_fail: · line 692
Quoted 10 lines
block.c +10
-0+{ + int bdrv_flags = 0; + + bdrv_flags = bs->open_flags & ~BDRV_O_CACHE_WB; + if (enable) { + bdrv_flags |= BDRV_O_CACHE_WB; + } + + return bdrv_reopen(bs, bdrv_flags); +}Is there any way we can manage todo this *without* closing and re-opening the file descriptor ?
Quoted 3 lines
One of the things we're considering for the future is to enable QEMU to be passed open FD(s) for its drives, from the management system, instead of having QEMU open the files itself.
What about cache mode, read-only flags etc. that are set with the right flags during the open? Must qemu just assume that the management has done the right thing?
And what about things like backing files or other information that depends on the content of the image file?
Quoted 7 lines
Quoted 2 lines
If QEMU expects to close+reopen any of its disks at any time the guest requests, this will complicate life somewhat
It does expect this. For example for making backing files temporarily read-write during a 'commit' monitor command, we already reopen the image. (Let's hope nobody uses -snapshot, live snapshots and commit, he would lose his disk...)
I think we need to use the most robust solution possible. We don't want to get into a situation that can be avoided. Especially in cases where human errors can (==will) be made.
I suggested using /proc/$pid/fd to reopen an existing file descriptor.
That interface is only available on Linux and possibly some of
{Solaris, *BSD, OSX}. So there needs to be a fallback, but in this situation it feels right to take advantage of whatever means are provided by the host OS to make safe transitions between image files.
Stefan
Re: [Qemu-devel] [PATCH 2/4] block: add a helper to change writeback mode on the fly
Quoted 79 lines · Stefan Hajnoczi
Quoted 66 lines · Kevin Wolf
Am 17.03.2011 15:44, schrieb Daniel P. Berrange:
Quoted 54 lines · Christoph Hellwig
Quoted 39 lines
Add a new
bdrv_change_cachethat can set/clear the writeback flag at runtime by stopping all I/O and closing/reopening the image file.All code is based on a patch from Prerna Saxena <[email protected]> with minimal refactoring.
Signed-off-by Christoph Hellwig <[email protected]>block.c +27
-0+static int bdrv_reopen (BlockDriverState *bs,int bdrv_flags) +{ + BlockDriver *drv = bs->drv; + int ret; + + if (bdrv_flags == bs->open_flags) { + return 0; + } + + /* Quiesce IO for the given block device */ + qemu_aio_flush(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv); + + /* + * A failed attempt to reopen the image file must lead to 'abort()' + */ + if (ret != 0) { + abort(); + } + + return ret; +} + +int bdrv_change_cache (BlockDriverState *bs,bool enable)block.c unlink_and_fail: · line 692
Quoted 10 lines
block.c +10
-0+{ + int bdrv_flags = 0; + + bdrv_flags = bs->open_flags & ~BDRV_O_CACHE_WB; + if (enable) { + bdrv_flags |= BDRV_O_CACHE_WB; + } + + return bdrv_reopen(bs, bdrv_flags); +}Is there any way we can manage todo this *without* closing and re-opening the file descriptor ?
Quoted 3 lines
One of the things we're considering for the future is to enable QEMU to be passed open FD(s) for its drives, from the management system, instead of having QEMU open the files itself.
What about cache mode, read-only flags etc. that are set with the right flags during the open? Must qemu just assume that the management has done the right thing?
And what about things like backing files or other information that depends on the content of the image file?
Quoted 7 lines
Quoted 2 lines
If QEMU expects to close+reopen any of its disks at any time the guest requests, this will complicate life somewhat
It does expect this. For example for making backing files temporarily read-write during a 'commit' monitor command, we already reopen the image. (Let's hope nobody uses -snapshot, live snapshots and commit, he would lose his disk...)
I think we need to use the most robust solution possible. We don't want to get into a situation that can be avoided. Especially in cases where human errors can (==will) be made.
Quoted 5 lines
I suggested using
/proc/$pid/fdto reopen an existing file descriptor. That interface is only available on Linux and possibly some of {Solaris, *BSD, OSX}. So there needs to be a fallback, but in this situation it feels right to take advantage of whatever means are provided by the host OS to make safe transitions between image files.
No need for such hacks. There could be an explicit reopen method, which could be implemented differently for each backing file type (file descriptor, file, socket, CDROM devices etc).
RFC PATCH 1/1 virtio_blk: add cache control support
In reply to Christoph HellwigAdd support for the new dynamic features config space field to allow en/disabling the write cache at runtime. The userspace interface is a SCSI-compatible sysfs attribute.
drivers/block/virtio_blk.c +73 -2
@@ -291,6 +291,73 @@ static ssize_t virtblk_serial_show(struc }DEVICE_ATTR (serial,S_IRUGO , virtblk_serial_show,NULL ); +static bool virtblk_has_wb_cache (struct virtio_blk *vblk) +{ +struct virtio_device *vdev = vblk->vdev; +u32 features; + +if (!virtio_has_feature (vdev,VIRTIO_BLK_F_FLUSH )) +return false; +if (!virtio_has_feature (vdev,VIRTIO_BLK_F_DYNAMIC )) +return true; + + vdev->config->get (vdev, offsetof(struct virtio_blk_config , features), + &features,sizeof (features)); + +if (features &VIRTIO_BLK_RT_WCE ) +return true; +return false; +} + +static ssize_t virtblk_cache_type_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct gendisk *disk =dev_to_disk (dev); + +if (virtblk_has_wb_cache (disk->private_data)) +return sprintf (buf,"write back\n" ); +else +return sprintf (buf,"write through\n" ); +} + +static ssize_t virtblk_cache_type_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) +{ +struct gendisk *disk =dev_to_disk (dev); +struct virtio_blk *vblk = disk->private_data; +struct virtio_device *vdev = vblk->vdev; +u32 features, features2 =0 ; + +if (!virtio_has_feature (vdev,VIRTIO_BLK_F_FLUSH ) || + !virtio_has_feature (vdev,VIRTIO_BLK_F_DYNAMIC )) +return -ENXIO ; + +if (strncmp (buf,"write through" ,sizeof ("write through" ) -1 ) ==0 ) { + ; + }else if (strncmp (buf,"write back" ,sizeof ("write back" ) -1 ) ==0 ) { +blk_queue_flush (disk->queue,REQ_FLUSH ); + features |=VIRTIO_BLK_RT_WCE ; + }else { +return -EINVAL ; + } + + vdev->config->set (vdev, offsetof(struct virtio_blk_config , features), + &features,sizeof (features)); + + vdev->config->get (vdev, offsetof(struct virtio_blk_config , features), + &features2,sizeof (features2)); + +if ((features &VIRTIO_BLK_RT_WCE ) != + (features2 &VIRTIO_BLK_RT_WCE )) +return -EIO ; + +if (!(features2 &VIRTIO_BLK_RT_WCE )) +blk_queue_flush (disk->queue,0 ); +return count; +} +static DEVICE_ATTR(cache_type, S_IRUGO|S_IWUSR, + virtblk_cache_type_show, virtblk_cache_type_store); +static int __devinit virtblk_probe (struct virtio_device *vdev) {struct virtio_blk *vblk;
@@ -377,7 +444,7 @@ static int __devinit virtblk_probe(struc index++;/* configure queue flush support */ -if (virtio_has_feature (vdev,VIRTIO_BLK_F_FLUSH )) +if (virtblk_has_wb_cache (vblk))blk_queue_flush (q,REQ_FLUSH );/* If disk is read-only in the host, the guest should obey */
@@ -456,6 +523,10 @@ static int __devinit virtblk_probe(strucif (err) goto out_del_disk; + err =device_create_file (disk_to_dev (vblk->disk), &dev_attr_cache_type); +if (err) + goto out_del_disk; +return 0 ; out_del_disk:
@@ -499,7 +570,7 @@ static const struct virtio_device_id id_static unsigned int features[] = {VIRTIO_BLK_F_SEG_MAX ,VIRTIO_BLK_F_SIZE_MAX ,VIRTIO_BLK_F_GEOMETRY ,VIRTIO_BLK_F_RO ,VIRTIO_BLK_F_BLK_SIZE ,VIRTIO_BLK_F_SCSI , -VIRTIO_BLK_F_FLUSH ,VIRTIO_BLK_F_TOPOLOGY +VIRTIO_BLK_F_FLUSH ,VIRTIO_BLK_F_TOPOLOGY ,VIRTIO_BLK_F_DYNAMIC };/*
include/linux/virtio_blk.h +4 -0
@@ -16,6 +16,7 @@#define VIRTIO_BLK_F_SCSI 7/* Supports scsi command passthru */ #define VIRTIO_BLK_F_FLUSH 9/* Cache flush command support */ #define VIRTIO_BLK_F_TOPOLOGY 10/* Topology information is available */ +#define VIRTIO_BLK_F_DYNAMIC 11/* Dynamic features field */ #define VIRTIO_BLK_ID_BYTES 20/* ID string length */
@@ -45,6 +46,9 @@ struct virtio_blk_config {__u16 min_io_size;/* optimal sustained I/O size in logical blocks. */ __u32 opt_io_size; +/* runtime controllable features */ +__u32 features; +#define VIRTIO_BLK_RT_WCE (1 << 0) } __attribute__((packed));
Re: [PATCH, RFC] virtio_blk: add cache control support
Quoted 5 lines · Christoph Hellwig
Add support for the new dynamic features config space field to allow en/disabling the write cache at runtime. The userspace interface is a SCSI-compatible sysfs attribute.
Signed-off-by Christoph Hellwig <[email protected]>
Hi Christoph,
Neat work. Minor comments:
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 337
Quoted 3 lines
drivers/block/virtio_blk.c +3
-0+if (strncmp (buf,"write through" ,sizeof ("write through" ) -1 ) ==0 ) { + ; + }else if (strncmp (buf,"write back" ,sizeof ("write back" ) -1 ) ==0 ) {
Is there a reason we're not letting gcc and/or strcmp do the
optimization work here?
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 352
Quoted 9 lines
drivers/block/virtio_blk.c +9
-0+ vdev->config->set (vdev, offsetof(struct virtio_blk_config , features), + &features,sizeof (features)); + + vdev->config->get (vdev, offsetof(struct virtio_blk_config , features), + &features2,sizeof (features2)); + +if ((features &VIRTIO_BLK_RT_WCE ) != + (features2 &VIRTIO_BLK_RT_WCE )) +return -EIO ;
This seems like a debugging check you left in. Or do you suspect
some issues?
Thanks,
Rusty.
Re: [PATCH, RFC] virtio_blk: add cache control support
Quoted 6 lines · Rusty Russell
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 337
Quoted 3 lines
drivers/block/virtio_blk.c +3
-0+if (strncmp (buf,"write through" ,sizeof ("write through" ) -1 ) ==0 ) { + ; + }else if (strncmp (buf,"write back" ,sizeof ("write back" ) -1 ) ==0 ) {Is there a reason we're not letting gcc and/or strcmp do the
optimization work here?
I'm happ to switch strcmp.
Quoted 4 lines
Quoted 4 lines
drivers/block/virtio_blk.c +4
-0+ vdev->config->set (vdev, offsetof(struct virtio_blk_config , features), + &features,sizeof (features)); + + vdev->config->get(vdev, offsetof(struct virtio_blk_config, features),
Quoted 8 lines
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 352
Quoted 5 lines
drivers/block/virtio_blk.c +5
-0+ &features2, sizeof(features2)); + +if ((features &VIRTIO_BLK_RT_WCE ) != + (features2 &VIRTIO_BLK_RT_WCE )) +return -EIO ;This seems like a debugging check you left in. Or do you suspect
some issues?
No, it's intentional. config space writes can't return errors, so we need to check that the value has really changed. I'll add a comment explaining it.
Re: [PATCH, RFC] virtio_blk: add cache control support
Quoted 9 lines · Christoph Hellwig
Quoted 6 lines · Rusty Russell
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 337
Quoted 3 lines
drivers/block/virtio_blk.c +3
-0+if (strncmp (buf,"write through" ,sizeof ("write through" ) -1 ) ==0 ) { + ; + }else if (strncmp (buf,"write back" ,sizeof ("write back" ) -1 ) ==0 ) {Is there a reason we're not letting gcc and/or strcmp do the
optimization work here?I'm happ to switch strcmp.
Of course, that's assuming buf is nul terminated.
Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
drivers/block/virtio_blk.c +4
-0+ vdev->config->set (vdev, offsetof(struct virtio_blk_config , features), + &features,sizeof (features)); + + vdev->config->get(vdev, offsetof(struct virtio_blk_config, features),Quoted 8 lines
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 352
Quoted 5 lines
drivers/block/virtio_blk.c +5
-0+ &features2, sizeof(features2)); + +if ((features &VIRTIO_BLK_RT_WCE ) != + (features2 &VIRTIO_BLK_RT_WCE )) +return -EIO ;This seems like a debugging check you left in. Or do you suspect
some issues?
Quoted 2 lines
No, it's intentional. config space writes can't return errors, so we need to check that the value has really changed. I'll add a comment explaining it.
OK, under what circumstances could it fail?
If you're using this mechanism to indicate that the host doesn't support the feature, that's making an assumption about the nature of config space writes which isn't true for non-PCI virtio.
ie. lguest and S/390 don't trap writes to config space.
Or perhaps they should? But we should be explicit about needing it...
Thanks,
Rusty.
Re: [Qemu-devel] Re: [PATCH, RFC] virtio_blk: add cache control support
Quoted 3 lines · Rusty Russell
Quoted 1 line
I'm happ to switch strcmp.
Of course, that's assuming buf is nul terminated.
It's the string the user writes into it, which normally should be nul-terminated.
Quoted 5 lines
Quoted 2 lines
No, it's intentional. config space writes can't return errors, so we need to check that the value has really changed. I'll add a comment explaining it.
OK, under what circumstances could it fail?
Quoted 7 lines
If you're using this mechanism to indicate that the host doesn't support the feature, that's making an assumption about the nature of config space writes which isn't true for non-PCI virtio.
ie. lguest and S/390 don't trap writes to config space.
Or perhaps they should? But we should be explicit about needing it...
We have the features flag to indicate if updating the caching mode is supported, but we we could still fail it for other reasons - e.g. we could fail to reopen the file with/without O_SYNC. But if lguest or S/390 don't support trapping config space write this feature won't work for them at all. As do other features that make use of config space write, e.g. updating the MAC address for virtio-net.
Re: [Qemu-devel] Re: [PATCH, RFC] virtio_blk: add cache control support
Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Rusty Russell
OK, under what circumstances could it fail?
If you're using this mechanism to indicate that the host doesn't support the feature, that's making an assumption about the nature of config space writes which isn't true for non-PCI virtio.
Quoted 7 lines
Quoted 3 lines
ie. lguest and S/390 don't trap writes to config space.
Or perhaps they should? But we should be explicit about needing it...
We have the features flag to indicate if updating the caching mode is supported, but we we could still fail it for other reasons - e.g. we could fail to reopen the file with/without
O_SYNC.
OK, then I think you need to make it a real command and feed it into the request queue.
The theory behind config space is that it's for advertising, not for interaction. And it's not ever very good at that...
Quoted 4 lines
But if lguest or S/390 don't support
trapping config space write this feature won't work for them at all. As do other features that make use of config space write, e.g. updating the MAC address for virtio-net.
Yes, and that was a mistake. What does qemu do with a partially-written MAC address? Lguest ignores it, what does S/390 do?
Alex?
Cheers,
Rusty.
Re: [Qemu-devel] Re: [PATCH, RFC] virtio_blk: add cache control support
In reply to Christoph HellwigQuoted 16 lines · Christoph Hellwig
Quoted 2 lines · Rusty Russell
Quoted 1 line
I'm happ to switch strcmp.
Of course, that's assuming buf is nul terminated.
It's the string the user writes into it, which normally should be nul-terminated.
Quoted 10 lines
Quoted 2 lines
No, it's intentional. config space writes can't return errors, so we need to check that the value has really changed. I'll add a comment explaining it.
OK, under what circumstances could it fail?
If you're using this mechanism to indicate that the host doesn't support the feature, that's making an assumption about the nature of config space writes which isn't true for non-PCI virtio.
ie. lguest and S/390 don't trap writes to config space.
Quoted 7 lines
Quoted 1 line
Or perhaps they should? But we should be explicit about needing it...
We have the features flag to indicate if updating the caching mode is supported, but we we could still fail it for other reasons - e.g. we could fail to reopen the file with/without
O_SYNC. But if lguest or S/390 don't support trapping config space write this feature won't work for them at all. As do other features that make use of config space write, e.g. updating the MAC address for virtio-net.
QEMU does not rely on config space writes for supporting mac address updates.
Whenever the config space is updated, we update the mac address in the virtio-net structure but since PCI only supports 4 byte accesses, it will only be partially updated at certain points in time.
This is okay though because as long as a guest updates it before we send a network packet out, when we refer to the mac address, it will be correct. We could just as well have the config space be in shared memory and only refer to the mac address in that shared memory area when transmitting a packet.
So the fact that we respond to config space writes doesn't mean that writes have a side effect other than updating the config space, which is really what I think the important point is here.
Regards,
Anthony Liguori
Re: [PATCH, RFC] virtio_blk: add cache control support
In reply to Rusty RussellQuoted 25 lines · Rusty Russell
Quoted 7 lines · Christoph Hellwig
Quoted 5 lines · Rusty Russell
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 337
Quoted 3 lines
drivers/block/virtio_blk.c +3
-0+if (strncmp (buf,"write through" ,sizeof ("write through" ) -1 ) ==0 ) { + ; + }else if (strncmp (buf,"write back" ,sizeof ("write back" ) -1 ) ==0 ) {Is there a reason we're not letting gcc and/or strcmp do the
optimization work here?I'm happ to switch strcmp.
Of course, that's assuming buf is nul terminated.
Quoted 11 lines
Quoted 11 lines
drivers/block/virtio_blk.c static ssize_t virtblk_serial_show(struc · line 352
Quoted 9 lines
drivers/block/virtio_blk.c +9
-0+ vdev->config->set (vdev, offsetof(struct virtio_blk_config , features), + &features,sizeof (features)); + + vdev->config->get (vdev, offsetof(struct virtio_blk_config , features), + &features2,sizeof (features2)); + +if ((features&VIRTIO_BLK_RT_WCE ) != + (features2&VIRTIO_BLK_RT_WCE )) +return -EIO ;This seems like a debugging check you left in. Or do you suspect
some issues?Quoted 2 lines
No, it's intentional. config space writes can't return errors, so we need to check that the value has really changed. I'll add a comment explaining it.
OK, under what circumstances could it fail?
Quoted 7 lines
If you're using this mechanism to indicate that the host doesn't support the feature, that's making an assumption about the nature of config space writes which isn't true for non-PCI virtio.
ie. lguest and S/390 don't trap writes to config space.
Or perhaps they should? But we should be explicit about needing it...
I don't think we ever operated on the assumption that config space writes would trap.
I don't think adding it is the right thing either because you can do byte access to the config space which makes atomicity difficult.
Any reason not to use a control queue to negotiate dynamic features? The authorative source of what the currently enabled features are can still be config space but the guest's enabling or disabling of a feature ought to be a control queue message.
Regards,
Anthony Liguori
Quoted 5 lines
Thanks,
Rusty.
Re: [PATCH, RFC] virtio_blk: add cache control support
Am 24.03.2011 04:05, schrieb Anthony Liguori:
Quoted 6 lines
Quoted 3 lines
ie. lguest and S/390 don't trap writes to config space.
Or perhaps they should? But we should be explicit about needing it...
I don't think we ever operated on the assumption that config space writes would trap.
I don't think adding it is the right thing either because you can do byte access to the config space which makes atomicity difficult.
There is the additional problem, that s390 has no MMIO and,therefore, there is no real HW support for trapping writes to an area. You can use page faults, or read-only faults on newer systems, but this is expensive. In addition, page faults only deliver the page frame, but not the offset within a page.
Quoted 2 lines
Any reason not to use a control queue to negotiate dynamic features?
Sounds reasonable.
Re: [PATCH, RFC] virtio_blk: add cache control support
Quoted 6 lines · Christian Borntraeger
Am 24.03.2011 04:05, schrieb Anthony Liguori:
Quoted 5 lines
Quoted 3 lines
ie. lguest and S/390 don't trap writes to config space.
Or perhaps they should? But we should be explicit about needing it...
I don't think we ever operated on the assumption that config space writes would trap.
Quoted 7 lines
Quoted 1 line
I don't think adding it is the right thing either because you can do byte access to the config space which makes atomicity difficult.
There is the additional problem, that s390 has no MMIO and,therefore, there is no real HW support for trapping writes to an area. You can use page faults, or read-only faults on newer systems, but this is expensive. In addition, page faults only deliver the page frame, but not the offset within a page.
That's not *really* a problem, since you have control over the config_set operation and could do whatever you wanted.
But I wanted to make sure we're all on the same page: you *can't* rely on the host knowing immediately what you write to the config space. If you want that, an actual queued request is necessary...
Thanks,
Rusty.