Skip to contentSkip to conversation

suppressing queue notification with queue depth parameter (was: [RFC][PATCH] Queue notify support for virtio block device.)

RFC PATCH In review Vadim Rozenfeld 2 participants 2 messages Jan 14, 2010

lore
Share & tools
lore
#0 lore raw

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
index cb1ae1f..93b584d 100644
@@ -28,6 +28,8 @@ typedef struct VirtIOBlock
     char 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 VirtIOBlockReq
     struct 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));
     else
qemu-config.c +4 -0
index c3203c8..6fcf958 100644
@@ -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
index 9d80bb2..6eecbe1 100644
@@ -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
index b048e89..517d290 100644
@@ -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);
#1 lore raw
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
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 +4 -0
index cb1ae1f..93b584d 100644
@@ -28,6 +28,8 @@ typedef struct VirtIOBlock
      char 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 VirtIOBlockReq
      struct 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
index c3203c8..6fcf958 100644
@@ -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
index 9d80bb2..6eecbe1 100644
@@ -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
index b048e89..517d290 100644
@@ -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