Message ID | 20231130174126.688486-1-herve.codina@bootlin.com |
---|---|
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:bcd1:0:b0:403:3b70:6f57 with SMTP id r17csp563623vqy; Thu, 30 Nov 2023 09:41:41 -0800 (PST) X-Google-Smtp-Source: AGHT+IGk/iBcqU6AtFSS2PnJBqB2vTLoB/Xe5ubS4TBJ/tJgf2Ozg5V0F6XqgYbOUlLcLNvrcRA+ X-Received: by 2002:a05:6a20:729c:b0:18c:91ff:8268 with SMTP id o28-20020a056a20729c00b0018c91ff8268mr18428008pzk.9.1701366101616; Thu, 30 Nov 2023 09:41:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701366101; cv=none; d=google.com; s=arc-20160816; b=g4hC2c7fXXRPj6EzKIYHjrBHE+OdQl4rpKXoeNoyzxB6uAL0AILOEAjgHtp2g7uMQ8 m72siho6b5/Rb/M4aHr4bD9kT/6HRn1VPhenNtNA6KQSOgIVwBqWSACmCOraSP0vSLvN Q5d0Rzg93ZlWr+z1YzYf/DBFWpk1mv7kuuzAxIriD/DMLcif0kMxpryy0GeqLMg8vPW7 GMlP1badMg5beyWQHxN2tVFotLatF5eo4ASKVktV8PEfw4U/aHmQMyOuCXUdevaMQLwO MRu684WBpLuj4taHv8S+/Jbr3zkIUAG6vDBkfrzQ/WzVb0Tj0/rter0AyER8Qw3LNZtC T0OQ== 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 :message-id:date:subject:cc:to:from:dkim-signature; bh=yvt6xwQtma5BgVNgEWdmqb5WwlVdI81bFmTFIjob+Mc=; fh=hxCb8OzaXBuSbXNrdSfbxd9E+OOUaTeXTLLu8usFTUA=; b=GRAEPuiLFDNICsLmnOJQiCxzupMgA7N9oi+p/owI5Zw1COp8FD9q0LhH/HqKb124ER pRPX29JzbuiHYm3Paado8XgNC3JQJvhiASRQBXPEZmD76cn3VMJsSn8zSpHV7aE31T1i UnDhytMfxzMjqFD+DrcPLe9swJ85zmTR56Wqqmd+mZ1Yig70tJS+m4eE/62aqsThJoTb 1hLPdnb7CF9+htBxG6qObopuulZlI1O3vcxdax37ufUCzKTdPjc3Vgf9njF7BJZehu49 uP+nIdTRq4aj1Iq5OZtEbArhyqSNm1J7VykrwNAck3A2izV1u5XSEzXXsJEeKR4qDbRN HBkw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=YoKRgwhA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from pete.vger.email (pete.vger.email. [2620:137:e000::3:6]) by mx.google.com with ESMTPS id c17-20020a6566d1000000b005c14fc66ccasi1773905pgw.370.2023.11.30.09.41.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Nov 2023 09:41:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) client-ip=2620:137:e000::3:6; Authentication-Results: mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=YoKRgwhA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 973ED82CB865; Thu, 30 Nov 2023 09:41:36 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345951AbjK3Rl0 (ORCPT <rfc822;ruipengqi7@gmail.com> + 99 others); Thu, 30 Nov 2023 12:41:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232284AbjK3RlZ (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 30 Nov 2023 12:41:25 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B547131; Thu, 30 Nov 2023 09:41:31 -0800 (PST) Received: by mail.gandi.net (Postfix) with ESMTPA id 96FB71BF204; Thu, 30 Nov 2023 17:41:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1701366090; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=yvt6xwQtma5BgVNgEWdmqb5WwlVdI81bFmTFIjob+Mc=; b=YoKRgwhAp78MJzd93oCesNXjw7Ycio+S7kvwK1i6xHARYrwsm3Wa6UMaMTzGYHM8bjZoWR vaHXZBcUrq/VEkYwbGp3kQyUbUGz+EuKc2OEqsZQEITDz+ovTU3Qk6lmBb8NzvOyCEzm6E RFWjvcAbKVUmLyk/eJJ31bDYUqdblg+w5aQPk+WE94qXsxAT/ABy63L31xjvdwnbtOEstw Gulzu+gVIApBU7xqWc65mKE10z1INu57LVSxd3I2penHHX204ZOcvU8VHNC9ybVkDedMJg N9pz+nzZ8VUMA9UROmEldwIbDjtSo6GR5bTN7ODHKx4Cc28ukjYUNszj73f6uQ== From: Herve Codina <herve.codina@bootlin.com> To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, "Rafael J. Wysocki" <rafael@kernel.org>, Rob Herring <robh+dt@kernel.org>, Frank Rowand <frowand.list@gmail.com> Cc: Lizhi Hou <lizhi.hou@amd.com>, Max Zhen <max.zhen@amd.com>, Sonal Santan <sonal.santan@amd.com>, Stefano Stabellini <stefano.stabellini@xilinx.com>, Jonathan Cameron <Jonathan.Cameron@Huawei.com>, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Allan Nielsen <allan.nielsen@microchip.com>, Horatiu Vultur <horatiu.vultur@microchip.com>, Steen Hegelund <steen.hegelund@microchip.com>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>, Herve Codina <herve.codina@bootlin.com> Subject: [PATCH 0/2] Synchronize DT overlay removal with devlink removals Date: Thu, 30 Nov 2023 18:41:07 +0100 Message-ID: <20231130174126.688486-1-herve.codina@bootlin.com> X-Mailer: git-send-email 2.42.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-GND-Sasl: herve.codina@bootlin.com X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on pete.vger.email Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (pete.vger.email [0.0.0.0]); Thu, 30 Nov 2023 09:41:36 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1784011661394531682 X-GMAIL-MSGID: 1784011661394531682 |
Series |
Synchronize DT overlay removal with devlink removals
|
|
Message
Herve Codina
Nov. 30, 2023, 5:41 p.m. UTC
Hi, In the following sequence: of_platform_depopulate(); /* Remove devices from a DT overlay node */ of_overlay_remove(); /* Remove the DT overlay node itself */ Some warnings are raised by __of_changeset_entry_destroy() which was called from of_overlay_remove(): ERROR: memory leak, expected refcount 1 instead of 2 ... The issue is that, during the device devlink removals triggered from the of_platform_depopulate(), jobs are put in a workqueue. These jobs drop the reference to the devices. When a device is no more referenced (refcount == 0), it is released and the reference to its of_node is dropped by a call to of_node_put(). These operations are fully correct except that, because of the workqueue, they are done asynchronously with respect to function calls. In the sequence provided, the jobs are run too late, after the call to __of_changeset_entry_destroy() and so a missing of_node_put() call is detected by __of_changeset_entry_destroy(). This series fixes this issue introducing device_link_wait_removal() in order to wait for the end of jobs execution (patch 1) and using this function to synchronize the overlay removal with the end of jobs execution (patch 2). Best regards, Hervé Herve Codina (2): driver core: Introduce device_link_wait_removal() of: overlay: Synchronize of_overlay_remove() with the devlink removals drivers/base/core.c | 26 +++++++++++++++++++++++--- drivers/of/overlay.c | 6 ++++++ include/linux/device.h | 1 + 3 files changed, 30 insertions(+), 3 deletions(-)
Comments
On Thu, Nov 30, 2023 at 06:41:07PM +0100, Herve Codina wrote: > Hi, +Saravana for comment Looks okay to me though. > > In the following sequence: > of_platform_depopulate(); /* Remove devices from a DT overlay node */ > of_overlay_remove(); /* Remove the DT overlay node itself */ > > Some warnings are raised by __of_changeset_entry_destroy() which was > called from of_overlay_remove(): > ERROR: memory leak, expected refcount 1 instead of 2 ... > > The issue is that, during the device devlink removals triggered from the > of_platform_depopulate(), jobs are put in a workqueue. > These jobs drop the reference to the devices. When a device is no more > referenced (refcount == 0), it is released and the reference to its > of_node is dropped by a call to of_node_put(). > These operations are fully correct except that, because of the > workqueue, they are done asynchronously with respect to function calls. > > In the sequence provided, the jobs are run too late, after the call to > __of_changeset_entry_destroy() and so a missing of_node_put() call is > detected by __of_changeset_entry_destroy(). > > This series fixes this issue introducing device_link_wait_removal() in > order to wait for the end of jobs execution (patch 1) and using this > function to synchronize the overlay removal with the end of jobs > execution (patch 2). > > Best regards, > Hervé > > Herve Codina (2): > driver core: Introduce device_link_wait_removal() > of: overlay: Synchronize of_overlay_remove() with the devlink removals > > drivers/base/core.c | 26 +++++++++++++++++++++++--- > drivers/of/overlay.c | 6 ++++++ > include/linux/device.h | 1 + > 3 files changed, 30 insertions(+), 3 deletions(-) > > -- > 2.42.0 >
On Wed, Dec 6, 2023 at 9:15 AM Rob Herring <robh@kernel.org> wrote: > > On Thu, Nov 30, 2023 at 06:41:07PM +0100, Herve Codina wrote: > > Hi, > > +Saravana for comment I'll respond to this within a week -- very swamped at the moment. The main thing I want to make sure is that we don't cause an indirect deadlock with this wait(). I'll go back and look at why we added the work queue and then check for device/devlink locking issues. -Saravana > > Looks okay to me though. > > > > > In the following sequence: > > of_platform_depopulate(); /* Remove devices from a DT overlay node */ > > of_overlay_remove(); /* Remove the DT overlay node itself */ > > > > Some warnings are raised by __of_changeset_entry_destroy() which was > > called from of_overlay_remove(): > > ERROR: memory leak, expected refcount 1 instead of 2 ... > > > > The issue is that, during the device devlink removals triggered from the > > of_platform_depopulate(), jobs are put in a workqueue. > > These jobs drop the reference to the devices. When a device is no more > > referenced (refcount == 0), it is released and the reference to its > > of_node is dropped by a call to of_node_put(). > > These operations are fully correct except that, because of the > > workqueue, they are done asynchronously with respect to function calls. > > > > In the sequence provided, the jobs are run too late, after the call to > > __of_changeset_entry_destroy() and so a missing of_node_put() call is > > detected by __of_changeset_entry_destroy(). > > > > This series fixes this issue introducing device_link_wait_removal() in > > order to wait for the end of jobs execution (patch 1) and using this > > function to synchronize the overlay removal with the end of jobs > > execution (patch 2). > > > > Best regards, > > Hervé > > > > Herve Codina (2): > > driver core: Introduce device_link_wait_removal() > > of: overlay: Synchronize of_overlay_remove() with the devlink removals > > > > drivers/base/core.c | 26 +++++++++++++++++++++++--- > > drivers/of/overlay.c | 6 ++++++ > > include/linux/device.h | 1 + > > 3 files changed, 30 insertions(+), 3 deletions(-) > > > > -- > > 2.42.0 > >
Hello Saravana, Rob, Hervé, [+Miquèl, who contributed to the discussion with Hervé and me] On Wed, 6 Dec 2023 19:09:06 -0800 Saravana Kannan <saravanak@google.com> wrote: > On Wed, Dec 6, 2023 at 9:15 AM Rob Herring <robh@kernel.org> wrote: > > > > On Thu, Nov 30, 2023 at 06:41:07PM +0100, Herve Codina wrote: > > > Hi, > > > > +Saravana for comment > > I'll respond to this within a week -- very swamped at the moment. The > main thing I want to make sure is that we don't cause an indirect > deadlock with this wait(). I'll go back and look at why we added the > work queue and then check for device/devlink locking issues. While working on a project unrelated to Hervé's work, I also ended up in getting sporadic but frequent "ERROR: memory leak, expected refcount 1 instead of..." messages, which persisted even after adding this patch series on my tree. My use case is the insertion and removal of a simple overlay describing a regulator-fixed and an I2C GPIO expander using it. The messages appear regardless of whether the insertion and removal is done from kernel code or via the configfs interface (out-of-tree patches from [0]). I reconstructed the sequence of operations, all of which stem from of_overlay_remove(): int of_overlay_remove(int *ovcs_id) { ... device_link_wait_removal(); // proposed by this patch series mutex_lock(&of_mutex); ... ret = __of_changeset_revert_notify(&ovcs->cset); // this ends up calling (excerpt from a long stack trace): // -> of_i2c_notify // -> device_remove // -> devm_regulator_release // -> device_link_remove // -> devlink_dev_release, which queues work for // device_link_release_fn, which in turn calls: // -> device_put // -> device_release // -> {platform,regulator,...}_dev*_release // -> of_node_put() [**] ... free_overlay_changeset(ovcs); // calls: // -> of_changeset_destroy // -> __of_changeset_entry_destroy // -> pr_err("ERROR: memory leak, expected refcount 1 instead of %d... // The error appears or not, based on when the workqueue runs err_unlock: mutex_unlock(&of_mutex); ... } So this adds up to the question of whether devlink removal should actually be run asynchronously or not. A simple short-term solution is to move the call to device_link_wait_removal() later, just before free_overlay_changeset(): diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 1a8a6620748c..eccf08cf2160 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -1375,12 +1375,6 @@ int of_overlay_remove(int *ovcs_id) goto out; } - /* - * Wait for any ongoing device link removals before removing some of - * nodes - */ - device_link_wait_removal(); - mutex_lock(&of_mutex); ovcs = idr_find(&ovcs_idr, *ovcs_id); @@ -1427,6 +1421,14 @@ int of_overlay_remove(int *ovcs_id) if (!ret) ret = ret_tmp; + /* + * Wait for any ongoing device link removals before removing some of + * nodes + */ + mutex_unlock(&of_mutex); + device_link_wait_removal(); + mutex_lock(&of_mutex); + free_overlay_changeset(ovcs); err_unlock: This obviously raises the question of whether unlocking and re-locking the mutex is potentially dangerous. I have no answer to this right away, but I tested this change with CONFIG_PROVE_LOCKING=y and no issue showed up after several overlay load/unload sequences so I am not aware of any actual issues with this change. [0] https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git/log/?h=topic/overlays Luca
Hi, On Wed, 20 Dec 2023 18:16:27 +0100 Luca Ceresoli <luca.ceresoli@bootlin.com> wrote: > Hello Saravana, Rob, Hervé, > > [+Miquèl, who contributed to the discussion with Hervé and me] > > On Wed, 6 Dec 2023 19:09:06 -0800 > Saravana Kannan <saravanak@google.com> wrote: > > > On Wed, Dec 6, 2023 at 9:15 AM Rob Herring <robh@kernel.org> wrote: > > > > > > On Thu, Nov 30, 2023 at 06:41:07PM +0100, Herve Codina wrote: > > > > Hi, > > > > > > +Saravana for comment > > > > I'll respond to this within a week -- very swamped at the moment. The > > main thing I want to make sure is that we don't cause an indirect > > deadlock with this wait(). I'll go back and look at why we added the > > work queue and then check for device/devlink locking issues. > > While working on a project unrelated to Hervé's work, I also ended up > in getting sporadic but frequent "ERROR: memory leak, expected refcount > 1 instead of..." messages, which persisted even after adding this patch > series on my tree. > > My use case is the insertion and removal of a simple overlay describing > a regulator-fixed and an I2C GPIO expander using it. The messages appear > regardless of whether the insertion and removal is done from kernel code > or via the configfs interface (out-of-tree patches from [0]). > > I reconstructed the sequence of operations, all of which stem from > of_overlay_remove(): > > int of_overlay_remove(int *ovcs_id) > { > ... > > device_link_wait_removal(); // proposed by this patch series > > mutex_lock(&of_mutex); > > ... > > ret = __of_changeset_revert_notify(&ovcs->cset); > // this ends up calling (excerpt from a long stack trace): > // -> of_i2c_notify > // -> device_remove > // -> devm_regulator_release > // -> device_link_remove > // -> devlink_dev_release, which queues work for > // device_link_release_fn, which in turn calls: > // -> device_put > // -> device_release > // -> {platform,regulator,...}_dev*_release > // -> of_node_put() [**] > > ... > > free_overlay_changeset(ovcs); > // calls: > // -> of_changeset_destroy > // -> __of_changeset_entry_destroy > // -> pr_err("ERROR: memory leak, expected refcount 1 instead of %d... > // The error appears or not, based on when the workqueue runs > > err_unlock: > mutex_unlock(&of_mutex); > > ... > } > > So this adds up to the question of whether devlink removal should actually > be run asynchronously or not. > > A simple short-term solution is to move the call to > device_link_wait_removal() later, just before free_overlay_changeset(): Indeed, during of_overlay_remove() notifications can be done and in Luca's use-case, they lead to some device removals and so devlink removals. That's why we move the synchronization calling device_link_wait_removal() after notifications and so just before free_overlay_changeset(). > > > diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c > index 1a8a6620748c..eccf08cf2160 100644 > --- a/drivers/of/overlay.c > +++ b/drivers/of/overlay.c > @@ -1375,12 +1375,6 @@ int of_overlay_remove(int *ovcs_id) > goto out; > } > > - /* > - * Wait for any ongoing device link removals before removing some of > - * nodes > - */ > - device_link_wait_removal(); > - > mutex_lock(&of_mutex); > > ovcs = idr_find(&ovcs_idr, *ovcs_id); > @@ -1427,6 +1421,14 @@ int of_overlay_remove(int *ovcs_id) > if (!ret) > ret = ret_tmp; > > + /* > + * Wait for any ongoing device link removals before removing some of > + * nodes > + */ > + mutex_unlock(&of_mutex); > + device_link_wait_removal(); > + mutex_lock(&of_mutex); > + > free_overlay_changeset(ovcs); > > err_unlock: > > > This obviously raises the question of whether unlocking and re-locking > the mutex is potentially dangerous. I have no answer to this right away, > but I tested this change with CONFIG_PROVE_LOCKING=y and no issue showed > up after several overlay load/unload sequences so I am not aware of any > actual issues with this change. > > [0] https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git/log/?h=topic/overlays > > Luca Thanks Luca for this complementary use-case related to this issue. Hervé
On Wed, Dec 6, 2023 at 7:09 PM Saravana Kannan <saravanak@google.com> wrote: > > On Wed, Dec 6, 2023 at 9:15 AM Rob Herring <robh@kernel.org> wrote: > > > > On Thu, Nov 30, 2023 at 06:41:07PM +0100, Herve Codina wrote: > > > Hi, > > > > +Saravana for comment > > I'll respond to this within a week -- very swamped at the moment. The > main thing I want to make sure is that we don't cause an indirect > deadlock with this wait(). I'll go back and look at why we added the > work queue and then check for device/devlink locking issues. > Sorry about the long delay, but I finally got back to this because Nuno nudged me to review a similar patch they sent. I'll leave some easy to address comments in the patches. -Saravana > -Saravana > > > > > Looks okay to me though. > > > > > > > > In the following sequence: > > > of_platform_depopulate(); /* Remove devices from a DT overlay node */ > > > of_overlay_remove(); /* Remove the DT overlay node itself */ > > > > > > Some warnings are raised by __of_changeset_entry_destroy() which was > > > called from of_overlay_remove(): > > > ERROR: memory leak, expected refcount 1 instead of 2 ... > > > > > > The issue is that, during the device devlink removals triggered from the > > > of_platform_depopulate(), jobs are put in a workqueue. > > > These jobs drop the reference to the devices. When a device is no more > > > referenced (refcount == 0), it is released and the reference to its > > > of_node is dropped by a call to of_node_put(). > > > These operations are fully correct except that, because of the > > > workqueue, they are done asynchronously with respect to function calls. > > > > > > In the sequence provided, the jobs are run too late, after the call to > > > __of_changeset_entry_destroy() and so a missing of_node_put() call is > > > detected by __of_changeset_entry_destroy(). > > > > > > This series fixes this issue introducing device_link_wait_removal() in > > > order to wait for the end of jobs execution (patch 1) and using this > > > function to synchronize the overlay removal with the end of jobs > > > execution (patch 2). > > > > > > Best regards, > > > Hervé > > > > > > Herve Codina (2): > > > driver core: Introduce device_link_wait_removal() > > > of: overlay: Synchronize of_overlay_remove() with the devlink removals > > > > > > drivers/base/core.c | 26 +++++++++++++++++++++++--- > > > drivers/of/overlay.c | 6 ++++++ > > > include/linux/device.h | 1 + > > > 3 files changed, 30 insertions(+), 3 deletions(-) > > > > > > -- > > > 2.42.0 > > >