From patchwork Mon Aug 29 07:08:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 9303189 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 BD76F607F0 for ; Mon, 29 Aug 2016 07:20:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A7240287B8 for ; Mon, 29 Aug 2016 07:20:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9BA62287CD; Mon, 29 Aug 2016 07:20:56 +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=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DAEDA287B8 for ; Mon, 29 Aug 2016 07:20:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756285AbcH2HUx (ORCPT ); Mon, 29 Aug 2016 03:20:53 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:35507 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750828AbcH2HUx (ORCPT ); Mon, 29 Aug 2016 03:20:53 -0400 Received: by mail-wm0-f65.google.com with SMTP id i5so8247264wmg.2 for ; Mon, 29 Aug 2016 00:20:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9bGAVpICcr2HRMXcHsDNz5t2YeOyQL15XBIDgLJUdzQ=; b=n2h/Z38R18Q6sOyK1gAsuKZ3oZa1db6HETBClGiNllvVx0PSJhrftAoNr6I7Gy/Mzx ZkGZbieFBprEJqmNOTYVRP9T622yehNFlzeapy6cBqYb/JtUPLmHljU852hiWfL1K8cd XBxbXj6CmgFtlPUtHfo4qeCa6PJe+lIsZx2q9/xPXXo9pgeCuGkKlzMOGD/rwL4rSr6O BOUz8Z51mDQLU2281KeVwg/9d2T/eukeoST8hMTvecyTrtnURcWkjxnvz2PP9sJALiHV HgVRBln3Wp5vbNpAeyP3c4osJXWq3ORvVojTZH6WNJ2o2UZTZF9lFX2v7jzXfTUQdRc1 wn3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=9bGAVpICcr2HRMXcHsDNz5t2YeOyQL15XBIDgLJUdzQ=; b=WJTIDY+p5Zyy+UZsQ4LTGuMGvDBio2dV2NSKg7/UKBVhAruPJSt496Kp+mmeo8cs/q w8wGoSQ9yvTQrTAn6LPKd4hIJjaGsdezybN00ez5VESr4lVSfB4FDYr1hQAKxJm4Ltpz 8iXxB/X8pvhhDCs0r6HJlLmWbABzEogsjtqzfvtALdVIfG0y0BZNYxgQvHKeOxdvOqzh ColeZWYca2XHb8aw9Criq9LhA95XVVP+6yzHQTNkbZO+GolBBoYV3NSszFDvFfLYMJq4 cDTjNuSJ2537KBSEJrd8Oz5xzngMblW/OPkCe5v/StLE+Pkj/oZbLkGhw/ez7ilHRs7b 9Mng== X-Gm-Message-State: AE9vXwPMbxFWY4OAU9Jwu+kG4XKCRSZg5ebOoMCT1+5Cs6aVVNSgl4GFmTa0HcIzoD1U1A== X-Received: by 10.28.18.149 with SMTP id 143mr8584493wms.28.1472454529143; Mon, 29 Aug 2016 00:08:49 -0700 (PDT) Received: from haswell.alporthouse.com ([78.156.65.138]) by smtp.gmail.com with ESMTPSA id v203sm11954826wmv.2.2016.08.29.00.08.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Aug 2016 00:08:48 -0700 (PDT) From: Chris Wilson To: dri-devel@lists.freedesktop.org Cc: intel-gfx@lists.freedesktop.org, Chris Wilson , Daniel Vetter , Maarten Lankhorst , =?UTF-8?q?Christian=20K=C3=B6nig?= , Alex Deucher , Sumit Semwal , linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org Subject: [PATCH 07/11] dma-buf: Restart reservation_object_get_fences_rcu() after writes Date: Mon, 29 Aug 2016 08:08:30 +0100 Message-Id: <20160829070834.22296-7-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160829070834.22296-1-chris@chris-wilson.co.uk> References: <20160829070834.22296-1-chris@chris-wilson.co.uk> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In order to be completely generic, we have to double check the read seqlock after acquiring a reference to the fence. If the driver is allocating fences from a SLAB_DESTROY_BY_RCU, or similar freelist, then within an RCU grace period a fence may be freed and reallocated. The RCU read side critical section does not prevent this reallocation, instead we have to inspect the reservation's seqlock to double check if the fences have been reassigned as we were acquiring our reference. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Christian König Cc: Alex Deucher Cc: Sumit Semwal Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Reviewed-by: Daniel Vetter --- drivers/dma-buf/reservation.c | 71 +++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 723d8af988e5..10fd441dd4ed 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -280,18 +280,24 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, unsigned *pshared_count, struct fence ***pshared) { - unsigned shared_count = 0; - unsigned retry = 1; - struct fence **shared = NULL, *fence_excl = NULL; - int ret = 0; + struct fence **shared = NULL; + struct fence *fence_excl; + unsigned shared_count; + int ret = 1; - while (retry) { + do { struct reservation_object_list *fobj; unsigned seq; + unsigned i; - seq = read_seqcount_begin(&obj->seq); + shared_count = i = 0; rcu_read_lock(); + seq = read_seqcount_begin(&obj->seq); + + fence_excl = rcu_dereference(obj->fence_excl); + if (fence_excl && !fence_get_rcu(fence_excl)) + goto unlock; fobj = rcu_dereference(obj->fence); if (fobj) { @@ -309,52 +315,37 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, } ret = -ENOMEM; - shared_count = 0; break; } shared = nshared; - memcpy(shared, fobj->shared, sz); shared_count = fobj->shared_count; - } else - shared_count = 0; - fence_excl = rcu_dereference(obj->fence_excl); - - retry = read_seqcount_retry(&obj->seq, seq); - if (retry) - goto unlock; - - if (!fence_excl || fence_get_rcu(fence_excl)) { - unsigned i; for (i = 0; i < shared_count; ++i) { - if (fence_get_rcu(shared[i])) - continue; - - /* uh oh, refcount failed, abort and retry */ - while (i--) - fence_put(shared[i]); - - if (fence_excl) { - fence_put(fence_excl); - fence_excl = NULL; - } - - retry = 1; - break; + shared[i] = rcu_dereference(fobj->shared[i]); + if (!fence_get_rcu(shared[i])) + break; } - } else - retry = 1; + } + + if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) { + while (i--) + fence_put(shared[i]); + fence_put(fence_excl); + goto unlock; + } + ret = 0; unlock: rcu_read_unlock(); - } - *pshared_count = shared_count; - if (shared_count) - *pshared = shared; - else { - *pshared = NULL; + } while (ret); + + if (!shared_count) { kfree(shared); + shared = NULL; } + + *pshared_count = shared_count; + *pshared = shared; *pfence_excl = fence_excl; return ret;