Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp123725pxb; Thu, 7 Apr 2022 00:36:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy+TcknX8ckGdw7yiSo1q3alCLfaPLliBZFZcT4/6rTSkb/qWB+Re562VEPZ/AYuoxWNDuo X-Received: by 2002:a50:9986:0:b0:413:bbdd:d5a1 with SMTP id m6-20020a509986000000b00413bbddd5a1mr12859106edb.26.1649316996249; Thu, 07 Apr 2022 00:36:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649316996; cv=none; d=google.com; s=arc-20160816; b=w5lS1KZPX3s18cHlH/Q7crXyLLB1Q7W7kn9maLdxo6O8byealwK/WNxPKkDQhfdqa1 DGaRXdouIwmF8IeeVaBMSGFfLuOf26rbduXzurrMY5kvZg7Rs0bkVmxhZloceFwJEwes 4BHs8y/iE3a4B9cPSzDFxsMMQDEJlD3b5kEHSxU/1VP8Dqb66CoHXXZ1RktrJQD/6fRZ xS9Zz0AejJluL9alnX50ICUzaNorTe3157s9m9UkggpXyChErS+pwgpZgL7BVwEp6+bt p2DB3D7MF+5McniJ0gjT/W2u4CRt26ObnrDBdIj8FZ4lB44X3UCsb0kQAH8PQBNGC4gq BIwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=MrMCPzeUnsgCf8A+1Oi4ZrjHm00y6px2hIOkkNlIGbQ=; b=LvtqpfFrb52l7D/r/kZXy2P+jmtlibtqIgLbTYvLmoXC+b6D3TTsTXOl6P0g107qYV Irp7cRvUif6idGVnWHEGjNWEvWJlweBLom4AHz5azp26o3w6zLQxrVW/EsA4wapxX9Hz BVhW1l58Z0yXT9blLmBmvEDKvpswsZvdiOHTvYxPxwTaHZLvolQXZ0TAbgFL5mkpRiUv zZbWj26hGKc+FjwDrscop9OXWEBFWe/Sx/2Uvir8dR64to0AXO2huwQsU7HWce2Vmybu cAyiXG7n8WeKLXPzfJCjTDBQsBfDvCpqGT4P5Jzpw7EGBF2I9GIeecQKz/J80nYe6jz2 YxVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=oiSqR8UT; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s23-20020a170906285700b006df76385da0si12684352ejc.576.2022.04.07.00.36.09; Thu, 07 Apr 2022 00:36:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=oiSqR8UT; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234352AbiDGBOG (ORCPT + 99 others); Wed, 6 Apr 2022 21:14:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33210 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235386AbiDGBNS (ORCPT ); Wed, 6 Apr 2022 21:13:18 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C7DF185958; Wed, 6 Apr 2022 18:11:09 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8933261DB3; Thu, 7 Apr 2022 01:11:09 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E9E44C385B4; Thu, 7 Apr 2022 01:11:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1649293869; bh=DOYeRWrBBQWdVD9Rx+PC9W95VT/yBtDywvBCWAM4ZbA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oiSqR8UT6nQKh+0dz4LqQf4DYe8iPeap02bLom76e0rxeIx9s38lGxp0SnWr8x7uT sr1xi76vntG8xgopq8LsKJM9CZwyEV7U//+92H5nfqeSMBCsODmBBSV3dhAWvfUQWw 8v5g9qGP1l9Rk3AlmeH1an/mWLutpS6lLc+t3R9Cm5Fe6SW5A/+pLaX1Gfw8MAac0Q 1dkCiH1PCFOjN6Za3GbZEpyKYTrRTiZWHOXEcHM4hkus0yZT6mjjJoyVetcPcowKwF PhDq45TGEJXrSzadckKxX9K0aZ5rQgfALIkGU4ilJmjAN3C62mXp4oHd6LZeD+1Wqe gtqp1r/Whacdg== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Niklas Schnelle , Matthew Rosato , Vasily Gorbik , Sasha Levin , gerald.schaefer@linux.ibm.com, hca@linux.ibm.com, agordeev@linux.ibm.com, linux-s390@vger.kernel.org Subject: [PATCH AUTOSEL 5.17 18/31] s390/pci: improve zpci_dev reference counting Date: Wed, 6 Apr 2022 21:10:16 -0400 Message-Id: <20220407011029.113321-18-sashal@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220407011029.113321-1-sashal@kernel.org> References: <20220407011029.113321-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Niklas Schnelle [ Upstream commit c122383d221dfa2f41cfe5e672540595de986fde ] Currently zpci_dev uses kref based reference counting but only accounts for one original reference plus one reference from an added pci_dev to its underlying zpci_dev. Counting just the original reference worked until the pci_dev reference was added in commit 2a671f77ee49 ("s390/pci: fix use after free of zpci_dev") because once a zpci_dev goes away, i.e. enters the reserved state, it would immediately get released. However with the pci_dev reference this is no longer the case and the zpci_dev may still appear in multiple availability events indicating that it was reserved. This was solved by detecting when the zpci_dev is already on its way out but still hanging around. This has however shown some light on how unusual our zpci_dev reference counting is. Improve upon this by modelling zpci_dev reference counting on pci_dev. Analogous to pci_get_slot() increment the reference count in get_zdev_by_fid(). Thus all users of get_zdev_by_fid() must drop the reference once they are done with the zpci_dev. Similar to pci_scan_single_device(), zpci_create_device() returns the device with an initial count of 1 and the device added to the zpci_list (analogous to the PCI bus' device_list). In turn users of zpci_create_device() must only drop the reference once the device is gone from the point of view of the zPCI subsystem, it might still be referenced by the common PCI subsystem though. Reviewed-by: Matthew Rosato Signed-off-by: Niklas Schnelle Signed-off-by: Vasily Gorbik Signed-off-by: Sasha Levin --- arch/s390/pci/pci.c | 1 + arch/s390/pci/pci_bus.h | 3 ++- arch/s390/pci/pci_clp.c | 9 +++++++-- arch/s390/pci/pci_event.c | 7 ++++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 792f8e0f2178..5bcd9228db5f 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -69,6 +69,7 @@ struct zpci_dev *get_zdev_by_fid(u32 fid) list_for_each_entry(tmp, &zpci_list, entry) { if (tmp->fid == fid) { zdev = tmp; + zpci_zdev_get(zdev); break; } } diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h index e359d2686178..ecef3a9e16c0 100644 --- a/arch/s390/pci/pci_bus.h +++ b/arch/s390/pci/pci_bus.h @@ -19,7 +19,8 @@ void zpci_bus_remove_device(struct zpci_dev *zdev, bool set_error); void zpci_release_device(struct kref *kref); static inline void zpci_zdev_put(struct zpci_dev *zdev) { - kref_put(&zdev->kref, zpci_release_device); + if (zdev) + kref_put(&zdev->kref, zpci_release_device); } static inline void zpci_zdev_get(struct zpci_dev *zdev) diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index be077b39da33..5011d27461fd 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -22,6 +22,8 @@ #include #include +#include "pci_bus.h" + bool zpci_unique_uid; void update_uid_checking(bool new) @@ -403,8 +405,11 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data) return; zdev = get_zdev_by_fid(entry->fid); - if (!zdev) - zpci_create_device(entry->fid, entry->fh, entry->config_state); + if (zdev) { + zpci_zdev_put(zdev); + return; + } + zpci_create_device(entry->fid, entry->fh, entry->config_state); } int clp_scan_pci_devices(void) diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index 2e3e5b278925..ea9db5cea64e 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c @@ -269,7 +269,7 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); if (!pdev) - return; + goto no_pdev; switch (ccdf->pec) { case 0x003a: /* Service Action or Error Recovery Successful */ @@ -286,6 +286,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) break; } pci_dev_put(pdev); +no_pdev: + zpci_zdev_put(zdev); } void zpci_event_error(void *data) @@ -314,6 +316,7 @@ static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh) static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) { struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); + bool existing_zdev = !!zdev; enum zpci_state state; zpci_dbg(3, "avl fid:%x, fh:%x, pec:%x\n", @@ -378,6 +381,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) default: break; } + if (existing_zdev) + zpci_zdev_put(zdev); } void zpci_event_availability(void *data) -- 2.35.1