From patchwork Mon Aug 29 17:10:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Butsykin X-Patchwork-Id: 9304551 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 528536077C for ; Mon, 29 Aug 2016 21:50:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 42C7C28673 for ; Mon, 29 Aug 2016 21:50:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 36F232867C; Mon, 29 Aug 2016 21:50:48 +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.8 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID 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 60D2828673 for ; Mon, 29 Aug 2016 21:50:47 +0000 (UTC) Received: from localhost ([::1]:45914 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beUS6-000236-EU for patchwork-qemu-devel@patchwork.kernel.org; Mon, 29 Aug 2016 17:50:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45985) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beUNT-0006Pp-4z for qemu-devel@nongnu.org; Mon, 29 Aug 2016 17:46:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1beUNR-0002mX-Sa for qemu-devel@nongnu.org; Mon, 29 Aug 2016 17:45:59 -0400 Received: from mail-eopbgr10098.outbound.protection.outlook.com ([40.107.1.98]:47456 helo=EUR02-HE1-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beUNL-0002l3-Fv; Mon, 29 Aug 2016 17:45:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=/uiGmJphTOHfU8Aa7qj9d1pDCr2hYZAwk7U+fkMPYW0=; b=EnUcTTFu/1CxI04bPZlMKZr8bpRncoTFFBk4CLOsMAp7RPWLY+PqPGivRnAD7MUHryVRjGbSwZ49PUdV1EzhCJ77Rj9PqA5Qrkkd9cVUGMd6FwnNc49ZCGCop46vFs/AmzGzTqUEpJh28u6O2aLOvTZ+J+edEXPVnRu/pomqAd4= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=pbutsykin@virtuozzo.com; Received: from pavelb-Z68P-DS3.sw.ru (195.214.232.10) by AM5PR0802MB2547.eurprd08.prod.outlook.com (10.175.45.23) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.587.13; Mon, 29 Aug 2016 17:11:18 +0000 From: Pavel Butsykin To: , Date: Mon, 29 Aug 2016 20:10:04 +0300 Message-ID: <20160829171021.4902-6-pbutsykin@virtuozzo.com> X-Mailer: git-send-email 2.8.3 In-Reply-To: <20160829171021.4902-1-pbutsykin@virtuozzo.com> References: <20160829171021.4902-1-pbutsykin@virtuozzo.com> MIME-Version: 1.0 X-Originating-IP: [195.214.232.10] X-ClientProxiedBy: AM5PR0901CA0011.eurprd09.prod.outlook.com (10.164.186.149) To AM5PR0802MB2547.eurprd08.prod.outlook.com (10.175.45.23) X-MS-Office365-Filtering-Correlation-Id: f1bd8294-6941-4b08-7798-08d3d02f7e92 X-Microsoft-Exchange-Diagnostics: 1; AM5PR0802MB2547; 2:Hfwhdg2xlki53U/NNwKfRvf0Q7fJUxHfrBH86gWl6gVaa44Q5xPXzcXHUldV4GOopvjMavN1eVTcAbADX0jCXfyZd6cQHtu1C5ukT14/8C9z0lYHtaWRU8+EzEcYpBHkVmDlUIiKHIgGz8ZvWip7nO3w9Pozxj7pCKPA+43yAjmlu/B7soQUTh7xzos0jee1; 3:WCojYWUyQPtPop8SAUh6XWn7+MRF0Ma5Y3vtYfDa4eTCiVNcuoPJzpVZk3oI+za6mvvC10CoxPds8kDPu+ZMErmWS235yls9u1hx2O1XwQOSStRJGS6rnihdUq5MEfpB X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:AM5PR0802MB2547; X-Microsoft-Exchange-Diagnostics: 1; AM5PR0802MB2547; 25:EuZvPHxq73NdF4DOIabCwb287+YqRH9WmIvEfDIqj4ngh/Svz3HajxHvk70u/e8GoSGz3byb07G/GRXcOPJF7Uew0rGnvPjhMT7aoodZ21FGLXNGGEJ0Ww0w787g8I9bGu6IRBc+EBKiKRfUOK1xIAwpCoTUqUn7wr74vTuYXXltMb1Z8uyVn0Kk7icc5oHBJzl7lz6jTg+Nf08N1RehFMnhRLN4+zs8TsBmQo9DSBrcGkspYXJPy//LgYzVya4hzt7AOnmnfV3+GJNnccRCpHfKUIDWq1uXf/UIZ7WCbugj+LQHbvDpMskWyiTqo7dlyRtd9VGId5cCIVPHbYQHo90OxHks+n9i3ih1Iii7VV2jUUMOm25PoNx+hhwve2oBJwtTcDqX1Vd7U8upjRy1CPZzwNPVmrPI2aGJcvwzAEDl8kzQOE6w5bNpRDmFzhoeKxNcAzCn0vBHuQ4N/rlyssiMJv8n6UcDJmxjGgTweLG+ph27GYver8Am+nCAoRWwQE0Sv9lK1v2TxvYRhCjluP+DwzM5Hpvz8gtnOjGkjbjinNPEfzzbaIGv6Bq3d6fTPcMDdH9QfCfkiXNE34YPPRdNjJZvy7e+hbB+StYQx7QlyJyyznTRfYhMwBvaHQq4qX1Fq/6ZqhJpYFdcKo4ViomoPmMEHA4XhZ6hckMSQaZUWQ3Bi1pOgz9cyIkAynGR7IlBPq00fVgiX+nESCaO1g==; 31:3WJ8OVQ/RedZGCqLrSAV2DOuNMjhS4geSTC66734Y8fGX9nsvCd+nRXFe3IzNOoyGzJzMc4nnbo56Vwp6cTZOSg+Xo04+BPXWY1gpSJ72qXuzR0bOcAU1d2ZrE6IYSGDXjWX4ZzyeBgsJyzDo/9XSibBY/qGP8Ude7GT5Bb8uKf0bsfuuqaqdV+NaAKYFlq05z6XHUK58ZlCf2iWb4jSdo3oRcpRW80vJkHycor+mA8= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6042046)(6043046); SRVR:AM5PR0802MB2547; BCL:0; PCL:0; RULEID:; SRVR:AM5PR0802MB2547; X-Microsoft-Exchange-Diagnostics: 1; AM5PR0802MB2547; 4:w1/A8aAnZ5cF1G2WpYtSgTw3u4/+W1JD2//T2LiTd9yrCil3SsJZN11oJUdSZkn4vlJWqAJn8s1KtqqMv6X1JU4x6Tf9FPdHAl+KCPlWp1ec3+mhCIZ1tUYikTRENW268ZaXQILHx1P3PZWQhtLvu2kHFp5TsROAEWV3mMZVQi5qxZ5+nTfosJYJqSbrXXALv5o+bqJNw+D9kjX8Hql87t9i5XITQX3kg2OweJ3ulXWNwvaONMQqGKI7m0yPi4pjVWZMc71cWVnUckxpygJbfW9gFs4zeVkp7KZHNGRRNruNjbmZYBdx6mNrGeJLdq2SmNaVfz7y2Aqt89IZZgOJs4aKOmdarbXAi8Ea1jKLLrRiXtEMOp7D33Ka9FWmHTGuOpFnaOkw6SFniWPVJPjNvqj5gM+R6sgr7UsOG8j1YQY= X-Forefront-PRVS: 0049B3F387 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(7916002)(199003)(189002)(3846002)(305945005)(77096005)(86362001)(1076002)(53416004)(92566002)(68736007)(42186005)(97736004)(5001770100001)(47776003)(105586002)(2906002)(6116002)(189998001)(50986999)(4326007)(48376002)(586003)(2950100001)(5003940100001)(50466002)(66066001)(19580405001)(19580395003)(76176999)(69596002)(5660300001)(229853001)(101416001)(36756003)(7736002)(8676002)(106356001)(50226002)(7846002)(81156014)(33646002)(81166006)(217873001); DIR:OUT; SFP:1102; SCL:1; SRVR:AM5PR0802MB2547; H:pavelb-Z68P-DS3.sw.ru; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: virtuozzo.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; AM5PR0802MB2547; 23:z+hNabcRIbhevlt2nIU17ZqpyFUrK3sklruoxsN?= =?us-ascii?Q?dLtM5pP8Lq21pJXW3Ho1yV0AN5zcb19utHqfhIZvp1IU0d3dJ2m6OU0sqoGS?= =?us-ascii?Q?f1YL1bGIigEpx+dqxlRbkI3XRlxlzKC/ye3skXk4vRBvGWWRIQajXZlfbZuI?= =?us-ascii?Q?bKBFjHgrsgMZpUFRt34VsdAKBuws74bDXsWw2P44y0tm6fT5X8pb3haGOkYI?= =?us-ascii?Q?cnVdj5kmdhK/6T9lUmp2BlEyMx1+4BVykhc0+tR50AJX9nIyABx/ujkofwrV?= =?us-ascii?Q?Js+GgU32rrfJppWbfAdAeN/PQehRxKoyen8CZ1f4Xg657kS70AZTUDI15VOe?= =?us-ascii?Q?IbJ2rfD0F4rc94jOK3VgIovtdPdksQiSmP7c6XospZt8zDiTisUT3P4sp9LX?= =?us-ascii?Q?hukpbpuF0GZoEPewBUdRvPEk3MTP9lYjbNbDCQ8x4Nvmo8muhmLv7Kgz//7y?= =?us-ascii?Q?EWA/jv564jqeKQyCEzjuqDu4/JzAh2pZalgXIA0LhHLL6/oLlgVohP5jKOtN?= =?us-ascii?Q?5ubcs/cnDrgPZlpX1jUEO2OgrA81voiDK7ad66nYEjPiGIW65pXxZ+Huw3PK?= =?us-ascii?Q?8DiIVi8bvl9oEV1TF2zQhAxy5sFh9IYzzxqM5HVZ/S3E5iQjRnrPVUwSiwyM?= =?us-ascii?Q?AhNPgyuXpUItpoWmNpl4l8YBb87rsagWKskz39iApJqLFPmeBV4W/UCWs6yn?= =?us-ascii?Q?sMmv2kiCKtejEv5oG8aCz0sgSPdpG6VGY/Bu/5yE7ybDD2DTpYGg9ZZgyy2A?= =?us-ascii?Q?3KzDKuQn2gwvTvCNL6Ratsz1g2bCaZZJtqsWpcKLhi44xafm1t8dq+fAwUg8?= =?us-ascii?Q?3uOORMO6tgX7exJNMHyaJRy/w4pIVv62EjDqAWFVjvQmCyoDKobvGVKfUYGZ?= =?us-ascii?Q?dBdflUlq8vjQsKVcnzT4Tljq1S+TVB+ux7r3YAnUwmZHQ8rZm4vGKSkRKOFu?= =?us-ascii?Q?RJiQqFuuaJlBo8STdR0USvULrFOm6A3oenDWq97yjVJA9/n/PlKD8CIZA+S1?= =?us-ascii?Q?EXWZDPQiRzRNVqUTnhGW5UzTm7SWGTeNVeqqT50L1k77CBK/BBgYAxuSZjda?= =?us-ascii?Q?hYiBVeSpKjEQq64MdVKL8SAMixc+VD4TOPqOC4xZJrg3eoMpg0pdubH5MbAd?= =?us-ascii?Q?Kdqmc9XbfFFrbstAO+5/7HeVarHebEdVugQv3cZuImUHVw2vos5jYaw=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1; AM5PR0802MB2547; 6:SCmrraV7JnzsQBCE/36UEW0+3CsznI9l3fZct3uYeAbwepmGo24oBEkCjwe+MYEJlFlBgP44xPA5Y8akkoMYKwlRQkQILsyspkKCkeJJCvOfEUw/qU9+o083bin+LtmrbweoUGX7maKzhna6oKoZFRhgX2Ke1BBZTfZZ66arZKOBMV/TjQztAMMrAa1mTRcT8TgmXZs2Lj/gHUdxx1w1T3SqXDUssQkf2IrdD9C2Exo2iNUjstwesDgsAN1QEAOiPIqnsVH1rGLAROTLAuBIBACpPoarU0wf42QZNJ8ME06mR6y6mPFgYeEP05QGfeOk; 5:ze5deCx+fwcuHSUE4WYeTSha9wd2KN27zla0pluAHLnTc55tW5LWhrHnkYcoTGbqGc5LO/uzijBmuKYrjI5N5S6SgtBXNYQ1PW/tgQC2/c9vv7KBb8f/4vvjfo6ZEwNKye+MogwQVqm28SOkyabjOQ==; 24:j04L2e05uBD9tR0TmkY8VVzPwO4s153x2fjrq6t/lqL8kjx6ciFr46LJXHK3rF8H7w33okFMzZ6f/ab8uBZqCdMZj76/NfRGaOrKUK2zrw4=; 7:ycI+knn/ntBD/nyJfrWFzDcKaDsAcfJs9RdqOmqOLw2RfuHbhaXH6QnqKgJwR0KtasxR89jz4GD8q6abAp6/cvHQyQSpngiRXAAPL4PC73d4/UGn6g93Jv54oT4KkCHDnYvVhabIh2mcngeLAFh59ozwISRp+TiKJhA+R7kiYfubP7ixVopKhSr8uyyuInrCgiUx1PDXpb1urVN0P/WDNphFJtPDizzJhbrTF/+RsmM5gDqol7XR2BgiUhR0lRH/ SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; AM5PR0802MB2547; 20:g5Dv8KT6zoaPZSeiO7LNPrT1BP71F813i9r58TmXY3FdHBWEIMAM9vHKJyC2aEfkUyG06kt5b/m5CVyQQFqUT4cRg6wB5gO3bdpH9WpPyj+5YsMIr66/KZlGRyCoQAdoL0mmBErx5aT5EWdOl6wdg3jFxw9IdDYPsmc044GvYeY= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Aug 2016 17:11:18.9505 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0802MB2547 X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 40.107.1.98 Subject: [Qemu-devel] [PATCH RFC v2 05/22] block/pcache: add aio requests into cache 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, famz@redhat.com, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, jsnow@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP For storing requests use an rbtree, here are add basic operations on the rbtree to work with cache nodes. Signed-off-by: Pavel Butsykin --- block/pcache.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 189 insertions(+), 1 deletion(-) diff --git a/block/pcache.c b/block/pcache.c index 7f221d6..f5022f9 100644 --- a/block/pcache.c +++ b/block/pcache.c @@ -27,6 +27,7 @@ #include "block/raw-aio.h" #include "qapi/error.h" #include "qapi/qmp/qstring.h" +#include "qemu/rbtree.h" #define PCACHE_DEBUG @@ -37,9 +38,53 @@ #define DPRINTF(fmt, ...) do { } while (0) #endif +typedef struct RbNodeKey { + uint64_t num; + uint32_t size; +} RbNodeKey; + +typedef struct BlockNode { + struct RbNode rb_node; + union { + RbNodeKey key; + struct { + uint64_t sector_num; + uint32_t nb_sectors; + }; + }; + QTAILQ_ENTRY(BlockNode) entry; +} BlockNode; + +typedef struct PCNode { + BlockNode cm; + + uint8_t *data; +} PCNode; + +typedef struct ReqStor { + struct { + struct RbRoot root; + CoMutex lock; + } tree; + + uint32_t curr_size; +} ReqStor; + +typedef struct BDRVPCacheState { + BlockDriverState **bs; + + ReqStor pcache; + + struct { + QTAILQ_HEAD(pcache_head, BlockNode) head; + CoMutex lock; + } list; +} BDRVPCacheState; + typedef struct PrefCacheAIOCB { BlockAIOCB common; + BDRVPCacheState *s; QEMUIOVector *qiov; uint64_t sector_num; uint32_t nb_sectors; @@ -64,6 +109,124 @@ static QemuOptsList runtime_opts = { }, }; +#define PCNODE(_n) ((PCNode *)(_n)) + +static int pcache_key_cmp(const RbNodeKey *key1, const RbNodeKey *key2) +{ + assert(key1 != NULL); + assert(key2 != NULL); + + if (key1->num >= key2->num + key2->size) { + return 1; + } + if (key1->num + key1->size <= key2->num) { + return -1; + } + + return 0; +} + +static void *node_insert(struct RbRoot *root, BlockNode *node) +{ + struct RbNode **new = &(root->rb_node), *parent = NULL; + + /* Figure out where to put new node */ + while (*new) { + BlockNode *this = container_of(*new, BlockNode, rb_node); + int result = pcache_key_cmp(&node->key, &this->key); + if (result == 0) { + return this; + } + parent = *new; + new = result < 0 ? &((*new)->rb_left) : &((*new)->rb_right); + } + /* Add new node and rebalance tree. */ + rb_link_node(&node->rb_node, parent, new); + rb_insert_color(&node->rb_node, root); + + return node; +} + +static inline PCNode *pcache_node_insert(struct RbRoot *root, PCNode *node) +{ + return node_insert(root, &node->cm); +} + +static inline void pcache_node_free(PCNode *node) +{ + g_free(node->data); + g_slice_free1(sizeof(*node), node); +} + +static inline void *pcache_node_alloc(RbNodeKey* key) +{ + PCNode *node = g_slice_alloc(sizeof(*node)); + + node->cm.sector_num = key->num; + node->cm.nb_sectors = key->size; + node->data = g_malloc(node->cm.nb_sectors << BDRV_SECTOR_BITS); + + return node; +} + +static bool pcache_node_find_and_create(PrefCacheAIOCB *acb, RbNodeKey *key, + PCNode **out_node) +{ + BDRVPCacheState *s = acb->s; + PCNode *new_node = pcache_node_alloc(key); + PCNode *found; + + qemu_co_mutex_lock(&s->pcache.tree.lock); + found = pcache_node_insert(&s->pcache.tree.root, new_node); + qemu_co_mutex_unlock(&s->pcache.tree.lock); + if (found != new_node) { + pcache_node_free(new_node); + *out_node = found; + return false; + } + atomic_add(&s->pcache.curr_size, new_node->cm.nb_sectors); + + qemu_co_mutex_lock(&s->list.lock); + QTAILQ_INSERT_HEAD(&s->list.head, &new_node->cm, entry); + qemu_co_mutex_unlock(&s->list.lock); + + *out_node = new_node; + return true; +} + +static inline void prefetch_init_key(PrefCacheAIOCB *acb, RbNodeKey* key) +{ + key->num = acb->sector_num; + key->size = acb->nb_sectors; +} + +enum { + PREFETCH_NEW_NODE = 0, + PREFETCH_FULL_UP = 1, + PREFETCH_PART_UP = 2 +}; + +static int32_t pcache_prefetch(PrefCacheAIOCB *acb) +{ + RbNodeKey key; + PCNode *node = NULL; + + prefetch_init_key(acb, &key); + if (pcache_node_find_and_create(acb, &key, &node)) { + return PREFETCH_NEW_NODE; + } + + /* Node covers the whole request */ + if (node->cm.sector_num <= acb->sector_num && + node->cm.sector_num + node->cm.nb_sectors >= acb->sector_num + + acb->nb_sectors) + { + return PREFETCH_FULL_UP; + } + + return PREFETCH_PART_UP; +} + static void pcache_aio_cb(void *opaque, int ret) { PrefCacheAIOCB *acb = opaque; @@ -80,6 +243,7 @@ static PrefCacheAIOCB *pcache_aio_get(BlockDriverState *bs, int64_t sector_num, { PrefCacheAIOCB *acb = qemu_aio_get(&pcache_aiocb_info, bs, cb, opaque); + acb->s = bs->opaque; acb->sector_num = sector_num; acb->nb_sectors = nb_sectors; acb->qiov = qiov; @@ -99,6 +263,8 @@ static BlockAIOCB *pcache_aio_readv(BlockDriverState *bs, PrefCacheAIOCB *acb = pcache_aio_get(bs, sector_num, qiov, nb_sectors, cb, opaque, QEMU_AIO_READ); + pcache_prefetch(acb); + bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, pcache_aio_cb, acb); return &acb->common; @@ -119,6 +285,17 @@ static BlockAIOCB *pcache_aio_writev(BlockDriverState *bs, return &acb->common; } +static void pcache_state_init(QemuOpts *opts, BDRVPCacheState *s) +{ + DPRINTF("pcache configure:\n"); + + s->pcache.tree.root = RB_ROOT; + qemu_co_mutex_init(&s->pcache.tree.lock); + QTAILQ_INIT(&s->list.head); + qemu_co_mutex_init(&s->list.lock); + s->pcache.curr_size = 0; +} + static int pcache_file_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -140,7 +317,9 @@ static int pcache_file_open(BlockDriverState *bs, QDict *options, int flags, if (local_err) { ret = -EINVAL; error_propagate(errp, local_err); + goto fail; } + pcache_state_init(opts, bs->opaque); fail: qemu_opts_del(opts); return ret; @@ -148,6 +327,15 @@ fail: static void pcache_close(BlockDriverState *bs) { + uint32_t cnt = 0; + BDRVPCacheState *s = bs->opaque; + BlockNode *node, *next; + QTAILQ_FOREACH_SAFE(node, &s->list.head, entry, next) { + QTAILQ_REMOVE(&s->list.head, node, entry); + pcache_node_free(PCNODE(node)); + cnt++; + } + DPRINTF("used %d nodes\n", cnt); } static void pcache_parse_filename(const char *filename, QDict *options, @@ -170,7 +358,7 @@ static bool pcache_recurse_is_first_non_filter(BlockDriverState *bs, static BlockDriver bdrv_pcache = { .format_name = "pcache", .protocol_name = "pcache", - .instance_size = 0, + .instance_size = sizeof(BDRVPCacheState), .bdrv_parse_filename = pcache_parse_filename, .bdrv_file_open = pcache_file_open,