From patchwork Wed Jan 4 06:12:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wen Congyang X-Patchwork-Id: 134214 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 217CC1007D9 for ; Wed, 4 Jan 2012 17:10:08 +1100 (EST) Received: from localhost ([::1]:54372 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiK30-0001Ih-9R for incoming@patchwork.ozlabs.org; Wed, 04 Jan 2012 01:10:02 -0500 Received: from eggs.gnu.org ([140.186.70.92]:33597) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiK2t-0001Ic-Pw for qemu-devel@nongnu.org; Wed, 04 Jan 2012 01:09:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RiK2r-00036z-Oz for qemu-devel@nongnu.org; Wed, 04 Jan 2012 01:09:55 -0500 Received: from [222.73.24.84] (port=60458 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiK2q-00036t-BA for qemu-devel@nongnu.org; Wed, 04 Jan 2012 01:09:53 -0500 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 18A2C170028; Wed, 4 Jan 2012 14:09:51 +0800 (CST) Received: from mailserver.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id q0469mnx017327; Wed, 4 Jan 2012 14:09:49 +0800 Received: from [10.167.225.226] ([10.167.225.226]) by mailserver.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.1FP4) with ESMTP id 2012010414085540-231815 ; Wed, 4 Jan 2012 14:08:55 +0800 Message-ID: <4F03EDB6.3030907@cn.fujitsu.com> Date: Wed, 04 Jan 2012 14:12:06 +0800 From: Wen Congyang User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100413 Fedora/3.0.4-2.fc13 Thunderbird/3.0.4 MIME-Version: 1.0 To: qemu-devel , Jan Kiszka , Dave Anderson , HATAYAMA Daisuke References: <4F03E735.2050804@cn.fujitsu.com> In-Reply-To: <4F03E735.2050804@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2012-01-04 14:08:55, Serialize by Router on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2012-01-04 14:08:56, Serialize complete at 2012-01-04 14:08:56 X-detected-operating-system: by eggs.gnu.org: FreeBSD 6.x (1) X-Received-From: 222.73.24.84 Subject: [Qemu-devel] [RFC][PATCH 09/14 v4] run dump at the background X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The new monitor command dump may take long time to finish. So we need run it at the background. Signed-off-by: Wen Congyang --- dump.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 139 insertions(+), 19 deletions(-) diff --git a/dump.c b/dump.c index ab29a4c..09ed96a 100644 --- a/dump.c +++ b/dump.c @@ -75,12 +75,20 @@ typedef struct DumpState { Monitor *mon; int fd; target_phys_addr_t memory_offset; + int64_t bandwidth; + RAMBlock *block; + ram_addr_t start; + target_phys_addr_t offset; + QEMUTimer *timer; } DumpState; +#define DEFAULT_THROTTLE (32 << 20) /* Default dump speed throttling */ + static DumpState *dump_get_current(void) { static DumpState current_dump = { .state = DUMP_STATE_SETUP, + .bandwidth = DEFAULT_THROTTLE, }; return ¤t_dump; @@ -91,11 +99,21 @@ static int dump_cleanup(DumpState *s) int ret = 0; free_memory_mapping_list(&s->list); + if (s->fd != -1) { close(s->fd); s->fd = -1; } + if (s->timer) { + qemu_del_timer(s->timer); + qemu_free_timer(s->timer); + } + + if (s->mon) { + monitor_resume(s->mon); + } + return ret; } @@ -330,25 +348,40 @@ static int write_data(DumpState *s, void *buf, int length, } /* write the memroy to vmcore. 1 page per I/O. */ -static int write_memory(DumpState *s, RAMBlock *block, - target_phys_addr_t *offset) +static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start, + target_phys_addr_t *offset, int64_t *size, + int64_t deadline) { int i, ret; + int64_t writen_size = 0; + int64_t time; - for (i = 0; i < block->length / TARGET_PAGE_SIZE; i++) { - ret = write_data(s, block->host + i * TARGET_PAGE_SIZE, + for (i = 0; i < *size / TARGET_PAGE_SIZE; i++) { + ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE, TARGET_PAGE_SIZE, offset); if (ret < 0) { return -1; } + writen_size += TARGET_PAGE_SIZE; + time = qemu_get_clock_ms(rt_clock); + if (time >= deadline) { + /* time out */ + *size = writen_size; + return 1; + } } - if ((block->length % TARGET_PAGE_SIZE) != 0) { - ret = write_data(s, block->host + i * TARGET_PAGE_SIZE, - block->length % TARGET_PAGE_SIZE, offset); + if ((*size % TARGET_PAGE_SIZE) != 0) { + ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE, + *size % TARGET_PAGE_SIZE, offset); if (ret < 0) { return -1; } + time = qemu_get_clock_ms(rt_clock); + if (time >= deadline) { + /* time out */ + return 1; + } } return 0; @@ -383,6 +416,9 @@ static DumpState *dump_init(Monitor *mon, int fd) s->error = NULL; s->mon = mon; s->fd = fd; + s->block = QLIST_FIRST(&ram_list.blocks); + s->start = 0; + s->timer = NULL; /* * get dump info: endian, class and architecture. @@ -425,6 +461,11 @@ static DumpState *dump_init(Monitor *mon, int fd) s->phdr_num += s->list.num; } + if (monitor_suspend(mon) != 0) { + monitor_printf(mon, "terminal does not allow synchronous " + "dump, continuing detached\n"); + } + return s; } @@ -482,6 +523,7 @@ static int dump_begin(DumpState *s) } s->memory_offset = offset; + s->offset = offset; return 0; } @@ -509,38 +551,116 @@ static int dump_completed(DumpState *s) return 0; } -/* write all memory to vmcore */ -static int dump_iterate(DumpState *s) +/* + * write memory to vmcore. + * + * this function has three return values: + * -1 : there was one error + * 0 : We haven't finished, caller have to go again + * 1 : We have finished, we can go to complete phase + */ +static int dump_iterate(DumpState *s, int64_t deadline) { - RAMBlock *block; - target_phys_addr_t offset = s->memory_offset; + RAMBlock *block = s->block; + target_phys_addr_t offset = s->offset; + int64_t size, remain, writen_size; + int64_t total = s->bandwidth / 10; int ret; - /* write all memory to vmcore */ - QLIST_FOREACH(block, &ram_list.blocks, next) { - ret = write_memory(s, block, &offset); + if ((block->length - s->start) >= total) { + size = total; + } else { + size = block->length - s->start; + } + + ret = write_memory(s, block, s->start, &offset, &size, deadline); + if (ret < 0) { + return -1; + } + + if (size == total || ret == 1) { + if ((size + s->start) == block->length) { + s->block = QLIST_NEXT(block, next); + s->start = 0; + } else { + s->start += size; + } + goto end; + } + + while (size < total) { + block = QLIST_NEXT(block, next); + if (!block) { + /* we have finished */ + return 1; + } + + remain = total - size; + if (remain >= block->length) { + writen_size = block->length; + } else { + writen_size = remain; + } + ret = write_memory(s, block, 0, &offset, &writen_size, deadline); if (ret < 0) { return -1; + } else if (ret == 1) { + break; } + size += writen_size; + } + if (writen_size == block->length) { + s->block = QLIST_NEXT(block, next); + s->start = 0; + } else { + s->block = block; + s->start = writen_size; + } + +end: + s->offset = offset; + if (!s->block) { + /* we have finished */ + return 1; } - return dump_completed(s); + return 0; } -static int create_vmcore(DumpState *s) +static void dump_rate_tick(void *opaque) { + DumpState *s = opaque; + int64_t begin, end; int ret; - ret = dump_begin(s); + begin = qemu_get_clock_ms(rt_clock); + ret = dump_iterate(s, begin + 100); if (ret < 0) { - return -1; + return; + } else if (ret == 1) { + dump_completed(s); + return; + } + end = qemu_get_clock_ms(rt_clock); + if (end - begin >= 100) { + qemu_mod_timer(s->timer, end + 10); + } else { + qemu_mod_timer(s->timer, begin + 100); } +} - ret = dump_iterate(s); +static int create_vmcore(DumpState *s) +{ + int ret; + + ret = dump_begin(s); if (ret < 0) { return -1; } + s->timer = qemu_new_timer_ms(rt_clock, dump_rate_tick, s); + qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100); + return 0; }