Received: by 2002:ac0:950c:0:0:0:0:0 with SMTP id f12csp2398339imc; Tue, 12 Mar 2019 13:02:09 -0700 (PDT) X-Google-Smtp-Source: APXvYqxID9xibWgENYiN2kYjECOYCXENe00IYRJjWbdwV3pWmMTdhQ9ziSzYkDECXxdrALjylL7U X-Received: by 2002:a62:ea0f:: with SMTP id t15mr40780600pfh.124.1552420929739; Tue, 12 Mar 2019 13:02:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1552420929; cv=none; d=google.com; s=arc-20160816; b=SE3gIRwTg/iKj2vHwUlD6tfAK9IWU6rkDeAaRNjBZaq35XT5vCLOjbL0oBREhKqImt yVz9CJIIxW714jbAhf4UC/kgA/lf2XBd8eg2f4SCpqvjm8t34l17ItIkEyoPMfdDEzZ1 0/2lXhEBCL8rJxrxZVJPkq4b1xj1h31KgXA9Oc314+pROPTj5nS0pCJucksSpvzsdIAD 72V6FcXCn012UfCRAkXkAr7jJ6t7C40jbAo7FAEkdDo8iGaC/qdadzxAE9udDc3u55VM 7u+yyHOZhDQm/AsRo0WlpvOxPcapliUYxvodzx3HFGiw4wKWa7Pb20SowBVvZf+/O3IS pGFQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:from:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:date; bh=s7YHVl39if8fZYrqgwt8ZsAhSjb6kIJKHMNBhujaKvA=; b=ONAOHbOOkMVT2Vjlb8sUuL/UnU1IseHYumoydrZHyUc/ZU+IfRaRrTyhKrRsw7M8Q+ gK6iaS+iDFGuNQZtHdLzm0PsyE7dc/hH2CrDZt6kGe9l148k2VC1DtcZGfnxIyZ6AEyH KZsetGtCNrXntkRYrfGPv9LXXkg2R+D5imyb126InT4eGaOEeaUedrctbNl0bvVxL5f7 7xUrEIiRqYcPgxFtevNunhJ9QMbin1MslT+0OlbyfdXUvzDnT/ywHwrA2vgw/S4v+8O4 77WYnPjUzJKONL5+LO81DOujW23eRj8XUG5WtAW542vQUZZhW6GfoSO49k98x2o3c2ui juhQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 4si8723324pft.276.2019.03.12.13.01.53; Tue, 12 Mar 2019 13:02:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727234AbfCLUBL (ORCPT + 99 others); Tue, 12 Mar 2019 16:01:11 -0400 Received: from fieldses.org ([173.255.197.46]:57402 "EHLO fieldses.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726585AbfCLUBL (ORCPT ); Tue, 12 Mar 2019 16:01:11 -0400 Received: by fieldses.org (Postfix, from userid 2815) id A76331C84; Tue, 12 Mar 2019 16:01:09 -0400 (EDT) Date: Tue, 12 Mar 2019 16:01:09 -0400 To: "J. Bruce Fields" Cc: linux-nfs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Trond Myklebust , Jeff Layton , David Howells , Tejun Heo , Peter Zijlstra , Shaohua Li , Oleg Nesterov Subject: Re: [PATCH 3/7] kthreads: allow multiple kthreadd's Message-ID: <20190312200109.GE29990@fieldses.org> References: <1549656647-25115-1-git-send-email-bfields@redhat.com> <1549656647-25115-4-git-send-email-bfields@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1549656647-25115-4-git-send-email-bfields@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) From: bfields@fieldses.org (J. Bruce Fields) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org I'd like to try to get this in 5.2. Can anyone give me an ACK for the kthread parts? Or tell me who to ask? Let me know if I should resend. Or, of course, tell me if I've missed something and this is all a terrible idea. --b. On Fri, Feb 08, 2019 at 03:10:43PM -0500, J. Bruce Fields wrote: > From: "J. Bruce Fields" > > Allow subsystems to run their own kthreadd's. > > I'm experimenting with this to allow nfsd to put its threads into its > own thread group to make it easy for the vfs to tell when nfsd is > breaking one of its own leases. > > Signed-off-by: J. Bruce Fields > --- > include/linux/kthread.h | 20 ++++++- > init/main.c | 4 +- > kernel/kthread.c | 113 ++++++++++++++++++++++++++++++---------- > 3 files changed, 107 insertions(+), 30 deletions(-) > > diff --git a/include/linux/kthread.h b/include/linux/kthread.h > index c1961761311d..10b5836dfb2a 100644 > --- a/include/linux/kthread.h > +++ b/include/linux/kthread.h > @@ -6,6 +6,24 @@ > #include > #include > > +struct kthread_group { > + char *name; > + spinlock_t create_lock; > + struct list_head create_list; > + struct task_struct *task; > +}; > + > +extern struct kthread_group kthreadd_default; > + > +struct kthread_group *kthread_start_group(char *); > +void kthread_stop_group(struct kthread_group *); > + > +struct task_struct *kthread_group_create_on_node(struct kthread_group *, > + int (*threadfn)(void *data), > + void *data, > + int node, > + const char namefmt[], ...); > + > __printf(4, 5) > struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), > void *data, > @@ -63,7 +81,7 @@ int kthread_park(struct task_struct *k); > void kthread_unpark(struct task_struct *k); > void kthread_parkme(void); > > -int kthreadd(void *unused); > +int kthreadd(void *); > extern struct task_struct *kthreadd_task; > extern int tsk_fork_get_node(struct task_struct *tsk); > > diff --git a/init/main.c b/init/main.c > index e2e80ca3165a..c4ed4d75aca7 100644 > --- a/init/main.c > +++ b/init/main.c > @@ -417,9 +417,9 @@ noinline void __ref rest_init(void) > rcu_read_unlock(); > > numa_default_policy(); > - pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); > + pid = kernel_thread(kthreadd, &kthreadd_default, CLONE_FS | CLONE_FILES); > rcu_read_lock(); > - kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); > + kthreadd_default.task = find_task_by_pid_ns(pid, &init_pid_ns); > rcu_read_unlock(); > > /* > diff --git a/kernel/kthread.c b/kernel/kthread.c > index 4428fd586cd8..b515557b98c9 100644 > --- a/kernel/kthread.c > +++ b/kernel/kthread.c > @@ -22,9 +22,44 @@ > #include > #include > > -static DEFINE_SPINLOCK(kthread_create_lock); > -static LIST_HEAD(kthread_create_list); > -struct task_struct *kthreadd_task; > +struct kthread_group kthreadd_default = { > + .name = "kthreadd", > + .create_lock = __SPIN_LOCK_UNLOCKED(kthreadd_default.create_lock), > + .create_list = LIST_HEAD_INIT(kthreadd_default.create_list), > +}; > + > +void wake_kthreadd(struct kthread_group *kg) > +{ > + wake_up_process(kg->task); > +} > + > +struct kthread_group *kthread_start_group(char *name) > +{ > + struct kthread_group *new; > + struct task_struct *task; > + > + new = kmalloc(sizeof(struct kthread_group), GFP_KERNEL); > + if (!new) > + return ERR_PTR(-ENOMEM); > + spin_lock_init(&new->create_lock); > + INIT_LIST_HEAD(&new->create_list); > + new->name = name; > + task = kthread_run(kthreadd, new, name); > + if (IS_ERR(task)) { > + kfree(new); > + return ERR_CAST(task); > + } > + new->task = task; > + return new; > +} > +EXPORT_SYMBOL_GPL(kthread_start_group); > + > +void kthread_stop_group(struct kthread_group *kg) > +{ > + kthread_stop(kg->task); > + kfree(kg); > +} > +EXPORT_SYMBOL_GPL(kthread_stop_group); > > struct kthread_create_info > { > @@ -279,11 +314,13 @@ static void create_kthread(struct kthread_create_info *create) > } > } > > -static __printf(4, 0) > -struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), > - void *data, int node, > - const char namefmt[], > - va_list args) > + > +static __printf(5, 0) > +struct task_struct *__kthread_group_create_on_node(struct kthread_group *kg, > + int (*threadfn)(void *data), > + void *data, int node, > + const char namefmt[], > + va_list args) > { > DECLARE_COMPLETION_ONSTACK(done); > struct task_struct *task; > @@ -297,11 +334,11 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), > create->node = node; > create->done = &done; > > - spin_lock(&kthread_create_lock); > - list_add_tail(&create->list, &kthread_create_list); > - spin_unlock(&kthread_create_lock); > + spin_lock(&kg->create_lock); > + list_add_tail(&create->list, &kg->create_list); > + spin_unlock(&kg->create_lock); > > - wake_up_process(kthreadd_task); > + wake_kthreadd(kg); > /* > * Wait for completion in killable state, for I might be chosen by > * the OOM killer while kthreadd is trying to allocate memory for > @@ -343,6 +380,25 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), > return task; > } > > +__printf(5, 0) > +struct task_struct *kthread_group_create_on_node(struct kthread_group *kg, > + int (*threadfn)(void *data), > + void *data, int node, > + const char namefmt[], > + ...) > +{ > + struct task_struct *task; > + va_list args; > + > + va_start(args, namefmt); > + task = __kthread_group_create_on_node(kg, threadfn, > + data, node, namefmt, args); > + va_end(args); > + > + return task; > +} > +EXPORT_SYMBOL_GPL(kthread_group_create_on_node); > + > /** > * kthread_create_on_node - create a kthread. > * @threadfn: the function to run until signal_pending(current). > @@ -375,7 +431,8 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), > va_list args; > > va_start(args, namefmt); > - task = __kthread_create_on_node(threadfn, data, node, namefmt, args); > + task = __kthread_group_create_on_node(&kthreadd_default, threadfn, > + data, node, namefmt, args); > va_end(args); > > return task; > @@ -555,30 +612,31 @@ int kthread_stop(struct task_struct *k) > } > EXPORT_SYMBOL(kthread_stop); > > -void kthread_do_work(void) > +void kthread_do_work(struct kthread_group *kg) > { > - spin_lock(&kthread_create_lock); > - while (!list_empty(&kthread_create_list)) { > + spin_lock(&kg->create_lock); > + while (!list_empty(&kg->create_list)) { > struct kthread_create_info *create; > > - create = list_entry(kthread_create_list.next, > + create = list_entry(kg->create_list.next, > struct kthread_create_info, list); > list_del_init(&create->list); > - spin_unlock(&kthread_create_lock); > + spin_unlock(&kg->create_lock); > > create_kthread(create); > > - spin_lock(&kthread_create_lock); > + spin_lock(&kg->create_lock); > } > - spin_unlock(&kthread_create_lock); > + spin_unlock(&kg->create_lock); > } > > -int kthreadd(void *unused) > +int kthreadd(void *data) > { > + struct kthread_group *kg = data; > struct task_struct *tsk = current; > > /* Setup a clean context for our children to inherit. */ > - set_task_comm(tsk, "kthreadd"); > + set_task_comm(tsk, kg->name); > ignore_signals(tsk); > set_cpus_allowed_ptr(tsk, cpu_all_mask); > set_mems_allowed(node_states[N_MEMORY]); > @@ -586,13 +644,13 @@ int kthreadd(void *unused) > current->flags |= PF_NOFREEZE; > cgroup_init_kthreadd(); > > - for (;;) { > + while (current == kthreadd_default.task || !kthread_should_stop()) { > set_current_state(TASK_INTERRUPTIBLE); > - if (list_empty(&kthread_create_list)) > + if (list_empty(&kg->create_list)) > schedule(); > __set_current_state(TASK_RUNNING); > > - kthread_do_work(); > + kthread_do_work(kg); > } > > return 0; > @@ -690,8 +748,9 @@ __kthread_create_worker(int cpu, unsigned int flags, > if (cpu >= 0) > node = cpu_to_node(cpu); > > - task = __kthread_create_on_node(kthread_worker_fn, worker, > - node, namefmt, args); > + task = __kthread_group_create_on_node(&kthreadd_default, > + kthread_worker_fn, > + worker, node, namefmt, args); > if (IS_ERR(task)) > goto fail_task; > > -- > 2.20.1