suppressing queue notification with queue depth parameter (was: [RFC][PATCH] Queue notify support for virtio block device.)
RFC PATCH v2 1/1 suppressing queue notification with queue depth parameter (was: [RFC][PATCH] Queue notify support for virtio block device.)
The following patch allows to suppress virtio queue notification with the number of requests passed as parameter.
Changes from v1:
- code styling,
- parameter "x-queue-depth-suppress-notify" for queue depth adjustment.
repository: /home/vadimr/work/upstream/qemu
branch: master
commit d23a1c2fbd23e3da9a671a35c95324d2c630e4c9
Author: Vadim Rozenfeld <[email protected]> Date: Thu Jan 14 08:09:26 2010 +0200
[RFC][PATCH v2] suppressing queue notification with queue depth
parameter
hw/virtio-blk.c +3 -0
@@ -28,6 +28,8 @@ typedef struct VirtIOBlockchar serial_str[BLOCK_SERIAL_STRLEN +1 ];QEMUBH *bh;size_t config_size; +unsigned int queue_depth; +unsigned int requests; } VirtIOBlock;static VirtIOBlock *to_virtio_blk (VirtIODevice *vdev)
@@ -87,6 +89,8 @@ typedef struct VirtIOBlockReqstruct VirtIOBlockReq *next; } VirtIOBlockReq; +static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue
*vq);
+
static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
{
VirtIOBlock *s = req->dev;
@@ -95,6 +99,11 @@ static void virtio_blk_req_complete(VirtIOBlockReq
*req, int status)
virtqueue_push(s->vq, &req->elem, req->qiov.size +
sizeof(*req->in));
virtio_notify(&s->vdev, s->vq);+ virtio_blk_handle_output(&s->vdev, s->vq);
+ if (--s->requests == (s->queue_depth - 1)) {
+ virtio_queue_set_notification(s->vq, 1);
+ }
+
qemu_free(req);
}
@@ -340,6 +349,10 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
exit(1);
}+ if (++s->requests == s->queue_depth) {
+ virtio_queue_set_notification(s->vq, 0);
+ }
+
req->out = (void *)req->elem.out_sg[0].iov_base;
req->in = (void *)req->elem.in_sg[req->elem.in_num -1].iov_base;
@@ -502,6 +515,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo)
s->vdev.reset = virtio_blk_reset;
s->bs = dinfo->bdrv;
s->rq = NULL;
+ s->queue_depth = drive_get_queue_depth(dinfo->bdrv);
if (strlen(ps))
strncpy(s->serial_str, ps, sizeof(s->serial_str));
elseqemu-config.c +4 -0
@@ -78,6 +78,10 @@ QemuOptsList qemu_drive_opts = { },{ .name = "readonly", .type = QEMU_OPT_BOOL, + },{ + .name = "x-queue-depth-suppress-notify", + .type = QEMU_OPT_NUMBER, + .help = "number of requests in queueu before suppressing
notify",
},
{ /* end if list */ }
},sysemu.h +2 -0
@@ -183,6 +183,7 @@ typedef struct DriveInfo {BlockInterfaceErrorAction on_read_error;BlockInterfaceErrorAction on_write_error;char serial[BLOCK_SERIAL_STRLEN +1 ]; +int queue_depth;QTAILQ_ENTRY (DriveInfo) next; } DriveInfo;
@@ -198,6 +199,7 @@ extern DriveInfo *drive_get_by_id(const char *id);extern int drive_get_max_bus (BlockInterfaceType type);extern void drive_uninit (DriveInfo *dinfo);extern const char *drive_get_serial (BlockDriverState *bdrv); +extern int drive_get_queue_depth (BlockDriverState *bdrv);extern BlockInterfaceErrorAction drive_get_on_error (BlockDriverState *bdrv,int is_read);
vl.c +0 -0
@@ -2043,6 +2043,18 @@ const char *drive_get_serial(BlockDriverState
*bdrv)
return "\0";
}
+int drive_get_queue_depth(BlockDriverState *bdrv)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->bdrv == bdrv)
+ return dinfo->queue_depth;
+ }
+
+ return 1;
+}
+
BlockInterfaceErrorAction drive_get_on_error(
BlockDriverState *bdrv, int is_read)
{
@@ -2110,6 +2122,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
const char *devaddr;
DriveInfo *dinfo;
int snapshot = 0;+ int queue_depth = 1;
*fatal_error = 1;
@@ -2141,6 +2154,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
file = qemu_opt_get(opts, "file");
serial = qemu_opt_get(opts, "serial");+ queue_depth = qemu_opt_get_number(opts,
"x-queue-depth-suppress-notify",1);
if ((buf = qemu_opt_get(opts, "if")) != NULL) {
pstrcpy(devname, sizeof(devname), buf);
@@ -2375,6 +2389,7 @@ DriveInfo *drive_init(QemuOpts *opts, void
*opaque,
dinfo->on_read_error = on_read_error;
dinfo->on_write_error = on_write_error;
dinfo->opts = opts;
+ dinfo->queue_depth = queue_depth;
if (serial)
strncpy(dinfo->serial, serial, sizeof(serial));
QTAILQ_INSERT_TAIL(&drives, dinfo, next);Quoted 136 lines · Vadim Rozenfeld
The following patch allows to suppress virtio queue notification with the number of requests passed as parameter.
Changes from v1:
- code styling,
- parameter "x-queue-depth-suppress-notify" for queue depth adjustment.repository:
/home/vadimr/work/upstream/qemu
branch: master
commitd23a1c2fbd23e3da9a671a35c95324d2c630e4c9Author: Vadim Rozenfeld<[email protected]> Date: Thu Jan 14 08:09:26 2010 +0200[RFC][PATCH v2] suppressing queue notification with queue depth
parameterhw/virtio-blk.c +4
-0@@ -28,6 +28,8 @@ typedef struct VirtIOBlockchar serial_str[BLOCK_SERIAL_STRLEN +1 ];QEMUBH *bh;size_t config_size; +unsigned int queue_depth; +unsigned int requests; } VirtIOBlock;static VirtIOBlock *to_virtio_blk (VirtIODevice *vdev)@@ -87,6 +89,8 @@ typedef struct VirtIOBlockReqstruct VirtIOBlockReq *next; } VirtIOBlockReq; +static void virtio_blk_handle_output (VirtIODevice *vdev,VirtQueue *vq); +static void virtio_blk_req_complete (VirtIOBlockReq *req,int status) {VirtIOBlock *s = req->dev;hw/virtio-blk.c +5
-0@@ -95,6 +99,11 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)virtqueue_push (s->vq,&req->elem, req->qiov.size +sizeof (*req->in));virtio_notify (&s->vdev, s->vq); +virtio_blk_handle_output (&s->vdev, s->vq); +if (--s->requests == (s->queue_depth -1 )) { +virtio_queue_set_notification (s->vq,1 ); + } +qemu_free (req);}hw/virtio-blk.c +4
-0@@ -340,6 +349,10 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)exit (1 ); } +if (++s->requests == s->queue_depth) { +virtio_queue_set_notification (s->vq,0 ); + } + req->out = (void *)req->elem.out_sg[0 ].iov_base; req->in = (void *)req->elem.in_sg[req->elem.in_num -1].iov_base;
hw/virtio-blk.c +1
-0@@ -502,6 +515,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo) s->vdev.reset = virtio_blk_reset; s->bs = dinfo->bdrv; s->rq =NULL ; + s->queue_depth =drive_get_queue_depth (dinfo->bdrv);if (strlen (ps))strncpy (s->serial_str, ps,sizeof (s->serial_str));else
qemu-config.c +4
-0@@ -78,6 +78,10 @@ QemuOptsList qemu_drive_opts = { },{ .name = "readonly", .type = QEMU_OPT_BOOL, + },{ + .name = "x-queue-depth-suppress-notify", + .type = QEMU_OPT_NUMBER, + .help = "number of requests in queueu before suppressing notify", }, { /* end if list */ }},sysemu.h +2
-0@@ -183,6 +183,7 @@ typedef struct DriveInfo {BlockInterfaceErrorAction on_read_error;BlockInterfaceErrorAction on_write_error;char serial[BLOCK_SERIAL_STRLEN +1 ]; +int queue_depth;QTAILQ_ENTRY (DriveInfo) next; } DriveInfo;@@ -198,6 +199,7 @@ extern DriveInfo *drive_get_by_id(const char *id);extern int drive_get_max_bus (BlockInterfaceType type);extern void drive_uninit (DriveInfo *dinfo);extern const char *drive_get_serial (BlockDriverState *bdrv); +extern int drive_get_queue_depth (BlockDriverState *bdrv);extern BlockInterfaceErrorAction drive_get_on_error (BlockDriverState *bdrv,int is_read);vl.c +12
-0@@ -2043,6 +2043,18 @@ const char *drive_get_serial(BlockDriverState *bdrv)return "\0" ; } +int drive_get_queue_depth (BlockDriverState *bdrv) +{ +DriveInfo *dinfo; + + QTAILQ_FOREACH(dinfo,&drives, next) { +if (dinfo->bdrv == bdrv) +return dinfo->queue_depth; + } + +return 1 ; +} +BlockInterfaceErrorAction drive_get_on_error (BlockDriverState *bdrv,int is_read){
vl.c DriveInfo *drive_init(QemuOpts *opts, void · line 2127
Quoted 6 lines
vl.c +1
-0@@ -2110,6 +2122,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, const char *devaddr;DriveInfo *dinfo;int snapshot =0 ; +int queue_depth =1 ;
It should be disabled by default. queue_depth=1 by default is going to be devastating for multi-spindle set-ups.
Regards,
Anthony Liguori