summaryrefslogtreecommitdiff
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a01f062e7007..5040db9a76a6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3670,7 +3670,21 @@ static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
unsigned long val;
if (mem_cgroup_is_root(memcg)) {
- mem_cgroup_flush_stats();
+ /*
+ * We can reach here from irq context through:
+ * uncharge_batch()
+ * |--memcg_check_events()
+ * |--mem_cgroup_threshold()
+ * |--__mem_cgroup_threshold()
+ * |--mem_cgroup_usage
+ *
+ * rstat flushing is an expensive operation that should not be
+ * done from irq context; use stale stats in this case.
+ * Arguably, usage threshold events are not reliable on the root
+ * memcg anyway since its usage is ill-defined.
+ */
+ if (in_task())
+ mem_cgroup_flush_stats();
val = memcg_page_state(memcg, NR_FILE_PAGES) +
memcg_page_state(memcg, NR_ANON_MAPPED);
if (swap)