From patchwork Thu Nov 10 06:41:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 17981 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp764964wru; Wed, 9 Nov 2022 22:56:13 -0800 (PST) X-Google-Smtp-Source: AMsMyM5sfQKPQt54qy7q00xG1l6gXhzThKwdpFWXNyZpUihZtNoOS9IEUeECyKOi64J/3o94mzTZ X-Received: by 2002:a05:6402:5211:b0:462:3a0e:cd0d with SMTP id s17-20020a056402521100b004623a0ecd0dmr62298225edd.130.1668063373377; Wed, 09 Nov 2022 22:56:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668063373; cv=none; d=google.com; s=arc-20160816; b=giSfZkYKCfAEEgUt4gsnc97bL3qmt4y9P7gEetpvckcisQCEi9zG8J+lo92EmrRp6z 1SgXpG1jmv222Sh/MGjx+DrtWpEIUQqFw59PcczQ7s0F7Q/oH5JcTUbMufklr1Y5FPBy 0AlNnavqob3U1jkV7VhBJZ5wdqkfqListMuPBkmrv1IEDkDeDpeHuZBlT/bPhbG2vLeA rAwKz46K+zWhxfnbsG3wJQKjOyAXJUw+ULrh10LHw3Tbi/xkVAqfSn40mCGBIxlhqyS2 OqD4RKLgcw8gWgZm1e/eO8Ywm4VbZiZZczUzYXBDVSaDDV/pFAT2LSg8nispzq5VKhiR P9zg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:subject:cc:to:from:date :user-agent:message-id; bh=zh82lRJhLdejkzcl1qSBp/gh+9EUWOIcf8Tr6Tqg+g4=; b=X6qNdlct6mOss8T8YpGA0uk4i79Xdq1gx6Wuz308XjxJydkzlso1fHifiPZ44BQiWJ wFMdLyT7emD5Gf36WkMtRrPhHW03ycHs2uTINbFOC1NQ/WOdJBdtF8VC2h/BemNDxFkG 2bkUzIXGMf7BBoHc8qK8SsqDAmSiZDccHJCMqvzTgvnSlIZO9lSToJ/PQLJA+7A+P1og IVV2bNhAOTxL8UhhRhjXXU96ufXtj0nPqpcM2Kp7sNf9J2irZBZuYn1vAUOzjow0dwY3 8KNqEXRI/wUHQN8PX4+njaCuaZl3SZ0YKAhHtaR5UqPqNy++ZY3455Qj706/Ab6tOgRf vihw== ARC-Authentication-Results: i=1; mx.google.com; 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 Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gb41-20020a170907962900b0077fd6028710si20577728ejc.670.2022.11.09.22.55.40; Wed, 09 Nov 2022 22:56:13 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232638AbiKJGmA (ORCPT + 99 others); Thu, 10 Nov 2022 01:42:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232572AbiKJGl2 (ORCPT ); Thu, 10 Nov 2022 01:41:28 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 40FD62180B for ; Wed, 9 Nov 2022 22:41:16 -0800 (PST) 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 ams.source.kernel.org (Postfix) with ESMTPS id 653B2B820DE for ; Thu, 10 Nov 2022 06:41:14 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16A11C4314A; Thu, 10 Nov 2022 06:41:12 +0000 (UTC) Received: from rostedt by gandalf.local.home with local (Exim 4.96) (envelope-from ) id 1ot1Fz-009Eg1-2F; Thu, 10 Nov 2022 01:41:47 -0500 Message-ID: <20221110064147.529154710@goodmis.org> User-Agent: quilt/0.66 Date: Thu, 10 Nov 2022 01:41:06 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Linus Torvalds , Thomas Gleixner , Stephen Boyd , Guenter Roeck , Anna-Maria Gleixner , Andrew Morton , Julia Lawall Subject: [PATCH v6 5/6] timers: Add timer_shutdown() to be called before freeing timers References: <20221110064101.429013735@goodmis.org> MIME-Version: 1.0 X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS 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 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749091219991508808?= X-GMAIL-MSGID: =?utf-8?q?1749091219991508808?= From: "Steven Rostedt (Google)" Before a timer is to be freed, it must be shutdown. But there are some locations were timer_shutdown_sync() can not be called due to the context the object that holds the timer is in when it is freed. For cases where the logic should keep the timer from being re-armed but still needs to be shutdown with a sync, a new API of timer_shutdown() is available. This is the same as del_timer() except that after it is called, the timer can not be re-armed. If it is, a WARN_ON_ONCE() will be triggered. The implementation of timer_shutdown() follows the timer_shutdown_sync() method of using the same code as del_timer() but will pass in a boolean that the timer is about to be freed, in which case the timer->function is set to NULL, just like timer_shutdown_sync(). Cc: Linus Torvalds Cc: Thomas Gleixner Cc: Stephen Boyd Cc: Anna-Maria Gleixner Cc: Andrew Morton Cc: Julia Lawall Tested-by: Guenter Roeck Signed-off-by: Steven Rostedt (Google) --- include/linux/timer.h | 35 ++++++++++++++++++++++++++++++++++- kernel/time/timer.c | 21 ++++++++------------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/include/linux/timer.h b/include/linux/timer.h index 4d56e20613eb..0b959b52d0db 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -168,12 +168,45 @@ static inline int timer_pending(const struct timer_list * timer) return !hlist_unhashed_lockless(&timer->entry); } +extern int __del_timer(struct timer_list * timer, bool free); + extern void add_timer_on(struct timer_list *timer, int cpu); -extern int del_timer(struct timer_list * timer); extern int mod_timer(struct timer_list *timer, unsigned long expires); extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); extern int timer_reduce(struct timer_list *timer, unsigned long expires); +/** + * del_timer - deactivate a timer. + * @timer: the timer to be deactivated + * + * del_timer() deactivates a timer - this works on both active and inactive + * timers. + * + * The function returns whether it has deactivated a pending timer or not. + * (ie. del_timer() of an inactive timer returns 0, del_timer() of an + * active timer returns 1.) + */ +static inline int del_timer(struct timer_list *timer) +{ + return __del_timer(timer, false); +} + +/** + * timer_shutdown - deactivate a timer and shut it down + * @timer: the timer to be deactivated + * + * timer_shutdown() deactivates a timer - this works on both active + * and inactive timers, and will prevent it from being rearmed. + * + * The function returns whether it has deactivated a pending timer or not. + * (ie. timer_shutdown() of an inactive timer returns 0, + * timer_shutdown() of an active timer returns 1.) + */ +static inline int timer_shutdown(struct timer_list *timer) +{ + return __del_timer(timer, true); +} + /* * The jiffies value which is added to now, when there is no timer * in the timer wheel: diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 111a3550b3f2..7c224766065e 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1240,18 +1240,7 @@ void add_timer_on(struct timer_list *timer, int cpu) } EXPORT_SYMBOL_GPL(add_timer_on); -/** - * del_timer - deactivate a timer. - * @timer: the timer to be deactivated - * - * del_timer() deactivates a timer - this works on both active and inactive - * timers. - * - * The function returns whether it has deactivated a pending timer or not. - * (ie. del_timer() of an inactive timer returns 0, del_timer() of an - * active timer returns 1.) - */ -int del_timer(struct timer_list *timer) +int __del_timer(struct timer_list *timer, bool free) { struct timer_base *base; unsigned long flags; @@ -1262,12 +1251,18 @@ int del_timer(struct timer_list *timer) if (timer_pending(timer)) { base = lock_timer_base(timer, &flags); ret = detach_if_pending(timer, base, true); + if (free) + timer->function = NULL; + raw_spin_unlock_irqrestore(&base->lock, flags); + } else if (free) { + base = lock_timer_base(timer, &flags); + timer->function = NULL; raw_spin_unlock_irqrestore(&base->lock, flags); } return ret; } -EXPORT_SYMBOL(del_timer); +EXPORT_SYMBOL(__del_timer); static int __try_to_del_timer_sync(struct timer_list *timer, bool free) {