Re: [Qemu-devel] [PATCH] Add wildcard trace event support

2011-10-20 Thread Mars.Cao

On 10/20/2011 05:38 PM, Mark Wu wrote:

A basic wildcard matching is supported in both the monitor command
trace-event and the events list file. That means you can enable/disable the
events having a common prefix in a batch. For example, virtio-blk trace events
could be enabled using:
 trace-event virtio_blk_* on

Signed-off-by: Mark Wuwu...@linux.vnet.ibm.com
---
  docs/tracing.txt |9 -
  trace/simple.c   |   19 +--
  trace/stderr.c   |   17 -
  3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 95ca16c..ea29f2c 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -132,12 +132,19 @@ This functionality is also provided through monitor 
commands:
means disabled.

  * trace-event NAME on|off
-  Enable/disable a given trace event.
+  Enable/disable a given trace event or a group of events having common prefix
+  through wildcard.

  The -trace events=file command line argument can be used to enable the
  events listed infile  from the very beginning of the program. This file must
  contain one event name per line.

+A basic wildcard matching is supported in both the monitor command trace
+-event and the events list file. That means you can enable/disable the events
+having a common prefix in a batch. For example, virtio-blk trace events could
+be enabled using:
+  trace-event virtio_blk_* on
+
  == Trace backends ==

  The tracetool script automates tedious trace event code generation and also
diff --git a/trace/simple.c b/trace/simple.c
index b639dda..869e315 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -324,14 +324,29 @@ void trace_print_events(FILE *stream, fprintf_function 
stream_printf)
  bool trace_event_set_state(const char *name, bool state)
  {
  unsigned int i;
-
+unsigned int len;
+bool wildcard = false;
+bool matched = false;
+
+len = strlen(name);
+if (name[len-1] == '*') {
+wildcard = true;
+len -= 1;
+}
  for (i = 0; i  NR_TRACE_EVENTS; i++) {
+if (wildcard) {
+if (!strncmp(trace_list[i].tp_name, name, len)) {
+trace_list[i].state = state;
+matched = true;
+}
+continue;
+}
  if (!strcmp(trace_list[i].tp_name, name)) {
  trace_list[i].state = state;
  return true;
  }
  }
-return false;
+return matched;
  }

  /* Helper function to create a thread with signals blocked.  Use glib's
diff --git a/trace/stderr.c b/trace/stderr.c
index 7107c4a..6a12977 100644
--- a/trace/stderr.c
+++ b/trace/stderr.c
@@ -15,14 +15,29 @@ void trace_print_events(FILE *stream, fprintf_function 
stream_printf)
  bool trace_event_set_state(const char *name, bool state)
  {
  unsigned int i;
+unsigned int len;
+bool wildcard = false;
+bool matched = false;

+len = strlen(name);
+if (name[len-1] == '*') {
+wildcard = true;
+len -= 1;
+}
  for (i = 0; i  NR_TRACE_EVENTS; i++) {
+if (wildcard) {
+if (!strncmp(trace_list[i].tp_name, name, len)) {
+trace_list[i].state = state;
+matched = true;
+}
+continue;
+}
  if (!strcmp(trace_list[i].tp_name, name)) {
  trace_list[i].state = state;
  return true;
  }
  }
-return false;
+return matched;
  }

  bool trace_backend_init(const char *events, const char *file)
I do think this idea of using wildcard (from Stefanha) is smarter than 
trace groups.
I did not find anything wrong with the code although it does not support 
events with wildcard like virtio_*_init.


Reviewed-by: Cao,Bing Bu m...@linux.vnet.ibm.com
Tested-by:   Cao,Bing Bu m...@linux.vnet.ibm.com




[Qemu-devel] [Question]WinDbg runs too slowly or exits unexpectly when debug windows guest driver under QEMU 0.15.50

2011-10-19 Thread Mars.Cao
WinDbg runs too slowly or exits unexpectedly when debug windows guest 
driver under QEMU 0.15.



I installed 2 windows (WinXP SP3)VMs on my host (RHEL6.1).
The basic debug method is :


1.Setup the Windows driver Kit in host


/usr/local/bin/qemu-system-x86_64 -drive 
file=winxpsp3.img,if=virtio,format=qcow2,cache=none,aio=threads -smp 2 
-net tap,ifname=tap0,script=no,downscript=no -net 
nic,model=virtio,macaddr=52:54:00:d6:be:bb -m 1024 --enable-kvm -serial 
tcp:127.0.0.1:4445,server,nowait -cdrom WDK.iso




power off.


2.Run the guest and edit the boot.ini of the guest windows


/usr/local/bin/qemu-system-x86_64 -drive 
file=winxp-guest.img,if=virtio,format=qcow2,cache=none,aio=threads -smp 
2 -net tap,ifname=tap1,script=no,downscript=no -net 
nic,model=virtio,macaddr=52:54:00:d6:be:ee -m 1024 --enable-kvm


edit boot.ini and duplicate the default boot option add the line /debug 
/debugport=COM1 /baudrate=115200



3.Run host and WinDbg


/usr/local/bin/qemu-system-x86_64 -drive 
file=winxpsp3.img,if=virtio,format=qcow2,cache=none,aio=threads -smp 2 
-net tap,ifname=tap0,script=no,downscript=no -net 
nic,model=virtio,macaddr=52:54:00:d6:be:bb -m 1024 --enable-kvm -serial 
tcp:127.0.0.1:4445,server,nowait


Run the host VM,and then run WinDbg then Ctrl+k kernel debug to 
connect the guest for debugging through COM1.



4.Run the guest to debug

Restart the guest,select the windows debug option in the boot menu.

/usr/local/bin/qemu-system-x86_64 -drive 
file=winxp-guest.img,if=virtio,format=qcow2,cache=none,aio=threads -smp 
2 -net tap,ifname=tap1,script=no,downscript=no -net 
nic,model=virtio,macaddr=52:54:00:d6:be:ee -m 1024 --enable-kvm -serial 
tcp:127.0.0.1:4445



There are several problems when debugging:

1).The Windows VM boot slow (more than 20 seconds)and does not run smoothly.
I use the qemu-kvm (version 0.12.1) which pre-installed in the RedHat 
RHEL6.1 with same option and same image file, the VM boots and runs much 
more better than using QEMU-0.15.0.


[root@oc2115466153 images]# /usr/local/bin/qemu-system-x86_64 --version
QEMU emulator version 0.15.50, Copyright (c) 2003-2008 Fabrice Bellard

[root@oc2115466153 images]# /usr/libexec/qemu-kvm --version
QEMU PC emulator version 0.12.1 (qemu-kvm-0.12.1.2), Copyright (c) 
2003-2008 Fabrice Bellard





2).The process of WinDbg on the host VM connecting to the guest occupy 
so much time.


It spend at least 10 minutes to connect the guest VM when debugging the 
windows kernel by WinDbg.


3).When WinDbg connecting to the guest VM(not connected yet),WinDbg exit 
unexpected sometimes, and sometimes can not connect to the guest. And 
the probability of the problem is high.




I have no idea what is wrong?
The COM rate is too slow,the QEMU is not used correctly or some bugs in 
QEMU?

Can anyone give me some tips?



Re: [Qemu-devel] [PATCH 0/3] block: zero write detection

2011-10-09 Thread Mars.cao

On 10/07/2011 11:49 PM, Stefan Hajnoczi wrote:

Image streaming copies data from the backing file into the image file.  It is
important to represent zero regions from the backing file efficiently during
streaming, otherwise the image file grows to the full virtual disk size and
loses sparseness.

There are two ways to implement zero write detection, they are subtly different:

1. Allow image formats to provide efficient representations for zero regions.
QED does this with zero clusters and it has been discussed for qcow2v3.

2. During streaming, check for zeroes and skip writing to the image file when
zeroes are detected.

However, there are some disadvantages to #2 because it leaves unallocated holes
in the image file.  If image streaming is aborted before it completes then it
will be necessary to reread all unallocated clusters from the backing file upon
resuming image streaming.  Potentionally worse is that a backing file over a
slow remote connection will have the zero regions fetched again and again if
the guest accesses them.  #1 avoids these problems because the image file
contains information on which regions are zeroes and do not need to be
refetched.

This patch series implements #1 with the existing QED zero cluster feature.  In
the future we can add qcow2v3 zero clusters too.  We can also implement #2
directly in the image streaming code as a fallback when the BlockDriver does
not support zero detection #1 itself.  That way we get the best possible zero
write detection, depending on the image format.

Here is a qemu-iotest to verify that zero write detection is working:
http://repo.or.cz/w/qemu-iotests/stefanha.git/commitdiff/226949695eef51bdcdea3e6ce3d7e5a863427f37

Stefan Hajnoczi (3):
   block: add zero write detection interface
   qed: add zero write detection support
   qemu-io: add zero write detection option

  block.c |   16 +++
  block.h |2 +
  block/qed.c |   81 +--
  block_int.h |   13 +
  qemu-io.c   |   35 -
  5 files changed, 132 insertions(+), 15 deletions(-)

I tested the patch by qemu-iotest 029 test case and also by manually, it 
worked as expected.


Tested-by: Cao,Bing Bu m...@linux.vnet.ibm.com



Re: [Qemu-devel] [PATCH V2] Add stdio char device on windows

2011-09-28 Thread Mars.cao
) {
+return -ENOMEM;
+}


I have not found any g_free for the CharDriverStart chr.

+
+chr-chr_write = win_stdio_write;
+
+if (stdio_nb_clients == 0) {
+if (is_console) {
+if (qemu_add_wait_object(hStdIn,
+ win_stdio_wait_func, chr)) {
+fprintf(stderr, qemu_add_wait_object: failed\n);
+}
+} else {
+DWORD   dwId;
+HANDLE *hInputThread;
+
+hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+hInputDoneEvent  = CreateEvent(NULL, FALSE, FALSE, NULL);
+hInputThread = CreateThread(NULL, 0, win_stdio_thread,
+chr, 0,dwId);


I do not think it is a good idea to create 3 static global variant for 
the 2 events and the thread.

Creating a new structure to contain the elements may be better.

+
+if (   hInputThread == INVALID_HANDLE_VALUE
+|| hInputReadyEvent == INVALID_HANDLE_VALUE
+|| hInputDoneEvent  == INVALID_HANDLE_VALUE) {
+fprintf(stderr, cannot create stdio thread or event\n);
+exit(1);
+}
+if (qemu_add_wait_object(hInputReadyEvent,
+ win_stdio_thread_wait_func, chr)) {
+fprintf(stderr, qemu_add_wait_object: failed\n);
+}
+}
+}
+
+dwMode |= ENABLE_LINE_INPUT;
+
+stdio_clients[stdio_nb_clients++] = chr;
+if (stdio_nb_clients == 1  is_console) {
+/* set the terminal in raw mode */
+/* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
+dwMode |= ENABLE_PROCESSED_INPUT;
+}
+
+SetConsoleMode(hStdIn, dwMode);
+
+chr-chr_set_echo = qemu_chr_set_echo_win_stdio;
+qemu_chr_fe_set_echo(chr, false);
+
+*_chr = chr;
+
+return 0;
+}
  #endif /* !_WIN32 */

  /***/
@@ -2519,6 +2713,7 @@ static const struct {
  { .name = pipe,  .open = qemu_chr_open_win_pipe },
  { .name = console,   .open = qemu_chr_open_win_con },
  { .name = serial,.open = qemu_chr_open_win },
+{ .name = stdio, .open = qemu_chr_open_win_stdio },
  #else
  { .name = file,  .open = qemu_chr_open_file_out },
  { .name = pipe,  .open = qemu_chr_open_pipe },


I am a new rookie in qemu-devel,so forgive my misunderstanding.
I will test your patch in future 2 days.

Reviewed by: Mars.Cao m...@linux.vnet.ibm.com



Re: [Qemu-devel] [PATCH V2] Add stdio char device on windows

2011-09-28 Thread Mars.cao

On 09/29/2011 12:25 AM, Fabien Chouteau wrote:

On 28/09/2011 11:57, Mars.cao wrote:

On 09/27/2011 11:42 PM, Fabien Chouteau wrote:

Simple implementation of an stdio char device on Windows.

Signed-off-by: Fabien Chouteauchout...@adacore.com
---
   qemu-char.c |  199 
++-
   1 files changed, 197 insertions(+), 2 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 09d2309..46acf1c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -538,6 +538,9 @@ int send_all(int fd, const void *_buf, int len1)
   }
   #endif /* !_WIN32 */

+#define STDIO_MAX_CLIENTS 1
+static int stdio_nb_clients;

Why change the default initial value (0) of stdio_nb_clients?
Did you mean we should support multiple stdio clients?
But I did not found any other stdio backend in the code.

I just removed the useless 0 initialization of this global variable.


+
   #ifndef _WIN32

   typedef struct {
@@ -545,8 +548,6 @@ typedef struct {
   int max_size;
   } FDCharDriver;

-#define STDIO_MAX_CLIENTS 1
-static int stdio_nb_clients = 0;

   static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
   {
@@ -1451,6 +1452,8 @@ static int qemu_chr_open_pp(QemuOpts *opts, 
CharDriverState **_chr)

   #else /* _WIN32 */

+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
   typedef struct {
   int max_size;
   HANDLE hcom, hrecv, hsend;
@@ -1809,6 +1812,197 @@ static int qemu_chr_open_win_file_out(QemuOpts *opts, 
CharDriverState **_chr)

   return qemu_chr_open_win_file(fd_out, _chr);
   }
+
+static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+HANDLE *hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+DWORD   dwSize;
+int len1;
+
+len1 = len;
+
+while (len1   0) {
+if (!WriteFile(hStdOut, buf, len1,dwSize, NULL)) {
+break;
+}
+buf  += dwSize;
+len1 -= dwSize;
+}
+
+return len - len1;
+}
+
+static HANDLE *hStdIn;
+
+static void win_stdio_wait_func(void *opaque)
+{
+CharDriverState *chr = opaque;
+INPUT_RECORD buf[4];
+int  ret;
+DWORDdwSize;
+int  i;
+
+ret = ReadConsoleInput(hStdIn, buf, sizeof(buf)/sizeof(*buf),dwSize);
+
+if (!ret) {
+/* Avoid error storm */
+qemu_del_wait_object(hStdIn, NULL, NULL);
+return;
+}
+
+for (i = 0; i   dwSize; i++) {
+KEY_EVENT_RECORD *kev =buf[i].Event.KeyEvent;
+
+if (buf[i].EventType == KEY_EVENT   kev-bKeyDown) {
+int j;
+if (kev-uChar.AsciiChar != 0) {
+for (j = 0; j   kev-wRepeatCount; j++)
+if (qemu_chr_be_can_write(chr)) {
+uint8_t c = kev-uChar.AsciiChar;
+qemu_chr_be_write(chr,c, 1);
+}
+}
+}
+}
+}
+
+static HANDLE  hInputReadyEvent;
+static HANDLE  hInputDoneEvent;
+static uint8_t win_stdio_buf;
+
+static DWORD WINAPI win_stdio_thread(LPVOID param)
+{
+int   ret;
+DWORD dwSize;
+
+while (1) {
+
+/* Wait for one byte */
+ret = ReadFile(hStdIn,win_stdio_buf, 1,dwSize, NULL);
+
+/* Exit in case of error, continue if nothing read */
+if (!ret) {
+break;
+}

I think a qemu_del_wait_object() should be added before break.

I don't see why, can you explain?
Sorry for that,I did not notice the qemu_del_wait_object() func after 
the while(1).:)

+if (!dwSize) {
+continue;
+}
+
+/* Some terminal emulator returns \r\n for Enter, just pass \n */
+if (win_stdio_buf == '\r') {
+continue;
+}
+
+/* Signal the main thread and wait until the byte was eaten */
+if (!SetEvent(hInputReadyEvent)) {
+break;
+}
+if (WaitForSingleObject(hInputDoneEvent, INFINITE) != WAIT_OBJECT_0) {
+break;
+}
+}
+
+qemu_del_wait_object(hInputReadyEvent, NULL, NULL);
+return 0;
+}
+
+static void win_stdio_thread_wait_func(void *opaque)
+{
+CharDriverState *chr = opaque;
+
+if (qemu_chr_be_can_write(chr)) {
+qemu_chr_be_write(chr,win_stdio_buf, 1);
+}
+
+SetEvent(hInputDoneEvent);
+}
+
+static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool echo)
+{
+DWORD dwMode = 0;
+
+GetConsoleMode(hStdIn,dwMode);
+
+if (echo) {
+SetConsoleMode(hStdIn, dwMode | ENABLE_ECHO_INPUT);
+} else {
+SetConsoleMode(hStdIn, dwMode   ~ENABLE_ECHO_INPUT);
+}
+}
+
+static int qemu_chr_open_win_stdio(QemuOpts *opts,
+CharDriverState **_chr)
+{
+CharDriverState *chr;
+DWORDdwMode;
+int  is_console = 0;
+
+hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+if (hStdIn == INVALID_HANDLE_VALUE) {
+fprintf(stderr, cannot open stdio: invalid handle\n

Re: [Qemu-devel] [PATCH v2] support add-cow format

2011-09-23 Thread Mars.cao

Hi,Dong Xu Wang,



On 09/22/2011 09:51 AM, Dong Xu Wang wrote:

ubuntu.img is a disk image which has been installed OS.
(1) Create a raw image with the same size of ubuntu.img
qemu-img create -f raw test.raw 8G
(2) Create a add-cow image which will store dirty bitmap
qemu-img create -f add-cow test.add-cow -o 
backing_file=ubuntu.img,image_file=test.raw
(3) Run qemu with add-cow image
qemu -drive if=virtio,file=test.add-cow -m 1024


I tested this patch on RHEL6.1 host and RHEL6.1 guest,and the image size 
is 10G.

Signed-off-by: Dong Xu Wangwdon...@linux.vnet.ibm.com
---
  Makefile.objs   |1 +
  block.c |4 +-
  block.h |1 +
  block/add-cow.c |  403 +++
  block_int.h |1 +
  qemu-img.c  |2 +-
  6 files changed, 409 insertions(+), 3 deletions(-)
  create mode 100644 block/add-cow.c

diff --git a/Makefile.objs b/Makefile.objs
index 1c65087..2521f0d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -31,6 +31,7 @@ block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o

  block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o 
vvfat.o
  block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o 
qcow2-cache.o
+block-nested-y += add-cow.o
  block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
  block-nested-y += qed-check.o
  block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
diff --git a/block.c b/block.c
index e3fe97f..66f2d39 100644
--- a/block.c
+++ b/block.c
@@ -106,7 +106,7 @@ int is_windows_drive(const char *filename)
  #endif

  /* check if the path starts with protocol: */
-static int path_has_protocol(const char *path)
+int path_has_protocol(const char *path)
  {
  #ifdef _WIN32
  if (is_windows_drive(path) ||
@@ -875,7 +875,7 @@ int bdrv_commit(BlockDriverState *bs)

  if (!drv)
  return -ENOMEDIUM;
-
+
  if (!bs-backing_hd) {
  return -ENOTSUP;
  }
diff --git a/block.h b/block.h
index 16bfa0a..8b09f12 100644
--- a/block.h
+++ b/block.h
@@ -256,6 +256,7 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, 
QEMUSnapshotInfo *sn);

  char *get_human_readable_size(char *buf, int buf_size, int64_t size);
  int path_is_absolute(const char *path);
+int path_has_protocol(const char *path);
  void path_combine(char *dest, int dest_size,
const char *base_path,
const char *filename);
diff --git a/block/add-cow.c b/block/add-cow.c
new file mode 100644
index 000..d27be6e
--- /dev/null
+++ b/block/add-cow.c
@@ -0,0 +1,403 @@
+#include qemu-common.h
+#include block_int.h
+#include module.h
+
+#define ADD_COW_MAGIC  (((uint64_t)'A'  56) | ((uint64_t)'D'  48) | \
+((uint64_t)'D'  40) | ((uint64_t)'_'  32) | \
+((uint64_t)'C'  24) | ((uint64_t)'O'  16) | \
+((uint64_t)'W'  8) | 0xFF)
+#define ADD_COW_VERSION 1
+
+typedef struct AddCowHeader {
+uint64_t magic;
+uint32_t version;
+char backing_file[1024];
+char image_file[1024];
+uint64_t size;
+uint32_t sectorsize;
+} QEMU_PACKED AddCowHeader;
+
+typedef struct BDRVAddCowState {
+CoMutex lock;
+CoMutex bitmap_lock;
+char image_file[1024];
+BlockDriverState *image_hd;
+uint8_t *bitmap;
+uint64_t bitmap_size;
+} BDRVAddCowState;
+
+static int add_cow_probe(const uint8_t *buf, int buf_size, const char 
*filename)
+{
+const AddCowHeader *header = (const void *)buf;
+
+if (be64_to_cpu(header-magic) == ADD_COW_MAGIC
+be32_to_cpu(header-version) == ADD_COW_VERSION) {
+return 100;
+} else {
+return 0;
+}
+}
+
+static int add_cow_open(BlockDriverState *bs, int flags)
+{
+AddCowHeader header;
+int64_t size;
+char image_filename[1024];
+int image_flags;
+BlockDriver *image_drv = NULL;
+int ret;
+BDRVAddCowState *state = (BDRVAddCowState *)(bs-opaque);
+
+if (bdrv_pread(bs-file, 0,header, sizeof(header)) != sizeof(header)) {
+goto fail;
+}
+
+if (be64_to_cpu(header.magic) != ADD_COW_MAGIC ||
+be32_to_cpu(header.version) != ADD_COW_VERSION) {
+goto fail;
+}
+
+size = be64_to_cpu(header.size);
+bs-total_sectors = size / 512;
+
+pstrcpy(bs-backing_file, sizeof(bs-backing_file),
+header.backing_file);
+pstrcpy(state-image_file, sizeof(state-image_file),
+header.image_file);
+
+state-bitmap_size = ((bs-total_sectors + 7)  3);
+if (!state-bitmap) {
+state-bitmap = g_malloc0(state-bitmap_size);
+}
+if (bdrv_pread(bs-file, sizeof(header), state-bitmap,  \
+state-bitmap_size) != state-bitmap_size) {
+goto fail;
+}
+   /* if there is a image_file, must be together with backing_file */
+if (state-image_file[0] != '\0') {
+state-image_hd = bdrv_new();
+if (path_has_protocol(state-image_file)) {
+