From patchwork Fri Jun 25 01:39:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 12343467 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C99AFC49EA7 for ; Fri, 25 Jun 2021 01:39:48 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 8143E613C0 for ; Fri, 25 Jun 2021 01:39:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8143E613C0 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=linux-foundation.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 8FA6F6B0036; Thu, 24 Jun 2021 21:39:47 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 882CE6B0070; Thu, 24 Jun 2021 21:39:47 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6FC4B6B0071; Thu, 24 Jun 2021 21:39:47 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0207.hostedemail.com [216.40.44.207]) by kanga.kvack.org (Postfix) with ESMTP id 3D8A16B0036 for ; Thu, 24 Jun 2021 21:39:47 -0400 (EDT) Received: from smtpin37.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id 69C988128200 for ; Fri, 25 Jun 2021 01:39:47 +0000 (UTC) X-FDA: 78290539614.37.4CAB60F Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by imf16.hostedemail.com (Postfix) with ESMTP id 18B3480192EE for ; Fri, 25 Jun 2021 01:39:46 +0000 (UTC) Received: by mail.kernel.org (Postfix) with ESMTPSA id E69B6610A7; Fri, 25 Jun 2021 01:39:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1624585186; bh=8aA8l0gUvl7gKVc+xnD7wWRrAJB4Gfj9ScpG9tt1Ikk=; h=Date:From:To:Subject:In-Reply-To:From; b=et+frLiJ9+f0WRKF0I6mkc5u6tojPbOzXj6Z7Oy1u3NfZSfGIKTczShOr66XwLUEi XU29UABB99WEWSX7WPhsxnYUic45VjvQAhZGTSDCyEp7cfXbAB/hj+86S4sYnRzo5l SU4MnduFiEmQe73GC+//UQvuOP6jYL1PpDSIml3E= Date: Thu, 24 Jun 2021 18:39:45 -0700 From: Andrew Morton To: akpm@linux-foundation.org, jenhaochen@google.com, linux-mm@kvack.org, liumartin@google.com, minchan@google.com, mm-commits@vger.kernel.org, nathan@kernel.org, ndesaulniers@google.com, oleg@redhat.com, pmladek@suse.com, stable@vger.kernel.org, tj@kernel.org, torvalds@linux-foundation.org Subject: [patch 15/24] kthread_worker: split code for canceling the delayed work timer Message-ID: <20210625013945.Wgs7ttT2t%akpm@linux-foundation.org> In-Reply-To: <20210624183838.ac3161ca4a43989665ac8b2f@linux-foundation.org> User-Agent: s-nail v14.8.16 X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 18B3480192EE X-Stat-Signature: yug89fw83j7nycrqungsum13dpfna96b Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=linux-foundation.org header.s=korg header.b=et+frLiJ; dmarc=none; spf=pass (imf16.hostedemail.com: domain of akpm@linux-foundation.org designates 198.145.29.99 as permitted sender) smtp.mailfrom=akpm@linux-foundation.org X-HE-Tag: 1624585186-194303 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Petr Mladek Subject: kthread_worker: split code for canceling the delayed work timer Patch series "kthread_worker: Fix race between kthread_mod_delayed_work() and kthread_cancel_delayed_work_sync()". This patchset fixes the race between kthread_mod_delayed_work() and kthread_cancel_delayed_work_sync() including proper return value handling. This patch (of 2): Simple code refactoring as a preparation step for fixing a race between kthread_mod_delayed_work() and kthread_cancel_delayed_work_sync(). It does not modify the existing behavior. Link: https://lkml.kernel.org/r/20210610133051.15337-2-pmladek@suse.com Signed-off-by: Petr Mladek Cc: Cc: Martin Liu Cc: Minchan Kim Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Oleg Nesterov Cc: Tejun Heo Cc: Signed-off-by: Andrew Morton --- kernel/kthread.c | 46 ++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) --- a/kernel/kthread.c~kthread_worker-split-code-for-canceling-the-delayed-work-timer +++ a/kernel/kthread.c @@ -1093,6 +1093,33 @@ void kthread_flush_work(struct kthread_w EXPORT_SYMBOL_GPL(kthread_flush_work); /* + * Make sure that the timer is neither set nor running and could + * not manipulate the work list_head any longer. + * + * The function is called under worker->lock. The lock is temporary + * released but the timer can't be set again in the meantime. + */ +static void kthread_cancel_delayed_work_timer(struct kthread_work *work, + unsigned long *flags) +{ + struct kthread_delayed_work *dwork = + container_of(work, struct kthread_delayed_work, work); + struct kthread_worker *worker = work->worker; + + /* + * del_timer_sync() must be called to make sure that the timer + * callback is not running. The lock must be temporary released + * to avoid a deadlock with the callback. In the meantime, + * any queuing is blocked by setting the canceling counter. + */ + work->canceling++; + raw_spin_unlock_irqrestore(&worker->lock, *flags); + del_timer_sync(&dwork->timer); + raw_spin_lock_irqsave(&worker->lock, *flags); + work->canceling--; +} + +/* * This function removes the work from the worker queue. Also it makes sure * that it won't get queued later via the delayed work's timer. * @@ -1106,23 +1133,8 @@ static bool __kthread_cancel_work(struct unsigned long *flags) { /* Try to cancel the timer if exists. */ - if (is_dwork) { - struct kthread_delayed_work *dwork = - container_of(work, struct kthread_delayed_work, work); - struct kthread_worker *worker = work->worker; - - /* - * del_timer_sync() must be called to make sure that the timer - * callback is not running. The lock must be temporary released - * to avoid a deadlock with the callback. In the meantime, - * any queuing is blocked by setting the canceling counter. - */ - work->canceling++; - raw_spin_unlock_irqrestore(&worker->lock, *flags); - del_timer_sync(&dwork->timer); - raw_spin_lock_irqsave(&worker->lock, *flags); - work->canceling--; - } + if (is_dwork) + kthread_cancel_delayed_work_timer(work, flags); /* * Try to remove the work from a worker list. It might either