From patchwork Thu Oct 27 10:46:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prasanna Kumar Kalever X-Patchwork-Id: 9399223 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1BDA7600BA for ; Thu, 27 Oct 2016 11:26:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E90A62A15A for ; Thu, 27 Oct 2016 11:26:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DCC2E2A15D; Thu, 27 Oct 2016 11:26:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 204B82A15A for ; Thu, 27 Oct 2016 11:26:10 +0000 (UTC) Received: from localhost ([::1]:40441 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzioz-0008UA-Vv for patchwork-qemu-devel@patchwork.kernel.org; Thu, 27 Oct 2016 07:26:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55793) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzilQ-000661-5h for qemu-devel@nongnu.org; Thu, 27 Oct 2016 07:22:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bzilK-0002fn-0X for qemu-devel@nongnu.org; Thu, 27 Oct 2016 07:22:28 -0400 Received: from [209.132.183.28] (port=37082 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1bzilJ-0002Za-PL for qemu-devel@nongnu.org; Thu, 27 Oct 2016 07:22:21 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BB89961B8A; Thu, 27 Oct 2016 10:46:11 +0000 (UTC) Received: from dhcp-0-155.blr.redhat.com (dhcp-0-155.blr.redhat.com [10.70.1.155]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u9RAk7dn021014; Thu, 27 Oct 2016 06:46:08 -0400 From: Prasanna Kumar Kalever To: qemu-devel@nongnu.org Date: Thu, 27 Oct 2016 16:16:03 +0530 Message-Id: <1477565163-10475-1-git-send-email-prasanna.kalever@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 27 Oct 2016 10:46:11 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v1 1/1] block/gluster: memory usage: use one glfs instance per volume X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, pkrempa@redhat.com, vbellur@redhat.com, jcody@redhat.com, armbru@redhat.com, bharata@linux.vnet.ibm.com, rtalur@redhat.com, Prasanna Kumar Kalever , ndevos@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Currently, for every drive accessed via gfapi we create a new glfs instance (call glfs_new() followed by glfs_init()) which could consume memory in few 100 MB's, from the table below it looks like for each instance ~300 MB VSZ was consumed Before: ------- Disks VSZ RSS 1 1098728 187756 2 1430808 198656 3 1764932 199704 4 2084728 202684 This patch maintains a list of pre-opened glfs objects. On adding a new drive belonging to the same gluster volume, we just reuse the existing glfs object by updating its refcount. With this approch we shrink up the unwanted memory consumption and glfs_new/glfs_init calls for accessing a disk (file) if belongs to same volume. From below table notice that the memory usage after adding a disk (which will reuse the existing glfs object hence) is in negligible compared to before. After: ------ Disks VSZ RSS 1 1101964 185768 2 1109604 194920 3 1114012 196036 4 1114496 199868 Disks: number of -drive VSZ: virtual memory size of the process in KiB RSS: resident set size, the non-swapped physical memory (in kiloBytes) VSZ and RSS are analyzed using 'ps aux' utility. Signed-off-by: Prasanna Kumar Kalever --- block/gluster.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 14 deletions(-) diff --git a/block/gluster.c b/block/gluster.c index 01b479f..367d692 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -54,6 +54,19 @@ typedef struct BDRVGlusterReopenState { } BDRVGlusterReopenState; +typedef struct GlfsPreopened { + char *volume; + glfs_t *fs; + int ref; +} GlfsPreopened; + +typedef struct ListElement { + QLIST_ENTRY(ListElement) list; + GlfsPreopened saved; +} ListElement; + +static QLIST_HEAD(glfs_list, ListElement) glfs_list; + static QemuOptsList qemu_gluster_create_opts = { .name = "qemu-gluster-create-opts", .head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head), @@ -182,6 +195,63 @@ static QemuOptsList runtime_tcp_opts = { }, }; +static int glfs_set_preopened(const char *volume, glfs_t *fs) +{ + ListElement *entry = NULL; + + entry = g_new(ListElement, 1); + if (!entry) { + errno = ENOMEM; + return -1; + } + + entry->saved.volume = g_strdup(volume); + if (!entry->saved.volume) { + g_free(entry->saved.volume); + errno = ENOMEM; + return -1; + } + + entry->saved.fs = fs; + entry->saved.ref = 1; + + QLIST_INSERT_HEAD(&glfs_list, entry, list); + + return 0; +} + +static glfs_t *glfs_find_preopened(const char *volume) +{ + ListElement *entry = NULL; + + QLIST_FOREACH(entry, &glfs_list, list) { + if (strcmp(entry->saved.volume, volume) == 0) { + entry->saved.ref++; + return entry->saved.fs; + } + } + + return NULL; +} + +static void glfs_clear_preopened(glfs_t *fs) +{ + ListElement *entry = NULL; + + QLIST_FOREACH(entry, &glfs_list, list) { + if (entry->saved.fs == fs) { + if (--entry->saved.ref) { + return; + } + + QLIST_REMOVE(entry, list); + + glfs_fini(entry->saved.fs); + g_free(entry); + } + } +} + static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path) { char *p, *q; @@ -319,11 +389,23 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf, int old_errno; GlusterServerList *server; + glfs = glfs_find_preopened(gconf->volume); + if (glfs) { + return glfs; + } + glfs = glfs_new(gconf->volume); if (!glfs) { goto out; } + ret = glfs_set_preopened(gconf->volume, glfs); + if (ret < 0) { + error_setg(errp, "glfs_set_preopened: Failed to register volume (%s)", + gconf->volume); + goto out; + } + for (server = gconf->server; server; server = server->next) { if (server->value->type == GLUSTER_TRANSPORT_UNIX) { ret = glfs_set_volfile_server(glfs, @@ -375,7 +457,7 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf, out: if (glfs) { old_errno = errno; - glfs_fini(glfs); + glfs_clear_preopened(glfs); errno = old_errno; } return NULL; @@ -741,9 +823,9 @@ out: if (s->fd) { glfs_close(s->fd); } - if (s->glfs) { - glfs_fini(s->glfs); - } + + glfs_clear_preopened(s->glfs); + return ret; } @@ -808,9 +890,8 @@ static void qemu_gluster_reopen_commit(BDRVReopenState *state) if (s->fd) { glfs_close(s->fd); } - if (s->glfs) { - glfs_fini(s->glfs); - } + + glfs_clear_preopened(s->glfs); /* use the newly opened image / connection */ s->fd = reop_s->fd; @@ -835,9 +916,7 @@ static void qemu_gluster_reopen_abort(BDRVReopenState *state) glfs_close(reop_s->fd); } - if (reop_s->glfs) { - glfs_fini(reop_s->glfs); - } + glfs_clear_preopened(reop_s->glfs); g_free(state->opaque); state->opaque = NULL; @@ -955,9 +1034,7 @@ static int qemu_gluster_create(const char *filename, out: g_free(tmp); qapi_free_BlockdevOptionsGluster(gconf); - if (glfs) { - glfs_fini(glfs); - } + glfs_clear_preopened(glfs); return ret; } @@ -1029,7 +1106,7 @@ static void qemu_gluster_close(BlockDriverState *bs) glfs_close(s->fd); s->fd = NULL; } - glfs_fini(s->glfs); + glfs_clear_preopened(s->glfs); } static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)