signal, x86: Delay calling signals in atomic on RT enabled kernels
[sfrench/cifs-2.6.git] / kernel / kthread.c
index a2c156ee8275c73a507cf7db3de0a6ca20ced88e..38c6dd822da87e9ccff4613402e7683cd92e7338 100644 (file)
@@ -61,6 +61,8 @@ struct kthread {
 #ifdef CONFIG_BLK_CGROUP
        struct cgroup_subsys_state *blkcg_css;
 #endif
+       /* To store the full name if task comm is truncated. */
+       char *full_name;
 };
 
 enum KTHREAD_BITS {
@@ -94,6 +96,18 @@ static inline struct kthread *__to_kthread(struct task_struct *p)
        return kthread;
 }
 
+void get_kthread_comm(char *buf, size_t buf_size, struct task_struct *tsk)
+{
+       struct kthread *kthread = to_kthread(tsk);
+
+       if (!kthread || !kthread->full_name) {
+               __get_task_comm(buf, buf_size, tsk);
+               return;
+       }
+
+       strscpy_pad(buf, kthread->full_name, buf_size);
+}
+
 bool set_kthread_struct(struct task_struct *p)
 {
        struct kthread *kthread;
@@ -121,10 +135,14 @@ void free_kthread_struct(struct task_struct *k)
         * Can be NULL if kmalloc() in set_kthread_struct() failed.
         */
        kthread = to_kthread(k);
+       if (!kthread)
+               return;
+
 #ifdef CONFIG_BLK_CGROUP
-       WARN_ON_ONCE(kthread && kthread->blkcg_css);
+       WARN_ON_ONCE(kthread->blkcg_css);
 #endif
        k->worker_private = NULL;
+       kfree(kthread->full_name);
        kfree(kthread);
 }
 
@@ -438,12 +456,22 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
        task = create->result;
        if (!IS_ERR(task)) {
                char name[TASK_COMM_LEN];
+               va_list aq;
+               int len;
 
                /*
                 * task is already visible to other tasks, so updating
                 * COMM must be protected.
                 */
-               vsnprintf(name, sizeof(name), namefmt, args);
+               va_copy(aq, args);
+               len = vsnprintf(name, sizeof(name), namefmt, aq);
+               va_end(aq);
+               if (len >= TASK_COMM_LEN) {
+                       struct kthread *kthread = to_kthread(task);
+
+                       /* leave it truncated when out of memory. */
+                       kthread->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
+               }
                set_task_comm(task, name);
        }
        kfree(create);