summaryrefslogtreecommitdiffstats
path: root/kernel/kthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kthread.c')
-rw-r--r--kernel/kthread.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c
index ba3992c8c375..8af313081b0d 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -20,7 +20,6 @@
20#include <linux/freezer.h> 20#include <linux/freezer.h>
21#include <linux/ptrace.h> 21#include <linux/ptrace.h>
22#include <linux/uaccess.h> 22#include <linux/uaccess.h>
23#include <linux/cgroup.h>
24#include <trace/events/sched.h> 23#include <trace/events/sched.h>
25 24
26static DEFINE_SPINLOCK(kthread_create_lock); 25static DEFINE_SPINLOCK(kthread_create_lock);
@@ -47,6 +46,9 @@ struct kthread {
47 void *data; 46 void *data;
48 struct completion parked; 47 struct completion parked;
49 struct completion exited; 48 struct completion exited;
49#ifdef CONFIG_BLK_CGROUP
50 struct cgroup_subsys_state *blkcg_css;
51#endif
50}; 52};
51 53
52enum KTHREAD_BITS { 54enum KTHREAD_BITS {
@@ -74,11 +76,17 @@ static inline struct kthread *to_kthread(struct task_struct *k)
74 76
75void free_kthread_struct(struct task_struct *k) 77void free_kthread_struct(struct task_struct *k)
76{ 78{
79 struct kthread *kthread;
80
77 /* 81 /*
78 * Can be NULL if this kthread was created by kernel_thread() 82 * Can be NULL if this kthread was created by kernel_thread()
79 * or if kmalloc() in kthread() failed. 83 * or if kmalloc() in kthread() failed.
80 */ 84 */
81 kfree(to_kthread(k)); 85 kthread = to_kthread(k);
86#ifdef CONFIG_BLK_CGROUP
87 WARN_ON_ONCE(kthread && kthread->blkcg_css);
88#endif
89 kfree(kthread);
82} 90}
83 91
84/** 92/**
@@ -196,7 +204,7 @@ static int kthread(void *_create)
196 struct kthread *self; 204 struct kthread *self;
197 int ret; 205 int ret;
198 206
199 self = kmalloc(sizeof(*self), GFP_KERNEL); 207 self = kzalloc(sizeof(*self), GFP_KERNEL);
200 set_kthread_struct(self); 208 set_kthread_struct(self);
201 209
202 /* If user was SIGKILLed, I release the structure. */ 210 /* If user was SIGKILLed, I release the structure. */
@@ -212,7 +220,6 @@ static int kthread(void *_create)
212 do_exit(-ENOMEM); 220 do_exit(-ENOMEM);
213 } 221 }
214 222
215 self->flags = 0;
216 self->data = data; 223 self->data = data;
217 init_completion(&self->exited); 224 init_completion(&self->exited);
218 init_completion(&self->parked); 225 init_completion(&self->parked);
@@ -1152,3 +1159,54 @@ void kthread_destroy_worker(struct kthread_worker *worker)
1152 kfree(worker); 1159 kfree(worker);
1153} 1160}
1154EXPORT_SYMBOL(kthread_destroy_worker); 1161EXPORT_SYMBOL(kthread_destroy_worker);
1162
1163#ifdef CONFIG_BLK_CGROUP
1164/**
1165 * kthread_associate_blkcg - associate blkcg to current kthread
1166 * @css: the cgroup info
1167 *
1168 * Current thread must be a kthread. The thread is running jobs on behalf of
1169 * other threads. In some cases, we expect the jobs attach cgroup info of
1170 * original threads instead of that of current thread. This function stores
1171 * original thread's cgroup info in current kthread context for later
1172 * retrieval.
1173 */
1174void kthread_associate_blkcg(struct cgroup_subsys_state *css)
1175{
1176 struct kthread *kthread;
1177
1178 if (!(current->flags & PF_KTHREAD))
1179 return;
1180 kthread = to_kthread(current);
1181 if (!kthread)
1182 return;
1183
1184 if (kthread->blkcg_css) {
1185 css_put(kthread->blkcg_css);
1186 kthread->blkcg_css = NULL;
1187 }
1188 if (css) {
1189 css_get(css);
1190 kthread->blkcg_css = css;
1191 }
1192}
1193EXPORT_SYMBOL(kthread_associate_blkcg);
1194
1195/**
1196 * kthread_blkcg - get associated blkcg css of current kthread
1197 *
1198 * Current thread must be a kthread.
1199 */
1200struct cgroup_subsys_state *kthread_blkcg(void)
1201{
1202 struct kthread *kthread;
1203
1204 if (current->flags & PF_KTHREAD) {
1205 kthread = to_kthread(current);
1206 if (kthread)
1207 return kthread->blkcg_css;
1208 }
1209 return NULL;
1210}
1211EXPORT_SYMBOL(kthread_blkcg);
1212#endif