From patchwork Mon Feb 1 05:57:45 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Vainman X-Patchwork-Id: 76037 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 o115vmCN030500 for ; Mon, 1 Feb 2010 05:57:48 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754188Ab0BAF5s (ORCPT ); Mon, 1 Feb 2010 00:57:48 -0500 Received: from fwil.voltaire.com ([193.47.165.2]:28321 "EHLO exil.voltaire.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754187Ab0BAF5s (ORCPT ); Mon, 1 Feb 2010 00:57:48 -0500 Received: from [127.0.0.1] ([172.25.5.22]) by exil.voltaire.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 1 Feb 2010 07:57:46 +0200 Message-ID: <4B666D59.4000101@gmail.com> Date: Mon, 01 Feb 2010 07:57:45 +0200 From: Alex Vainman Reply-To: alexv@voltaire.com User-Agent: Thunderbird 2.0.0.23 (Windows/20090812) MIME-Version: 1.0 To: roland , Roland Dreier , linux-rdma@vger.kernel.org, alexr@voltaire.com Subject: [PATCH v2 3/4] libibverbs: Undo changes in memory range tree when madvise() fails X-OriginalArrivalTime: 01 Feb 2010 05:57:46.0699 (UTC) FILETIME=[7A6291B0:01CAA303] Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@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]); Mon, 01 Feb 2010 05:57:49 +0000 (UTC) diff --git a/src/memory.c b/src/memory.c index 6a3305f..4dd9bdd 100644 --- a/src/memory.c +++ b/src/memory.c @@ -489,6 +489,39 @@ static struct ibv_mem_node *get_start_node(uintptr_t start, uintptr_t end, return node; } +/* + * This function is being called if madvise() fails and comes to + * undo merging/splitting operations performed on the node. + */ +static struct ibv_mem_node *undo_node(struct ibv_mem_node *node, + uintptr_t start, int inc) +{ + struct ibv_mem_node *tmp = NULL; + + /* + * This condition can be true only if we merged this + * node with the previous one, so we need to split them. + */ + if (start > node->start) { + tmp = split_range(node, start); + if (tmp) { + node->refcnt += inc; + node = tmp; + } else + return NULL; + } + + tmp = __mm_prev(node); + if (tmp && tmp->refcnt == node->refcnt) + node = merge_ranges(node, tmp); + + tmp = __mm_next(node); + if (tmp && tmp->refcnt == node->refcnt) + node = merge_ranges(tmp, node); + + return node; +} + static int ibv_madvise_range(void *base, size_t size, int advice) { uintptr_t start, end; @@ -541,8 +574,10 @@ static int ibv_madvise_range(void *base, size_t size, int advice) ret = madvise((void *) node->start, node->end - node->start + 1, advice); - if (ret) + if (ret) { + node = undo_node(node, start, inc); goto out; + } } node->refcnt += inc;