From patchwork Tue Feb 6 12:09:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 197399 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp1498729dyb; Tue, 6 Feb 2024 04:22:24 -0800 (PST) X-Google-Smtp-Source: AGHT+IE7KEkincoOnezzgXpxyZqt/M0/buI7fdG4eF2RMZ6QeeiRr0lEzwS7kYidFWNEFto0sN/m X-Received: by 2002:a17:906:2408:b0:a38:3eb1:40a1 with SMTP id z8-20020a170906240800b00a383eb140a1mr717167eja.26.1707222143920; Tue, 06 Feb 2024 04:22:23 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707222143; cv=pass; d=google.com; s=arc-20160816; b=NnArCYeu8PYxDqXshsG/dok9MmXTXwwR/mHE+N62WttNJ9WtrXVX1fJTse4xYEXbG/ l28dRIBh+fTgd/0JYmD33QN65GKNOXDnQJBiVaqqNmFvuvnHPPyTtdZU0bI4vt4RBXqh ehG8Lsz91eZFKNLvjFSJoGLwOb8AzZS5Id1NyFa1DQuNlHcupObFrHY3/4RXDqxYJdfR EX3roIrtT/NVsQgFuxItKs0kErv72MB3mFIuSN7+mtD2tSvXvjp30z5TwhxP4y8dgLu8 Bi0G6X+x2h3OWm4kWaPEc8vLB+cnpWxvtnhM4EncC8e1lH7aH49NvlUMoZr3r6Ss6hWU auBg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:list-unsubscribe:list-subscribe:list-id:precedence :references:subject:cc:to:from:date:user-agent:message-id; bh=SQywd03Pi2cOJEzNpCdc+jpMmfh3LsORrC2f0wzMBtk=; fh=P0hReqcfz3LlpsvRMhHWKk5bcGmM1gaD3f10tvb/Jmg=; b=EOwNPn36Bslb4joWj6A+F8sdn1jY+4BZ0pesnGfGuclsSUMzDStD5vLSc41Nx6dJbj jUcddZC2EAGPgTN/eWf3nOaw5vn8mfuyFVNeFofRfz/A0iBrDcRAg9fWnsVhshMZWakC f4Kf+MzGdOEejScQ7W297XwlcQU3lujFRGJ7UkiuNQiFQh7dbq+ri154Sp9GelyC3LIy DEnOv6Zvkv09DBKc1h99t/oYBozJJmlvWRs/soTbxQ3HfF0X2qd5w2ztueDMWMwAxHga 6oAjeEUHBNzyWujA7szvx004S8RNEYAvEdBRowuPhjrKFxvN4gd7g4pcQp5/dycCP1Jy WNPg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of linux-kernel+bounces-54898-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-54898-ouuuleilei=gmail.com@vger.kernel.org" X-Forwarded-Encrypted: i=1; AJvYcCXNsGEYjGbvZhBITOokHoXnSvOGbR3/6ZfjxRtvgQi6+AT5hM9Jgt7aChnnwPnCGfh3zhz7jnRLn7Pg16BziGvha64rdg== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id kk7-20020a170907766700b00a382baad7b5si571176ejc.919.2024.02.06.04.22.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Feb 2024 04:22:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-54898-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of linux-kernel+bounces-54898-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-54898-ouuuleilei=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 1BAF21F25828 for ; Tue, 6 Feb 2024 12:21:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B75841419A2; Tue, 6 Feb 2024 12:09:30 +0000 (UTC) Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3615D137C31; Tue, 6 Feb 2024 12:09:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707221362; cv=none; b=JEq+9yV8CKf9q9sWgBRH6upoWmJWTMJGU6Ny3rvQLxlpdOhEnxndUMGANvrClDWtxiMQFFI2j9AsFP3eENneS+Lk9utRywlo4FzU4dz0wz6jiPR9DD0j+2aPZGTT4sCrqgFIvp9nvOFmCk9oICzExIJRrk/+7vGXv57kruS/wL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707221362; c=relaxed/simple; bh=Eo3GAzrlb3xQR8bxqyZh35WxLBG0y/2yNLrd3Y39mjg=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=JXPP19sXIbQKo/GHsuH4S035MxQk5MDS1ZFAsc3Nhk43mS9eA9FreQdxeQVB7y1WTeQrjXStLkCoVfjCQSHvOXkiaFOrWryCXFd4pvMNxlpU/tvz/EWzYHkNtOKAMMTeozbmiVEFdSPYx5zxtg5CyrMNQod5hyQ+NG4Qc+SDFCg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C375DC433C7; Tue, 6 Feb 2024 12:09:21 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rXKGs-00000006bCq-16q1; Tue, 06 Feb 2024 07:09:50 -0500 Message-ID: <20240206120950.121281039@rostedt.homelinux.com> User-Agent: quilt/0.67 Date: Tue, 06 Feb 2024 07:09:28 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Linus Torvalds , Greg Kroah-Hartman , Sasha Levin , Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Al Viro Subject: [v6.6][PATCH 23/57] eventfs: Use simple_recursive_removal() to clean up dentries References: <20240206120905.570408983@rostedt.homelinux.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790152166825236190 X-GMAIL-MSGID: 1790152166825236190 From: "Steven Rostedt (Google)" Looking at how dentry is removed via the tracefs system, I found that eventfs does not do everything that it did under tracefs. The tracefs removal of a dentry calls simple_recursive_removal() that does a lot more than a simple d_invalidate(). As it should be a requirement that any eventfs_inode that has a dentry, so does its parent. When removing a eventfs_inode, if it has a dentry, a call to simple_recursive_removal() on that dentry should clean up all the dentries underneath it. Add WARN_ON_ONCE() to check for the parent having a dentry if any children do. Link: https://lore.kernel.org/all/20231101022553.GE1957730@ZenIV/ Link: https://lkml.kernel.org/r/20231101172650.552471568@goodmis.org Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Mark Rutland Cc: Andrew Morton Cc: Al Viro Fixes: 5bdcd5f5331a2 ("eventfs: Implement removal of meta data from eventfs") Signed-off-by: Steven Rostedt (Google) (cherry picked from commit 407c6726ca71b33330d2d6345d9ea7ebc02575e9) --- fs/tracefs/event_inode.c | 77 +++++++++++++++++++++++----------------- fs/tracefs/internal.h | 2 -- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index 0087a3f455f1..f8a594a50ae6 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -967,30 +967,29 @@ static void unhook_dentry(struct dentry *dentry) { if (!dentry) return; - - /* Keep the dentry from being freed yet (see eventfs_workfn()) */ + /* + * Need to add a reference to the dentry that is expected by + * simple_recursive_removal(), which will include a dput(). + */ dget(dentry); - dentry->d_fsdata = NULL; - d_invalidate(dentry); - mutex_lock(&eventfs_mutex); - /* dentry should now have at least a single reference */ - WARN_ONCE((int)d_count(dentry) < 1, - "dentry %px (%s) less than one reference (%d) after invalidate\n", - dentry, dentry->d_name.name, d_count(dentry)); - mutex_unlock(&eventfs_mutex); + /* + * Also add a reference for the dput() in eventfs_workfn(). + * That is required as that dput() will free the ei after + * the SRCU grace period is over. + */ + dget(dentry); } /** * eventfs_remove_rec - remove eventfs dir or file from list * @ei: eventfs_inode to be removed. - * @head: the list head to place the deleted @ei and children * @level: prevent recursion from going more than 3 levels deep. * * This function recursively removes eventfs_inodes which * contains info of files and/or directories. */ -static void eventfs_remove_rec(struct eventfs_inode *ei, struct list_head *head, int level) +static void eventfs_remove_rec(struct eventfs_inode *ei, int level) { struct eventfs_inode *ei_child; @@ -1009,13 +1008,26 @@ static void eventfs_remove_rec(struct eventfs_inode *ei, struct list_head *head, /* search for nested folders or files */ list_for_each_entry_srcu(ei_child, &ei->children, list, lockdep_is_held(&eventfs_mutex)) { - eventfs_remove_rec(ei_child, head, level + 1); + /* Children only have dentry if parent does */ + WARN_ON_ONCE(ei_child->dentry && !ei->dentry); + eventfs_remove_rec(ei_child, level + 1); } + ei->is_freed = 1; + for (int i = 0; i < ei->nr_entries; i++) { + if (ei->d_children[i]) { + /* Children only have dentry if parent does */ + WARN_ON_ONCE(!ei->dentry); + unhook_dentry(ei->d_children[i]); + } + } + + unhook_dentry(ei->dentry); + list_del_rcu(&ei->list); - list_add_tail(&ei->del_list, head); + call_srcu(&eventfs_srcu, &ei->rcu, free_rcu_ei); } /** @@ -1026,30 +1038,22 @@ static void eventfs_remove_rec(struct eventfs_inode *ei, struct list_head *head, */ void eventfs_remove_dir(struct eventfs_inode *ei) { - struct eventfs_inode *tmp; - LIST_HEAD(ei_del_list); + struct dentry *dentry; if (!ei) return; - /* - * Move the deleted eventfs_inodes onto the ei_del_list - * which will also set the is_freed value. Note, this has to be - * done under the eventfs_mutex, but the deletions of - * the dentries must be done outside the eventfs_mutex. - * Hence moving them to this temporary list. - */ mutex_lock(&eventfs_mutex); - eventfs_remove_rec(ei, &ei_del_list, 0); + dentry = ei->dentry; + eventfs_remove_rec(ei, 0); mutex_unlock(&eventfs_mutex); - list_for_each_entry_safe(ei, tmp, &ei_del_list, del_list) { - for (int i = 0; i < ei->nr_entries; i++) - unhook_dentry(ei->d_children[i]); - unhook_dentry(ei->dentry); - list_del(&ei->del_list); - call_srcu(&eventfs_srcu, &ei->rcu, free_rcu_ei); - } + /* + * If any of the ei children has a dentry, then the ei itself + * must have a dentry. + */ + if (dentry) + simple_recursive_removal(dentry, NULL); } /** @@ -1060,10 +1064,17 @@ void eventfs_remove_dir(struct eventfs_inode *ei) */ void eventfs_remove_events_dir(struct eventfs_inode *ei) { - struct dentry *dentry = ei->dentry; + struct dentry *dentry; + dentry = ei->dentry; eventfs_remove_dir(ei); - /* Matches the dget() from eventfs_create_events_dir() */ + /* + * Matches the dget() done by tracefs_start_creating() + * in eventfs_create_events_dir() when it the dentry was + * created. In other words, it's a normal dentry that + * sticks around while the other ei->dentry are created + * and destroyed dynamically. + */ dput(dentry); } diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h index 06a1f220b901..ccee18ca66c7 100644 --- a/fs/tracefs/internal.h +++ b/fs/tracefs/internal.h @@ -55,12 +55,10 @@ struct eventfs_inode { /* * Union - used for deletion * @llist: for calling dput() if needed after RCU - * @del_list: list of eventfs_inode to delete * @rcu: eventfs_inode to delete in RCU */ union { struct llist_node llist; - struct list_head del_list; struct rcu_head rcu; }; unsigned int is_freed:1;