Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp609942pxb; Mon, 16 Aug 2021 12:59:02 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwYZkssE6OY9Jrnf6m7LrhagZojmYH2du1aE2cCfGPW+XLX/ibQCwOperufqqcRkxrS2NnN X-Received: by 2002:a17:907:9604:: with SMTP id gb4mr190882ejc.142.1629143942549; Mon, 16 Aug 2021 12:59:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629143942; cv=none; d=google.com; s=arc-20160816; b=M6PIyKH5TUHpWntiaUM+qaZN5F+SkeakOY38MSLvNubQvYTLSZce85DtpTB2vDJn3a CyQRtRIeN5p5MoeDvctI3BY2BFwhuC2V1DF/5EXwIL8/AOaMbTvJ6/Bc0qCrTi8AcwYM WfU+8bAZjVT1LeE/tTnnEDzl/NXAPus3cnogEcmhnFNi7rM69UZEepUOqoYiXjuufWgL 9mRh2VqIkeryqzXFZ4BCbQmXoI7wwPFzvR6E45ByBQHafJie/QNIPsxRSnnO60BpyPMr 1dw9uS9RnbmT840s3I/QQZaB1wWjjxa5R3/PKUowk4VTvCAmtvbrpQZ1/d1X+jvuzEJ3 HJDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:content-language :in-reply-to:mime-version:user-agent:date:message-id:from:references :cc:to:subject:dkim-signature; bh=+saKVJjJalaJDnX4+jNqeDzwSfBJAZWy7Qzg/fGGg+o=; b=DOt1tjKvXd4o7cV4SFk02hnNhsPaKVBSqvq8Ein3tqQyu5tJI5+pEvBB4TH5LJAp3M HDUP+uINDeMJ7xfO0HKlsT4qvmO8H6CwmlRDV+oEffTT+7WTTmp5pyLQvP8qt+zAoahN ByZH3Nl/U8SW91bhoxCA9ftlK+Z7tJA9XO33QfNBd2jNVMH1SgOD18dDvECZ3T+N9Xq1 ZqrPLm+w8syhinSh1ni9ZYs6Msvel83m71JLejGLEr4EMgSVitWJbHzEHLURLlqJqdR8 tnhM0MQR6WEmmGCkQpQrxL7rX6moKIuZx+L7MlfrKbhd/oeJnWTvnrs01OQdEyjaucG+ Tf8g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=k39jaarY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j3si40962edp.549.2021.08.16.12.58.39; Mon, 16 Aug 2021 12:59:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=k39jaarY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231143AbhHPT5e (ORCPT + 99 others); Mon, 16 Aug 2021 15:57:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229802AbhHPT5d (ORCPT ); Mon, 16 Aug 2021 15:57:33 -0400 Received: from mail-qk1-x730.google.com (mail-qk1-x730.google.com [IPv6:2607:f8b0:4864:20::730]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD6D2C061764; Mon, 16 Aug 2021 12:57:01 -0700 (PDT) Received: by mail-qk1-x730.google.com with SMTP id p22so19224842qki.10; Mon, 16 Aug 2021 12:57:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=+saKVJjJalaJDnX4+jNqeDzwSfBJAZWy7Qzg/fGGg+o=; b=k39jaarYdVvbWUg7u8G81x/luF+uLju4OCIi51zoba19TopgGEBfLn6oJgrLWPbOc7 irNIPNGJm+shRREK2nr48tqqxvjlm4Cyd+Z7GyZg8vbb6BzQpxia0VvcKw4Ko3XAk2O7 r27wPqL2ZFHiIVfIqh3kH1ffLtysGEgHUzM30nGrYumToBfzZ06OOxxGIrWxJYLBJK49 sjnPp9ywWqr/wGBVlSCGEnTubninTgDDUHtUKGRN52eKySy5ex85mao+K/HhlewuIQ0n h2vbLYSyDyIbqSf4g0oDuYGAChThRtZwD5LC2dO3A6ro5DeY8mirm7C29ANc6gwql2lp bXYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=+saKVJjJalaJDnX4+jNqeDzwSfBJAZWy7Qzg/fGGg+o=; b=c2tily5Lc062XOgJ7ZY46cws5M4mYLGisRPcAhFQo63eUvgWJo9VuvTp+iBdZr3x+f PoV7Dl13cxNDCYNHGUexcQ3apdWu/dPiFqMb7kTs1uGusv9D9WXnZ92y5Rb+i2wmCHWh jlmEMH3uQEz+7Us4tWIeTMnB10vGBFCz9DqnIRx/VW96gK2f3NWDsPOgySG1I9GJozsb F5uBuxwxFXC4/4/fxb1X+M+F61ePnQoq1+6dFZY8xFydknkWEB9oyCgGiSL67Bqsi3gz 6LKvvaemrTKFuvVUOdaoE0h30qyzuVbTTUGzCru+hpvjYDGaXuKLUOWrqW+WRcl9IyOX 3B8w== X-Gm-Message-State: AOAM530zpEkZ+tf1GY4lDPPNUN02k0V1vFtMOklYT7bad21EavpjpVQe T7UYgk/rBgFkj9RbB0+dq80= X-Received: by 2002:a37:2ec1:: with SMTP id u184mr11129qkh.500.1629143820874; Mon, 16 Aug 2021 12:57:00 -0700 (PDT) Received: from [192.168.1.49] (c-67-187-90-124.hsd1.tn.comcast.net. [67.187.90.124]) by smtp.gmail.com with ESMTPSA id h17sm112739qkl.46.2021.08.16.12.57.00 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 16 Aug 2021 12:57:00 -0700 (PDT) Subject: Re: of_node_put() usage is buggy all over drivers/of/base.c?! To: Rob Herring , Vladimir Oltean Cc: Sascha Hauer , devicetree@vger.kernel.org, "linux-kernel@vger.kernel.org" , netdev References: <20210814010139.kzryimmp4rizlznt@skbuf> <9accd63a-961c-4dab-e167-9e2654917a94@gmail.com> <20210816144622.tgslast6sbblclda@skbuf> <4cad28e0-d6b4-800d-787b-936ffaca7be3@gmail.com> From: Frank Rowand Message-ID: <2e98373f-c37c-0d26-5c9a-1f15ade243c1@gmail.com> Date: Mon, 16 Aug 2021 14:56:59 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.11.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 8/16/21 2:20 PM, Rob Herring wrote: > On Mon, Aug 16, 2021 at 10:14 AM Frank Rowand wrote: >> >> On 8/16/21 9:46 AM, Vladimir Oltean wrote: >>> Hi Frank, >>> >>> On Mon, Aug 16, 2021 at 09:33:03AM -0500, Frank Rowand wrote: >>>> Hi Vladimir, >>>> >>>> On 8/13/21 8:01 PM, Vladimir Oltean wrote: >>>>> Hi, >>>>> >>>>> I was debugging an RCU stall which happened during the probing of a >>>>> driver. Activating lock debugging, I see: >>>> >>>> I took a quick look at sja1105_mdiobus_register() in v5.14-rc1 and v5.14-rc6. >>>> >>>> Looking at the following stack trace, I did not see any calls to >>>> of_find_compatible_node() in sja1105_mdiobus_register(). I am >>>> guessing that maybe there is an inlined function that calls >>>> of_find_compatible_node(). This would likely be either >>>> sja1105_mdiobus_base_tx_register() or sja1105_mdioux_base_t1_register(). >>> >>> Yes, it is sja1105_mdiobus_base_t1_register which is inlined. >>> >>>>> >>>>> [ 101.710694] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:938 >>>>> [ 101.719119] in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 1534, name: sh >>>>> [ 101.726763] INFO: lockdep is turned off. >>>>> [ 101.730674] irq event stamp: 0 >>>>> [ 101.733716] hardirqs last enabled at (0): [<0000000000000000>] 0x0 >>>>> [ 101.739973] hardirqs last disabled at (0): [] copy_process+0xa78/0x1a98 >>>>> [ 101.748146] softirqs last enabled at (0): [] copy_process+0xa78/0x1a98 >>>>> [ 101.756313] softirqs last disabled at (0): [<0000000000000000>] 0x0 >>>>> [ 101.762569] CPU: 4 PID: 1534 Comm: sh Not tainted 5.14.0-rc5+ #272 >>>>> [ 101.774558] Call trace: >>>>> [ 101.794734] __might_sleep+0x50/0x88 >>>>> [ 101.798297] __mutex_lock+0x60/0x938 >>>>> [ 101.801863] mutex_lock_nested+0x38/0x50 >>>>> [ 101.805775] kernfs_remove+0x2c/0x50 <---- this takes mutex_lock(&kernfs_mutex); >>>>> [ 101.809341] sysfs_remove_dir+0x54/0x70 >>>> >>>> The __kobject_del() occurs only if the refcount on the node >>>> becomes zero. This should never be true when of_find_compatible_node() >>>> calls of_node_put() unless a "from" node is passed to of_find_compatible_node(). >>> >>> I figured that was the assumption, that the of_node_put would never >>> trigger a sysfs file / kobject deletion from there. >>> >>>> In both sja1105_mdiobus_base_tx_register() and sja1105_mdioux_base_t1_register() >>>> a from node ("mdio") is passed to of_find_compatible_node() without first doing an >>>> of_node_get(mdio). If you add the of_node_get() calls the problem should be fixed. >>> >>> The answer seems simple enough, but stupid question, but why does >>> of_find_compatible_node call of_node_put on "from" in the first place? >> >> Actually a good question. >> >> I do not know why of_find_compatible_node() calls of_node_put() instead of making >> the caller of of_find_compatible_node() responsible. That pattern was created >> long before I was involved in devicetree and I have not gone back to read the >> review comments of when that code was created. > > Because it is an iterator function and they all drop the ref from the > prior iteration. That is what I was expecting before reading through the code. But instead I found of_find_compatible_node(): raw_spin_lock_irqsave(&devtree_lock, flags); for_each_of_allnodes_from(from, np) if (__of_device_is_compatible(np, compatible, type, NULL) && of_node_get(np)) break; of_node_put(from); raw_spin_unlock_irqrestore(&devtree_lock, flags); for_each_of_allnodes_fromir: #define for_each_of_allnodes_from(from, dn) \ for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn)) and __of_find_all_nodes() is: struct device_node *__of_find_all_nodes(struct device_node *prev) { struct device_node *np; if (!prev) { np = of_root; } else if (prev->child) { np = prev->child; } else { /* Walk back up looking for a sibling, or the end of the structure */ np = prev; while (np->parent && !np->sibling) np = np->parent; np = np->sibling; /* Might be null at the end of the tree */ } return np; } So the iterator is not using of_node_get() and of_node_put() for each node that is traversed. The protection against a node disappearing during the iteration is provided by holding devtree_lock. > > I would say any open coded call where from is not NULL is an error. I assume you mean any open coded call of of_find_compatible_node(). There are at least a couple of instances of that. I did only a partial grep while looking at Vladimir's issue. Doing the full grep now, I see 13 instances of architecture and driver code calling of_find_compatible_node(). > It's not reliable because the DT search order is not defined and could > change. Someone want to write a coccinelle script to check that? > > The above code should be using of_get_compatible_child() instead. Yes, of_get_compatible_child() should be used here. Thanks for pointing that out. There are 13 instances of architecture and driver code calling of_find_compatible_node(). If possible, it would be good to change all of them to of_get_compatible_child(). If we could replace all driver usage of of_find_compatible_node() with a from parameter of NULL to a new wrapper without a from parameter, where the wrapper calls of_find_compatible_node() with the from parameter set to NULL, then we could prevent this problem from recurring. (I did not look at all 13 instances yet, to see if this can be done.) > > Rob >