kthread() could bail out early before we initialize blkcg_css (if the kthread is killed very early. Please see xchg() statement in kthread()), which confuses free_kthread_struct. Instead of moving the blkcg_css initialization early, we simply zero the whole 'self' data structure, which doesn't sound much overhead.
Showing the changes to kernel/kthread.c (1 of 1 file). Show all
Unified · Split
| @@ -204,7 +204,7 @@ static int kthread(void *_create) · 203 unmodified lines | |||
| 204 | struct kthread *self; | 204 | struct kthread *self; |
| 205 | int ret; | 205 | int ret; |
| 206 | 206 | ||
| 207 | self = kmalloc(sizeof(*self), GFP_KERNEL); | 207 | self = kzalloc(sizeof(*self), GFP_KERNEL); |
| 208 | set_kthread_struct(self); | 208 | set_kthread_struct(self); |
| 209 | 209 | ||
| 210 | /* If user was SIGKILLed, I release the structure. */ | 210 | /* If user was SIGKILLed, I release the structure. */ |
| @@ -220,13 +220,9 @@ static int kthread(void *_create) · 9 unmodified lines | |||
| 220 | do_exit(-ENOMEM); | 220 | do_exit(-ENOMEM); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | self->flags = 0; | ||
| 224 | self->data = data; | 223 | self->data = data; |
| 225 | init_completion(&self->exited); | 224 | init_completion(&self->exited); |
| 226 | init_completion(&self->parked); | 225 | init_completion(&self->parked); |
| 227 | #ifdef CONFIG_BLK_CGROUP | ||
| 228 | self->blkcg_css = NULL; | ||
| 229 | #endif | ||
| 230 | current->vfork_done = &self->exited; | 226 | current->vfork_done = &self->exited; |
| 231 | 227 | ||
| 232 | /* OK, tell user we're spawned, wait for stop or wakeup */ | 228 | /* OK, tell user we're spawned, wait for stop or wakeup */ |