From nobody Fri Dec 19 04:51:20 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52498EC875E for ; Thu, 7 Sep 2023 23:41:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240210AbjIGXlr (ORCPT ); Thu, 7 Sep 2023 19:41:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34272 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231601AbjIGXlq (ORCPT ); Thu, 7 Sep 2023 19:41:46 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36EF91BD3 for ; Thu, 7 Sep 2023 16:40:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1694130052; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=0oM1ssWxMjgdk1YS4u11+h65Kummyok+rDsO3Fg0IQw=; b=X17/LaSIFNZpRmq0RAnDKFU9dAZGAEfbWADNpA1h8Unn/M583b23QvBFDrVeVoxRZuZc3p 3uwz6vreDJd2Ty0cwNQfX0GkoMhf/e5nWMK+ejYKb7VvR23o+AmYnTux+B96lL3CPrWNAb gA8F4veepkBDj/z6yaZ360zCNWcUUYo= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-126-6NQ9vefGMWyv6XydIaa9ag-1; Thu, 07 Sep 2023 19:40:50 -0400 X-MC-Unique: 6NQ9vefGMWyv6XydIaa9ag-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8775C948C02; Thu, 7 Sep 2023 23:40:50 +0000 (UTC) Received: from pasta.redhat.com (unknown [10.45.224.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2DD1C412F2CF; Thu, 7 Sep 2023 23:40:49 +0000 (UTC) From: Andreas Gruenbacher To: Linus Torvalds Cc: Andreas Gruenbacher , Andrew Morton , linux-kernel@vger.kernel.org Subject: [RFC] kthread: Add kthread_stop_put Date: Fri, 8 Sep 2023 01:40:48 +0200 Message-Id: <20230907234048.2499820-1-agruenba@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a kthread_stop_put() helper that stops a thread and puts its task struct. Use it to replace the various instances of kthread_stop() followed by put_task_struct(). Remove the kthread_stop_put() macro in usbip that is similar but doesn't return the result of kthread_stop(). Signed-off-by: Andreas Gruenbacher diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index de9e69f70af7..76f468c9f761 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -618,6 +618,5 @@ int ivpu_job_done_thread_init(struct ivpu_device *vdev) =20 void ivpu_job_done_thread_fini(struct ivpu_device *vdev) { - kthread_stop(vdev->job_done_thread); - put_task_struct(vdev->job_done_thread); + kthread_stop_put(vdev->job_done_thread); } diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-= fence-chain.c index c0979c8049b5..9c2a0c082a76 100644 --- a/drivers/dma-buf/st-dma-fence-chain.c +++ b/drivers/dma-buf/st-dma-fence-chain.c @@ -476,10 +476,9 @@ static int find_race(void *arg) for (i =3D 0; i < ncpus; i++) { int ret; =20 - ret =3D kthread_stop(threads[i]); + ret =3D kthread_stop_put(threads[i]); if (ret && !err) err =3D ret; - put_task_struct(threads[i]); } kfree(threads); =20 @@ -591,8 +590,7 @@ static int wait_forward(void *arg) for (i =3D 0; i < fc.chain_length; i++) dma_fence_signal(fc.fences[i]); =20 - err =3D kthread_stop(tsk); - put_task_struct(tsk); + err =3D kthread_stop_put(tsk); =20 err: fence_chains_fini(&fc); @@ -621,8 +619,7 @@ static int wait_backward(void *arg) for (i =3D fc.chain_length; i--; ) dma_fence_signal(fc.fences[i]); =20 - err =3D kthread_stop(tsk); - put_task_struct(tsk); + err =3D kthread_stop_put(tsk); =20 err: fence_chains_fini(&fc); @@ -669,8 +666,7 @@ static int wait_random(void *arg) for (i =3D 0; i < fc.chain_length; i++) dma_fence_signal(fc.fences[i]); =20 - err =3D kthread_stop(tsk); - put_task_struct(tsk); + err =3D kthread_stop_put(tsk); =20 err: fence_chains_fini(&fc); diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c index fb6e0a6ae2c9..b7c6f7ea9e0c 100644 --- a/drivers/dma-buf/st-dma-fence.c +++ b/drivers/dma-buf/st-dma-fence.c @@ -548,11 +548,9 @@ static int race_signal_callback(void *arg) for (i =3D 0; i < ARRAY_SIZE(t); i++) { int err; =20 - err =3D kthread_stop(t[i].task); + err =3D kthread_stop_put(t[i].task); if (err && !ret) ret =3D err; - - put_task_struct(t[i].task); } } =20 diff --git a/drivers/gpu/drm/i915/gt/selftest_migrate.c b/drivers/gpu/drm/i= 915/gt/selftest_migrate.c index 3def5ca72dec..0fb07f073baa 100644 --- a/drivers/gpu/drm/i915/gt/selftest_migrate.c +++ b/drivers/gpu/drm/i915/gt/selftest_migrate.c @@ -719,11 +719,9 @@ static int threaded_migrate(struct intel_migrate *migr= ate, if (IS_ERR_OR_NULL(tsk)) continue; =20 - status =3D kthread_stop(tsk); + status =3D kthread_stop_put(tsk); if (status && !err) err =3D status; - - put_task_struct(tsk); } =20 kfree(thread); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/= interface.c index f3f2c07423a6..33c8143619f0 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -672,8 +672,7 @@ int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t= ring_ref, static void xenvif_disconnect_queue(struct xenvif_queue *queue) { if (queue->task) { - kthread_stop(queue->task); - put_task_struct(queue->task); + kthread_stop_put(queue->task); queue->task =3D NULL; } =20 diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_com= mon.h index d8cbd2dfc2c2..282efca64a01 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -298,12 +298,6 @@ struct usbip_device { __k; \ }) =20 -#define kthread_stop_put(k) \ - do { \ - kthread_stop(k); \ - put_task_struct(k); \ - } while (0) - /* usbip_common.c */ void usbip_dump_urb(struct urb *purb); void usbip_dump_header(struct usbip_header *pdu); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 33ca04733e93..ecf789b7168c 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1126,8 +1126,7 @@ static int init_threads(struct gfs2_sbd *sdp) return 0; =20 fail: - kthread_stop(sdp->sd_logd_process); - put_task_struct(sdp->sd_logd_process); + kthread_stop_put(sdp->sd_logd_process); sdp->sd_logd_process =3D NULL; return error; } @@ -1135,13 +1134,11 @@ static int init_threads(struct gfs2_sbd *sdp) void gfs2_destroy_threads(struct gfs2_sbd *sdp) { if (sdp->sd_logd_process) { - kthread_stop(sdp->sd_logd_process); - put_task_struct(sdp->sd_logd_process); + kthread_stop_put(sdp->sd_logd_process); sdp->sd_logd_process =3D NULL; } if (sdp->sd_quotad_process) { - kthread_stop(sdp->sd_quotad_process); - put_task_struct(sdp->sd_quotad_process); + kthread_stop_put(sdp->sd_quotad_process); sdp->sd_quotad_process =3D NULL; } } diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 2c30ade43bc8..b11f53c1ba2e 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -86,6 +86,7 @@ void free_kthread_struct(struct task_struct *k); void kthread_bind(struct task_struct *k, unsigned int cpu); void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask); int kthread_stop(struct task_struct *k); +int kthread_stop_put(struct task_struct *k); bool kthread_should_stop(void); bool kthread_should_park(void); bool kthread_should_stop_or_park(void); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index d309ba84e08a..1782f90cd8c6 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1852,15 +1852,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc= , struct irqaction *new) struct task_struct *t =3D new->thread; =20 new->thread =3D NULL; - kthread_stop(t); - put_task_struct(t); + kthread_stop_put(t); } if (new->secondary && new->secondary->thread) { struct task_struct *t =3D new->secondary->thread; =20 new->secondary->thread =3D NULL; - kthread_stop(t); - put_task_struct(t); + kthread_stop_put(t); } out_mput: module_put(desc->owner); @@ -1971,12 +1969,9 @@ static struct irqaction *__free_irq(struct irq_desc = *desc, void *dev_id) * the same bit to a newly requested action. */ if (action->thread) { - kthread_stop(action->thread); - put_task_struct(action->thread); - if (action->secondary && action->secondary->thread) { - kthread_stop(action->secondary->thread); - put_task_struct(action->secondary->thread); - } + kthread_stop_put(action->thread); + if (action->secondary && action->secondary->thread) + kthread_stop_put(action->secondary->thread); } =20 /* Last action releases resources */ diff --git a/kernel/kthread.c b/kernel/kthread.c index c46128ec0c0a..99ee8d11bfcc 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -715,6 +715,30 @@ int kthread_stop(struct task_struct *k) } EXPORT_SYMBOL(kthread_stop); =20 +/** + * kthread_stop_put - stop a thread and put its task struct + * + * Stops a kthread and put its task_struct. This is meant for callers + * that are holding an extra reference on the task struct, for example: + * + * t =3D kthread_create(...); + * if (!IS_ERR(t)) { + * get_task_struct(t); + * wake_up_process(t); + * } + * + * Returns the result of kthread_stop(). + */ +int kthread_stop_put(struct task_struct *k) +{ + int ret; + + ret =3D kthread_stop(k); + put_task_struct(k); + return ret; +} +EXPORT_SYMBOL(kthread_stop_put); + int kthreadd(void *unused) { struct task_struct *tsk =3D current; diff --git a/kernel/smpboot.c b/kernel/smpboot.c index f47d8f375946..1992b62e980b 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -272,8 +272,7 @@ static void smpboot_destroy_threads(struct smp_hotplug_= thread *ht) struct task_struct *tsk =3D *per_cpu_ptr(ht->store, cpu); =20 if (tsk) { - kthread_stop(tsk); - put_task_struct(tsk); + kthread_stop_put(tsk); *per_cpu_ptr(ht->store, cpu) =3D NULL; } } diff --git a/mm/damon/core.c b/mm/damon/core.c index bcd2bd9d6c10..2f54f153d7f5 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -699,8 +699,7 @@ static int __damon_stop(struct damon_ctx *ctx) if (tsk) { get_task_struct(tsk); mutex_unlock(&ctx->kdamond_lock); - kthread_stop(tsk); - put_task_struct(tsk); + kthread_stop_put(tsk); return 0; } mutex_unlock(&ctx->kdamond_lock); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index f56b8d697014..826250a0f5b1 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3982,8 +3982,7 @@ static void __net_exit pg_net_exit(struct net *net) list_for_each_safe(q, n, &list) { t =3D list_entry(q, struct pktgen_thread, th_list); list_del(&t->th_list); - kthread_stop(t->tsk); - put_task_struct(t->tsk); + kthread_stop_put(t->tsk); kfree(t); }