This is an updated patch for collecting block device statistics. Thanks to several people on #qemu channel for giving me feedback about the first version[1].

This patch collects per-block-device statistics and allows them to be displayed in the monitor through a 'info blockstats' command. It generalises the VMDK-only support for this which was added to KVM's version of QEMU.

Screenshot showing 'info blockstats' command being run for a Solaris guest which is doing some moderate disk activity:

http://www.annexia.org/tmp/Screenshot-QEMU-2.png

Rich.

[1] Previous patch was: http://lists.gnu.org/archive/html/qemu-devel/2007-11/msg00489.html

--
Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/
Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom.  Registered in
England and Wales under Company Registration No. 03798903
Index: block.c
===================================================================
RCS file: /sources/qemu/qemu/block.c,v
retrieving revision 1.49
diff -u -r1.49 block.c
--- block.c	18 Nov 2007 01:44:35 -0000	1.49
+++ block.c	27 Nov 2007 11:33:04 -0000
@@ -521,8 +521,11 @@
             return ret;
         else if (ret != len)
             return -EINVAL;
-        else
+        else {
+	    bs->rd_bytes += (unsigned) len;
+	    bs->rd_ops ++;
             return 0;
+	}
     } else {
         return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
     }
@@ -553,8 +556,11 @@
             return ret;
         else if (ret != len)
             return -EIO;
-        else
+        else {
+	    bs->wr_bytes += (unsigned) len;
+	    bs->wr_ops ++;
             return 0;
+	}
     } else {
         return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
     }
@@ -902,6 +908,24 @@
         term_printf("\n");
     }
 }
+
+/* The "info blockstats" command. */
+void bdrv_info_stats (void)
+{
+    BlockDriverState *bs;
+
+    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+	term_printf ("%s:"
+		     " rd_bytes=%" PRIu64
+		     " wr_bytes=%" PRIu64
+		     " rd_operations=%" PRIu64
+		     " wr_operations=%" PRIu64
+		     "\n",
+		     bs->device_name,
+		     bs->rd_bytes, bs->wr_bytes,
+		     bs->rd_ops, bs->wr_ops);
+    }
+}
 #endif
 
 void bdrv_get_backing_filename(BlockDriverState *bs,
@@ -1064,6 +1088,7 @@
                                 BlockDriverCompletionFunc *cb, void *opaque)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverAIOCB *ret;
 
     if (!drv)
         return NULL;
@@ -1076,7 +1101,15 @@
         buf += 512;
     }
 
-    return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
+    ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
+
+    if (ret) {
+	/* Update stats even though technically transfer has not happened. */
+	bs->rd_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
+	bs->rd_ops ++;
+    }
+
+    return ret;
 }
 
 BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
@@ -1084,6 +1117,7 @@
                                  BlockDriverCompletionFunc *cb, void *opaque)
 {
     BlockDriver *drv = bs->drv;
+    BlockDriverAIOCB *ret;
 
     if (!drv)
         return NULL;
@@ -1093,7 +1127,15 @@
         memcpy(bs->boot_sector_data, buf, 512);
     }
 
-    return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
+    ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
+
+    if (ret) {
+	/* Update stats even though technically transfer has not happened. */
+	bs->wr_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
+	bs->wr_ops ++;
+    }
+
+    return ret;
 }
 
 void bdrv_aio_cancel(BlockDriverAIOCB *acb)
Index: block.h
===================================================================
RCS file: /sources/qemu/qemu/block.h,v
retrieving revision 1.2
diff -u -r1.2 block.h
--- block.h	17 Nov 2007 17:14:37 -0000	1.2
+++ block.h	27 Nov 2007 11:33:04 -0000
@@ -47,6 +47,7 @@
 
 #ifndef QEMU_IMG
 void bdrv_info(void);
+void bdrv_info_stats(void);
 #endif
 
 void bdrv_init(void);
Index: block_int.h
===================================================================
RCS file: /sources/qemu/qemu/block_int.h,v
retrieving revision 1.14
diff -u -r1.14 block_int.h
--- block_int.h	11 Nov 2007 02:51:16 -0000	1.14
+++ block_int.h	27 Nov 2007 11:33:04 -0000
@@ -114,6 +114,12 @@
 
     void *sync_aiocb;
 
+    /* I/O stats (display with "info blockstats"). */
+    uint64_t rd_bytes;
+    uint64_t wr_bytes;
+    uint64_t rd_ops;
+    uint64_t wr_ops;
+
     /* NOTE: the following infos are only hints for real hardware
        drivers. They are not used by the block driver */
     int cyls, heads, secs, translation;
Index: monitor.c
===================================================================
RCS file: /sources/qemu/qemu/monitor.c,v
retrieving revision 1.87
diff -u -r1.87 monitor.c
--- monitor.c	18 Nov 2007 01:44:35 -0000	1.87
+++ monitor.c	27 Nov 2007 11:33:05 -0000
@@ -260,6 +260,11 @@
     bdrv_info();
 }
 
+static void do_info_blockstats(void)
+{
+    bdrv_info_stats();
+}
+
 /* get the current CPU defined by the user */
 static int mon_set_cpu(int cpu_index)
 {
@@ -1332,6 +1337,8 @@
       "", "show the network state" },
     { "block", "", do_info_block,
       "", "show the block devices" },
+    { "blockstats", "", do_info_blockstats,
+      "", "show block device statistics" },
     { "registers", "", do_info_registers,
       "", "show the cpu registers" },
     { "cpus", "", do_info_cpus,

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to