On Fri, 30 May 2014 02:51:10 -0400 Naoya Horiguchi <n-horiguchi@xxxxxxxxxxxxx> wrote: > Currently memory error handler handles action optional errors in the deferred > manner by default. And if a recovery aware application wants to handle it > immediately, it can do it by setting PF_MCE_EARLY flag. However, such signal > can be sent only to the main thread, so it's problematic if the application > wants to have a dedicated thread to handler such signals. > > So this patch adds dedicated thread support to memory error handler. We have > PF_MCE_EARLY flags for each thread separately, so with this patch AO signal > is sent to the thread with PF_MCE_EARLY flag set, not the main thread. If > you want to implement a dedicated thread, you call prctl() to set PF_MCE_EARLY > on the thread. > > Memory error handler collects processes to be killed, so this patch lets it > check PF_MCE_EARLY flag on each thread in the collecting routines. > > No behavioral change for all non-early kill cases. > > ... > > --- mmotm-2014-05-21-16-57.orig/mm/memory-failure.c > +++ mmotm-2014-05-21-16-57/mm/memory-failure.c > @@ -380,15 +380,44 @@ static void kill_procs(struct list_head *to_kill, int forcekill, int trapno, > } > } > > -static int task_early_kill(struct task_struct *tsk, int force_early) > +/* > + * Find a dedicated thread which is supposed to handle SIGBUS(BUS_MCEERR_AO) > + * on behalf of the thread group. Return task_struct of the (first found) > + * dedicated thread if found, and return NULL otherwise. > + */ > +static struct task_struct *find_early_kill_thread(struct task_struct *tsk) > +{ > + struct task_struct *t; > + rcu_read_lock(); > + for_each_thread(tsk, t) > + if ((t->flags & PF_MCE_PROCESS) && (t->flags & PF_MCE_EARLY)) > + goto found; > + t = NULL; > +found: > + rcu_read_unlock(); > + return t; > +} > + > +/* > + * Determine whether a given process is "early kill" process which expects > + * to be signaled when some page under the process is hwpoisoned. > + * Return task_struct of the dedicated thread (main thread unless explicitly > + * specified) if the process is "early kill," and otherwise returns NULL. > + */ > +static struct task_struct *task_early_kill(struct task_struct *tsk, > + int force_early) > { > + struct task_struct *t; > if (!tsk->mm) > - return 0; > + return NULL; > if (force_early) > - return 1; > - if (tsk->flags & PF_MCE_PROCESS) > - return !!(tsk->flags & PF_MCE_EARLY); > - return sysctl_memory_failure_early_kill; > + return tsk; > + t = find_early_kill_thread(tsk); > + if (t) > + return t; > + if (sysctl_memory_failure_early_kill) > + return tsk; > + return NULL; > } The above two functions are to be called under read_lock(tasklist_lock), which is rather important... Given this requirement, did find_early_kill_thread() need rcu_read_lock()? -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>