--- /dev/null
+From e04ef476fd330485e5a88c7018d29c55cf411fe2 Mon Sep 17 00:00:00 2001
+From: Richard W.M. Jones <rjones@redhat.com>
+Date: Tue, 5 Oct 2010 09:54:10 +0100
+Subject: [PATCH] Trace reads and writes to qemu block devices.
+
+NB: This patch is not suitable for nor intended to go upstream in
+its current form.
+
+When qemu opens a block device, this patch creates a trace file
+in /tmp with a name related to the block device. Reads and writes
+to the device cause lines to be written to the trace file:
+
+ S <total_sectors>
+ W <sector> <nb_sectors>
+ R <sector> <nb_sectors>
+
+'S' is the summary line, printed first which just tells you how
+many sectors are on the device.
+
+'W' and 'R' are writes and reads, for the range <sector> through
+to <sector> + <nb_sectors> - 1.
+---
+ block.c | 29 +++++++++++++++++++++++++++++
+ block_int.h | 3 +++
+ 2 files changed, 32 insertions(+), 0 deletions(-)
+
+diff --git a/block.c b/block.c
+index ebbc376..26ead5b 100644
+--- a/block.c
++++ b/block.c
+@@ -474,6 +474,23 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+ goto free_and_fail;
+ }
+
++ /* Open trace file in /tmp based on filename. XXX */
++ size_t len = strlen (filename);
++ char *trace_file = qemu_malloc (10 + len);
++ snprintf (trace_file, 10 + len, "/tmp/%s.qtr", filename);
++ size_t i;
++ for (i = 5; i < 5 + len; ++i) {
++ if (trace_file[i] == '/')
++ trace_file[i] = '_';
++ }
++ bs->trace_fp = fopen (trace_file, "w");
++ if (bs->trace_fp) {
++ setlinebuf (bs->trace_fp);
++ fprintf (bs->trace_fp, "S %" PRIi64 "\n", bs->total_sectors);
++ } else {
++ perror (trace_file);
++ }
++
+ #ifndef _WIN32
+ if (bs->is_temporary) {
+ unlink(filename);
+@@ -665,6 +682,10 @@ void bdrv_close(BlockDriverState *bs)
+ bdrv_close(bs->file);
+ }
+
++ if (bs->trace_fp)
++ fclose (bs->trace_fp);
++ bs->trace_fp = NULL;
++
+ /* call the change callback */
+ bs->media_changed = 1;
+ if (bs->change_cb)
+@@ -1995,6 +2016,10 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
+ /* Update stats even though technically transfer has not happened. */
+ bs->rd_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
+ bs->rd_ops ++;
++
++ if (bs->trace_fp)
++ fprintf (bs->trace_fp,
++ "R %" PRIi64 " %d\n", sector_num, nb_sectors);
+ }
+
+ return ret;
+@@ -2028,6 +2053,10 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
+ if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+ bs->wr_highest_sector = sector_num + nb_sectors - 1;
+ }
++
++ if (bs->trace_fp)
++ fprintf (bs->trace_fp,
++ "W %" PRIi64 " %d\n", sector_num, nb_sectors);
+ }
+
+ return ret;
+diff --git a/block_int.h b/block_int.h
+index e8e7156..03e7c9b 100644
+--- a/block_int.h
++++ b/block_int.h
+@@ -178,6 +178,9 @@ struct BlockDriverState {
+ uint64_t wr_ops;
+ uint64_t wr_highest_sector;
+
++ /* Trace to file. */
++ FILE *trace_fp;
++
+ /* Whether the disk can expand beyond total_sectors */
+ int growable;
+
+--
+1.7.3.1
+