Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753363AbdLSThM (ORCPT ); Tue, 19 Dec 2017 14:37:12 -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 S1752813AbdLSTg5 (ORCPT ); Tue, 19 Dec 2017 14:36:57 -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="4018602" 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 36/60] hyper_dmabuf: error handling when share_pages fails Date: Tue, 19 Dec 2017 11:29:52 -0800 Message-Id: <1513711816-2618-36-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: 4203 Lines: 119 From: Mateusz Polrola When error occurs while sharing pages, all pages already shared needs to be un-shared and proper error code has to be returned. Signed-off-by: Dongwon Kim --- drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c | 6 ++- .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c | 50 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c index f1581d5..375b664 100644 --- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -242,6 +242,10 @@ static int hyper_dmabuf_export_remote(struct file *filp, void *data) operands[6] = page_info->last_len; operands[7] = ops->share_pages (page_info->pages, export_remote_attr->remote_domain, page_info->nents, &sgt_info->refs_info); + if (operands[7] < 0) { + dev_err(hyper_dmabuf_private.device, "pages sharing failed\n"); + goto fail_map_req; + } /* driver/application specific private info, max 4x4 bytes */ operands[8] = export_remote_attr->private[0]; 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 1416a69..908eda8 100644 --- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c @@ -109,6 +109,16 @@ int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents, lvl2_table[i] = gnttab_grant_foreign_access(domid, pfn_to_mfn(page_to_pfn(pages[i])), true /* read-only from remote domain */); + if (lvl2_table[i] == -ENOSPC) { + dev_err(hyper_dmabuf_private.device, "No more space left in grant table\n"); + + /* Unshare all already shared pages for lvl2 */ + while(i--) { + gnttab_end_foreign_access_ref(lvl2_table[i], 0); + gnttab_free_grant_reference(lvl2_table[i]); + } + goto err_cleanup; + } } /* Share 2nd level addressing pages in readonly mode*/ @@ -116,6 +126,23 @@ int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents, lvl3_table[i] = gnttab_grant_foreign_access(domid, virt_to_mfn((unsigned long)lvl2_table+i*PAGE_SIZE ), true); + if (lvl3_table[i] == -ENOSPC) { + dev_err(hyper_dmabuf_private.device, "No more space left in grant table\n"); + + /* Unshare all already shared pages for lvl3 */ + while(i--) { + gnttab_end_foreign_access_ref(lvl3_table[i], 1); + gnttab_free_grant_reference(lvl3_table[i]); + } + + /* Unshare all pages for lvl2 */ + while(nents--) { + gnttab_end_foreign_access_ref(lvl2_table[nents], 0); + gnttab_free_grant_reference(lvl2_table[nents]); + } + + goto err_cleanup; + } } /* Share lvl3_table in readonly mode*/ @@ -123,6 +150,23 @@ int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents, virt_to_mfn((unsigned long)lvl3_table), true); + if (lvl3_gref == -ENOSPC) { + dev_err(hyper_dmabuf_private.device, "No more space left in grant table\n"); + + /* Unshare all pages for lvl3 */ + while(i--) { + gnttab_end_foreign_access_ref(lvl3_table[i], 1); + gnttab_free_grant_reference(lvl3_table[i]); + } + + /* Unshare all pages for lvl2 */ + while(nents--) { + gnttab_end_foreign_access_ref(lvl2_table[nents], 0); + gnttab_free_grant_reference(lvl2_table[nents]); + } + + goto err_cleanup; + } /* Store lvl3_table page to be freed later */ sh_pages_info->lvl3_table = lvl3_table; @@ -136,6 +180,12 @@ int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents, dev_dbg(hyper_dmabuf_private.device, "%s exit\n", __func__); return lvl3_gref; + +err_cleanup: + free_pages((unsigned long)lvl2_table, n_lvl2_grefs); + free_pages((unsigned long)lvl3_table, 1); + + return -ENOSPC; } int hyper_dmabuf_xen_unshare_pages(void **refs_info, int nents) { -- 2.7.4