Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753334AbdLSThI (ORCPT ); Tue, 19 Dec 2017 14:37:08 -0500 Received: from mga01.intel.com ([192.55.52.88]:17651 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753183AbdLSTgt (ORCPT ); Tue, 19 Dec 2017 14:36:49 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,428,1508828400"; d="scan'208";a="4018580" From: Dongwon Kim To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, xen-devel@lists.xenproject.org, mateuszx.potrola@intel.com, dongwon.kim@intel.com Subject: [RFC PATCH 30/60] hyper_dmabuf: free already mapped pages when error happens Date: Tue, 19 Dec 2017 11:29:46 -0800 Message-Id: <1513711816-2618-30-git-send-email-dongwon.kim@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> References: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3974 Lines: 115 From: Mateusz Polrola It is needed to freeing already-mapped pages if it gets error before finishing mapping all pages. Signed-off-by: Dongwon Kim --- .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c | 43 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c index c03e5a0..524f75c 100644 --- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c @@ -255,7 +255,7 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n if (lvl3_map_ops.status) { dev_err(hyper_dmabuf_private.device, "HYPERVISOR map grant ref failed status = %d", lvl3_map_ops.status); - return NULL; + goto error_cleanup_lvl3; } else { lvl3_unmap_ops.handle = lvl3_map_ops.handle; } @@ -263,7 +263,7 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n /* Map all second level pages */ if (gnttab_alloc_pages(n_lvl2_grefs, lvl2_table_pages)) { dev_err(hyper_dmabuf_private.device, "Cannot allocate pages\n"); - return NULL; + goto error_cleanup_lvl3; } for (i = 0; i < n_lvl2_grefs; i++) { @@ -277,6 +277,9 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n if (gnttab_unmap_refs(&lvl3_unmap_ops, NULL, &lvl3_table_page, 1)) { dev_err(hyper_dmabuf_private.device, "xen: cannot unmap top level page\n"); return NULL; + } else { + /* Mark that page was unmapped */ + lvl3_unmap_ops.handle = -1; } if (gnttab_map_refs(lvl2_map_ops, NULL, lvl2_table_pages, n_lvl2_grefs)) { @@ -290,7 +293,7 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n dev_err(hyper_dmabuf_private.device, "HYPERVISOR map grant ref failed status = %d", lvl2_map_ops[i].status); - return NULL; + goto error_cleanup_lvl2; } else { lvl2_unmap_ops[i].handle = lvl2_map_ops[i].handle; } @@ -298,7 +301,7 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n if (gnttab_alloc_pages(nents, data_pages)) { dev_err(hyper_dmabuf_private.device, "Cannot allocate pages\n"); - return NULL; + goto error_cleanup_lvl2; } k = 0; @@ -343,6 +346,11 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n n_lvl2_grefs)) { dev_err(hyper_dmabuf_private.device, "Cannot unmap 2nd level refs\n"); return NULL; + } else { + /* Mark that pages were unmapped */ + for (i = 0; i < n_lvl2_grefs; i++) { + lvl2_unmap_ops[i].handle = -1; + } } for (i = 0; i < nents; i++) { @@ -350,7 +358,7 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n dev_err(hyper_dmabuf_private.device, "HYPERVISOR map grant ref failed status = %d\n", data_map_ops[i].status); - return NULL; + goto error_cleanup_data; } else { data_unmap_ops[i].handle = data_map_ops[i].handle; } @@ -369,6 +377,31 @@ struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int n dev_dbg(hyper_dmabuf_private.device, "%s exit\n", __func__); return data_pages; + +error_cleanup_data: + gnttab_unmap_refs(data_unmap_ops, NULL, data_pages, + nents); + + gnttab_free_pages(nents, data_pages); + +error_cleanup_lvl2: + if (lvl2_unmap_ops[0].handle != -1) + gnttab_unmap_refs(lvl2_unmap_ops, NULL, lvl2_table_pages, + n_lvl2_grefs); + gnttab_free_pages(n_lvl2_grefs, lvl2_table_pages); + +error_cleanup_lvl3: + if (lvl3_unmap_ops.handle != -1) + gnttab_unmap_refs(&lvl3_unmap_ops, NULL, &lvl3_table_page, 1); + gnttab_free_pages(1, &lvl3_table_page); + + kfree(lvl2_table_pages); + kfree(lvl2_map_ops); + kfree(lvl2_unmap_ops); + kfree(data_map_ops); + + + return NULL; } int hyper_dmabuf_xen_unmap_shared_pages(void **refs_info, int nents) { -- 2.7.4