From patchwork Sun Apr 25 13:27:34 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 94942 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3PDTYhF019937 for ; Sun, 25 Apr 2010 13:29:34 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752478Ab0DYN3V (ORCPT ); Sun, 25 Apr 2010 09:29:21 -0400 Received: from mtagate2.uk.ibm.com ([194.196.100.162]:40448 "EHLO mtagate2.uk.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751804Ab0DYN3U (ORCPT ); Sun, 25 Apr 2010 09:29:20 -0400 Received: from d06nrmr1407.portsmouth.uk.ibm.com (d06nrmr1407.portsmouth.uk.ibm.com [9.149.38.185]) by mtagate2.uk.ibm.com (8.13.1/8.13.1) with ESMTP id o3PDTJqZ010420 for ; Sun, 25 Apr 2010 13:29:19 GMT Received: from d06av01.portsmouth.uk.ibm.com (d06av01.portsmouth.uk.ibm.com [9.149.37.212]) by d06nrmr1407.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o3PDTJg6737280 for ; Sun, 25 Apr 2010 14:29:19 +0100 Received: from d06av01.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av01.portsmouth.uk.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id o3PDTIp1032466 for ; Sun, 25 Apr 2010 14:29:18 +0100 Received: from localhost.localdomain (chv03608.de.ibm.com [9.145.135.171]) by d06av01.portsmouth.uk.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id o3PDTHEd032459; Sun, 25 Apr 2010 14:29:17 +0100 From: Stefan Hajnoczi To: Avi Kivity Cc: Leszek Urbanski , Ryan Harper , kvm@vger.kernel.org, Stefan Hajnoczi Subject: Re: [PATCH] block: Free iovec arrays allocated by multiwrite_merge() Date: Sun, 25 Apr 2010 14:27:34 +0100 Message-Id: <1272202054-4831-1-git-send-email-stefanha@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0 In-Reply-To: <4BD43747.1070403@redhat.com> References: <4BD43747.1070403@redhat.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sun, 25 Apr 2010 13:29:34 +0000 (UTC) diff --git a/Makefile.objs b/Makefile.objs index 59ec879..82a4fac 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -7,7 +7,7 @@ qobject-obj-y += qerror.o ####################################################################### # block-obj-y is code used by both qemu system emulation and qemu-img -block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o +block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o leakcheck.o block-obj-y += nbd.o block.o aio.o aes.o osdep.o block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/leakcheck.c b/leakcheck.c new file mode 100644 index 0000000..a5fa51a --- /dev/null +++ b/leakcheck.c @@ -0,0 +1,17 @@ +#include + +static FILE *fp; + +extern void leakcheck_log(char action, void *old_addr, void *addr, size_t size, void *ret1); + +void leakcheck_log(char action, void *old_addr, void *addr, size_t size, void *ret1) +{ + if (!fp) { + fp = fopen("/tmp/leakcheck.log", "w"); + if (!fp) { + return; + } + } + + fprintf(fp, "%c %p %p %zd %p\n", action, old_addr, addr, size, ret1); +} diff --git a/leakcheck.py b/leakcheck.py new file mode 100755 index 0000000..64b1a1b --- /dev/null +++ b/leakcheck.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +import sys + +class Event(object): + def __init__(self, num, action, old_addr, addr, size, ret_addr): + self.num = num + self.action = action + self.old_addr = old_addr + self.addr = addr + self.size = size + self.ret_addr = ret_addr + + def __str__(self): + return '%d %s %s %s %s %s' % (self.num, self.action, self.old_addr, self.addr, self.size, self.ret_addr) + +def malloc(event): + if event.addr in allocs: + sys.stderr.write('malloc returned duplicate address from %s\n' % event) + allocs[event.addr] = event + +def free(event): + if event.addr == '(nil)': + return + if event.addr not in allocs: + sys.stderr.write('free of unallocated address from %s\n' % event) + return + malloc_event = allocs[event.addr] + del allocs[event.addr] + if (malloc_event.action in 'msz' and event.action == 'f') or \ + (malloc_event.action == 'a' and event.action == 'v'): + return + sys.stderr.write('mismatched actions for %s and %s\n' % (malloc_event, event)) + +def realloc(event): + free(Event(event.num, 'f', event.old_addr, '(nil)', 0, event.ret_addr)) + malloc(Event(event.num, 'm', '(nil)', event.addr, event.size, event.ret_addr)) + +allocs = {} +watermark = 0 +event_num = 0 +for line in sys.stdin: + event_num += 1 + + cmd = line.strip() + if cmd == 'watermark': + watermark = event_num + continue + + action, old_addr, addr, size, ret_addr = cmd.split() + event = Event(event_num, action, old_addr, addr, size, ret_addr) + if action in 'amsz': + malloc(event) + elif action in 'fv': + free(event) + elif action == 'r': + realloc(event) + else: + sys.stderr.write('invalid action "%c"\n' % action) + sys.exit(1) + +for event in sorted(allocs.itervalues(), key=lambda e: e.num): + if event.num > watermark: + print event diff --git a/osdep.c b/osdep.c index 8a710e7..40788e5 100644 --- a/osdep.c +++ b/osdep.c @@ -95,6 +95,8 @@ void qemu_vfree(void *ptr) #else +extern void leakcheck_log(char action, void *old_addr, void *addr, size_t size, void *ret1); + void *qemu_memalign(size_t alignment, size_t size) { #if defined(_POSIX_C_SOURCE) && !defined(__sun__) @@ -110,7 +112,9 @@ void *qemu_memalign(size_t alignment, size_t size) #elif defined(CONFIG_BSD) return oom_check(valloc(size)); #else - return oom_check(memalign(alignment, size)); + void *p = oom_check(memalign(alignment, size)); + leakcheck_log('a', NULL, p, size, __builtin_return_address(0)); + return p; #endif } @@ -126,6 +130,7 @@ void *qemu_vmalloc(size_t size) void qemu_vfree(void *ptr) { + leakcheck_log('v', NULL, ptr, 0, __builtin_return_address(0)); free(ptr); } diff --git a/qemu-malloc.c b/qemu-malloc.c index 6cdc5de..bf832f2 100644 --- a/qemu-malloc.c +++ b/qemu-malloc.c @@ -24,6 +24,8 @@ #include "qemu-common.h" #include +extern void leakcheck_log(char action, void *old_addr, void *addr, size_t size, void *ret1); + static void *oom_check(void *ptr) { if (ptr == NULL) { @@ -39,6 +41,7 @@ void *get_mmap_addr(unsigned long size) void qemu_free(void *ptr) { + leakcheck_log('f', NULL, ptr, 0, __builtin_return_address(0)); free(ptr); } @@ -51,7 +54,7 @@ static int allow_zero_malloc(void) #endif } -void *qemu_malloc(size_t size) +static void *qemu_malloc_common(size_t size) { if (!size && !allow_zero_malloc()) { abort(); @@ -59,19 +62,30 @@ void *qemu_malloc(size_t size) return oom_check(malloc(size ? size : 1)); } +void *qemu_malloc(size_t size) +{ + void *p = qemu_malloc_common(size); + leakcheck_log('m', NULL, p, size, __builtin_return_address(0)); + return p; +} + void *qemu_realloc(void *ptr, size_t size) { if (!size && !allow_zero_malloc()) { abort(); } - return oom_check(realloc(ptr, size ? size : 1)); + size = size ? size : 1; + void *p = oom_check(realloc(ptr, size)); + leakcheck_log('r', ptr, p, size, __builtin_return_address(0)); + return p; } void *qemu_mallocz(size_t size) { void *ptr; - ptr = qemu_malloc(size); + ptr = qemu_malloc_common(size); memset(ptr, 0, size); + leakcheck_log('z', NULL, ptr, size, __builtin_return_address(0)); return ptr; } @@ -79,8 +93,9 @@ char *qemu_strdup(const char *str) { char *ptr; size_t len = strlen(str); - ptr = qemu_malloc(len + 1); + ptr = qemu_malloc_common(len + 1); memcpy(ptr, str, len + 1); + leakcheck_log('s', NULL, ptr, len + 1, __builtin_return_address(0)); return ptr; } @@ -93,8 +108,9 @@ char *qemu_strndup(const char *str, size_t size) size = end - str; } - new = qemu_malloc(size + 1); + new = qemu_malloc_common(size + 1); new[size] = 0; + leakcheck_log('s', NULL, new, size + 1, __builtin_return_address(0)); return memcpy(new, str, size); }