Skip to content

Commit

Permalink
kthread: add a mechanism to store cgroup info
Browse files Browse the repository at this point in the history
kthread usually runs jobs on behalf of other threads. The jobs should be
charged to cgroup of original threads. But the jobs run in a kthread,
where we lose the cgroup context of original threads. The patch adds a
machanism to record cgroup info of original threads in kthread context.
Later we can retrieve the cgroup info and attach the cgroup info to jobs.

Since this mechanism is only required by kthread, we store the cgroup
info in kthread data instead of generic task_struct.

Acked-by: Tejun Heo <[email protected]>
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
shligit authored and axboe committed Sep 26, 2017
1 parent e365806 commit 05e3db9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
11 changes: 11 additions & 0 deletions include/linux/kthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/* Simple interface for creating and stopping kernel threads without mess. */
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/cgroup.h>

__printf(4, 5)
struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
Expand Down Expand Up @@ -198,4 +199,14 @@ bool kthread_cancel_delayed_work_sync(struct kthread_delayed_work *work);

void kthread_destroy_worker(struct kthread_worker *worker);

#ifdef CONFIG_CGROUPS
void kthread_associate_blkcg(struct cgroup_subsys_state *css);
struct cgroup_subsys_state *kthread_blkcg(void);
#else
static inline void kthread_associate_blkcg(struct cgroup_subsys_state *css) { }
static inline struct cgroup_subsys_state *kthread_blkcg(void)
{
return NULL;
}
#endif
#endif /* _LINUX_KTHREAD_H */
66 changes: 64 additions & 2 deletions kernel/kthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <linux/freezer.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <linux/cgroup.h>
#include <trace/events/sched.h>

static DEFINE_SPINLOCK(kthread_create_lock);
Expand All @@ -47,6 +46,9 @@ struct kthread {
void *data;
struct completion parked;
struct completion exited;
#ifdef CONFIG_CGROUPS
struct cgroup_subsys_state *blkcg_css;
#endif
};

enum KTHREAD_BITS {
Expand Down Expand Up @@ -74,11 +76,17 @@ static inline struct kthread *to_kthread(struct task_struct *k)

void free_kthread_struct(struct task_struct *k)
{
struct kthread *kthread;

/*
* Can be NULL if this kthread was created by kernel_thread()
* or if kmalloc() in kthread() failed.
*/
kfree(to_kthread(k));
kthread = to_kthread(k);
#ifdef CONFIG_CGROUPS
WARN_ON_ONCE(kthread && kthread->blkcg_css);
#endif
kfree(kthread);
}

/**
Expand Down Expand Up @@ -216,6 +224,9 @@ static int kthread(void *_create)
self->data = data;
init_completion(&self->exited);
init_completion(&self->parked);
#ifdef CONFIG_CGROUPS
self->blkcg_css = NULL;
#endif
current->vfork_done = &self->exited;

/* OK, tell user we're spawned, wait for stop or wakeup */
Expand Down Expand Up @@ -1154,3 +1165,54 @@ void kthread_destroy_worker(struct kthread_worker *worker)
kfree(worker);
}
EXPORT_SYMBOL(kthread_destroy_worker);

#ifdef CONFIG_CGROUPS
/**
* kthread_associate_blkcg - associate blkcg to current kthread
* @css: the cgroup info
*
* Current thread must be a kthread. The thread is running jobs on behalf of
* other threads. In some cases, we expect the jobs attach cgroup info of
* original threads instead of that of current thread. This function stores
* original thread's cgroup info in current kthread context for later
* retrieval.
*/
void kthread_associate_blkcg(struct cgroup_subsys_state *css)
{
struct kthread *kthread;

if (!(current->flags & PF_KTHREAD))
return;
kthread = to_kthread(current);
if (!kthread)
return;

if (kthread->blkcg_css) {
css_put(kthread->blkcg_css);
kthread->blkcg_css = NULL;
}
if (css) {
css_get(css);
kthread->blkcg_css = css;
}
}
EXPORT_SYMBOL(kthread_associate_blkcg);

/**
* kthread_blkcg - get associated blkcg css of current kthread
*
* Current thread must be a kthread.
*/
struct cgroup_subsys_state *kthread_blkcg(void)
{
struct kthread *kthread;

if (current->flags & PF_KTHREAD) {
kthread = to_kthread(current);
if (kthread)
return kthread->blkcg_css;
}
return NULL;
}
EXPORT_SYMBOL(kthread_blkcg);
#endif

0 comments on commit 05e3db9

Please sign in to comment.