Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp3970430pxb; Sat, 13 Feb 2021 16:27:16 -0800 (PST) X-Google-Smtp-Source: ABdhPJwILPrKosLxWVjM4KaLHX9JWHEYBcj5n0a3RnaBMD9sutoDBFYr5BDSPgEYLYkfqVBrhzVr X-Received: by 2002:a17:906:ada:: with SMTP id z26mr9227300ejf.218.1613262435826; Sat, 13 Feb 2021 16:27:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613262435; cv=none; d=google.com; s=arc-20160816; b=bQSEDkOpTjgD69ZdOV+y1GtuUPkfYr/6PMCtEM+hC24K3fp18YnbvA+KfcePm1RDjJ QZq3ti3kUjtZRzmtqxPF4Mo1J5ItKAShGbOk/xFaoro2xilwmSkXOSYNLkRd4l7ZW5X+ 6LpijOePpZF8lv9f3x4JgY8z4VMK9DCPW56uUKhJNpJowerW9OcLZzzKIw9XP4PDUPDc oCCcFVLCk1WgexTwV77jrv//NLN7Vrn6R9IjT6NtJlNODAjBf/PtEX6a9ZNmPv910wXp fPymFpLv82lNEy2nCZS3dW5TMtK8Y5TQEPx6fPHbg3oeYVh7OTCpqoDJFBSGFVXjLLOD nOqA== 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=N3dunhjuge82EZFNBw1SP5OgsJ3YUo0+A3T8/54pbBw=; b=EeCil0Raxhd5XFa7Qd0bPZq/GourtN/ViQPN485yOjHLGyNhSfCJ9ThfQ3I/JTjJNg zT/U9gzHW493lME29gX9u+Sql0KOflzo/+LCasLYryD+g9/74ZyNOtvZqHbe5cF9c9Rq 2SJA3ldezmo7WOJm1mhwWC5a7W5CC4hrE87taXaQ1e98VzRXq8D5iUazdKlCYwM1itNO gvlu/pg+57h6ZqogzfniIo+0K3EW1XMIeIlHv3JRPvejk9FgCsJqwMS9i+TCbow9ebkv Lu9FtB3J5xd/w1oeuEcjnCymQDBR7LPmlNWMsLb+qTQoeHjIL6frCa/asagR9XFk2qrb yu3g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@android.com header.s=20161025 header.b=kkvhtd0e; 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=REJECT sp=REJECT dis=NONE) header.from=android.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id kd11si9293355ejc.396.2021.02.13.16.26.27; Sat, 13 Feb 2021 16:27:15 -0800 (PST) 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=@android.com header.s=20161025 header.b=kkvhtd0e; 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=REJECT sp=REJECT dis=NONE) header.from=android.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229759AbhBNAHN (ORCPT + 99 others); Sat, 13 Feb 2021 19:07:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44286 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229690AbhBNAHM (ORCPT ); Sat, 13 Feb 2021 19:07:12 -0500 Received: from mail-pl1-x62e.google.com (mail-pl1-x62e.google.com [IPv6:2607:f8b0:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E575EC061574 for ; Sat, 13 Feb 2021 16:06:31 -0800 (PST) Received: by mail-pl1-x62e.google.com with SMTP id z7so1734095plk.7 for ; Sat, 13 Feb 2021 16:06:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=N3dunhjuge82EZFNBw1SP5OgsJ3YUo0+A3T8/54pbBw=; b=kkvhtd0et8dKiabKSEuyFORv6JemghPpBfB2zKZJz21JBc9w3UJk+ws+VHSkT/wPfJ gPJ/Y7Wrxsm7RBrzrgkn6Zpvx3iaBYt+HzZ8185SHiiSQ/WZ1qX8WVtP0J3Rt3nrQGtN /xutdAmTO/GCd9vOfUOXHcduzFlZpV75pzmDU+heB8t5nz1zYWVwWx/6eMiqFqBRTcyj AbDiJhJlEvIHItF51O6KkQ611lgv4KGZlAYHsz5ZpP/Y03Krm7eAA1xVhG5LRcD46Gdn 1W4DTLl7ZsbcXkXTE5oVpcbWz+jDywSF1a126jssEHr+mawlNgLnqEfKTKr0lqoy135t 8Iyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=N3dunhjuge82EZFNBw1SP5OgsJ3YUo0+A3T8/54pbBw=; b=chRFNtdB8/rn/tZUt1mw0J3Qe+JkrUsA/FUa9MMoyiWUpSlEY7JdQYY/KcoERpADR5 OyTj/u36Xu/cuG5gO4McH7gGsniTfaRb54Dhww9/8gG1OILy5nCMtWqqXRoYu01C/yzM a80fIzlLj1rd6Kzb4c4tW5a44mRApEzjbM8KuiZWntkK7hWVkLwSfyv7blZdJ2TW8rt7 3OrL9IOSNVW5G7Krs3G505+AcN0jLQd0ihuJYssGq/7nx1rC3UaBS3NOb+YGEQ2uJZm6 Yl4P96nMQkUIG8JVgqbbYII20VaH2YDTvIF9fTCq2dGzt7Ku/oyO6qnhFV/ga4RkSIlD NZ0w== X-Gm-Message-State: AOAM532TFtuFEwspZ9FWF8Eu2adGpfCi4z7NMJUPci5BJpFnMYWaNfhd iUsJUKK6guQSq8KHyDAyAblREg== X-Received: by 2002:a17:902:728a:b029:e3:530:cc73 with SMTP id d10-20020a170902728ab02900e30530cc73mr8534117pll.60.1613261191285; Sat, 13 Feb 2021 16:06:31 -0800 (PST) Received: from zzyiwei.c.googlers.com.com (152.33.83.34.bc.googleusercontent.com. [34.83.33.152]) by smtp.gmail.com with ESMTPSA id r5sm13080545pfh.13.2021.02.13.16.06.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 13 Feb 2021 16:06:30 -0800 (PST) From: Yiwei Zhang To: Andrew Morton , Felix Kuehling , Jens Axboe , Petr Mladek , "J. Bruce Fields" , Peter Zijlstra , Frederic Weisbecker , Marcelo Tosatti , Ilias Stamatis , Rob Clark , Mathieu Desnoyers , Liang Chen Cc: linux-kernel@vger.kernel.org, kernel-team@android.com, Yiwei Zhang Subject: [PATCH] kthread: add kthread_mod_pending_delayed_work api Date: Sun, 14 Feb 2021 00:06:11 +0000 Message-Id: <20210214000611.2169820-1-zzyiwei@android.com> X-Mailer: git-send-email 2.30.0.478.g8a0d178c01-goog MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The existing kthread_mod_delayed_work api will queue a new work if failing to cancel the current work due to no longer being pending. However, there's a case that the same work can be enqueued from both an async request and a delayed work, and a racing could happen if the async request comes right after the timeout delayed work gets scheduled, because the clean up work may not be safe to run twice. Signed-off-by: Yiwei Zhang --- include/linux/kthread.h | 3 +++ kernel/kthread.c | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 65b81e0c494d..250cdc5ff2a5 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -192,6 +192,9 @@ bool kthread_queue_delayed_work(struct kthread_worker *worker, bool kthread_mod_delayed_work(struct kthread_worker *worker, struct kthread_delayed_work *dwork, unsigned long delay); +bool kthread_mod_pending_delayed_work(struct kthread_worker *worker, + struct kthread_delayed_work *dwork, + unsigned long delay); void kthread_flush_work(struct kthread_work *work); void kthread_flush_worker(struct kthread_worker *worker); diff --git a/kernel/kthread.c b/kernel/kthread.c index a5eceecd4513..13881076afdd 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -1142,6 +1142,54 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker, } EXPORT_SYMBOL_GPL(kthread_mod_delayed_work); +/** + * kthread_mod_pending_delayed_work - modify delay of a pending delayed work + * @worker: kthread worker to use + * @dwork: kthread delayed work to queue + * @delay: number of jiffies to wait before queuing + * + * If @dwork is still pending modify @dwork's timer so that it expires after + * @delay. If @dwork is still pending and @delay is zero, @work is guaranteed to + * be queued immediately. + * + * Return: %true if @dwork was pending and its timer was modified, + * %false otherwise. + * + * A special case is when the work is being canceled in parallel. + * It might be caused either by the real kthread_cancel_delayed_work_sync() + * or yet another kthread_mod_delayed_work() call. We let the other command + * win and return %false here. The caller is supposed to synchronize these + * operations a reasonable way. + * + * This function is safe to call from any context including IRQ handler. + * See __kthread_cancel_work() and kthread_delayed_work_timer_fn() + * for details. + */ +bool kthread_mod_pending_delayed_work(struct kthread_worker *worker, + struct kthread_delayed_work *dwork, + unsigned long delay) +{ + struct kthread_work *work = &dwork->work; + unsigned long flags; + int ret = true; + + raw_spin_lock_irqsave(&worker->lock, flags); + if (!work->worker || work->canceling || + !__kthread_cancel_work(work, true, &flags)) { + ret = false; + goto out; + } + + /* Work must not be used with >1 worker, see kthread_queue_work() */ + WARN_ON_ONCE(work->worker != worker); + + __kthread_queue_delayed_work(worker, dwork, delay); +out: + raw_spin_unlock_irqrestore(&worker->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(kthread_mod_pending_delayed_work); + static bool __kthread_cancel_work_sync(struct kthread_work *work, bool is_dwork) { struct kthread_worker *worker = work->worker; -- 2.30.0.478.g8a0d178c01-goog