All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-07 13:17 ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-07 13:17 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Tetsuo Handa, Vlastimil Babka, Mel Gorman, linux-mm, LKML, Michal Hocko

From: Michal Hocko <mhocko@suse.com>

We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
per cpu lru caches. This seems more than necessary because both can run
on a single WQ. Both do not block on locks requiring a memory allocation
nor perform any allocations themselves. We will save one rescuer thread
this way.

On the other hand drain_all_pages() queues work on the system wq which
doesn't have rescuer and so this depend on memory allocation (when all
workers are stuck allocating and new ones cannot be created). This is
not critical as there should be somebody invoking the OOM killer (e.g.
the forking worker) and get the situation unstuck and eventually
performs the draining. Quite annoying though. This worker should be
using WQ_RECLAIM as well. We can reuse the same one as for lru draining
and vmstat.

Changes since v1
- rename vmstat_wq to mm_percpu_wq - per Mel
- make sure we are not trying to enqueue anything while the WQ hasn't
  been intialized yet. This shouldn't happen because the initialization
  is done from an init code but some init section might be triggering
  those paths indirectly so just warn and skip the draining in that case
  per Vlastimil
- do not propagate error from setup_vmstat to keep the previous behavior
  per Mel

Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---

Hi,
this has been previous posted [1] as an RFC. There was no fundamental
opposition and some minor comments are addressed in this patch I
believe.

To remind the original motivation, Tetsuo has noted that drain_all_pages
doesn't use WQ_RECLAIM [1] and asked whether we can move the worker to
the vmstat_wq which is WQ_RECLAIM. I think the deadlock he has described
shouldn't happen but it would be really better to have the rescuer. I
also think that we do not really need 2 or more workqueues and also pull
lru draining in.

[1] http://lkml.kernel.org/r/20170207210908.530-1-mhocko@kernel.org

 mm/internal.h   |  7 +++++++
 mm/page_alloc.c |  9 ++++++++-
 mm/swap.c       | 27 ++++++++-------------------
 mm/vmstat.c     | 14 ++++++++------
 4 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index 823a7a89099b..04d08ef91224 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -486,6 +486,13 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
 enum ttu_flags;
 struct tlbflush_unmap_batch;
 
+
+/*
+ * only for MM internal work items which do not depend on
+ * any allocations or locks which might depend on allocations
+ */
+extern struct workqueue_struct *mm_percpu_wq;
+
 #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
 void try_to_unmap_flush(void);
 void try_to_unmap_flush_dirty(void);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 1c72dd91c82e..1aa5729c8f98 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2362,6 +2362,13 @@ void drain_all_pages(struct zone *zone)
 	 */
 	static cpumask_t cpus_with_pcps;
 
+	/*
+	 * Make sure nobody triggers this path before mm_percpu_wq is fully
+	 * initialized.
+	 */
+	if (WARN_ON_ONCE(!mm_percpu_wq))
+		return;
+
 	/* Workqueues cannot recurse */
 	if (current->flags & PF_WQ_WORKER)
 		return;
@@ -2411,7 +2418,7 @@ void drain_all_pages(struct zone *zone)
 	for_each_cpu(cpu, &cpus_with_pcps) {
 		struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
 		INIT_WORK(work, drain_local_pages_wq);
-		schedule_work_on(cpu, work);
+		queue_work_on(cpu, mm_percpu_wq, work);
 	}
 	for_each_cpu(cpu, &cpus_with_pcps)
 		flush_work(per_cpu_ptr(&pcpu_drain, cpu));
diff --git a/mm/swap.c b/mm/swap.c
index ac98eb443a03..361bdb1575ab 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -677,30 +677,19 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
 
 static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
 
-/*
- * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
- * workqueue, aiding in getting memory freed.
- */
-static struct workqueue_struct *lru_add_drain_wq;
-
-static int __init lru_init(void)
-{
-	lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
-
-	if (WARN(!lru_add_drain_wq,
-		"Failed to create workqueue lru_add_drain_wq"))
-		return -ENOMEM;
-
-	return 0;
-}
-early_initcall(lru_init);
-
 void lru_add_drain_all(void)
 {
 	static DEFINE_MUTEX(lock);
 	static struct cpumask has_work;
 	int cpu;
 
+	/*
+	 * Make sure nobody triggers this path before mm_percpu_wq is fully
+	 * initialized.
+	 */
+	if (WARN_ON(!mm_percpu_wq))
+		return;
+
 	mutex_lock(&lock);
 	get_online_cpus();
 	cpumask_clear(&has_work);
@@ -714,7 +703,7 @@ void lru_add_drain_all(void)
 		    pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
 		    need_activate_page_drain(cpu)) {
 			INIT_WORK(work, lru_add_drain_per_cpu);
-			queue_work_on(cpu, lru_add_drain_wq, work);
+			queue_work_on(cpu, mm_percpu_wq, work);
 			cpumask_set_cpu(cpu, &has_work);
 		}
 	}
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 9557fc0f36a4..ff9c49c47f32 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1563,7 +1563,6 @@ static const struct file_operations proc_vmstat_file_operations = {
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SMP
-static struct workqueue_struct *vmstat_wq;
 static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
 int sysctl_stat_interval __read_mostly = HZ;
 
@@ -1621,7 +1620,7 @@ static void vmstat_update(struct work_struct *w)
 		 * to occur in the future. Keep on running the
 		 * update worker thread.
 		 */
-		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
+		queue_delayed_work_on(smp_processor_id(), mm_percpu_wq,
 				this_cpu_ptr(&vmstat_work),
 				round_jiffies_relative(sysctl_stat_interval));
 	}
@@ -1700,7 +1699,7 @@ static void vmstat_shepherd(struct work_struct *w)
 		struct delayed_work *dw = &per_cpu(vmstat_work, cpu);
 
 		if (!delayed_work_pending(dw) && need_update(cpu))
-			queue_delayed_work_on(cpu, vmstat_wq, dw, 0);
+			queue_delayed_work_on(cpu, mm_percpu_wq, dw, 0);
 	}
 	put_online_cpus();
 
@@ -1716,7 +1715,6 @@ static void __init start_shepherd_timer(void)
 		INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
 			vmstat_update);
 
-	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
 	schedule_delayed_work(&shepherd,
 		round_jiffies_relative(sysctl_stat_interval));
 }
@@ -1762,11 +1760,15 @@ static int vmstat_cpu_dead(unsigned int cpu)
 
 #endif
 
+struct workqueue_struct *mm_percpu_wq;
+
 static int __init setup_vmstat(void)
 {
-#ifdef CONFIG_SMP
-	int ret;
+	int ret __maybe_unused;
 
+	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+
+#ifdef CONFIG_SMP
 	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
 					NULL, vmstat_cpu_dead);
 	if (ret < 0)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-07 13:17 ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-07 13:17 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Tetsuo Handa, Vlastimil Babka, Mel Gorman, linux-mm, LKML, Michal Hocko

From: Michal Hocko <mhocko@suse.com>

We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
per cpu lru caches. This seems more than necessary because both can run
on a single WQ. Both do not block on locks requiring a memory allocation
nor perform any allocations themselves. We will save one rescuer thread
this way.

On the other hand drain_all_pages() queues work on the system wq which
doesn't have rescuer and so this depend on memory allocation (when all
workers are stuck allocating and new ones cannot be created). This is
not critical as there should be somebody invoking the OOM killer (e.g.
the forking worker) and get the situation unstuck and eventually
performs the draining. Quite annoying though. This worker should be
using WQ_RECLAIM as well. We can reuse the same one as for lru draining
and vmstat.

Changes since v1
- rename vmstat_wq to mm_percpu_wq - per Mel
- make sure we are not trying to enqueue anything while the WQ hasn't
  been intialized yet. This shouldn't happen because the initialization
  is done from an init code but some init section might be triggering
  those paths indirectly so just warn and skip the draining in that case
  per Vlastimil
- do not propagate error from setup_vmstat to keep the previous behavior
  per Mel

Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---

Hi,
this has been previous posted [1] as an RFC. There was no fundamental
opposition and some minor comments are addressed in this patch I
believe.

To remind the original motivation, Tetsuo has noted that drain_all_pages
doesn't use WQ_RECLAIM [1] and asked whether we can move the worker to
the vmstat_wq which is WQ_RECLAIM. I think the deadlock he has described
shouldn't happen but it would be really better to have the rescuer. I
also think that we do not really need 2 or more workqueues and also pull
lru draining in.

[1] http://lkml.kernel.org/r/20170207210908.530-1-mhocko@kernel.org

 mm/internal.h   |  7 +++++++
 mm/page_alloc.c |  9 ++++++++-
 mm/swap.c       | 27 ++++++++-------------------
 mm/vmstat.c     | 14 ++++++++------
 4 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index 823a7a89099b..04d08ef91224 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -486,6 +486,13 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
 enum ttu_flags;
 struct tlbflush_unmap_batch;
 
+
+/*
+ * only for MM internal work items which do not depend on
+ * any allocations or locks which might depend on allocations
+ */
+extern struct workqueue_struct *mm_percpu_wq;
+
 #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
 void try_to_unmap_flush(void);
 void try_to_unmap_flush_dirty(void);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 1c72dd91c82e..1aa5729c8f98 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2362,6 +2362,13 @@ void drain_all_pages(struct zone *zone)
 	 */
 	static cpumask_t cpus_with_pcps;
 
+	/*
+	 * Make sure nobody triggers this path before mm_percpu_wq is fully
+	 * initialized.
+	 */
+	if (WARN_ON_ONCE(!mm_percpu_wq))
+		return;
+
 	/* Workqueues cannot recurse */
 	if (current->flags & PF_WQ_WORKER)
 		return;
@@ -2411,7 +2418,7 @@ void drain_all_pages(struct zone *zone)
 	for_each_cpu(cpu, &cpus_with_pcps) {
 		struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
 		INIT_WORK(work, drain_local_pages_wq);
-		schedule_work_on(cpu, work);
+		queue_work_on(cpu, mm_percpu_wq, work);
 	}
 	for_each_cpu(cpu, &cpus_with_pcps)
 		flush_work(per_cpu_ptr(&pcpu_drain, cpu));
diff --git a/mm/swap.c b/mm/swap.c
index ac98eb443a03..361bdb1575ab 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -677,30 +677,19 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
 
 static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
 
-/*
- * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
- * workqueue, aiding in getting memory freed.
- */
-static struct workqueue_struct *lru_add_drain_wq;
-
-static int __init lru_init(void)
-{
-	lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
-
-	if (WARN(!lru_add_drain_wq,
-		"Failed to create workqueue lru_add_drain_wq"))
-		return -ENOMEM;
-
-	return 0;
-}
-early_initcall(lru_init);
-
 void lru_add_drain_all(void)
 {
 	static DEFINE_MUTEX(lock);
 	static struct cpumask has_work;
 	int cpu;
 
+	/*
+	 * Make sure nobody triggers this path before mm_percpu_wq is fully
+	 * initialized.
+	 */
+	if (WARN_ON(!mm_percpu_wq))
+		return;
+
 	mutex_lock(&lock);
 	get_online_cpus();
 	cpumask_clear(&has_work);
@@ -714,7 +703,7 @@ void lru_add_drain_all(void)
 		    pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
 		    need_activate_page_drain(cpu)) {
 			INIT_WORK(work, lru_add_drain_per_cpu);
-			queue_work_on(cpu, lru_add_drain_wq, work);
+			queue_work_on(cpu, mm_percpu_wq, work);
 			cpumask_set_cpu(cpu, &has_work);
 		}
 	}
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 9557fc0f36a4..ff9c49c47f32 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1563,7 +1563,6 @@ static const struct file_operations proc_vmstat_file_operations = {
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SMP
-static struct workqueue_struct *vmstat_wq;
 static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
 int sysctl_stat_interval __read_mostly = HZ;
 
@@ -1621,7 +1620,7 @@ static void vmstat_update(struct work_struct *w)
 		 * to occur in the future. Keep on running the
 		 * update worker thread.
 		 */
-		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
+		queue_delayed_work_on(smp_processor_id(), mm_percpu_wq,
 				this_cpu_ptr(&vmstat_work),
 				round_jiffies_relative(sysctl_stat_interval));
 	}
@@ -1700,7 +1699,7 @@ static void vmstat_shepherd(struct work_struct *w)
 		struct delayed_work *dw = &per_cpu(vmstat_work, cpu);
 
 		if (!delayed_work_pending(dw) && need_update(cpu))
-			queue_delayed_work_on(cpu, vmstat_wq, dw, 0);
+			queue_delayed_work_on(cpu, mm_percpu_wq, dw, 0);
 	}
 	put_online_cpus();
 
@@ -1716,7 +1715,6 @@ static void __init start_shepherd_timer(void)
 		INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
 			vmstat_update);
 
-	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
 	schedule_delayed_work(&shepherd,
 		round_jiffies_relative(sysctl_stat_interval));
 }
@@ -1762,11 +1760,15 @@ static int vmstat_cpu_dead(unsigned int cpu)
 
 #endif
 
+struct workqueue_struct *mm_percpu_wq;
+
 static int __init setup_vmstat(void)
 {
-#ifdef CONFIG_SMP
-	int ret;
+	int ret __maybe_unused;
 
+	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+
+#ifdef CONFIG_SMP
 	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
 					NULL, vmstat_cpu_dead);
 	if (ret < 0)
-- 
2.11.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-07 13:17 ` Michal Hocko
@ 2017-03-07 13:34   ` Vlastimil Babka
  -1 siblings, 0 replies; 29+ messages in thread
From: Vlastimil Babka @ 2017-03-07 13:34 UTC (permalink / raw)
  To: Michal Hocko, Andrew Morton
  Cc: Tetsuo Handa, Mel Gorman, linux-mm, LKML, Michal Hocko

On 03/07/2017 02:17 PM, Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
> 
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.
> 
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil
> - do not propagate error from setup_vmstat to keep the previous behavior
>   per Mel
> 
> Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Michal Hocko <mhocko@suse.com>

Acked-by: Vlastimil Babka <vbabka@suse.cz>

> ---
> 
> Hi,
> this has been previous posted [1] as an RFC. There was no fundamental
> opposition and some minor comments are addressed in this patch I
> believe.
> 
> To remind the original motivation, Tetsuo has noted that drain_all_pages
> doesn't use WQ_RECLAIM [1] and asked whether we can move the worker to
> the vmstat_wq which is WQ_RECLAIM. I think the deadlock he has described
> shouldn't happen but it would be really better to have the rescuer. I
> also think that we do not really need 2 or more workqueues and also pull
> lru draining in.
> 
> [1] http://lkml.kernel.org/r/20170207210908.530-1-mhocko@kernel.org
> 
>  mm/internal.h   |  7 +++++++
>  mm/page_alloc.c |  9 ++++++++-
>  mm/swap.c       | 27 ++++++++-------------------
>  mm/vmstat.c     | 14 ++++++++------
>  4 files changed, 31 insertions(+), 26 deletions(-)
> 
> diff --git a/mm/internal.h b/mm/internal.h
> index 823a7a89099b..04d08ef91224 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -486,6 +486,13 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
>  enum ttu_flags;
>  struct tlbflush_unmap_batch;
>  
> +
> +/*
> + * only for MM internal work items which do not depend on
> + * any allocations or locks which might depend on allocations
> + */
> +extern struct workqueue_struct *mm_percpu_wq;
> +
>  #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
>  void try_to_unmap_flush(void);
>  void try_to_unmap_flush_dirty(void);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 1c72dd91c82e..1aa5729c8f98 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -2362,6 +2362,13 @@ void drain_all_pages(struct zone *zone)
>  	 */
>  	static cpumask_t cpus_with_pcps;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON_ONCE(!mm_percpu_wq))
> +		return;
> +
>  	/* Workqueues cannot recurse */
>  	if (current->flags & PF_WQ_WORKER)
>  		return;
> @@ -2411,7 +2418,7 @@ void drain_all_pages(struct zone *zone)
>  	for_each_cpu(cpu, &cpus_with_pcps) {
>  		struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
>  		INIT_WORK(work, drain_local_pages_wq);
> -		schedule_work_on(cpu, work);
> +		queue_work_on(cpu, mm_percpu_wq, work);
>  	}
>  	for_each_cpu(cpu, &cpus_with_pcps)
>  		flush_work(per_cpu_ptr(&pcpu_drain, cpu));
> diff --git a/mm/swap.c b/mm/swap.c
> index ac98eb443a03..361bdb1575ab 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -677,30 +677,19 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
>  
>  static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
>  
> -/*
> - * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
> - * workqueue, aiding in getting memory freed.
> - */
> -static struct workqueue_struct *lru_add_drain_wq;
> -
> -static int __init lru_init(void)
> -{
> -	lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
> -
> -	if (WARN(!lru_add_drain_wq,
> -		"Failed to create workqueue lru_add_drain_wq"))
> -		return -ENOMEM;
> -
> -	return 0;
> -}
> -early_initcall(lru_init);
> -
>  void lru_add_drain_all(void)
>  {
>  	static DEFINE_MUTEX(lock);
>  	static struct cpumask has_work;
>  	int cpu;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON(!mm_percpu_wq))
> +		return;
> +
>  	mutex_lock(&lock);
>  	get_online_cpus();
>  	cpumask_clear(&has_work);
> @@ -714,7 +703,7 @@ void lru_add_drain_all(void)
>  		    pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
>  		    need_activate_page_drain(cpu)) {
>  			INIT_WORK(work, lru_add_drain_per_cpu);
> -			queue_work_on(cpu, lru_add_drain_wq, work);
> +			queue_work_on(cpu, mm_percpu_wq, work);
>  			cpumask_set_cpu(cpu, &has_work);
>  		}
>  	}
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 9557fc0f36a4..ff9c49c47f32 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1563,7 +1563,6 @@ static const struct file_operations proc_vmstat_file_operations = {
>  #endif /* CONFIG_PROC_FS */
>  
>  #ifdef CONFIG_SMP
> -static struct workqueue_struct *vmstat_wq;
>  static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
>  int sysctl_stat_interval __read_mostly = HZ;
>  
> @@ -1621,7 +1620,7 @@ static void vmstat_update(struct work_struct *w)
>  		 * to occur in the future. Keep on running the
>  		 * update worker thread.
>  		 */
> -		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
> +		queue_delayed_work_on(smp_processor_id(), mm_percpu_wq,
>  				this_cpu_ptr(&vmstat_work),
>  				round_jiffies_relative(sysctl_stat_interval));
>  	}
> @@ -1700,7 +1699,7 @@ static void vmstat_shepherd(struct work_struct *w)
>  		struct delayed_work *dw = &per_cpu(vmstat_work, cpu);
>  
>  		if (!delayed_work_pending(dw) && need_update(cpu))
> -			queue_delayed_work_on(cpu, vmstat_wq, dw, 0);
> +			queue_delayed_work_on(cpu, mm_percpu_wq, dw, 0);
>  	}
>  	put_online_cpus();
>  
> @@ -1716,7 +1715,6 @@ static void __init start_shepherd_timer(void)
>  		INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
>  			vmstat_update);
>  
> -	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
>  	schedule_delayed_work(&shepherd,
>  		round_jiffies_relative(sysctl_stat_interval));
>  }
> @@ -1762,11 +1760,15 @@ static int vmstat_cpu_dead(unsigned int cpu)
>  
>  #endif
>  
> +struct workqueue_struct *mm_percpu_wq;
> +
>  static int __init setup_vmstat(void)
>  {
> -#ifdef CONFIG_SMP
> -	int ret;
> +	int ret __maybe_unused;
>  
> +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> +
> +#ifdef CONFIG_SMP
>  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
>  					NULL, vmstat_cpu_dead);
>  	if (ret < 0)
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-07 13:34   ` Vlastimil Babka
  0 siblings, 0 replies; 29+ messages in thread
From: Vlastimil Babka @ 2017-03-07 13:34 UTC (permalink / raw)
  To: Michal Hocko, Andrew Morton
  Cc: Tetsuo Handa, Mel Gorman, linux-mm, LKML, Michal Hocko

On 03/07/2017 02:17 PM, Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
> 
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.
> 
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil
> - do not propagate error from setup_vmstat to keep the previous behavior
>   per Mel
> 
> Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Michal Hocko <mhocko@suse.com>

Acked-by: Vlastimil Babka <vbabka@suse.cz>

> ---
> 
> Hi,
> this has been previous posted [1] as an RFC. There was no fundamental
> opposition and some minor comments are addressed in this patch I
> believe.
> 
> To remind the original motivation, Tetsuo has noted that drain_all_pages
> doesn't use WQ_RECLAIM [1] and asked whether we can move the worker to
> the vmstat_wq which is WQ_RECLAIM. I think the deadlock he has described
> shouldn't happen but it would be really better to have the rescuer. I
> also think that we do not really need 2 or more workqueues and also pull
> lru draining in.
> 
> [1] http://lkml.kernel.org/r/20170207210908.530-1-mhocko@kernel.org
> 
>  mm/internal.h   |  7 +++++++
>  mm/page_alloc.c |  9 ++++++++-
>  mm/swap.c       | 27 ++++++++-------------------
>  mm/vmstat.c     | 14 ++++++++------
>  4 files changed, 31 insertions(+), 26 deletions(-)
> 
> diff --git a/mm/internal.h b/mm/internal.h
> index 823a7a89099b..04d08ef91224 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -486,6 +486,13 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
>  enum ttu_flags;
>  struct tlbflush_unmap_batch;
>  
> +
> +/*
> + * only for MM internal work items which do not depend on
> + * any allocations or locks which might depend on allocations
> + */
> +extern struct workqueue_struct *mm_percpu_wq;
> +
>  #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
>  void try_to_unmap_flush(void);
>  void try_to_unmap_flush_dirty(void);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 1c72dd91c82e..1aa5729c8f98 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -2362,6 +2362,13 @@ void drain_all_pages(struct zone *zone)
>  	 */
>  	static cpumask_t cpus_with_pcps;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON_ONCE(!mm_percpu_wq))
> +		return;
> +
>  	/* Workqueues cannot recurse */
>  	if (current->flags & PF_WQ_WORKER)
>  		return;
> @@ -2411,7 +2418,7 @@ void drain_all_pages(struct zone *zone)
>  	for_each_cpu(cpu, &cpus_with_pcps) {
>  		struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
>  		INIT_WORK(work, drain_local_pages_wq);
> -		schedule_work_on(cpu, work);
> +		queue_work_on(cpu, mm_percpu_wq, work);
>  	}
>  	for_each_cpu(cpu, &cpus_with_pcps)
>  		flush_work(per_cpu_ptr(&pcpu_drain, cpu));
> diff --git a/mm/swap.c b/mm/swap.c
> index ac98eb443a03..361bdb1575ab 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -677,30 +677,19 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
>  
>  static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
>  
> -/*
> - * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
> - * workqueue, aiding in getting memory freed.
> - */
> -static struct workqueue_struct *lru_add_drain_wq;
> -
> -static int __init lru_init(void)
> -{
> -	lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
> -
> -	if (WARN(!lru_add_drain_wq,
> -		"Failed to create workqueue lru_add_drain_wq"))
> -		return -ENOMEM;
> -
> -	return 0;
> -}
> -early_initcall(lru_init);
> -
>  void lru_add_drain_all(void)
>  {
>  	static DEFINE_MUTEX(lock);
>  	static struct cpumask has_work;
>  	int cpu;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON(!mm_percpu_wq))
> +		return;
> +
>  	mutex_lock(&lock);
>  	get_online_cpus();
>  	cpumask_clear(&has_work);
> @@ -714,7 +703,7 @@ void lru_add_drain_all(void)
>  		    pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
>  		    need_activate_page_drain(cpu)) {
>  			INIT_WORK(work, lru_add_drain_per_cpu);
> -			queue_work_on(cpu, lru_add_drain_wq, work);
> +			queue_work_on(cpu, mm_percpu_wq, work);
>  			cpumask_set_cpu(cpu, &has_work);
>  		}
>  	}
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 9557fc0f36a4..ff9c49c47f32 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1563,7 +1563,6 @@ static const struct file_operations proc_vmstat_file_operations = {
>  #endif /* CONFIG_PROC_FS */
>  
>  #ifdef CONFIG_SMP
> -static struct workqueue_struct *vmstat_wq;
>  static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
>  int sysctl_stat_interval __read_mostly = HZ;
>  
> @@ -1621,7 +1620,7 @@ static void vmstat_update(struct work_struct *w)
>  		 * to occur in the future. Keep on running the
>  		 * update worker thread.
>  		 */
> -		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
> +		queue_delayed_work_on(smp_processor_id(), mm_percpu_wq,
>  				this_cpu_ptr(&vmstat_work),
>  				round_jiffies_relative(sysctl_stat_interval));
>  	}
> @@ -1700,7 +1699,7 @@ static void vmstat_shepherd(struct work_struct *w)
>  		struct delayed_work *dw = &per_cpu(vmstat_work, cpu);
>  
>  		if (!delayed_work_pending(dw) && need_update(cpu))
> -			queue_delayed_work_on(cpu, vmstat_wq, dw, 0);
> +			queue_delayed_work_on(cpu, mm_percpu_wq, dw, 0);
>  	}
>  	put_online_cpus();
>  
> @@ -1716,7 +1715,6 @@ static void __init start_shepherd_timer(void)
>  		INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
>  			vmstat_update);
>  
> -	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
>  	schedule_delayed_work(&shepherd,
>  		round_jiffies_relative(sysctl_stat_interval));
>  }
> @@ -1762,11 +1760,15 @@ static int vmstat_cpu_dead(unsigned int cpu)
>  
>  #endif
>  
> +struct workqueue_struct *mm_percpu_wq;
> +
>  static int __init setup_vmstat(void)
>  {
> -#ifdef CONFIG_SMP
> -	int ret;
> +	int ret __maybe_unused;
>  
> +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> +
> +#ifdef CONFIG_SMP
>  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
>  					NULL, vmstat_cpu_dead);
>  	if (ret < 0)
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-07 13:17 ` Michal Hocko
@ 2017-03-07 13:50   ` Tetsuo Handa
  -1 siblings, 0 replies; 29+ messages in thread
From: Tetsuo Handa @ 2017-03-07 13:50 UTC (permalink / raw)
  To: mhocko, akpm; +Cc: vbabka, mgorman, linux-mm, linux-kernel, mhocko

Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
> 
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.

Is "there should be somebody invoking the OOM killer" really true?
According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp

  kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
  workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.

__GFP_FS allocations could get stuck waiting for drain_all_pages() ?
Also, order > 0 allocation request by the forking worker could get stuck
at too_many_isolated() in mm/compaction.c ?

> 
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil
> - do not propagate error from setup_vmstat to keep the previous behavior
>   per Mel
> 
> Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> ---
> 
> Hi,
> this has been previous posted [1] as an RFC. There was no fundamental
> opposition and some minor comments are addressed in this patch I
> believe.
> 
> To remind the original motivation, Tetsuo has noted that drain_all_pages
> doesn't use WQ_RECLAIM [1] and asked whether we can move the worker to
> the vmstat_wq which is WQ_RECLAIM. I think the deadlock he has described
> shouldn't happen but it would be really better to have the rescuer. I
> also think that we do not really need 2 or more workqueues and also pull
> lru draining in.
> 
> [1] http://lkml.kernel.org/r/20170207210908.530-1-mhocko@kernel.org
> 
>  mm/internal.h   |  7 +++++++
>  mm/page_alloc.c |  9 ++++++++-
>  mm/swap.c       | 27 ++++++++-------------------
>  mm/vmstat.c     | 14 ++++++++------
>  4 files changed, 31 insertions(+), 26 deletions(-)
> 
> diff --git a/mm/internal.h b/mm/internal.h
> index 823a7a89099b..04d08ef91224 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -486,6 +486,13 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
>  enum ttu_flags;
>  struct tlbflush_unmap_batch;
>  
> +
> +/*
> + * only for MM internal work items which do not depend on
> + * any allocations or locks which might depend on allocations
> + */
> +extern struct workqueue_struct *mm_percpu_wq;
> +
>  #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
>  void try_to_unmap_flush(void);
>  void try_to_unmap_flush_dirty(void);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 1c72dd91c82e..1aa5729c8f98 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -2362,6 +2362,13 @@ void drain_all_pages(struct zone *zone)
>  	 */
>  	static cpumask_t cpus_with_pcps;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON_ONCE(!mm_percpu_wq))
> +		return;
> +
>  	/* Workqueues cannot recurse */
>  	if (current->flags & PF_WQ_WORKER)
>  		return;
> @@ -2411,7 +2418,7 @@ void drain_all_pages(struct zone *zone)
>  	for_each_cpu(cpu, &cpus_with_pcps) {
>  		struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
>  		INIT_WORK(work, drain_local_pages_wq);
> -		schedule_work_on(cpu, work);
> +		queue_work_on(cpu, mm_percpu_wq, work);
>  	}
>  	for_each_cpu(cpu, &cpus_with_pcps)
>  		flush_work(per_cpu_ptr(&pcpu_drain, cpu));
> diff --git a/mm/swap.c b/mm/swap.c
> index ac98eb443a03..361bdb1575ab 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -677,30 +677,19 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
>  
>  static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
>  
> -/*
> - * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
> - * workqueue, aiding in getting memory freed.
> - */
> -static struct workqueue_struct *lru_add_drain_wq;
> -
> -static int __init lru_init(void)
> -{
> -	lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
> -
> -	if (WARN(!lru_add_drain_wq,
> -		"Failed to create workqueue lru_add_drain_wq"))
> -		return -ENOMEM;
> -
> -	return 0;
> -}
> -early_initcall(lru_init);
> -
>  void lru_add_drain_all(void)
>  {
>  	static DEFINE_MUTEX(lock);
>  	static struct cpumask has_work;
>  	int cpu;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON(!mm_percpu_wq))
> +		return;
> +
>  	mutex_lock(&lock);
>  	get_online_cpus();
>  	cpumask_clear(&has_work);
> @@ -714,7 +703,7 @@ void lru_add_drain_all(void)
>  		    pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
>  		    need_activate_page_drain(cpu)) {
>  			INIT_WORK(work, lru_add_drain_per_cpu);
> -			queue_work_on(cpu, lru_add_drain_wq, work);
> +			queue_work_on(cpu, mm_percpu_wq, work);
>  			cpumask_set_cpu(cpu, &has_work);
>  		}
>  	}
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 9557fc0f36a4..ff9c49c47f32 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1563,7 +1563,6 @@ static const struct file_operations proc_vmstat_file_operations = {
>  #endif /* CONFIG_PROC_FS */
>  
>  #ifdef CONFIG_SMP
> -static struct workqueue_struct *vmstat_wq;
>  static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
>  int sysctl_stat_interval __read_mostly = HZ;
>  
> @@ -1621,7 +1620,7 @@ static void vmstat_update(struct work_struct *w)
>  		 * to occur in the future. Keep on running the
>  		 * update worker thread.
>  		 */
> -		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
> +		queue_delayed_work_on(smp_processor_id(), mm_percpu_wq,
>  				this_cpu_ptr(&vmstat_work),
>  				round_jiffies_relative(sysctl_stat_interval));
>  	}
> @@ -1700,7 +1699,7 @@ static void vmstat_shepherd(struct work_struct *w)
>  		struct delayed_work *dw = &per_cpu(vmstat_work, cpu);
>  
>  		if (!delayed_work_pending(dw) && need_update(cpu))
> -			queue_delayed_work_on(cpu, vmstat_wq, dw, 0);
> +			queue_delayed_work_on(cpu, mm_percpu_wq, dw, 0);
>  	}
>  	put_online_cpus();
>  
> @@ -1716,7 +1715,6 @@ static void __init start_shepherd_timer(void)
>  		INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
>  			vmstat_update);
>  
> -	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
>  	schedule_delayed_work(&shepherd,
>  		round_jiffies_relative(sysctl_stat_interval));
>  }
> @@ -1762,11 +1760,15 @@ static int vmstat_cpu_dead(unsigned int cpu)
>  
>  #endif
>  
> +struct workqueue_struct *mm_percpu_wq;
> +
>  static int __init setup_vmstat(void)
>  {
> -#ifdef CONFIG_SMP
> -	int ret;
> +	int ret __maybe_unused;
>  
> +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> +
> +#ifdef CONFIG_SMP
>  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
>  					NULL, vmstat_cpu_dead);
>  	if (ret < 0)
> -- 
> 2.11.0
> 
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-07 13:50   ` Tetsuo Handa
  0 siblings, 0 replies; 29+ messages in thread
From: Tetsuo Handa @ 2017-03-07 13:50 UTC (permalink / raw)
  To: mhocko, akpm; +Cc: vbabka, mgorman, linux-mm, linux-kernel, mhocko

Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
> 
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.

Is "there should be somebody invoking the OOM killer" really true?
According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp

  kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
  workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.

__GFP_FS allocations could get stuck waiting for drain_all_pages() ?
Also, order > 0 allocation request by the forking worker could get stuck
at too_many_isolated() in mm/compaction.c ?

> 
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil
> - do not propagate error from setup_vmstat to keep the previous behavior
>   per Mel
> 
> Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> ---
> 
> Hi,
> this has been previous posted [1] as an RFC. There was no fundamental
> opposition and some minor comments are addressed in this patch I
> believe.
> 
> To remind the original motivation, Tetsuo has noted that drain_all_pages
> doesn't use WQ_RECLAIM [1] and asked whether we can move the worker to
> the vmstat_wq which is WQ_RECLAIM. I think the deadlock he has described
> shouldn't happen but it would be really better to have the rescuer. I
> also think that we do not really need 2 or more workqueues and also pull
> lru draining in.
> 
> [1] http://lkml.kernel.org/r/20170207210908.530-1-mhocko@kernel.org
> 
>  mm/internal.h   |  7 +++++++
>  mm/page_alloc.c |  9 ++++++++-
>  mm/swap.c       | 27 ++++++++-------------------
>  mm/vmstat.c     | 14 ++++++++------
>  4 files changed, 31 insertions(+), 26 deletions(-)
> 
> diff --git a/mm/internal.h b/mm/internal.h
> index 823a7a89099b..04d08ef91224 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -486,6 +486,13 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
>  enum ttu_flags;
>  struct tlbflush_unmap_batch;
>  
> +
> +/*
> + * only for MM internal work items which do not depend on
> + * any allocations or locks which might depend on allocations
> + */
> +extern struct workqueue_struct *mm_percpu_wq;
> +
>  #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
>  void try_to_unmap_flush(void);
>  void try_to_unmap_flush_dirty(void);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 1c72dd91c82e..1aa5729c8f98 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -2362,6 +2362,13 @@ void drain_all_pages(struct zone *zone)
>  	 */
>  	static cpumask_t cpus_with_pcps;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON_ONCE(!mm_percpu_wq))
> +		return;
> +
>  	/* Workqueues cannot recurse */
>  	if (current->flags & PF_WQ_WORKER)
>  		return;
> @@ -2411,7 +2418,7 @@ void drain_all_pages(struct zone *zone)
>  	for_each_cpu(cpu, &cpus_with_pcps) {
>  		struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
>  		INIT_WORK(work, drain_local_pages_wq);
> -		schedule_work_on(cpu, work);
> +		queue_work_on(cpu, mm_percpu_wq, work);
>  	}
>  	for_each_cpu(cpu, &cpus_with_pcps)
>  		flush_work(per_cpu_ptr(&pcpu_drain, cpu));
> diff --git a/mm/swap.c b/mm/swap.c
> index ac98eb443a03..361bdb1575ab 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -677,30 +677,19 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
>  
>  static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
>  
> -/*
> - * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
> - * workqueue, aiding in getting memory freed.
> - */
> -static struct workqueue_struct *lru_add_drain_wq;
> -
> -static int __init lru_init(void)
> -{
> -	lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
> -
> -	if (WARN(!lru_add_drain_wq,
> -		"Failed to create workqueue lru_add_drain_wq"))
> -		return -ENOMEM;
> -
> -	return 0;
> -}
> -early_initcall(lru_init);
> -
>  void lru_add_drain_all(void)
>  {
>  	static DEFINE_MUTEX(lock);
>  	static struct cpumask has_work;
>  	int cpu;
>  
> +	/*
> +	 * Make sure nobody triggers this path before mm_percpu_wq is fully
> +	 * initialized.
> +	 */
> +	if (WARN_ON(!mm_percpu_wq))
> +		return;
> +
>  	mutex_lock(&lock);
>  	get_online_cpus();
>  	cpumask_clear(&has_work);
> @@ -714,7 +703,7 @@ void lru_add_drain_all(void)
>  		    pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
>  		    need_activate_page_drain(cpu)) {
>  			INIT_WORK(work, lru_add_drain_per_cpu);
> -			queue_work_on(cpu, lru_add_drain_wq, work);
> +			queue_work_on(cpu, mm_percpu_wq, work);
>  			cpumask_set_cpu(cpu, &has_work);
>  		}
>  	}
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 9557fc0f36a4..ff9c49c47f32 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1563,7 +1563,6 @@ static const struct file_operations proc_vmstat_file_operations = {
>  #endif /* CONFIG_PROC_FS */
>  
>  #ifdef CONFIG_SMP
> -static struct workqueue_struct *vmstat_wq;
>  static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
>  int sysctl_stat_interval __read_mostly = HZ;
>  
> @@ -1621,7 +1620,7 @@ static void vmstat_update(struct work_struct *w)
>  		 * to occur in the future. Keep on running the
>  		 * update worker thread.
>  		 */
> -		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
> +		queue_delayed_work_on(smp_processor_id(), mm_percpu_wq,
>  				this_cpu_ptr(&vmstat_work),
>  				round_jiffies_relative(sysctl_stat_interval));
>  	}
> @@ -1700,7 +1699,7 @@ static void vmstat_shepherd(struct work_struct *w)
>  		struct delayed_work *dw = &per_cpu(vmstat_work, cpu);
>  
>  		if (!delayed_work_pending(dw) && need_update(cpu))
> -			queue_delayed_work_on(cpu, vmstat_wq, dw, 0);
> +			queue_delayed_work_on(cpu, mm_percpu_wq, dw, 0);
>  	}
>  	put_online_cpus();
>  
> @@ -1716,7 +1715,6 @@ static void __init start_shepherd_timer(void)
>  		INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu),
>  			vmstat_update);
>  
> -	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
>  	schedule_delayed_work(&shepherd,
>  		round_jiffies_relative(sysctl_stat_interval));
>  }
> @@ -1762,11 +1760,15 @@ static int vmstat_cpu_dead(unsigned int cpu)
>  
>  #endif
>  
> +struct workqueue_struct *mm_percpu_wq;
> +
>  static int __init setup_vmstat(void)
>  {
> -#ifdef CONFIG_SMP
> -	int ret;
> +	int ret __maybe_unused;
>  
> +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> +
> +#ifdef CONFIG_SMP
>  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
>  					NULL, vmstat_cpu_dead);
>  	if (ret < 0)
> -- 
> 2.11.0
> 
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-07 13:50   ` Tetsuo Handa
@ 2017-03-07 14:23     ` Michal Hocko
  -1 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-07 14:23 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: akpm, vbabka, mgorman, linux-mm, linux-kernel

On Tue 07-03-17 22:50:48, Tetsuo Handa wrote:
> Michal Hocko wrote:
> > From: Michal Hocko <mhocko@suse.com>
> > 
> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > per cpu lru caches. This seems more than necessary because both can run
> > on a single WQ. Both do not block on locks requiring a memory allocation
> > nor perform any allocations themselves. We will save one rescuer thread
> > this way.
> > 
> > On the other hand drain_all_pages() queues work on the system wq which
> > doesn't have rescuer and so this depend on memory allocation (when all
> > workers are stuck allocating and new ones cannot be created). This is
> > not critical as there should be somebody invoking the OOM killer (e.g.
> > the forking worker) and get the situation unstuck and eventually
> > performs the draining. Quite annoying though. This worker should be
> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > and vmstat.
> 
> Is "there should be somebody invoking the OOM killer" really true?

in most cases there should be... I didn't say there will be...

> According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp
> 
>   kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
>   workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.
> 
> __GFP_FS allocations could get stuck waiting for drain_all_pages() ?
> Also, order > 0 allocation request by the forking worker could get stuck
> at too_many_isolated() in mm/compaction.c ?

There might be some extreme cases which however do not change the
justification of this patch. I didn't see such cases reported anywhere
- other than in your stress testing where we do not really know what is
going on yet - and so I didn't mention them and nor I have marked the
patch for stable.

I am wondering what is the point of this feedback actually? Do you
see anything wrong in the patch or is this about the wording of the
changelog? If it is the later is your concern serious enough to warrant
the rewording/reposting?
-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-07 14:23     ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-07 14:23 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: akpm, vbabka, mgorman, linux-mm, linux-kernel

On Tue 07-03-17 22:50:48, Tetsuo Handa wrote:
> Michal Hocko wrote:
> > From: Michal Hocko <mhocko@suse.com>
> > 
> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > per cpu lru caches. This seems more than necessary because both can run
> > on a single WQ. Both do not block on locks requiring a memory allocation
> > nor perform any allocations themselves. We will save one rescuer thread
> > this way.
> > 
> > On the other hand drain_all_pages() queues work on the system wq which
> > doesn't have rescuer and so this depend on memory allocation (when all
> > workers are stuck allocating and new ones cannot be created). This is
> > not critical as there should be somebody invoking the OOM killer (e.g.
> > the forking worker) and get the situation unstuck and eventually
> > performs the draining. Quite annoying though. This worker should be
> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > and vmstat.
> 
> Is "there should be somebody invoking the OOM killer" really true?

in most cases there should be... I didn't say there will be...

> According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp
> 
>   kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
>   workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.
> 
> __GFP_FS allocations could get stuck waiting for drain_all_pages() ?
> Also, order > 0 allocation request by the forking worker could get stuck
> at too_many_isolated() in mm/compaction.c ?

There might be some extreme cases which however do not change the
justification of this patch. I didn't see such cases reported anywhere
- other than in your stress testing where we do not really know what is
going on yet - and so I didn't mention them and nor I have marked the
patch for stable.

I am wondering what is the point of this feedback actually? Do you
see anything wrong in the patch or is this about the wording of the
changelog? If it is the later is your concern serious enough to warrant
the rewording/reposting?
-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-07 14:23     ` Michal Hocko
@ 2017-03-08 11:50       ` Tetsuo Handa
  -1 siblings, 0 replies; 29+ messages in thread
From: Tetsuo Handa @ 2017-03-08 11:50 UTC (permalink / raw)
  To: mhocko; +Cc: akpm, vbabka, mgorman, linux-mm, linux-kernel

Michal Hocko wrote:
> On Tue 07-03-17 22:50:48, Tetsuo Handa wrote:
> > Michal Hocko wrote:
> > > From: Michal Hocko <mhocko@suse.com>
> > > 
> > > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > > per cpu lru caches. This seems more than necessary because both can run
> > > on a single WQ. Both do not block on locks requiring a memory allocation
> > > nor perform any allocations themselves. We will save one rescuer thread
> > > this way.
> > > 
> > > On the other hand drain_all_pages() queues work on the system wq which
> > > doesn't have rescuer and so this depend on memory allocation (when all
> > > workers are stuck allocating and new ones cannot be created). This is
> > > not critical as there should be somebody invoking the OOM killer (e.g.
> > > the forking worker) and get the situation unstuck and eventually
> > > performs the draining. Quite annoying though. This worker should be
> > > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > > and vmstat.
> > 
> > Is "there should be somebody invoking the OOM killer" really true?
> 
> in most cases there should be... I didn't say there will be...

It can become critical if there is nobody who can invoke the OOM killer.

> 
> > According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp
> > 
> >   kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
> >   workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.
> > 
> > __GFP_FS allocations could get stuck waiting for drain_all_pages() ?
> > Also, order > 0 allocation request by the forking worker could get stuck
> > at too_many_isolated() in mm/compaction.c ?
> 
> There might be some extreme cases which however do not change the
> justification of this patch. I didn't see such cases reported anywhere
> - other than in your stress testing where we do not really know what is
> going on yet - and so I didn't mention them and nor I have marked the
> patch for stable.

As shown in my stress testing, warn_alloc() is not powerful enough when
something we did not imagine happens.

> 
> I am wondering what is the point of this feedback actually? Do you
> see anything wrong in the patch or is this about the wording of the
> changelog? If it is the later is your concern serious enough to warrant
> the rewording/reposting?

I don't see anything wrong in the patch. I just thought

  This is not critical as there should be somebody invoking the OOM killer
  (e.g. the forking worker) and get the situation unstuck and eventually
  performs the draining. Quite annoying though.

part can be dropped because there is no guarantee that something we do not
imagine won't happen.

> -- 
> Michal Hocko
> SUSE Labs
> 

After applying this patch, we might be able to replace

        if (unlikely(!mutex_trylock(&pcpu_drain_mutex))) {
                if (!zone)
                        return;
                mutex_lock(&pcpu_drain_mutex);
        }

with

        if (mutex_lock_killable(&pcpu_drain_mutex))
		return;

because forward progress will be guaranteed by this patch and
we can favor pcpu_drain_mutex owner to use other CPU's time for
flushing queued works when many other allocating threads are
almost busy looping.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-08 11:50       ` Tetsuo Handa
  0 siblings, 0 replies; 29+ messages in thread
From: Tetsuo Handa @ 2017-03-08 11:50 UTC (permalink / raw)
  To: mhocko; +Cc: akpm, vbabka, mgorman, linux-mm, linux-kernel

Michal Hocko wrote:
> On Tue 07-03-17 22:50:48, Tetsuo Handa wrote:
> > Michal Hocko wrote:
> > > From: Michal Hocko <mhocko@suse.com>
> > > 
> > > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > > per cpu lru caches. This seems more than necessary because both can run
> > > on a single WQ. Both do not block on locks requiring a memory allocation
> > > nor perform any allocations themselves. We will save one rescuer thread
> > > this way.
> > > 
> > > On the other hand drain_all_pages() queues work on the system wq which
> > > doesn't have rescuer and so this depend on memory allocation (when all
> > > workers are stuck allocating and new ones cannot be created). This is
> > > not critical as there should be somebody invoking the OOM killer (e.g.
> > > the forking worker) and get the situation unstuck and eventually
> > > performs the draining. Quite annoying though. This worker should be
> > > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > > and vmstat.
> > 
> > Is "there should be somebody invoking the OOM killer" really true?
> 
> in most cases there should be... I didn't say there will be...

It can become critical if there is nobody who can invoke the OOM killer.

> 
> > According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp
> > 
> >   kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
> >   workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.
> > 
> > __GFP_FS allocations could get stuck waiting for drain_all_pages() ?
> > Also, order > 0 allocation request by the forking worker could get stuck
> > at too_many_isolated() in mm/compaction.c ?
> 
> There might be some extreme cases which however do not change the
> justification of this patch. I didn't see such cases reported anywhere
> - other than in your stress testing where we do not really know what is
> going on yet - and so I didn't mention them and nor I have marked the
> patch for stable.

As shown in my stress testing, warn_alloc() is not powerful enough when
something we did not imagine happens.

> 
> I am wondering what is the point of this feedback actually? Do you
> see anything wrong in the patch or is this about the wording of the
> changelog? If it is the later is your concern serious enough to warrant
> the rewording/reposting?

I don't see anything wrong in the patch. I just thought

  This is not critical as there should be somebody invoking the OOM killer
  (e.g. the forking worker) and get the situation unstuck and eventually
  performs the draining. Quite annoying though.

part can be dropped because there is no guarantee that something we do not
imagine won't happen.

> -- 
> Michal Hocko
> SUSE Labs
> 

After applying this patch, we might be able to replace

        if (unlikely(!mutex_trylock(&pcpu_drain_mutex))) {
                if (!zone)
                        return;
                mutex_lock(&pcpu_drain_mutex);
        }

with

        if (mutex_lock_killable(&pcpu_drain_mutex))
		return;

because forward progress will be guaranteed by this patch and
we can favor pcpu_drain_mutex owner to use other CPU's time for
flushing queued works when many other allocating threads are
almost busy looping.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-08 11:50       ` Tetsuo Handa
@ 2017-03-08 13:01         ` Michal Hocko
  -1 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-08 13:01 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: akpm, vbabka, mgorman, linux-mm, linux-kernel

On Wed 08-03-17 20:50:45, Tetsuo Handa wrote:
> Michal Hocko wrote:
> > On Tue 07-03-17 22:50:48, Tetsuo Handa wrote:
> > > Michal Hocko wrote:
> > > > From: Michal Hocko <mhocko@suse.com>
> > > > 
> > > > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > > > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > > > per cpu lru caches. This seems more than necessary because both can run
> > > > on a single WQ. Both do not block on locks requiring a memory allocation
> > > > nor perform any allocations themselves. We will save one rescuer thread
> > > > this way.
> > > > 
> > > > On the other hand drain_all_pages() queues work on the system wq which
> > > > doesn't have rescuer and so this depend on memory allocation (when all
> > > > workers are stuck allocating and new ones cannot be created). This is
> > > > not critical as there should be somebody invoking the OOM killer (e.g.
> > > > the forking worker) and get the situation unstuck and eventually
> > > > performs the draining. Quite annoying though. This worker should be
> > > > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > > > and vmstat.
> > > 
> > > Is "there should be somebody invoking the OOM killer" really true?
> > 
> > in most cases there should be... I didn't say there will be...
> 
> It can become critical if there is nobody who can invoke the OOM killer.

I am not aware of any "real life" bug report that would make this
critical and worth backporting to stable trees and what not.

> > > According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp
> > > 
> > >   kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
> > >   workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.
> > > 
> > > __GFP_FS allocations could get stuck waiting for drain_all_pages() ?
> > > Also, order > 0 allocation request by the forking worker could get stuck
> > > at too_many_isolated() in mm/compaction.c ?
> > 
> > There might be some extreme cases which however do not change the
> > justification of this patch. I didn't see such cases reported anywhere
> > - other than in your stress testing where we do not really know what is
> > going on yet - and so I didn't mention them and nor I have marked the
> > patch for stable.
> 
> As shown in my stress testing, warn_alloc() is not powerful enough when
> something we did not imagine happens.

yes, your stress testing is hitting many corner cases and it is good to
deal with them long term but that doesn't mean normal workloads should
be too stressed about backporting this patch because it is not very
likely they would ever hit a problem here.
 
> > I am wondering what is the point of this feedback actually? Do you
> > see anything wrong in the patch or is this about the wording of the
> > changelog? If it is the later is your concern serious enough to warrant
> > the rewording/reposting?
> 
> I don't see anything wrong in the patch. I just thought

OK
 
>   This is not critical as there should be somebody invoking the OOM killer
>   (e.g. the forking worker) and get the situation unstuck and eventually
>   performs the draining. Quite annoying though.
> 
> part can be dropped because there is no guarantee that something we do not
> imagine won't happen.

I do not consider "something we do not imagine won't happen" as critical
enough. And the changelog tries to be explicit about the expectations
and argues why people do not have to be scared and automatically
backport it because it is urgent.

> After applying this patch, we might be able to replace
> 
>         if (unlikely(!mutex_trylock(&pcpu_drain_mutex))) {
>                 if (!zone)
>                         return;
>                 mutex_lock(&pcpu_drain_mutex);
>         }
> 
> with
> 
>         if (mutex_lock_killable(&pcpu_drain_mutex))
> 		return;
> 
> because forward progress will be guaranteed by this patch and
> we can favor pcpu_drain_mutex owner to use other CPU's time for
> flushing queued works when many other allocating threads are
> almost busy looping.

But we do not really want to make this synchronous, I believe. Not with
a proper justification numbers.

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-08 13:01         ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-08 13:01 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: akpm, vbabka, mgorman, linux-mm, linux-kernel

On Wed 08-03-17 20:50:45, Tetsuo Handa wrote:
> Michal Hocko wrote:
> > On Tue 07-03-17 22:50:48, Tetsuo Handa wrote:
> > > Michal Hocko wrote:
> > > > From: Michal Hocko <mhocko@suse.com>
> > > > 
> > > > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > > > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > > > per cpu lru caches. This seems more than necessary because both can run
> > > > on a single WQ. Both do not block on locks requiring a memory allocation
> > > > nor perform any allocations themselves. We will save one rescuer thread
> > > > this way.
> > > > 
> > > > On the other hand drain_all_pages() queues work on the system wq which
> > > > doesn't have rescuer and so this depend on memory allocation (when all
> > > > workers are stuck allocating and new ones cannot be created). This is
> > > > not critical as there should be somebody invoking the OOM killer (e.g.
> > > > the forking worker) and get the situation unstuck and eventually
> > > > performs the draining. Quite annoying though. This worker should be
> > > > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > > > and vmstat.
> > > 
> > > Is "there should be somebody invoking the OOM killer" really true?
> > 
> > in most cases there should be... I didn't say there will be...
> 
> It can become critical if there is nobody who can invoke the OOM killer.

I am not aware of any "real life" bug report that would make this
critical and worth backporting to stable trees and what not.

> > > According to http://lkml.kernel.org/r/201703031948.CHJ81278.VOHSFFFOOLJQMt@I-love.SAKURA.ne.jp
> > > 
> > >   kthreadd (PID = 2) is trying to allocate "struct task_struct" requested by
> > >   workqueue managers (PID = 19, 157, 10499) but is blocked on memory allocation.
> > > 
> > > __GFP_FS allocations could get stuck waiting for drain_all_pages() ?
> > > Also, order > 0 allocation request by the forking worker could get stuck
> > > at too_many_isolated() in mm/compaction.c ?
> > 
> > There might be some extreme cases which however do not change the
> > justification of this patch. I didn't see such cases reported anywhere
> > - other than in your stress testing where we do not really know what is
> > going on yet - and so I didn't mention them and nor I have marked the
> > patch for stable.
> 
> As shown in my stress testing, warn_alloc() is not powerful enough when
> something we did not imagine happens.

yes, your stress testing is hitting many corner cases and it is good to
deal with them long term but that doesn't mean normal workloads should
be too stressed about backporting this patch because it is not very
likely they would ever hit a problem here.
 
> > I am wondering what is the point of this feedback actually? Do you
> > see anything wrong in the patch or is this about the wording of the
> > changelog? If it is the later is your concern serious enough to warrant
> > the rewording/reposting?
> 
> I don't see anything wrong in the patch. I just thought

OK
 
>   This is not critical as there should be somebody invoking the OOM killer
>   (e.g. the forking worker) and get the situation unstuck and eventually
>   performs the draining. Quite annoying though.
> 
> part can be dropped because there is no guarantee that something we do not
> imagine won't happen.

I do not consider "something we do not imagine won't happen" as critical
enough. And the changelog tries to be explicit about the expectations
and argues why people do not have to be scared and automatically
backport it because it is urgent.

> After applying this patch, we might be able to replace
> 
>         if (unlikely(!mutex_trylock(&pcpu_drain_mutex))) {
>                 if (!zone)
>                         return;
>                 mutex_lock(&pcpu_drain_mutex);
>         }
> 
> with
> 
>         if (mutex_lock_killable(&pcpu_drain_mutex))
> 		return;
> 
> because forward progress will be guaranteed by this patch and
> we can favor pcpu_drain_mutex owner to use other CPU's time for
> flushing queued works when many other allocating threads are
> almost busy looping.

But we do not really want to make this synchronous, I believe. Not with
a proper justification numbers.

-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-07 13:17 ` Michal Hocko
@ 2017-03-09 14:26   ` Mel Gorman
  -1 siblings, 0 replies; 29+ messages in thread
From: Mel Gorman @ 2017-03-09 14:26 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, linux-mm, LKML,
	Michal Hocko

On Tue, Mar 07, 2017 at 02:17:51PM +0100, Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
> 
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.
> 
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil
> - do not propagate error from setup_vmstat to keep the previous behavior
>   per Mel
> 
> Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Michal Hocko <mhocko@suse.com>

Acked-by: Mel Gorman <mgorman@suse.de>
> +struct workqueue_struct *mm_percpu_wq;
> +
>  static int __init setup_vmstat(void)
>  {
> -#ifdef CONFIG_SMP
> -	int ret;
> +	int ret __maybe_unused;
>  
> +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> +
> +#ifdef CONFIG_SMP
>  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
>  					NULL, vmstat_cpu_dead);
>  	if (ret < 0)

Should the workqueue also have been renamed to mm_percpu_wq?

-- 
Mel Gorman
SUSE Labs

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-09 14:26   ` Mel Gorman
  0 siblings, 0 replies; 29+ messages in thread
From: Mel Gorman @ 2017-03-09 14:26 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, linux-mm, LKML,
	Michal Hocko

On Tue, Mar 07, 2017 at 02:17:51PM +0100, Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
> 
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
> 
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.
> 
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil
> - do not propagate error from setup_vmstat to keep the previous behavior
>   per Mel
> 
> Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Signed-off-by: Michal Hocko <mhocko@suse.com>

Acked-by: Mel Gorman <mgorman@suse.de>
> +struct workqueue_struct *mm_percpu_wq;
> +
>  static int __init setup_vmstat(void)
>  {
> -#ifdef CONFIG_SMP
> -	int ret;
> +	int ret __maybe_unused;
>  
> +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> +
> +#ifdef CONFIG_SMP
>  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
>  					NULL, vmstat_cpu_dead);
>  	if (ret < 0)

Should the workqueue also have been renamed to mm_percpu_wq?

-- 
Mel Gorman
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-09 14:26   ` Mel Gorman
@ 2017-03-09 14:44     ` Michal Hocko
  -1 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-09 14:44 UTC (permalink / raw)
  To: Mel Gorman; +Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, linux-mm, LKML

On Thu 09-03-17 14:26:02, Mel Gorman wrote:
> On Tue, Mar 07, 2017 at 02:17:51PM +0100, Michal Hocko wrote:
> > From: Michal Hocko <mhocko@suse.com>
> > 
> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > per cpu lru caches. This seems more than necessary because both can run
> > on a single WQ. Both do not block on locks requiring a memory allocation
> > nor perform any allocations themselves. We will save one rescuer thread
> > this way.
> > 
> > On the other hand drain_all_pages() queues work on the system wq which
> > doesn't have rescuer and so this depend on memory allocation (when all
> > workers are stuck allocating and new ones cannot be created). This is
> > not critical as there should be somebody invoking the OOM killer (e.g.
> > the forking worker) and get the situation unstuck and eventually
> > performs the draining. Quite annoying though. This worker should be
> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > and vmstat.
> > 
> > Changes since v1
> > - rename vmstat_wq to mm_percpu_wq - per Mel
> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >   been intialized yet. This shouldn't happen because the initialization
> >   is done from an init code but some init section might be triggering
> >   those paths indirectly so just warn and skip the draining in that case
> >   per Vlastimil
> > - do not propagate error from setup_vmstat to keep the previous behavior
> >   per Mel
> > 
> > Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > Signed-off-by: Michal Hocko <mhocko@suse.com>
> 
> Acked-by: Mel Gorman <mgorman@suse.de>

Thanks!

> > +struct workqueue_struct *mm_percpu_wq;
> > +
> >  static int __init setup_vmstat(void)
> >  {
> > -#ifdef CONFIG_SMP
> > -	int ret;
> > +	int ret __maybe_unused;
> >  
> > +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> > +
> > +#ifdef CONFIG_SMP
> >  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
> >  					NULL, vmstat_cpu_dead);
> >  	if (ret < 0)
> 
> Should the workqueue also have been renamed to mm_percpu_wq?

Of course. Andrew, could you fold the following in
---
diff --git a/mm/vmstat.c b/mm/vmstat.c
index ff9c49c47f32..4bbc775f9d08 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1766,7 +1766,7 @@ static int __init setup_vmstat(void)
 {
 	int ret __maybe_unused;
 
-	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+	mm_percpu_wq = alloc_workqueue("mm_percpu_wq", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
 
 #ifdef CONFIG_SMP
 	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
-- 
Michal Hocko
SUSE Labs

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-09 14:44     ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-09 14:44 UTC (permalink / raw)
  To: Mel Gorman; +Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, linux-mm, LKML

On Thu 09-03-17 14:26:02, Mel Gorman wrote:
> On Tue, Mar 07, 2017 at 02:17:51PM +0100, Michal Hocko wrote:
> > From: Michal Hocko <mhocko@suse.com>
> > 
> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > per cpu lru caches. This seems more than necessary because both can run
> > on a single WQ. Both do not block on locks requiring a memory allocation
> > nor perform any allocations themselves. We will save one rescuer thread
> > this way.
> > 
> > On the other hand drain_all_pages() queues work on the system wq which
> > doesn't have rescuer and so this depend on memory allocation (when all
> > workers are stuck allocating and new ones cannot be created). This is
> > not critical as there should be somebody invoking the OOM killer (e.g.
> > the forking worker) and get the situation unstuck and eventually
> > performs the draining. Quite annoying though. This worker should be
> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > and vmstat.
> > 
> > Changes since v1
> > - rename vmstat_wq to mm_percpu_wq - per Mel
> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >   been intialized yet. This shouldn't happen because the initialization
> >   is done from an init code but some init section might be triggering
> >   those paths indirectly so just warn and skip the draining in that case
> >   per Vlastimil
> > - do not propagate error from setup_vmstat to keep the previous behavior
> >   per Mel
> > 
> > Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > Signed-off-by: Michal Hocko <mhocko@suse.com>
> 
> Acked-by: Mel Gorman <mgorman@suse.de>

Thanks!

> > +struct workqueue_struct *mm_percpu_wq;
> > +
> >  static int __init setup_vmstat(void)
> >  {
> > -#ifdef CONFIG_SMP
> > -	int ret;
> > +	int ret __maybe_unused;
> >  
> > +	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
> > +
> > +#ifdef CONFIG_SMP
> >  	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
> >  					NULL, vmstat_cpu_dead);
> >  	if (ret < 0)
> 
> Should the workqueue also have been renamed to mm_percpu_wq?

Of course. Andrew, could you fold the following in
---
diff --git a/mm/vmstat.c b/mm/vmstat.c
index ff9c49c47f32..4bbc775f9d08 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1766,7 +1766,7 @@ static int __init setup_vmstat(void)
 {
 	int ret __maybe_unused;
 
-	mm_percpu_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+	mm_percpu_wq = alloc_workqueue("mm_percpu_wq", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
 
 #ifdef CONFIG_SMP
 	ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-07 13:17 ` Michal Hocko
@ 2017-03-10 23:31   ` Yang Li
  -1 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-10 23:31 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Michal Hocko, Li Yang

On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> From: Michal Hocko <mhocko@suse.com>
>
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
>
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.
>
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil

So what's the plan if this really happens?  Shall we put the
initialization of the mm_percpu_wq earlier?  Or if it is really
harmless we can probably remove the warnings.

I'm seeing this on arm64 with a linux-next tree:

[    0.276449] WARNING: CPU: 2 PID: 1 at mm/page_alloc.c:2423
drain_all_pages+0x244/0x25c
[    0.276537] Modules linked in:

[    0.276594] CPU: 2 PID: 1 Comm: swapper/0 Not tainted
4.11.0-rc1-next-20170310-00027-g64dfbc5 #127
[    0.276693] Hardware name: Freescale Layerscape 2088A RDB Board (DT)
[    0.276764] task: ffffffc07c4a6d00 task.stack: ffffffc07c4a8000
[    0.276831] PC is at drain_all_pages+0x244/0x25c
[    0.276886] LR is at start_isolate_page_range+0x14c/0x1f0
[    0.276946] pc : [<ffffff80081636bc>] lr : [<ffffff80081c675c>]
pstate: 80000045
[    0.277028] sp : ffffffc07c4abb10
[    0.277066] x29: ffffffc07c4abb10 x28: 00000000000ff000
[    0.277128] x27: 0000000000000004 x26: 0000000000000000
[    0.277190] x25: 00000000000ff400 x24: 0000000000000040
[    0.277252] x23: ffffff8008ab0000 x22: ffffff8008c46000
[    0.277313] x21: ffffff8008c2b700 x20: ffffff8008c2b200
[    0.277374] x19: ffffff8008c2b200 x18: ffffff80088b5068
[    0.277436] x17: 000000000000000e x16: 0000000000000007
[    0.277497] x15: 0000000000000001 x14: ffffffffffffffff
[    0.277559] x13: 0000000000000068 x12: 0000000000000001
[    0.277620] x11: ffffff8008c2b6e0 x10: 0000000000010000
[    0.277682] x9 : ffffff8008c2b6e0 x8 : 00000000000000cd
[    0.277743] x7 : ffffffc07c4abb70 x6 : ffffff8008c2b868
[    0.277804] x5 : ffffff8008b84b4e x4 : 0000000000000000
[    0.277866] x3 : 0000000000000c00 x2 : 0000000000000311
[    0.277927] x1 : 0000000000000001 x0 : ffffff8008bc8000

[    0.278008] ---[ end trace 905d0cf24acf61bb ]---
[    0.278060] Call trace:
[    0.278089] Exception stack(0xffffffc07c4ab940 to 0xffffffc07c4aba70)
[    0.278162] b940: ffffff8008c2b200 0000008000000000
ffffffc07c4abb10 ffffff80081636bc
[    0.278249] b960: ffffff8008ba8dd0 ffffff8008ba8c80
ffffff8008c2c580 ffffff8008bc5f08
[    0.278336] b980: ffffffbebffdafff ffffffbebffdb000
ffffff8008c797d8 ffffffbebffdafff
[    0.278423] b9a0: ffffffbebffdb000 ffffffc07c667000
ffffffc07c4ab9c0 ffffff800817ff7c
[    0.278510] b9c0: ffffffc07c4aba40 ffffff8008180618
00000000000003d0 0000000000000f60
[    0.278597] b9e0: ffffff8008bc8000 0000000000000001
0000000000000311 0000000000000c00
[    0.278684] ba00: 0000000000000000 ffffff8008b84b4e
ffffff8008c2b868 ffffffc07c4abb70
[    0.278771] ba20: 00000000000000cd ffffff8008c2b6e0
0000000000010000 ffffff8008c2b6e0
[    0.278858] ba40: 0000000000000001 0000000000000068
ffffffffffffffff 0000000000000001
[    0.278945] ba60: 0000000000000007 000000000000000e
[    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
[    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
[    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
[    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
[    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
[    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
[    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
[    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
[    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
[    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
[    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20


Regards,
Leo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-10 23:31   ` Yang Li
  0 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-10 23:31 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Michal Hocko, Li Yang

On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> From: Michal Hocko <mhocko@suse.com>
>
> We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> per cpu lru caches. This seems more than necessary because both can run
> on a single WQ. Both do not block on locks requiring a memory allocation
> nor perform any allocations themselves. We will save one rescuer thread
> this way.
>
> On the other hand drain_all_pages() queues work on the system wq which
> doesn't have rescuer and so this depend on memory allocation (when all
> workers are stuck allocating and new ones cannot be created). This is
> not critical as there should be somebody invoking the OOM killer (e.g.
> the forking worker) and get the situation unstuck and eventually
> performs the draining. Quite annoying though. This worker should be
> using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> and vmstat.
>
> Changes since v1
> - rename vmstat_wq to mm_percpu_wq - per Mel
> - make sure we are not trying to enqueue anything while the WQ hasn't
>   been intialized yet. This shouldn't happen because the initialization
>   is done from an init code but some init section might be triggering
>   those paths indirectly so just warn and skip the draining in that case
>   per Vlastimil

So what's the plan if this really happens?  Shall we put the
initialization of the mm_percpu_wq earlier?  Or if it is really
harmless we can probably remove the warnings.

I'm seeing this on arm64 with a linux-next tree:

[    0.276449] WARNING: CPU: 2 PID: 1 at mm/page_alloc.c:2423
drain_all_pages+0x244/0x25c
[    0.276537] Modules linked in:

[    0.276594] CPU: 2 PID: 1 Comm: swapper/0 Not tainted
4.11.0-rc1-next-20170310-00027-g64dfbc5 #127
[    0.276693] Hardware name: Freescale Layerscape 2088A RDB Board (DT)
[    0.276764] task: ffffffc07c4a6d00 task.stack: ffffffc07c4a8000
[    0.276831] PC is at drain_all_pages+0x244/0x25c
[    0.276886] LR is at start_isolate_page_range+0x14c/0x1f0
[    0.276946] pc : [<ffffff80081636bc>] lr : [<ffffff80081c675c>]
pstate: 80000045
[    0.277028] sp : ffffffc07c4abb10
[    0.277066] x29: ffffffc07c4abb10 x28: 00000000000ff000
[    0.277128] x27: 0000000000000004 x26: 0000000000000000
[    0.277190] x25: 00000000000ff400 x24: 0000000000000040
[    0.277252] x23: ffffff8008ab0000 x22: ffffff8008c46000
[    0.277313] x21: ffffff8008c2b700 x20: ffffff8008c2b200
[    0.277374] x19: ffffff8008c2b200 x18: ffffff80088b5068
[    0.277436] x17: 000000000000000e x16: 0000000000000007
[    0.277497] x15: 0000000000000001 x14: ffffffffffffffff
[    0.277559] x13: 0000000000000068 x12: 0000000000000001
[    0.277620] x11: ffffff8008c2b6e0 x10: 0000000000010000
[    0.277682] x9 : ffffff8008c2b6e0 x8 : 00000000000000cd
[    0.277743] x7 : ffffffc07c4abb70 x6 : ffffff8008c2b868
[    0.277804] x5 : ffffff8008b84b4e x4 : 0000000000000000
[    0.277866] x3 : 0000000000000c00 x2 : 0000000000000311
[    0.277927] x1 : 0000000000000001 x0 : ffffff8008bc8000

[    0.278008] ---[ end trace 905d0cf24acf61bb ]---
[    0.278060] Call trace:
[    0.278089] Exception stack(0xffffffc07c4ab940 to 0xffffffc07c4aba70)
[    0.278162] b940: ffffff8008c2b200 0000008000000000
ffffffc07c4abb10 ffffff80081636bc
[    0.278249] b960: ffffff8008ba8dd0 ffffff8008ba8c80
ffffff8008c2c580 ffffff8008bc5f08
[    0.278336] b980: ffffffbebffdafff ffffffbebffdb000
ffffff8008c797d8 ffffffbebffdafff
[    0.278423] b9a0: ffffffbebffdb000 ffffffc07c667000
ffffffc07c4ab9c0 ffffff800817ff7c
[    0.278510] b9c0: ffffffc07c4aba40 ffffff8008180618
00000000000003d0 0000000000000f60
[    0.278597] b9e0: ffffff8008bc8000 0000000000000001
0000000000000311 0000000000000c00
[    0.278684] ba00: 0000000000000000 ffffff8008b84b4e
ffffff8008c2b868 ffffffc07c4abb70
[    0.278771] ba20: 00000000000000cd ffffff8008c2b6e0
0000000000010000 ffffff8008c2b6e0
[    0.278858] ba40: 0000000000000001 0000000000000068
ffffffffffffffff 0000000000000001
[    0.278945] ba60: 0000000000000007 000000000000000e
[    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
[    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
[    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
[    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
[    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
[    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
[    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
[    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
[    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
[    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
[    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20


Regards,
Leo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-10 23:31   ` Yang Li
@ 2017-03-13  9:58     ` Michal Hocko
  -1 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-13  9:58 UTC (permalink / raw)
  To: Yang Li
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang

On Fri 10-03-17 17:31:56, Yang Li wrote:
> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> > From: Michal Hocko <mhocko@suse.com>
> >
> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > per cpu lru caches. This seems more than necessary because both can run
> > on a single WQ. Both do not block on locks requiring a memory allocation
> > nor perform any allocations themselves. We will save one rescuer thread
> > this way.
> >
> > On the other hand drain_all_pages() queues work on the system wq which
> > doesn't have rescuer and so this depend on memory allocation (when all
> > workers are stuck allocating and new ones cannot be created). This is
> > not critical as there should be somebody invoking the OOM killer (e.g.
> > the forking worker) and get the situation unstuck and eventually
> > performs the draining. Quite annoying though. This worker should be
> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > and vmstat.
> >
> > Changes since v1
> > - rename vmstat_wq to mm_percpu_wq - per Mel
> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >   been intialized yet. This shouldn't happen because the initialization
> >   is done from an init code but some init section might be triggering
> >   those paths indirectly so just warn and skip the draining in that case
> >   per Vlastimil
> 
> So what's the plan if this really happens?  Shall we put the
> initialization of the mm_percpu_wq earlier?

yes

> Or if it is really harmless we can probably remove the warnings.

Yeah, it is harmless but if we can move it earlier then it would be
prefferable to fix this.

> 
> I'm seeing this on arm64 with a linux-next tree:
[...]
> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20

The following should address this. I didn't get to test it yet though.
---
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 21ee5503c702..8362dca071cb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -32,6 +32,8 @@ struct user_struct;
 struct writeback_control;
 struct bdi_writeback;
 
+void init_mm_internals(void);
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES	/* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
 
diff --git a/init/main.c b/init/main.c
index 51aa8f336819..c72d35250e84 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
 
 	workqueue_init();
 
+	init_mm_internals();
+
 	do_pre_smp_initcalls();
 	lockup_detector_init();
 
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 4bbc775f9d08..d0871fc1aeca 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
 
 struct workqueue_struct *mm_percpu_wq;
 
-static int __init setup_vmstat(void)
+void __init init_mm_internals(void)
 {
 	int ret __maybe_unused;
 
@@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
 	proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
 	proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
 #endif
-	return 0;
 }
-module_init(setup_vmstat)
 
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
 

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-13  9:58     ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-13  9:58 UTC (permalink / raw)
  To: Yang Li
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang

On Fri 10-03-17 17:31:56, Yang Li wrote:
> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> > From: Michal Hocko <mhocko@suse.com>
> >
> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> > per cpu lru caches. This seems more than necessary because both can run
> > on a single WQ. Both do not block on locks requiring a memory allocation
> > nor perform any allocations themselves. We will save one rescuer thread
> > this way.
> >
> > On the other hand drain_all_pages() queues work on the system wq which
> > doesn't have rescuer and so this depend on memory allocation (when all
> > workers are stuck allocating and new ones cannot be created). This is
> > not critical as there should be somebody invoking the OOM killer (e.g.
> > the forking worker) and get the situation unstuck and eventually
> > performs the draining. Quite annoying though. This worker should be
> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> > and vmstat.
> >
> > Changes since v1
> > - rename vmstat_wq to mm_percpu_wq - per Mel
> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >   been intialized yet. This shouldn't happen because the initialization
> >   is done from an init code but some init section might be triggering
> >   those paths indirectly so just warn and skip the draining in that case
> >   per Vlastimil
> 
> So what's the plan if this really happens?  Shall we put the
> initialization of the mm_percpu_wq earlier?

yes

> Or if it is really harmless we can probably remove the warnings.

Yeah, it is harmless but if we can move it earlier then it would be
prefferable to fix this.

> 
> I'm seeing this on arm64 with a linux-next tree:
[...]
> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20

The following should address this. I didn't get to test it yet though.
---
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 21ee5503c702..8362dca071cb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -32,6 +32,8 @@ struct user_struct;
 struct writeback_control;
 struct bdi_writeback;
 
+void init_mm_internals(void);
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES	/* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
 
diff --git a/init/main.c b/init/main.c
index 51aa8f336819..c72d35250e84 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
 
 	workqueue_init();
 
+	init_mm_internals();
+
 	do_pre_smp_initcalls();
 	lockup_detector_init();
 
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 4bbc775f9d08..d0871fc1aeca 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
 
 struct workqueue_struct *mm_percpu_wq;
 
-static int __init setup_vmstat(void)
+void __init init_mm_internals(void)
 {
 	int ret __maybe_unused;
 
@@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
 	proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
 	proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
 #endif
-	return 0;
 }
-module_init(setup_vmstat)
 
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
 

-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-13  9:58     ` Michal Hocko
  (?)
@ 2017-03-14 23:07       ` Yang Li
  -1 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-14 23:07 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang, linux-arm-kernel

On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
> On Fri 10-03-17 17:31:56, Yang Li wrote:
>> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> > From: Michal Hocko <mhocko@suse.com>
>> >
>> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
>> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
>> > per cpu lru caches. This seems more than necessary because both can run
>> > on a single WQ. Both do not block on locks requiring a memory allocation
>> > nor perform any allocations themselves. We will save one rescuer thread
>> > this way.
>> >
>> > On the other hand drain_all_pages() queues work on the system wq which
>> > doesn't have rescuer and so this depend on memory allocation (when all
>> > workers are stuck allocating and new ones cannot be created). This is
>> > not critical as there should be somebody invoking the OOM killer (e.g.
>> > the forking worker) and get the situation unstuck and eventually
>> > performs the draining. Quite annoying though. This worker should be
>> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
>> > and vmstat.
>> >
>> > Changes since v1
>> > - rename vmstat_wq to mm_percpu_wq - per Mel
>> > - make sure we are not trying to enqueue anything while the WQ hasn't
>> >   been intialized yet. This shouldn't happen because the initialization
>> >   is done from an init code but some init section might be triggering
>> >   those paths indirectly so just warn and skip the draining in that case
>> >   per Vlastimil
>>
>> So what's the plan if this really happens?  Shall we put the
>> initialization of the mm_percpu_wq earlier?
>
> yes
>
>> Or if it is really harmless we can probably remove the warnings.
>
> Yeah, it is harmless but if we can move it earlier then it would be
> prefferable to fix this.
>
>>
>> I'm seeing this on arm64 with a linux-next tree:
> [...]
>> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
>> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
>> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
>> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
>> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
>> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
>> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
>> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
>> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
>> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
>> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
>
> The following should address this. I didn't get to test it yet though.
> ---
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 21ee5503c702..8362dca071cb 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -32,6 +32,8 @@ struct user_struct;
>  struct writeback_control;
>  struct bdi_writeback;
>
> +void init_mm_internals(void);
> +
>  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
>  extern unsigned long max_mapnr;
>
> diff --git a/init/main.c b/init/main.c
> index 51aa8f336819..c72d35250e84 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
>
>         workqueue_init();
>
> +       init_mm_internals();
> +
>         do_pre_smp_initcalls();
>         lockup_detector_init();
>
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 4bbc775f9d08..d0871fc1aeca 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
>
>  struct workqueue_struct *mm_percpu_wq;
>
> -static int __init setup_vmstat(void)
> +void __init init_mm_internals(void)
>  {
>         int ret __maybe_unused;
>
> @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
>         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
>         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
>  #endif
> -       return 0;
>  }
> -module_init(setup_vmstat)
>
>  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)

I did a test on arm64.  This do fix the warnings.

Regards,
Leo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-14 23:07       ` Yang Li
  0 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-14 23:07 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang, linux-arm-kernel

On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
> On Fri 10-03-17 17:31:56, Yang Li wrote:
>> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> > From: Michal Hocko <mhocko@suse.com>
>> >
>> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
>> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
>> > per cpu lru caches. This seems more than necessary because both can run
>> > on a single WQ. Both do not block on locks requiring a memory allocation
>> > nor perform any allocations themselves. We will save one rescuer thread
>> > this way.
>> >
>> > On the other hand drain_all_pages() queues work on the system wq which
>> > doesn't have rescuer and so this depend on memory allocation (when all
>> > workers are stuck allocating and new ones cannot be created). This is
>> > not critical as there should be somebody invoking the OOM killer (e.g.
>> > the forking worker) and get the situation unstuck and eventually
>> > performs the draining. Quite annoying though. This worker should be
>> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
>> > and vmstat.
>> >
>> > Changes since v1
>> > - rename vmstat_wq to mm_percpu_wq - per Mel
>> > - make sure we are not trying to enqueue anything while the WQ hasn't
>> >   been intialized yet. This shouldn't happen because the initialization
>> >   is done from an init code but some init section might be triggering
>> >   those paths indirectly so just warn and skip the draining in that case
>> >   per Vlastimil
>>
>> So what's the plan if this really happens?  Shall we put the
>> initialization of the mm_percpu_wq earlier?
>
> yes
>
>> Or if it is really harmless we can probably remove the warnings.
>
> Yeah, it is harmless but if we can move it earlier then it would be
> prefferable to fix this.
>
>>
>> I'm seeing this on arm64 with a linux-next tree:
> [...]
>> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
>> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
>> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
>> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
>> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
>> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
>> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
>> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
>> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
>> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
>> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
>
> The following should address this. I didn't get to test it yet though.
> ---
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 21ee5503c702..8362dca071cb 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -32,6 +32,8 @@ struct user_struct;
>  struct writeback_control;
>  struct bdi_writeback;
>
> +void init_mm_internals(void);
> +
>  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
>  extern unsigned long max_mapnr;
>
> diff --git a/init/main.c b/init/main.c
> index 51aa8f336819..c72d35250e84 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
>
>         workqueue_init();
>
> +       init_mm_internals();
> +
>         do_pre_smp_initcalls();
>         lockup_detector_init();
>
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 4bbc775f9d08..d0871fc1aeca 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
>
>  struct workqueue_struct *mm_percpu_wq;
>
> -static int __init setup_vmstat(void)
> +void __init init_mm_internals(void)
>  {
>         int ret __maybe_unused;
>
> @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
>         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
>         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
>  #endif
> -       return 0;
>  }
> -module_init(setup_vmstat)
>
>  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)

I did a test on arm64.  This do fix the warnings.

Regards,
Leo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-14 23:07       ` Yang Li
  0 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-14 23:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
> On Fri 10-03-17 17:31:56, Yang Li wrote:
>> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> > From: Michal Hocko <mhocko@suse.com>
>> >
>> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
>> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
>> > per cpu lru caches. This seems more than necessary because both can run
>> > on a single WQ. Both do not block on locks requiring a memory allocation
>> > nor perform any allocations themselves. We will save one rescuer thread
>> > this way.
>> >
>> > On the other hand drain_all_pages() queues work on the system wq which
>> > doesn't have rescuer and so this depend on memory allocation (when all
>> > workers are stuck allocating and new ones cannot be created). This is
>> > not critical as there should be somebody invoking the OOM killer (e.g.
>> > the forking worker) and get the situation unstuck and eventually
>> > performs the draining. Quite annoying though. This worker should be
>> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
>> > and vmstat.
>> >
>> > Changes since v1
>> > - rename vmstat_wq to mm_percpu_wq - per Mel
>> > - make sure we are not trying to enqueue anything while the WQ hasn't
>> >   been intialized yet. This shouldn't happen because the initialization
>> >   is done from an init code but some init section might be triggering
>> >   those paths indirectly so just warn and skip the draining in that case
>> >   per Vlastimil
>>
>> So what's the plan if this really happens?  Shall we put the
>> initialization of the mm_percpu_wq earlier?
>
> yes
>
>> Or if it is really harmless we can probably remove the warnings.
>
> Yeah, it is harmless but if we can move it earlier then it would be
> prefferable to fix this.
>
>>
>> I'm seeing this on arm64 with a linux-next tree:
> [...]
>> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
>> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
>> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
>> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
>> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
>> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
>> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
>> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
>> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
>> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
>> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
>
> The following should address this. I didn't get to test it yet though.
> ---
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 21ee5503c702..8362dca071cb 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -32,6 +32,8 @@ struct user_struct;
>  struct writeback_control;
>  struct bdi_writeback;
>
> +void init_mm_internals(void);
> +
>  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
>  extern unsigned long max_mapnr;
>
> diff --git a/init/main.c b/init/main.c
> index 51aa8f336819..c72d35250e84 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
>
>         workqueue_init();
>
> +       init_mm_internals();
> +
>         do_pre_smp_initcalls();
>         lockup_detector_init();
>
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 4bbc775f9d08..d0871fc1aeca 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
>
>  struct workqueue_struct *mm_percpu_wq;
>
> -static int __init setup_vmstat(void)
> +void __init init_mm_internals(void)
>  {
>         int ret __maybe_unused;
>
> @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
>         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
>         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
>  #endif
> -       return 0;
>  }
> -module_init(setup_vmstat)
>
>  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)

I did a test on arm64.  This do fix the warnings.

Regards,
Leo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-14 23:07       ` Yang Li
  (?)
@ 2017-03-15  7:39         ` Michal Hocko
  -1 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-15  7:39 UTC (permalink / raw)
  To: Yang Li
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang, linux-arm-kernel

On Tue 14-03-17 18:07:38, Yang Li wrote:
> On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
> > On Fri 10-03-17 17:31:56, Yang Li wrote:
> >> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> >> > From: Michal Hocko <mhocko@suse.com>
> >> >
> >> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> >> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> >> > per cpu lru caches. This seems more than necessary because both can run
> >> > on a single WQ. Both do not block on locks requiring a memory allocation
> >> > nor perform any allocations themselves. We will save one rescuer thread
> >> > this way.
> >> >
> >> > On the other hand drain_all_pages() queues work on the system wq which
> >> > doesn't have rescuer and so this depend on memory allocation (when all
> >> > workers are stuck allocating and new ones cannot be created). This is
> >> > not critical as there should be somebody invoking the OOM killer (e.g.
> >> > the forking worker) and get the situation unstuck and eventually
> >> > performs the draining. Quite annoying though. This worker should be
> >> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> >> > and vmstat.
> >> >
> >> > Changes since v1
> >> > - rename vmstat_wq to mm_percpu_wq - per Mel
> >> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >> >   been intialized yet. This shouldn't happen because the initialization
> >> >   is done from an init code but some init section might be triggering
> >> >   those paths indirectly so just warn and skip the draining in that case
> >> >   per Vlastimil
> >>
> >> So what's the plan if this really happens?  Shall we put the
> >> initialization of the mm_percpu_wq earlier?
> >
> > yes
> >
> >> Or if it is really harmless we can probably remove the warnings.
> >
> > Yeah, it is harmless but if we can move it earlier then it would be
> > prefferable to fix this.
> >
> >>
> >> I'm seeing this on arm64 with a linux-next tree:
> > [...]
> >> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
> >> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
> >> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
> >> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
> >> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
> >> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
> >> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
> >> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
> >> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
> >> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
> >> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
> >
> > The following should address this. I didn't get to test it yet though.
> > ---
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 21ee5503c702..8362dca071cb 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -32,6 +32,8 @@ struct user_struct;
> >  struct writeback_control;
> >  struct bdi_writeback;
> >
> > +void init_mm_internals(void);
> > +
> >  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
> >  extern unsigned long max_mapnr;
> >
> > diff --git a/init/main.c b/init/main.c
> > index 51aa8f336819..c72d35250e84 100644
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
> >
> >         workqueue_init();
> >
> > +       init_mm_internals();
> > +
> >         do_pre_smp_initcalls();
> >         lockup_detector_init();
> >
> > diff --git a/mm/vmstat.c b/mm/vmstat.c
> > index 4bbc775f9d08..d0871fc1aeca 100644
> > --- a/mm/vmstat.c
> > +++ b/mm/vmstat.c
> > @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
> >
> >  struct workqueue_struct *mm_percpu_wq;
> >
> > -static int __init setup_vmstat(void)
> > +void __init init_mm_internals(void)
> >  {
> >         int ret __maybe_unused;
> >
> > @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
> >         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
> >         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
> >  #endif
> > -       return 0;
> >  }
> > -module_init(setup_vmstat)
> >
> >  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
> 
> I did a test on arm64.  This do fix the warnings.

Thanks! Can I assume your
Tested-by: Yang Li <pku.leo@gmail.com>

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-15  7:39         ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-15  7:39 UTC (permalink / raw)
  To: Yang Li
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang, linux-arm-kernel

On Tue 14-03-17 18:07:38, Yang Li wrote:
> On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
> > On Fri 10-03-17 17:31:56, Yang Li wrote:
> >> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> >> > From: Michal Hocko <mhocko@suse.com>
> >> >
> >> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> >> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> >> > per cpu lru caches. This seems more than necessary because both can run
> >> > on a single WQ. Both do not block on locks requiring a memory allocation
> >> > nor perform any allocations themselves. We will save one rescuer thread
> >> > this way.
> >> >
> >> > On the other hand drain_all_pages() queues work on the system wq which
> >> > doesn't have rescuer and so this depend on memory allocation (when all
> >> > workers are stuck allocating and new ones cannot be created). This is
> >> > not critical as there should be somebody invoking the OOM killer (e.g.
> >> > the forking worker) and get the situation unstuck and eventually
> >> > performs the draining. Quite annoying though. This worker should be
> >> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> >> > and vmstat.
> >> >
> >> > Changes since v1
> >> > - rename vmstat_wq to mm_percpu_wq - per Mel
> >> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >> >   been intialized yet. This shouldn't happen because the initialization
> >> >   is done from an init code but some init section might be triggering
> >> >   those paths indirectly so just warn and skip the draining in that case
> >> >   per Vlastimil
> >>
> >> So what's the plan if this really happens?  Shall we put the
> >> initialization of the mm_percpu_wq earlier?
> >
> > yes
> >
> >> Or if it is really harmless we can probably remove the warnings.
> >
> > Yeah, it is harmless but if we can move it earlier then it would be
> > prefferable to fix this.
> >
> >>
> >> I'm seeing this on arm64 with a linux-next tree:
> > [...]
> >> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
> >> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
> >> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
> >> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
> >> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
> >> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
> >> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
> >> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
> >> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
> >> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
> >> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
> >
> > The following should address this. I didn't get to test it yet though.
> > ---
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 21ee5503c702..8362dca071cb 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -32,6 +32,8 @@ struct user_struct;
> >  struct writeback_control;
> >  struct bdi_writeback;
> >
> > +void init_mm_internals(void);
> > +
> >  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
> >  extern unsigned long max_mapnr;
> >
> > diff --git a/init/main.c b/init/main.c
> > index 51aa8f336819..c72d35250e84 100644
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
> >
> >         workqueue_init();
> >
> > +       init_mm_internals();
> > +
> >         do_pre_smp_initcalls();
> >         lockup_detector_init();
> >
> > diff --git a/mm/vmstat.c b/mm/vmstat.c
> > index 4bbc775f9d08..d0871fc1aeca 100644
> > --- a/mm/vmstat.c
> > +++ b/mm/vmstat.c
> > @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
> >
> >  struct workqueue_struct *mm_percpu_wq;
> >
> > -static int __init setup_vmstat(void)
> > +void __init init_mm_internals(void)
> >  {
> >         int ret __maybe_unused;
> >
> > @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
> >         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
> >         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
> >  #endif
> > -       return 0;
> >  }
> > -module_init(setup_vmstat)
> >
> >  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
> 
> I did a test on arm64.  This do fix the warnings.

Thanks! Can I assume your
Tested-by: Yang Li <pku.leo@gmail.com>

-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-15  7:39         ` Michal Hocko
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Hocko @ 2017-03-15  7:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue 14-03-17 18:07:38, Yang Li wrote:
> On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
> > On Fri 10-03-17 17:31:56, Yang Li wrote:
> >> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
> >> > From: Michal Hocko <mhocko@suse.com>
> >> >
> >> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
> >> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
> >> > per cpu lru caches. This seems more than necessary because both can run
> >> > on a single WQ. Both do not block on locks requiring a memory allocation
> >> > nor perform any allocations themselves. We will save one rescuer thread
> >> > this way.
> >> >
> >> > On the other hand drain_all_pages() queues work on the system wq which
> >> > doesn't have rescuer and so this depend on memory allocation (when all
> >> > workers are stuck allocating and new ones cannot be created). This is
> >> > not critical as there should be somebody invoking the OOM killer (e.g.
> >> > the forking worker) and get the situation unstuck and eventually
> >> > performs the draining. Quite annoying though. This worker should be
> >> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
> >> > and vmstat.
> >> >
> >> > Changes since v1
> >> > - rename vmstat_wq to mm_percpu_wq - per Mel
> >> > - make sure we are not trying to enqueue anything while the WQ hasn't
> >> >   been intialized yet. This shouldn't happen because the initialization
> >> >   is done from an init code but some init section might be triggering
> >> >   those paths indirectly so just warn and skip the draining in that case
> >> >   per Vlastimil
> >>
> >> So what's the plan if this really happens?  Shall we put the
> >> initialization of the mm_percpu_wq earlier?
> >
> > yes
> >
> >> Or if it is really harmless we can probably remove the warnings.
> >
> > Yeah, it is harmless but if we can move it earlier then it would be
> > prefferable to fix this.
> >
> >>
> >> I'm seeing this on arm64 with a linux-next tree:
> > [...]
> >> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
> >> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
> >> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
> >> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
> >> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
> >> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
> >> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
> >> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
> >> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
> >> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
> >> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
> >
> > The following should address this. I didn't get to test it yet though.
> > ---
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 21ee5503c702..8362dca071cb 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -32,6 +32,8 @@ struct user_struct;
> >  struct writeback_control;
> >  struct bdi_writeback;
> >
> > +void init_mm_internals(void);
> > +
> >  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
> >  extern unsigned long max_mapnr;
> >
> > diff --git a/init/main.c b/init/main.c
> > index 51aa8f336819..c72d35250e84 100644
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
> >
> >         workqueue_init();
> >
> > +       init_mm_internals();
> > +
> >         do_pre_smp_initcalls();
> >         lockup_detector_init();
> >
> > diff --git a/mm/vmstat.c b/mm/vmstat.c
> > index 4bbc775f9d08..d0871fc1aeca 100644
> > --- a/mm/vmstat.c
> > +++ b/mm/vmstat.c
> > @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
> >
> >  struct workqueue_struct *mm_percpu_wq;
> >
> > -static int __init setup_vmstat(void)
> > +void __init init_mm_internals(void)
> >  {
> >         int ret __maybe_unused;
> >
> > @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
> >         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
> >         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
> >  #endif
> > -       return 0;
> >  }
> > -module_init(setup_vmstat)
> >
> >  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
> 
> I did a test on arm64.  This do fix the warnings.

Thanks! Can I assume your
Tested-by: Yang Li <pku.leo@gmail.com>

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
  2017-03-15  7:39         ` Michal Hocko
  (?)
@ 2017-03-15 16:31           ` Yang Li
  -1 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-15 16:31 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang, linux-arm-kernel

On Wed, Mar 15, 2017 at 2:39 AM, Michal Hocko <mhocko@kernel.org> wrote:
> On Tue 14-03-17 18:07:38, Yang Li wrote:
>> On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> > On Fri 10-03-17 17:31:56, Yang Li wrote:
>> >> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> >> > From: Michal Hocko <mhocko@suse.com>
>> >> >
>> >> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
>> >> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
>> >> > per cpu lru caches. This seems more than necessary because both can run
>> >> > on a single WQ. Both do not block on locks requiring a memory allocation
>> >> > nor perform any allocations themselves. We will save one rescuer thread
>> >> > this way.
>> >> >
>> >> > On the other hand drain_all_pages() queues work on the system wq which
>> >> > doesn't have rescuer and so this depend on memory allocation (when all
>> >> > workers are stuck allocating and new ones cannot be created). This is
>> >> > not critical as there should be somebody invoking the OOM killer (e.g.
>> >> > the forking worker) and get the situation unstuck and eventually
>> >> > performs the draining. Quite annoying though. This worker should be
>> >> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
>> >> > and vmstat.
>> >> >
>> >> > Changes since v1
>> >> > - rename vmstat_wq to mm_percpu_wq - per Mel
>> >> > - make sure we are not trying to enqueue anything while the WQ hasn't
>> >> >   been intialized yet. This shouldn't happen because the initialization
>> >> >   is done from an init code but some init section might be triggering
>> >> >   those paths indirectly so just warn and skip the draining in that case
>> >> >   per Vlastimil
>> >>
>> >> So what's the plan if this really happens?  Shall we put the
>> >> initialization of the mm_percpu_wq earlier?
>> >
>> > yes
>> >
>> >> Or if it is really harmless we can probably remove the warnings.
>> >
>> > Yeah, it is harmless but if we can move it earlier then it would be
>> > prefferable to fix this.
>> >
>> >>
>> >> I'm seeing this on arm64 with a linux-next tree:
>> > [...]
>> >> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
>> >> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
>> >> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
>> >> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
>> >> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
>> >> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
>> >> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
>> >> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
>> >> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
>> >> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
>> >> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
>> >
>> > The following should address this. I didn't get to test it yet though.
>> > ---
>> > diff --git a/include/linux/mm.h b/include/linux/mm.h
>> > index 21ee5503c702..8362dca071cb 100644
>> > --- a/include/linux/mm.h
>> > +++ b/include/linux/mm.h
>> > @@ -32,6 +32,8 @@ struct user_struct;
>> >  struct writeback_control;
>> >  struct bdi_writeback;
>> >
>> > +void init_mm_internals(void);
>> > +
>> >  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
>> >  extern unsigned long max_mapnr;
>> >
>> > diff --git a/init/main.c b/init/main.c
>> > index 51aa8f336819..c72d35250e84 100644
>> > --- a/init/main.c
>> > +++ b/init/main.c
>> > @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
>> >
>> >         workqueue_init();
>> >
>> > +       init_mm_internals();
>> > +
>> >         do_pre_smp_initcalls();
>> >         lockup_detector_init();
>> >
>> > diff --git a/mm/vmstat.c b/mm/vmstat.c
>> > index 4bbc775f9d08..d0871fc1aeca 100644
>> > --- a/mm/vmstat.c
>> > +++ b/mm/vmstat.c
>> > @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
>> >
>> >  struct workqueue_struct *mm_percpu_wq;
>> >
>> > -static int __init setup_vmstat(void)
>> > +void __init init_mm_internals(void)
>> >  {
>> >         int ret __maybe_unused;
>> >
>> > @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
>> >         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
>> >         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
>> >  #endif
>> > -       return 0;
>> >  }
>> > -module_init(setup_vmstat)
>> >
>> >  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
>>
>> I did a test on arm64.  This do fix the warnings.
>
> Thanks! Can I assume your
> Tested-by: Yang Li <pku.leo@gmail.com>

Sure.

Tested-by: Li Yang <pku.leo@gmail.com>

Regards,
Leo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-15 16:31           ` Yang Li
  0 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-15 16:31 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Tetsuo Handa, Vlastimil Babka, Mel Gorman,
	linux-mm, LKML, Li Yang, linux-arm-kernel

On Wed, Mar 15, 2017 at 2:39 AM, Michal Hocko <mhocko@kernel.org> wrote:
> On Tue 14-03-17 18:07:38, Yang Li wrote:
>> On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> > On Fri 10-03-17 17:31:56, Yang Li wrote:
>> >> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> >> > From: Michal Hocko <mhocko@suse.com>
>> >> >
>> >> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
>> >> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
>> >> > per cpu lru caches. This seems more than necessary because both can run
>> >> > on a single WQ. Both do not block on locks requiring a memory allocation
>> >> > nor perform any allocations themselves. We will save one rescuer thread
>> >> > this way.
>> >> >
>> >> > On the other hand drain_all_pages() queues work on the system wq which
>> >> > doesn't have rescuer and so this depend on memory allocation (when all
>> >> > workers are stuck allocating and new ones cannot be created). This is
>> >> > not critical as there should be somebody invoking the OOM killer (e.g.
>> >> > the forking worker) and get the situation unstuck and eventually
>> >> > performs the draining. Quite annoying though. This worker should be
>> >> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
>> >> > and vmstat.
>> >> >
>> >> > Changes since v1
>> >> > - rename vmstat_wq to mm_percpu_wq - per Mel
>> >> > - make sure we are not trying to enqueue anything while the WQ hasn't
>> >> >   been intialized yet. This shouldn't happen because the initialization
>> >> >   is done from an init code but some init section might be triggering
>> >> >   those paths indirectly so just warn and skip the draining in that case
>> >> >   per Vlastimil
>> >>
>> >> So what's the plan if this really happens?  Shall we put the
>> >> initialization of the mm_percpu_wq earlier?
>> >
>> > yes
>> >
>> >> Or if it is really harmless we can probably remove the warnings.
>> >
>> > Yeah, it is harmless but if we can move it earlier then it would be
>> > prefferable to fix this.
>> >
>> >>
>> >> I'm seeing this on arm64 with a linux-next tree:
>> > [...]
>> >> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
>> >> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
>> >> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
>> >> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
>> >> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
>> >> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
>> >> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
>> >> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
>> >> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
>> >> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
>> >> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
>> >
>> > The following should address this. I didn't get to test it yet though.
>> > ---
>> > diff --git a/include/linux/mm.h b/include/linux/mm.h
>> > index 21ee5503c702..8362dca071cb 100644
>> > --- a/include/linux/mm.h
>> > +++ b/include/linux/mm.h
>> > @@ -32,6 +32,8 @@ struct user_struct;
>> >  struct writeback_control;
>> >  struct bdi_writeback;
>> >
>> > +void init_mm_internals(void);
>> > +
>> >  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
>> >  extern unsigned long max_mapnr;
>> >
>> > diff --git a/init/main.c b/init/main.c
>> > index 51aa8f336819..c72d35250e84 100644
>> > --- a/init/main.c
>> > +++ b/init/main.c
>> > @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
>> >
>> >         workqueue_init();
>> >
>> > +       init_mm_internals();
>> > +
>> >         do_pre_smp_initcalls();
>> >         lockup_detector_init();
>> >
>> > diff --git a/mm/vmstat.c b/mm/vmstat.c
>> > index 4bbc775f9d08..d0871fc1aeca 100644
>> > --- a/mm/vmstat.c
>> > +++ b/mm/vmstat.c
>> > @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
>> >
>> >  struct workqueue_struct *mm_percpu_wq;
>> >
>> > -static int __init setup_vmstat(void)
>> > +void __init init_mm_internals(void)
>> >  {
>> >         int ret __maybe_unused;
>> >
>> > @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
>> >         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
>> >         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
>> >  #endif
>> > -       return 0;
>> >  }
>> > -module_init(setup_vmstat)
>> >
>> >  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
>>
>> I did a test on arm64.  This do fix the warnings.
>
> Thanks! Can I assume your
> Tested-by: Yang Li <pku.leo@gmail.com>

Sure.

Tested-by: Li Yang <pku.leo@gmail.com>

Regards,
Leo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH] mm: move pcp and lru-pcp drainging into single wq
@ 2017-03-15 16:31           ` Yang Li
  0 siblings, 0 replies; 29+ messages in thread
From: Yang Li @ 2017-03-15 16:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 15, 2017 at 2:39 AM, Michal Hocko <mhocko@kernel.org> wrote:
> On Tue 14-03-17 18:07:38, Yang Li wrote:
>> On Mon, Mar 13, 2017 at 4:58 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> > On Fri 10-03-17 17:31:56, Yang Li wrote:
>> >> On Tue, Mar 7, 2017 at 7:17 AM, Michal Hocko <mhocko@kernel.org> wrote:
>> >> > From: Michal Hocko <mhocko@suse.com>
>> >> >
>> >> > We currently have 2 specific WQ_RECLAIM workqueues in the mm code.
>> >> > vmstat_wq for updating pcp stats and lru_add_drain_wq dedicated to drain
>> >> > per cpu lru caches. This seems more than necessary because both can run
>> >> > on a single WQ. Both do not block on locks requiring a memory allocation
>> >> > nor perform any allocations themselves. We will save one rescuer thread
>> >> > this way.
>> >> >
>> >> > On the other hand drain_all_pages() queues work on the system wq which
>> >> > doesn't have rescuer and so this depend on memory allocation (when all
>> >> > workers are stuck allocating and new ones cannot be created). This is
>> >> > not critical as there should be somebody invoking the OOM killer (e.g.
>> >> > the forking worker) and get the situation unstuck and eventually
>> >> > performs the draining. Quite annoying though. This worker should be
>> >> > using WQ_RECLAIM as well. We can reuse the same one as for lru draining
>> >> > and vmstat.
>> >> >
>> >> > Changes since v1
>> >> > - rename vmstat_wq to mm_percpu_wq - per Mel
>> >> > - make sure we are not trying to enqueue anything while the WQ hasn't
>> >> >   been intialized yet. This shouldn't happen because the initialization
>> >> >   is done from an init code but some init section might be triggering
>> >> >   those paths indirectly so just warn and skip the draining in that case
>> >> >   per Vlastimil
>> >>
>> >> So what's the plan if this really happens?  Shall we put the
>> >> initialization of the mm_percpu_wq earlier?
>> >
>> > yes
>> >
>> >> Or if it is really harmless we can probably remove the warnings.
>> >
>> > Yeah, it is harmless but if we can move it earlier then it would be
>> > prefferable to fix this.
>> >
>> >>
>> >> I'm seeing this on arm64 with a linux-next tree:
>> > [...]
>> >> [    0.279000] [<ffffff80081636bc>] drain_all_pages+0x244/0x25c
>> >> [    0.279065] [<ffffff80081c675c>] start_isolate_page_range+0x14c/0x1f0
>> >> [    0.279137] [<ffffff8008166a48>] alloc_contig_range+0xec/0x354
>> >> [    0.279203] [<ffffff80081c6c5c>] cma_alloc+0x100/0x1fc
>> >> [    0.279263] [<ffffff8008481714>] dma_alloc_from_contiguous+0x3c/0x44
>> >> [    0.279336] [<ffffff8008b25720>] atomic_pool_init+0x7c/0x208
>> >> [    0.279399] [<ffffff8008b258f0>] arm64_dma_init+0x44/0x4c
>> >> [    0.279461] [<ffffff8008083144>] do_one_initcall+0x38/0x128
>> >> [    0.279525] [<ffffff8008b20d30>] kernel_init_freeable+0x1a0/0x240
>> >> [    0.279596] [<ffffff8008807778>] kernel_init+0x10/0xfc
>> >> [    0.279654] [<ffffff8008082b70>] ret_from_fork+0x10/0x20
>> >
>> > The following should address this. I didn't get to test it yet though.
>> > ---
>> > diff --git a/include/linux/mm.h b/include/linux/mm.h
>> > index 21ee5503c702..8362dca071cb 100644
>> > --- a/include/linux/mm.h
>> > +++ b/include/linux/mm.h
>> > @@ -32,6 +32,8 @@ struct user_struct;
>> >  struct writeback_control;
>> >  struct bdi_writeback;
>> >
>> > +void init_mm_internals(void);
>> > +
>> >  #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
>> >  extern unsigned long max_mapnr;
>> >
>> > diff --git a/init/main.c b/init/main.c
>> > index 51aa8f336819..c72d35250e84 100644
>> > --- a/init/main.c
>> > +++ b/init/main.c
>> > @@ -1023,6 +1023,8 @@ static noinline void __init kernel_init_freeable(void)
>> >
>> >         workqueue_init();
>> >
>> > +       init_mm_internals();
>> > +
>> >         do_pre_smp_initcalls();
>> >         lockup_detector_init();
>> >
>> > diff --git a/mm/vmstat.c b/mm/vmstat.c
>> > index 4bbc775f9d08..d0871fc1aeca 100644
>> > --- a/mm/vmstat.c
>> > +++ b/mm/vmstat.c
>> > @@ -1762,7 +1762,7 @@ static int vmstat_cpu_dead(unsigned int cpu)
>> >
>> >  struct workqueue_struct *mm_percpu_wq;
>> >
>> > -static int __init setup_vmstat(void)
>> > +void __init init_mm_internals(void)
>> >  {
>> >         int ret __maybe_unused;
>> >
>> > @@ -1792,9 +1792,7 @@ static int __init setup_vmstat(void)
>> >         proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
>> >         proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
>> >  #endif
>> > -       return 0;
>> >  }
>> > -module_init(setup_vmstat)
>> >
>> >  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
>>
>> I did a test on arm64.  This do fix the warnings.
>
> Thanks! Can I assume your
> Tested-by: Yang Li <pku.leo@gmail.com>

Sure.

Tested-by: Li Yang <pku.leo@gmail.com>

Regards,
Leo

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2017-03-15 16:32 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-07 13:17 [PATCH] mm: move pcp and lru-pcp drainging into single wq Michal Hocko
2017-03-07 13:17 ` Michal Hocko
2017-03-07 13:34 ` Vlastimil Babka
2017-03-07 13:34   ` Vlastimil Babka
2017-03-07 13:50 ` Tetsuo Handa
2017-03-07 13:50   ` Tetsuo Handa
2017-03-07 14:23   ` Michal Hocko
2017-03-07 14:23     ` Michal Hocko
2017-03-08 11:50     ` Tetsuo Handa
2017-03-08 11:50       ` Tetsuo Handa
2017-03-08 13:01       ` Michal Hocko
2017-03-08 13:01         ` Michal Hocko
2017-03-09 14:26 ` Mel Gorman
2017-03-09 14:26   ` Mel Gorman
2017-03-09 14:44   ` Michal Hocko
2017-03-09 14:44     ` Michal Hocko
2017-03-10 23:31 ` Yang Li
2017-03-10 23:31   ` Yang Li
2017-03-13  9:58   ` Michal Hocko
2017-03-13  9:58     ` Michal Hocko
2017-03-14 23:07     ` Yang Li
2017-03-14 23:07       ` Yang Li
2017-03-14 23:07       ` Yang Li
2017-03-15  7:39       ` Michal Hocko
2017-03-15  7:39         ` Michal Hocko
2017-03-15  7:39         ` Michal Hocko
2017-03-15 16:31         ` Yang Li
2017-03-15 16:31           ` Yang Li
2017-03-15 16:31           ` Yang Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.