[...]
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1446,6 +1446,32 @@ struct tlbflush_unmap_batch {
>       bool writable;
>  };
> 
> +struct memalloc_info {
> +     /*
> +      * 0: not doing __GFP_RECLAIM allocation.
> +      * 1: doing non-recursive __GFP_RECLAIM allocation.
> +      * 2: doing recursive __GFP_RECLAIM allocation.
> +      */
> +     u8 valid;
> +     /*
> +      * bit 0: Will be reported as OOM victim.
> +      * bit 1: Will be reported as dying task.
> +      * bit 2: Will be reported as stalling task.
> +      * bit 3: Will be reported as exiting task.
> +      * bit 7: Will be reported unconditionally.
> +      */
> +     u8 type;
> +     /* Index used for memalloc_in_flight[] counter. */
> +     u8 idx;

        u8 __pad;       is also needed perhaps.

> +     /* For progress monitoring. */
> +     unsigned int sequence;
> +     /* Started time in jiffies as of valid == 1. */
> +     unsigned long start;
> +     /* Requested order and gfp flags as of valid == 1. */
> +     unsigned int order;
> +     gfp_t gfp;
> +};
> +

[...]
> +
> +/*
> + * check_memalloc_stalling_tasks - Check for memory allocation stalls.
> + *
> + * @timeout: Timeout in jiffies.
> + *
> + * Returns number of stalling tasks.
> + *
> + * This function is marked as "noinline" in order to allow inserting dynamic
> + * probes (e.g. printing more information as needed using SystemTap, calling
> + * panic() if this function returned non 0 value).
> + */
> +static noinline int check_memalloc_stalling_tasks(unsigned long timeout)
> +{
> +     char buf[256];
> +     struct task_struct *g, *p;
> +     unsigned long now;
> +     unsigned long expire;
> +     unsigned int sigkill_pending = 0;
> +     unsigned int exiting_tasks = 0;
> +     unsigned int memdie_pending = 0;
> +     unsigned int stalling_tasks = 0;
> +
> +     cond_resched();
> +     now = jiffies;
> +     /*
> +      * Report tasks that stalled for more than half of timeout duration
> +      * because such tasks might be correlated with tasks that already
> +      * stalled for full timeout duration.
> +      */
> +     expire = now - timeout * (HZ / 2);
> +     /* Count stalling tasks, dying and victim tasks. */
> +     preempt_disable();
> +     rcu_read_lock();
> +     for_each_process_thread(g, p) {
> +             u8 type = 0;
> +
> +             if (test_tsk_thread_flag(p, TIF_MEMDIE)) {
> +                     type |= 1;
> +                     memdie_pending++;
> +             }
> +             if (fatal_signal_pending(p)) {
> +                     type |= 2;
> +                     sigkill_pending++;
> +             }
> +             if ((p->flags & PF_EXITING) && p->state != TASK_DEAD) {
> +                     type |= 8;
> +                     exiting_tasks++;
> +             }
> +             if (is_stalling_task(p, expire)) {
> +                     type |= 4;
> +                     stalling_tasks++;
> +             }
> +             if (p->flags & PF_KSWAPD)
> +                     type |= 128;
> +             p->memalloc.type = type;
> +     }

The numbers assigned to type may be replaced with texts, 
for instance,
        MEMALLOC_TYPE_VICTIM 
        MEMALLOC_TYPE_DYING 
        MEMALLOC_TYPE_STALLING
        MEMALLOC_TYPE_EXITING
        MEMALLOC_TYPE_REPORT

> +     rcu_read_unlock();
> +     preempt_enable();
> +     if (!stalling_tasks)
> +             return 0;
> +     cond_resched();
> +     /* Report stalling tasks, dying and victim tasks. */
> +     pr_warn("MemAlloc-Info: stalling=%u dying=%u exiting=%u victim=%u 
> oom_count=%u\n",
> +             stalling_tasks, sigkill_pending, exiting_tasks, memdie_pending,
> +             out_of_memory_count);
> +     cond_resched();
> +     sigkill_pending = 0;
> +     exiting_tasks = 0;
> +     memdie_pending = 0;
> +     stalling_tasks = 0;
> +     preempt_disable();
> +     rcu_read_lock();
> + restart_report:
> +     for_each_process_thread(g, p) {
> +             bool can_cont;
> +             u8 type;
> +
> +             if (likely(!p->memalloc.type))
> +                     continue;
> +             p->memalloc.type = 0;
> +             /* Recheck in case state changed meanwhile. */
> +             type = 0;
> +             if (test_tsk_thread_flag(p, TIF_MEMDIE)) {
> +                     type |= 1;
> +                     memdie_pending++;
> +             }
> +             if (fatal_signal_pending(p)) {
> +                     type |= 2;
> +                     sigkill_pending++;
> +             }
> +             if ((p->flags & PF_EXITING) && p->state != TASK_DEAD) {
> +                     type |= 8;
> +                     exiting_tasks++;
> +             }
> +             if (is_stalling_task(p, expire)) {
> +                     type |= 4;
> +                     stalling_tasks++;
> +                     snprintf(buf, sizeof(buf),
> +                              " seq=%u gfp=0x%x(%pGg) order=%u delay=%lu",
> +                              memalloc.sequence, memalloc.gfp,
> +                              &memalloc.gfp,
> +                              memalloc.order, now - memalloc.start);
> +             } else {
> +                     buf[0] = '\0';
> +             }
> +             if (p->flags & PF_KSWAPD)
> +                     type |= 128;

ditto

thanks
Hillf


Reply via email to