diff for duplicates of <20140922185736.GB6630@cmpxchg.org> diff --git a/a/1.txt b/N1/1.txt index 54985a3..82ac1b9 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -451,648 +451,3 @@ Thanks for your thorough review, Vladimir! Here is the delta patch: --- -From 3601538347af756b9bfe05142ab21b5ae44f8cdd Mon Sep 17 00:00:00 2001 -From: Johannes Weiner <hannes@cmpxchg.org> -Date: Mon, 22 Sep 2014 13:54:24 -0400 -Subject: [patch] mm: memcontrol: lockless page counters fix - -- renamed limited to failcnt again [vladimir] -- base page counter range on on LONG_MAX [vladimir] -- page_counter_read() [vladimir] -- page_counter_sub() [vladimir] -- rework the nofail charging [vladimir] -- page_counter_reset_watermark() [vladimir] -- fixed hugepage limit page alignment [vladimir] -- fixed page_counter_sub() return value [vladimir] -- fixed kmem's idea of unlimited [vladimir] -- fixed tcp memcontrol's idea of unlimited [vladimir] -- fixed tcp memcontrol's usage reporting [vladimir] -- serialize page_counter_limit() callsites [vladimir] ---- - include/linux/memcontrol.h | 24 ++++++--- - include/net/sock.h | 8 +-- - mm/hugetlb_cgroup.c | 22 ++++---- - mm/memcontrol.c | 123 +++++++++++++++++++++++++-------------------- - net/ipv4/tcp_memcontrol.c | 18 ++++--- - 5 files changed, 115 insertions(+), 80 deletions(-) - -diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h -index bf8fb1a05597..a8b939376a5d 100644 ---- a/include/linux/memcontrol.h -+++ b/include/linux/memcontrol.h -@@ -62,13 +62,13 @@ struct page_counter { - - /* legacy */ - unsigned long watermark; -- unsigned long limited; -+ unsigned long failcnt; - }; - - #if BITS_PER_LONG == 32 --#define PAGE_COUNTER_MAX ULONG_MAX -+#define PAGE_COUNTER_MAX LONG_MAX - #else --#define PAGE_COUNTER_MAX (ULONG_MAX / PAGE_SIZE) -+#define PAGE_COUNTER_MAX (LONG_MAX / PAGE_SIZE) - #endif - - static inline void page_counter_init(struct page_counter *counter, -@@ -79,13 +79,25 @@ static inline void page_counter_init(struct page_counter *counter, - counter->parent = parent; - } - --int page_counter_cancel(struct page_counter *counter, unsigned long nr_pages); --int page_counter_charge(struct page_counter *counter, unsigned long nr_pages, -- struct page_counter **fail); -+static inline unsigned long page_counter_read(struct page_counter *counter) -+{ -+ return atomic_long_read(&counter->count); -+} -+ -+int page_counter_sub(struct page_counter *counter, unsigned long nr_pages); -+void page_counter_charge(struct page_counter *counter, unsigned long nr_pages); -+int page_counter_try_charge(struct page_counter *counter, -+ unsigned long nr_pages, -+ struct page_counter **fail); - int page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages); - int page_counter_limit(struct page_counter *counter, unsigned long limit); - int page_counter_memparse(const char *buf, unsigned long *nr_pages); - -+static inline void page_counter_reset_watermark(struct page_counter *counter) -+{ -+ counter->watermark = page_counter_read(counter); -+} -+ - int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm, - gfp_t gfp_mask, struct mem_cgroup **memcgp); - void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg, -diff --git a/include/net/sock.h b/include/net/sock.h -index f41749982668..9aa435de3ef1 100644 ---- a/include/net/sock.h -+++ b/include/net/sock.h -@@ -1217,9 +1217,9 @@ static inline void memcg_memory_allocated_add(struct cg_proto *prot, - unsigned long amt, - int *parent_status) - { -- page_counter_charge(&prot->memory_allocated, amt, NULL); -+ page_counter_charge(&prot->memory_allocated, amt); - -- if (atomic_long_read(&prot->memory_allocated.count) > -+ if (page_counter_read(&prot->memory_allocated) > - prot->memory_allocated.limit) - *parent_status = OVER_LIMIT; - } -@@ -1236,7 +1236,7 @@ sk_memory_allocated(const struct sock *sk) - struct proto *prot = sk->sk_prot; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) -- return atomic_long_read(&sk->sk_cgrp->memory_allocated.count); -+ return page_counter_read(&sk->sk_cgrp->memory_allocated); - - return atomic_long_read(prot->memory_allocated); - } -@@ -1250,7 +1250,7 @@ sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status) - memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status); - /* update the root cgroup regardless */ - atomic_long_add_return(amt, prot->memory_allocated); -- return atomic_long_read(&sk->sk_cgrp->memory_allocated.count); -+ return page_counter_read(&sk->sk_cgrp->memory_allocated); - } - - return atomic_long_add_return(amt, prot->memory_allocated); -diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c -index e619b6b62f1f..abd1e8dc7b46 100644 ---- a/mm/hugetlb_cgroup.c -+++ b/mm/hugetlb_cgroup.c -@@ -61,7 +61,7 @@ static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg) - int idx; - - for (idx = 0; idx < hugetlb_max_hstate; idx++) { -- if (atomic_long_read(&h_cg->hugepage[idx].count)) -+ if (page_counter_read(&h_cg->hugepage[idx])) - return true; - } - return false; -@@ -127,11 +127,11 @@ static void hugetlb_cgroup_move_parent(int idx, struct hugetlb_cgroup *h_cg, - if (!parent) { - parent = root_h_cgroup; - /* root has no limit */ -- page_counter_charge(&parent->hugepage[idx], nr_pages, NULL); -+ page_counter_charge(&parent->hugepage[idx], nr_pages); - } - counter = &h_cg->hugepage[idx]; - /* Take the pages off the local counter */ -- page_counter_cancel(counter, nr_pages); -+ page_counter_sub(counter, nr_pages); - - set_hugetlb_cgroup(page, parent); - out: -@@ -186,7 +186,7 @@ again: - } - rcu_read_unlock(); - -- ret = page_counter_charge(&h_cg->hugepage[idx], nr_pages, &counter); -+ ret = page_counter_try_charge(&h_cg->hugepage[idx], nr_pages, &counter); - css_put(&h_cg->css); - done: - *ptr = h_cg; -@@ -254,18 +254,20 @@ static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css, - - switch (MEMFILE_ATTR(cft->private)) { - case RES_USAGE: -- return (u64)atomic_long_read(&counter->count) * PAGE_SIZE; -+ return (u64)page_counter_read(counter) * PAGE_SIZE; - case RES_LIMIT: - return (u64)counter->limit * PAGE_SIZE; - case RES_MAX_USAGE: - return (u64)counter->watermark * PAGE_SIZE; - case RES_FAILCNT: -- return counter->limited; -+ return counter->failcnt; - default: - BUG(); - } - } - -+static DEFINE_MUTEX(hugetlb_limit_mutex); -+ - static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off) - { -@@ -285,8 +287,10 @@ static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of, - - switch (MEMFILE_ATTR(of_cft(of)->private)) { - case RES_LIMIT: -- nr_pages = ALIGN(nr_pages, huge_page_shift(&hstates[idx])); -+ nr_pages = ALIGN(nr_pages, 1UL<<huge_page_order(&hstates[idx])); -+ mutex_lock(&hugetlb_limit_mutex); - ret = page_counter_limit(&h_cg->hugepage[idx], nr_pages); -+ mutex_unlock(&hugetlb_limit_mutex); - break; - default: - ret = -EINVAL; -@@ -306,10 +310,10 @@ static ssize_t hugetlb_cgroup_reset(struct kernfs_open_file *of, - - switch (MEMFILE_ATTR(of_cft(of)->private)) { - case RES_MAX_USAGE: -- counter->watermark = atomic_long_read(&counter->count); -+ page_counter_reset_watermark(counter); - break; - case RES_FAILCNT: -- counter->limited = 0; -+ counter->failcnt = 0; - break; - default: - ret = -EINVAL; -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index dfd3b15a57e8..9dec20b3c928 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -65,7 +65,7 @@ - - #include <trace/events/vmscan.h> - --int page_counter_cancel(struct page_counter *counter, unsigned long nr_pages) -+int page_counter_sub(struct page_counter *counter, unsigned long nr_pages) - { - long new; - -@@ -74,28 +74,41 @@ int page_counter_cancel(struct page_counter *counter, unsigned long nr_pages) - if (WARN_ON(unlikely(new < 0))) - atomic_long_set(&counter->count, 0); - -- return new > 1; -+ return new > 0; - } - --int page_counter_charge(struct page_counter *counter, unsigned long nr_pages, -- struct page_counter **fail) -+void page_counter_charge(struct page_counter *counter, unsigned long nr_pages) -+{ -+ struct page_counter *c; -+ -+ for (c = counter; c; c = c->parent) { -+ long new; -+ -+ new = atomic_long_add_return(nr_pages, &c->count); -+ -+ if (new > c->watermark) -+ c->watermark = new; -+ } -+} -+ -+int page_counter_try_charge(struct page_counter *counter, -+ unsigned long nr_pages, -+ struct page_counter **fail) - { - struct page_counter *c; - - for (c = counter; c; c = c->parent) { - for (;;) { -- unsigned long count; -- unsigned long new; -+ long count; -+ long new; - - count = atomic_long_read(&c->count); - - new = count + nr_pages; - if (new > c->limit) { -- c->limited++; -- if (fail) { -- *fail = c; -- goto failed; -- } -+ c->failcnt++; -+ *fail = c; -+ goto failed; - } - - if (atomic_long_cmpxchg(&c->count, count, new) != count) -@@ -111,7 +124,7 @@ int page_counter_charge(struct page_counter *counter, unsigned long nr_pages, - - failed: - for (c = counter; c != *fail; c = c->parent) -- page_counter_cancel(c, nr_pages); -+ page_counter_sub(c, nr_pages); - - return -ENOMEM; - } -@@ -124,7 +137,7 @@ int page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages) - for (c = counter; c; c = c->parent) { - int remainder; - -- remainder = page_counter_cancel(c, nr_pages); -+ remainder = page_counter_sub(c, nr_pages); - if (c == counter && !remainder) - ret = 0; - } -@@ -135,8 +148,8 @@ int page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages) - int page_counter_limit(struct page_counter *counter, unsigned long limit) - { - for (;;) { -- unsigned long count; - unsigned long old; -+ long count; - - count = atomic_long_read(&counter->count); - -@@ -751,7 +764,7 @@ static void disarm_kmem_keys(struct mem_cgroup *memcg) - * This check can't live in kmem destruction function, - * since the charges will outlive the cgroup - */ -- WARN_ON(atomic_long_read(&memcg->kmem.count)); -+ WARN_ON(page_counter_read(&memcg->kmem)); - } - #else - static void disarm_kmem_keys(struct mem_cgroup *memcg) -@@ -858,7 +871,7 @@ static void mem_cgroup_remove_exceeded(struct mem_cgroup_per_zone *mz, - - static unsigned long soft_limit_excess(struct mem_cgroup *memcg) - { -- unsigned long nr_pages = atomic_long_read(&memcg->memory.count); -+ unsigned long nr_pages = page_counter_read(&memcg->memory); - unsigned long soft_limit = ACCESS_ONCE(memcg->soft_limit); - unsigned long excess = 0; - -@@ -1609,13 +1622,13 @@ static unsigned long mem_cgroup_margin(struct mem_cgroup *memcg) - unsigned long count; - unsigned long limit; - -- count = atomic_long_read(&memcg->memory.count); -+ count = page_counter_read(&memcg->memory); - limit = ACCESS_ONCE(memcg->memory.limit); - if (count < limit) - margin = limit - count; - - if (do_swap_account) { -- count = atomic_long_read(&memcg->memsw.count); -+ count = page_counter_read(&memcg->memsw); - limit = ACCESS_ONCE(memcg->memsw.limit); - if (count < limit) - margin = min(margin, limit - count); -@@ -1763,14 +1776,14 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p) - rcu_read_unlock(); - - pr_info("memory: usage %llukB, limit %llukB, failcnt %lu\n", -- K((u64)atomic_long_read(&memcg->memory.count)), -- K((u64)memcg->memory.limit), memcg->memory.limited); -+ K((u64)page_counter_read(&memcg->memory)), -+ K((u64)memcg->memory.limit), memcg->memory.failcnt); - pr_info("memory+swap: usage %llukB, limit %llukB, failcnt %lu\n", -- K((u64)atomic_long_read(&memcg->memsw.count)), -- K((u64)memcg->memsw.limit), memcg->memsw.limited); -+ K((u64)page_counter_read(&memcg->memsw)), -+ K((u64)memcg->memsw.limit), memcg->memsw.failcnt); - pr_info("kmem: usage %llukB, limit %llukB, failcnt %lu\n", -- K((u64)atomic_long_read(&memcg->kmem.count)), -- K((u64)memcg->kmem.limit), memcg->kmem.limited); -+ K((u64)page_counter_read(&memcg->kmem)), -+ K((u64)memcg->kmem.limit), memcg->kmem.failcnt); - - for_each_mem_cgroup_tree(iter, memcg) { - pr_info("Memory cgroup stats for "); -@@ -2604,10 +2617,10 @@ retry: - if (consume_stock(memcg, nr_pages)) - goto done; - -- if (!page_counter_charge(&memcg->memory, batch, &counter)) { -+ if (!page_counter_try_charge(&memcg->memory, batch, &counter)) { - if (!do_swap_account) - goto done_restock; -- if (!page_counter_charge(&memcg->memsw, batch, &counter)) -+ if (!page_counter_try_charge(&memcg->memsw, batch, &counter)) - goto done_restock; - page_counter_uncharge(&memcg->memory, batch); - mem_over_limit = mem_cgroup_from_counter(counter, memsw); -@@ -2877,7 +2890,7 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, - struct page_counter *counter; - int ret = 0; - -- ret = page_counter_charge(&memcg->kmem, nr_pages, &counter); -+ ret = page_counter_try_charge(&memcg->kmem, nr_pages, &counter); - if (ret < 0) - return ret; - -@@ -2898,9 +2911,9 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, - * when the allocation triggers should have been already - * directed to the root cgroup in memcontrol.h - */ -- page_counter_charge(&memcg->memory, nr_pages, NULL); -+ page_counter_charge(&memcg->memory, nr_pages); - if (do_swap_account) -- page_counter_charge(&memcg->memsw, nr_pages, NULL); -+ page_counter_charge(&memcg->memsw, nr_pages); - ret = 0; - } else if (ret) - page_counter_uncharge(&memcg->kmem, nr_pages); -@@ -3558,9 +3571,9 @@ static int mem_cgroup_move_parent(struct page *page, - pc, child, parent); - if (!ret) { - /* Take charge off the local counters */ -- page_counter_cancel(&child->memory, nr_pages); -+ page_counter_sub(&child->memory, nr_pages); - if (do_swap_account) -- page_counter_cancel(&child->memsw, nr_pages); -+ page_counter_sub(&child->memsw, nr_pages); - } - - if (nr_pages > 1) -@@ -3665,7 +3678,7 @@ void mem_cgroup_print_bad_page(struct page *page) - } - #endif - --static DEFINE_MUTEX(set_limit_mutex); -+static DEFINE_MUTEX(memcg_limit_mutex); - - static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, - unsigned long limit) -@@ -3684,7 +3697,7 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, - retry_count = MEM_CGROUP_RECLAIM_RETRIES * - mem_cgroup_count_children(memcg); - -- oldusage = atomic_long_read(&memcg->memory.count); -+ oldusage = page_counter_read(&memcg->memory); - - do { - if (signal_pending(current)) { -@@ -3692,23 +3705,23 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, - break; - } - -- mutex_lock(&set_limit_mutex); -+ mutex_lock(&memcg_limit_mutex); - if (limit > memcg->memsw.limit) { -- mutex_unlock(&set_limit_mutex); -+ mutex_unlock(&memcg_limit_mutex); - ret = -EINVAL; - break; - } - if (limit > memcg->memory.limit) - enlarge = true; - ret = page_counter_limit(&memcg->memory, limit); -- mutex_unlock(&set_limit_mutex); -+ mutex_unlock(&memcg_limit_mutex); - - if (!ret) - break; - - try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, true); - -- curusage = atomic_long_read(&memcg->memory.count); -+ curusage = page_counter_read(&memcg->memory); - /* Usage is reduced ? */ - if (curusage >= oldusage) - retry_count--; -@@ -3735,7 +3748,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, - retry_count = MEM_CGROUP_RECLAIM_RETRIES * - mem_cgroup_count_children(memcg); - -- oldusage = atomic_long_read(&memcg->memsw.count); -+ oldusage = page_counter_read(&memcg->memsw); - - do { - if (signal_pending(current)) { -@@ -3743,23 +3756,23 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, - break; - } - -- mutex_lock(&set_limit_mutex); -+ mutex_lock(&memcg_limit_mutex); - if (limit < memcg->memory.limit) { -- mutex_unlock(&set_limit_mutex); -+ mutex_unlock(&memcg_limit_mutex); - ret = -EINVAL; - break; - } - if (limit > memcg->memsw.limit) - enlarge = true; - ret = page_counter_limit(&memcg->memsw, limit); -- mutex_unlock(&set_limit_mutex); -+ mutex_unlock(&memcg_limit_mutex); - - if (!ret) - break; - - try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, false); - -- curusage = atomic_long_read(&memcg->memsw.count); -+ curusage = page_counter_read(&memcg->memsw); - /* Usage is reduced ? */ - if (curusage >= oldusage) - retry_count--; -@@ -3960,8 +3973,8 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg) - * right after the check. RES_USAGE should be safe as we always - * charge before adding to the LRU. - */ -- } while (atomic_long_read(&memcg->memory.count) - -- atomic_long_read(&memcg->kmem.count) > 0); -+ } while (page_counter_read(&memcg->memory) - -+ page_counter_read(&memcg->kmem) > 0); - } - - /* -@@ -4001,7 +4014,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg) - /* we call try-to-free pages for make this cgroup empty */ - lru_add_drain_all(); - /* try to free all pages in this cgroup */ -- while (nr_retries && atomic_long_read(&memcg->memory.count)) { -+ while (nr_retries && page_counter_read(&memcg->memory)) { - int progress; - - if (signal_pending(current)) -@@ -4098,9 +4111,9 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) - val += tree_stat(memcg, MEM_CGROUP_STAT_SWAP); - } else { - if (!swap) -- val = atomic_long_read(&memcg->memory.count); -+ val = page_counter_read(&memcg->memory); - else -- val = atomic_long_read(&memcg->memsw.count); -+ val = page_counter_read(&memcg->memsw); - } - return val << PAGE_SHIFT; - } -@@ -4139,13 +4152,13 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css, - return mem_cgroup_usage(memcg, false); - if (counter == &memcg->memsw) - return mem_cgroup_usage(memcg, true); -- return (u64)atomic_long_read(&counter->count) * PAGE_SIZE; -+ return (u64)page_counter_read(counter) * PAGE_SIZE; - case RES_LIMIT: - return (u64)counter->limit * PAGE_SIZE; - case RES_MAX_USAGE: - return (u64)counter->watermark * PAGE_SIZE; - case RES_FAILCNT: -- return counter->limited; -+ return counter->failcnt; - case RES_SOFT_LIMIT: - return (u64)memcg->soft_limit * PAGE_SIZE; - default: -@@ -4234,10 +4247,12 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg, - { - int ret; - -+ mutex_lock(&memcg_limit_mutex); - if (!memcg_kmem_is_active(memcg)) - ret = memcg_activate_kmem(memcg, limit); - else - ret = page_counter_limit(&memcg->kmem, limit); -+ mutex_unlock(&memcg_limit_mutex); - return ret; - } - -@@ -4255,7 +4270,7 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg) - * after this point, because it has at least one child already. - */ - if (memcg_kmem_is_active(parent)) -- ret = __memcg_activate_kmem(memcg, ULONG_MAX); -+ ret = __memcg_activate_kmem(memcg, PAGE_COUNTER_MAX); - mutex_unlock(&activate_kmem_mutex); - return ret; - } -@@ -4331,10 +4346,10 @@ static ssize_t mem_cgroup_reset(struct kernfs_open_file *of, char *buf, - - switch (MEMFILE_ATTR(of_cft(of)->private)) { - case RES_MAX_USAGE: -- counter->watermark = atomic_long_read(&counter->count); -+ page_counter_reset_watermark(counter); - break; - case RES_FAILCNT: -- counter->limited = 0; -+ counter->failcnt = 0; - break; - default: - BUG(); -@@ -4934,7 +4949,7 @@ static void kmem_cgroup_css_offline(struct mem_cgroup *memcg) - - memcg_kmem_mark_dead(memcg); - -- if (atomic_long_read(&memcg->kmem.count)) -+ if (page_counter_read(&memcg->kmem)) - return; - - if (memcg_kmem_test_and_clear_dead(memcg)) -@@ -5603,7 +5618,7 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css) - * call_rcu() - * offline_css() - * reparent_charges() -- * page_counter_charge() -+ * page_counter_try_charge() - * css_put() - * css_free() - * pc->mem_cgroup = dead memcg -diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c -index 9a448bdb19e9..272327134a1b 100644 ---- a/net/ipv4/tcp_memcontrol.c -+++ b/net/ipv4/tcp_memcontrol.c -@@ -68,7 +68,7 @@ static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages) - cg_proto->sysctl_mem[i] = min_t(long, nr_pages, - sysctl_tcp_mem[i]); - -- if (nr_pages == ULONG_MAX / PAGE_SIZE) -+ if (nr_pages == PAGE_COUNTER_MAX) - clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); - else { - /* -@@ -106,6 +106,8 @@ enum { - RES_FAILCNT, - }; - -+static DEFINE_MUTEX(tcp_limit_mutex); -+ - static ssize_t tcp_cgroup_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off) - { -@@ -121,7 +123,9 @@ static ssize_t tcp_cgroup_write(struct kernfs_open_file *of, - ret = page_counter_memparse(buf, &nr_pages); - if (ret) - break; -+ mutex_lock(&tcp_limit_mutex); - ret = tcp_update_limit(memcg, nr_pages); -+ mutex_unlock(&tcp_limit_mutex); - break; - default: - ret = -EINVAL; -@@ -145,14 +149,15 @@ static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) - break; - case RES_USAGE: - if (!cg_proto) -- return atomic_long_read(&tcp_memory_allocated); -- val = atomic_long_read(&cg_proto->memory_allocated.count); -+ val = atomic_long_read(&tcp_memory_allocated); -+ else -+ val = page_counter_read(&cg_proto->memory_allocated); - val *= PAGE_SIZE; - break; - case RES_FAILCNT: - if (!cg_proto) - return 0; -- val = cg_proto->memory_allocated.limited; -+ val = cg_proto->memory_allocated.failcnt; - break; - case RES_MAX_USAGE: - if (!cg_proto) -@@ -179,11 +184,10 @@ static ssize_t tcp_cgroup_reset(struct kernfs_open_file *of, - - switch (of_cft(of)->private) { - case RES_MAX_USAGE: -- cg_proto->memory_allocated.watermark = -- atomic_long_read(&cg_proto->memory_allocated.count); -+ page_counter_reset_watermark(&cg_proto->memory_allocated); - break; - case RES_FAILCNT: -- cg_proto->memory_allocated.limited = 0; -+ cg_proto->memory_allocated.failcnt = 0; - break; - } - --- -2.1.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> diff --git a/a/content_digest b/N1/content_digest index dd677e0..3528829 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -464,651 +464,6 @@ "\n" "Here is the delta patch:\n" "\n" - "---\n" - "From 3601538347af756b9bfe05142ab21b5ae44f8cdd Mon Sep 17 00:00:00 2001\n" - "From: Johannes Weiner <hannes@cmpxchg.org>\n" - "Date: Mon, 22 Sep 2014 13:54:24 -0400\n" - "Subject: [patch] mm: memcontrol: lockless page counters fix\n" - "\n" - "- renamed limited to failcnt again [vladimir]\n" - "- base page counter range on on LONG_MAX [vladimir]\n" - "- page_counter_read() [vladimir]\n" - "- page_counter_sub() [vladimir]\n" - "- rework the nofail charging [vladimir]\n" - "- page_counter_reset_watermark() [vladimir]\n" - "- fixed hugepage limit page alignment [vladimir]\n" - "- fixed page_counter_sub() return value [vladimir]\n" - "- fixed kmem's idea of unlimited [vladimir]\n" - "- fixed tcp memcontrol's idea of unlimited [vladimir]\n" - "- fixed tcp memcontrol's usage reporting [vladimir]\n" - "- serialize page_counter_limit() callsites [vladimir]\n" - "---\n" - " include/linux/memcontrol.h | 24 ++++++---\n" - " include/net/sock.h | 8 +--\n" - " mm/hugetlb_cgroup.c | 22 ++++----\n" - " mm/memcontrol.c | 123 +++++++++++++++++++++++++--------------------\n" - " net/ipv4/tcp_memcontrol.c | 18 ++++---\n" - " 5 files changed, 115 insertions(+), 80 deletions(-)\n" - "\n" - "diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h\n" - "index bf8fb1a05597..a8b939376a5d 100644\n" - "--- a/include/linux/memcontrol.h\n" - "+++ b/include/linux/memcontrol.h\n" - "@@ -62,13 +62,13 @@ struct page_counter {\n" - " \n" - " \t/* legacy */\n" - " \tunsigned long watermark;\n" - "-\tunsigned long limited;\n" - "+\tunsigned long failcnt;\n" - " };\n" - " \n" - " #if BITS_PER_LONG == 32\n" - "-#define PAGE_COUNTER_MAX ULONG_MAX\n" - "+#define PAGE_COUNTER_MAX LONG_MAX\n" - " #else\n" - "-#define PAGE_COUNTER_MAX (ULONG_MAX / PAGE_SIZE)\n" - "+#define PAGE_COUNTER_MAX (LONG_MAX / PAGE_SIZE)\n" - " #endif\n" - " \n" - " static inline void page_counter_init(struct page_counter *counter,\n" - "@@ -79,13 +79,25 @@ static inline void page_counter_init(struct page_counter *counter,\n" - " \tcounter->parent = parent;\n" - " }\n" - " \n" - "-int page_counter_cancel(struct page_counter *counter, unsigned long nr_pages);\n" - "-int page_counter_charge(struct page_counter *counter, unsigned long nr_pages,\n" - "-\t\t\tstruct page_counter **fail);\n" - "+static inline unsigned long page_counter_read(struct page_counter *counter)\n" - "+{\n" - "+\treturn atomic_long_read(&counter->count);\n" - "+}\n" - "+\n" - "+int page_counter_sub(struct page_counter *counter, unsigned long nr_pages);\n" - "+void page_counter_charge(struct page_counter *counter, unsigned long nr_pages);\n" - "+int page_counter_try_charge(struct page_counter *counter,\n" - "+\t\t\t unsigned long nr_pages,\n" - "+\t\t\t struct page_counter **fail);\n" - " int page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages);\n" - " int page_counter_limit(struct page_counter *counter, unsigned long limit);\n" - " int page_counter_memparse(const char *buf, unsigned long *nr_pages);\n" - " \n" - "+static inline void page_counter_reset_watermark(struct page_counter *counter)\n" - "+{\n" - "+\tcounter->watermark = page_counter_read(counter);\n" - "+}\n" - "+\n" - " int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm,\n" - " \t\t\t gfp_t gfp_mask, struct mem_cgroup **memcgp);\n" - " void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg,\n" - "diff --git a/include/net/sock.h b/include/net/sock.h\n" - "index f41749982668..9aa435de3ef1 100644\n" - "--- a/include/net/sock.h\n" - "+++ b/include/net/sock.h\n" - "@@ -1217,9 +1217,9 @@ static inline void memcg_memory_allocated_add(struct cg_proto *prot,\n" - " \t\t\t\t\t unsigned long amt,\n" - " \t\t\t\t\t int *parent_status)\n" - " {\n" - "-\tpage_counter_charge(&prot->memory_allocated, amt, NULL);\n" - "+\tpage_counter_charge(&prot->memory_allocated, amt);\n" - " \n" - "-\tif (atomic_long_read(&prot->memory_allocated.count) >\n" - "+\tif (page_counter_read(&prot->memory_allocated) >\n" - " \t prot->memory_allocated.limit)\n" - " \t\t*parent_status = OVER_LIMIT;\n" - " }\n" - "@@ -1236,7 +1236,7 @@ sk_memory_allocated(const struct sock *sk)\n" - " \tstruct proto *prot = sk->sk_prot;\n" - " \n" - " \tif (mem_cgroup_sockets_enabled && sk->sk_cgrp)\n" - "-\t\treturn atomic_long_read(&sk->sk_cgrp->memory_allocated.count);\n" - "+\t\treturn page_counter_read(&sk->sk_cgrp->memory_allocated);\n" - " \n" - " \treturn atomic_long_read(prot->memory_allocated);\n" - " }\n" - "@@ -1250,7 +1250,7 @@ sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status)\n" - " \t\tmemcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status);\n" - " \t\t/* update the root cgroup regardless */\n" - " \t\tatomic_long_add_return(amt, prot->memory_allocated);\n" - "-\t\treturn atomic_long_read(&sk->sk_cgrp->memory_allocated.count);\n" - "+\t\treturn page_counter_read(&sk->sk_cgrp->memory_allocated);\n" - " \t}\n" - " \n" - " \treturn atomic_long_add_return(amt, prot->memory_allocated);\n" - "diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c\n" - "index e619b6b62f1f..abd1e8dc7b46 100644\n" - "--- a/mm/hugetlb_cgroup.c\n" - "+++ b/mm/hugetlb_cgroup.c\n" - "@@ -61,7 +61,7 @@ static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg)\n" - " \tint idx;\n" - " \n" - " \tfor (idx = 0; idx < hugetlb_max_hstate; idx++) {\n" - "-\t\tif (atomic_long_read(&h_cg->hugepage[idx].count))\n" - "+\t\tif (page_counter_read(&h_cg->hugepage[idx]))\n" - " \t\t\treturn true;\n" - " \t}\n" - " \treturn false;\n" - "@@ -127,11 +127,11 @@ static void hugetlb_cgroup_move_parent(int idx, struct hugetlb_cgroup *h_cg,\n" - " \tif (!parent) {\n" - " \t\tparent = root_h_cgroup;\n" - " \t\t/* root has no limit */\n" - "-\t\tpage_counter_charge(&parent->hugepage[idx], nr_pages, NULL);\n" - "+\t\tpage_counter_charge(&parent->hugepage[idx], nr_pages);\n" - " \t}\n" - " \tcounter = &h_cg->hugepage[idx];\n" - " \t/* Take the pages off the local counter */\n" - "-\tpage_counter_cancel(counter, nr_pages);\n" - "+\tpage_counter_sub(counter, nr_pages);\n" - " \n" - " \tset_hugetlb_cgroup(page, parent);\n" - " out:\n" - "@@ -186,7 +186,7 @@ again:\n" - " \t}\n" - " \trcu_read_unlock();\n" - " \n" - "-\tret = page_counter_charge(&h_cg->hugepage[idx], nr_pages, &counter);\n" - "+\tret = page_counter_try_charge(&h_cg->hugepage[idx], nr_pages, &counter);\n" - " \tcss_put(&h_cg->css);\n" - " done:\n" - " \t*ptr = h_cg;\n" - "@@ -254,18 +254,20 @@ static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css,\n" - " \n" - " \tswitch (MEMFILE_ATTR(cft->private)) {\n" - " \tcase RES_USAGE:\n" - "-\t\treturn (u64)atomic_long_read(&counter->count) * PAGE_SIZE;\n" - "+\t\treturn (u64)page_counter_read(counter) * PAGE_SIZE;\n" - " \tcase RES_LIMIT:\n" - " \t\treturn (u64)counter->limit * PAGE_SIZE;\n" - " \tcase RES_MAX_USAGE:\n" - " \t\treturn (u64)counter->watermark * PAGE_SIZE;\n" - " \tcase RES_FAILCNT:\n" - "-\t\treturn counter->limited;\n" - "+\t\treturn counter->failcnt;\n" - " \tdefault:\n" - " \t\tBUG();\n" - " \t}\n" - " }\n" - " \n" - "+static DEFINE_MUTEX(hugetlb_limit_mutex);\n" - "+\n" - " static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of,\n" - " \t\t\t\t char *buf, size_t nbytes, loff_t off)\n" - " {\n" - "@@ -285,8 +287,10 @@ static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of,\n" - " \n" - " \tswitch (MEMFILE_ATTR(of_cft(of)->private)) {\n" - " \tcase RES_LIMIT:\n" - "-\t\tnr_pages = ALIGN(nr_pages, huge_page_shift(&hstates[idx]));\n" - "+\t\tnr_pages = ALIGN(nr_pages, 1UL<<huge_page_order(&hstates[idx]));\n" - "+\t\tmutex_lock(&hugetlb_limit_mutex);\n" - " \t\tret = page_counter_limit(&h_cg->hugepage[idx], nr_pages);\n" - "+\t\tmutex_unlock(&hugetlb_limit_mutex);\n" - " \t\tbreak;\n" - " \tdefault:\n" - " \t\tret = -EINVAL;\n" - "@@ -306,10 +310,10 @@ static ssize_t hugetlb_cgroup_reset(struct kernfs_open_file *of,\n" - " \n" - " \tswitch (MEMFILE_ATTR(of_cft(of)->private)) {\n" - " \tcase RES_MAX_USAGE:\n" - "-\t\tcounter->watermark = atomic_long_read(&counter->count);\n" - "+\t\tpage_counter_reset_watermark(counter);\n" - " \t\tbreak;\n" - " \tcase RES_FAILCNT:\n" - "-\t\tcounter->limited = 0;\n" - "+\t\tcounter->failcnt = 0;\n" - " \t\tbreak;\n" - " \tdefault:\n" - " \t\tret = -EINVAL;\n" - "diff --git a/mm/memcontrol.c b/mm/memcontrol.c\n" - "index dfd3b15a57e8..9dec20b3c928 100644\n" - "--- a/mm/memcontrol.c\n" - "+++ b/mm/memcontrol.c\n" - "@@ -65,7 +65,7 @@\n" - " \n" - " #include <trace/events/vmscan.h>\n" - " \n" - "-int page_counter_cancel(struct page_counter *counter, unsigned long nr_pages)\n" - "+int page_counter_sub(struct page_counter *counter, unsigned long nr_pages)\n" - " {\n" - " \tlong new;\n" - " \n" - "@@ -74,28 +74,41 @@ int page_counter_cancel(struct page_counter *counter, unsigned long nr_pages)\n" - " \tif (WARN_ON(unlikely(new < 0)))\n" - " \t\tatomic_long_set(&counter->count, 0);\n" - " \n" - "-\treturn new > 1;\n" - "+\treturn new > 0;\n" - " }\n" - " \n" - "-int page_counter_charge(struct page_counter *counter, unsigned long nr_pages,\n" - "-\t\t\tstruct page_counter **fail)\n" - "+void page_counter_charge(struct page_counter *counter, unsigned long nr_pages)\n" - "+{\n" - "+\tstruct page_counter *c;\n" - "+\n" - "+\tfor (c = counter; c; c = c->parent) {\n" - "+\t\tlong new;\n" - "+\n" - "+\t\tnew = atomic_long_add_return(nr_pages, &c->count);\n" - "+\n" - "+\t\tif (new > c->watermark)\n" - "+\t\t\tc->watermark = new;\n" - "+\t}\n" - "+}\n" - "+\n" - "+int page_counter_try_charge(struct page_counter *counter,\n" - "+\t\t\t unsigned long nr_pages,\n" - "+\t\t\t struct page_counter **fail)\n" - " {\n" - " \tstruct page_counter *c;\n" - " \n" - " \tfor (c = counter; c; c = c->parent) {\n" - " \t\tfor (;;) {\n" - "-\t\t\tunsigned long count;\n" - "-\t\t\tunsigned long new;\n" - "+\t\t\tlong count;\n" - "+\t\t\tlong new;\n" - " \n" - " \t\t\tcount = atomic_long_read(&c->count);\n" - " \n" - " \t\t\tnew = count + nr_pages;\n" - " \t\t\tif (new > c->limit) {\n" - "-\t\t\t\tc->limited++;\n" - "-\t\t\t\tif (fail) {\n" - "-\t\t\t\t\t*fail = c;\n" - "-\t\t\t\t\tgoto failed;\n" - "-\t\t\t\t}\n" - "+\t\t\t\tc->failcnt++;\n" - "+\t\t\t\t*fail = c;\n" - "+\t\t\t\tgoto failed;\n" - " \t\t\t}\n" - " \n" - " \t\t\tif (atomic_long_cmpxchg(&c->count, count, new) != count)\n" - "@@ -111,7 +124,7 @@ int page_counter_charge(struct page_counter *counter, unsigned long nr_pages,\n" - " \n" - " failed:\n" - " \tfor (c = counter; c != *fail; c = c->parent)\n" - "-\t\tpage_counter_cancel(c, nr_pages);\n" - "+\t\tpage_counter_sub(c, nr_pages);\n" - " \n" - " \treturn -ENOMEM;\n" - " }\n" - "@@ -124,7 +137,7 @@ int page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages)\n" - " \tfor (c = counter; c; c = c->parent) {\n" - " \t\tint remainder;\n" - " \n" - "-\t\tremainder = page_counter_cancel(c, nr_pages);\n" - "+\t\tremainder = page_counter_sub(c, nr_pages);\n" - " \t\tif (c == counter && !remainder)\n" - " \t\t\tret = 0;\n" - " \t}\n" - "@@ -135,8 +148,8 @@ int page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages)\n" - " int page_counter_limit(struct page_counter *counter, unsigned long limit)\n" - " {\n" - " \tfor (;;) {\n" - "-\t\tunsigned long count;\n" - " \t\tunsigned long old;\n" - "+\t\tlong count;\n" - " \n" - " \t\tcount = atomic_long_read(&counter->count);\n" - " \n" - "@@ -751,7 +764,7 @@ static void disarm_kmem_keys(struct mem_cgroup *memcg)\n" - " \t * This check can't live in kmem destruction function,\n" - " \t * since the charges will outlive the cgroup\n" - " \t */\n" - "-\tWARN_ON(atomic_long_read(&memcg->kmem.count));\n" - "+\tWARN_ON(page_counter_read(&memcg->kmem));\n" - " }\n" - " #else\n" - " static void disarm_kmem_keys(struct mem_cgroup *memcg)\n" - "@@ -858,7 +871,7 @@ static void mem_cgroup_remove_exceeded(struct mem_cgroup_per_zone *mz,\n" - " \n" - " static unsigned long soft_limit_excess(struct mem_cgroup *memcg)\n" - " {\n" - "-\tunsigned long nr_pages = atomic_long_read(&memcg->memory.count);\n" - "+\tunsigned long nr_pages = page_counter_read(&memcg->memory);\n" - " \tunsigned long soft_limit = ACCESS_ONCE(memcg->soft_limit);\n" - " \tunsigned long excess = 0;\n" - " \n" - "@@ -1609,13 +1622,13 @@ static unsigned long mem_cgroup_margin(struct mem_cgroup *memcg)\n" - " \tunsigned long count;\n" - " \tunsigned long limit;\n" - " \n" - "-\tcount = atomic_long_read(&memcg->memory.count);\n" - "+\tcount = page_counter_read(&memcg->memory);\n" - " \tlimit = ACCESS_ONCE(memcg->memory.limit);\n" - " \tif (count < limit)\n" - " \t\tmargin = limit - count;\n" - " \n" - " \tif (do_swap_account) {\n" - "-\t\tcount = atomic_long_read(&memcg->memsw.count);\n" - "+\t\tcount = page_counter_read(&memcg->memsw);\n" - " \t\tlimit = ACCESS_ONCE(memcg->memsw.limit);\n" - " \t\tif (count < limit)\n" - " \t\t\tmargin = min(margin, limit - count);\n" - "@@ -1763,14 +1776,14 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)\n" - " \trcu_read_unlock();\n" - " \n" - " \tpr_info(\"memory: usage %llukB, limit %llukB, failcnt %lu\\n\",\n" - "-\t\tK((u64)atomic_long_read(&memcg->memory.count)),\n" - "-\t\tK((u64)memcg->memory.limit), memcg->memory.limited);\n" - "+\t\tK((u64)page_counter_read(&memcg->memory)),\n" - "+\t\tK((u64)memcg->memory.limit), memcg->memory.failcnt);\n" - " \tpr_info(\"memory+swap: usage %llukB, limit %llukB, failcnt %lu\\n\",\n" - "-\t\tK((u64)atomic_long_read(&memcg->memsw.count)),\n" - "-\t\tK((u64)memcg->memsw.limit), memcg->memsw.limited);\n" - "+\t\tK((u64)page_counter_read(&memcg->memsw)),\n" - "+\t\tK((u64)memcg->memsw.limit), memcg->memsw.failcnt);\n" - " \tpr_info(\"kmem: usage %llukB, limit %llukB, failcnt %lu\\n\",\n" - "-\t\tK((u64)atomic_long_read(&memcg->kmem.count)),\n" - "-\t\tK((u64)memcg->kmem.limit), memcg->kmem.limited);\n" - "+\t\tK((u64)page_counter_read(&memcg->kmem)),\n" - "+\t\tK((u64)memcg->kmem.limit), memcg->kmem.failcnt);\n" - " \n" - " \tfor_each_mem_cgroup_tree(iter, memcg) {\n" - " \t\tpr_info(\"Memory cgroup stats for \");\n" - "@@ -2604,10 +2617,10 @@ retry:\n" - " \tif (consume_stock(memcg, nr_pages))\n" - " \t\tgoto done;\n" - " \n" - "-\tif (!page_counter_charge(&memcg->memory, batch, &counter)) {\n" - "+\tif (!page_counter_try_charge(&memcg->memory, batch, &counter)) {\n" - " \t\tif (!do_swap_account)\n" - " \t\t\tgoto done_restock;\n" - "-\t\tif (!page_counter_charge(&memcg->memsw, batch, &counter))\n" - "+\t\tif (!page_counter_try_charge(&memcg->memsw, batch, &counter))\n" - " \t\t\tgoto done_restock;\n" - " \t\tpage_counter_uncharge(&memcg->memory, batch);\n" - " \t\tmem_over_limit = mem_cgroup_from_counter(counter, memsw);\n" - "@@ -2877,7 +2890,7 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp,\n" - " \tstruct page_counter *counter;\n" - " \tint ret = 0;\n" - " \n" - "-\tret = page_counter_charge(&memcg->kmem, nr_pages, &counter);\n" - "+\tret = page_counter_try_charge(&memcg->kmem, nr_pages, &counter);\n" - " \tif (ret < 0)\n" - " \t\treturn ret;\n" - " \n" - "@@ -2898,9 +2911,9 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp,\n" - " \t\t * when the allocation triggers should have been already\n" - " \t\t * directed to the root cgroup in memcontrol.h\n" - " \t\t */\n" - "-\t\tpage_counter_charge(&memcg->memory, nr_pages, NULL);\n" - "+\t\tpage_counter_charge(&memcg->memory, nr_pages);\n" - " \t\tif (do_swap_account)\n" - "-\t\t\tpage_counter_charge(&memcg->memsw, nr_pages, NULL);\n" - "+\t\t\tpage_counter_charge(&memcg->memsw, nr_pages);\n" - " \t\tret = 0;\n" - " \t} else if (ret)\n" - " \t\tpage_counter_uncharge(&memcg->kmem, nr_pages);\n" - "@@ -3558,9 +3571,9 @@ static int mem_cgroup_move_parent(struct page *page,\n" - " \t\t\t\tpc, child, parent);\n" - " \tif (!ret) {\n" - " \t\t/* Take charge off the local counters */\n" - "-\t\tpage_counter_cancel(&child->memory, nr_pages);\n" - "+\t\tpage_counter_sub(&child->memory, nr_pages);\n" - " \t\tif (do_swap_account)\n" - "-\t\t\tpage_counter_cancel(&child->memsw, nr_pages);\n" - "+\t\t\tpage_counter_sub(&child->memsw, nr_pages);\n" - " \t}\n" - " \n" - " \tif (nr_pages > 1)\n" - "@@ -3665,7 +3678,7 @@ void mem_cgroup_print_bad_page(struct page *page)\n" - " }\n" - " #endif\n" - " \n" - "-static DEFINE_MUTEX(set_limit_mutex);\n" - "+static DEFINE_MUTEX(memcg_limit_mutex);\n" - " \n" - " static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,\n" - " \t\t\t\t unsigned long limit)\n" - "@@ -3684,7 +3697,7 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,\n" - " \tretry_count = MEM_CGROUP_RECLAIM_RETRIES *\n" - " \t\t mem_cgroup_count_children(memcg);\n" - " \n" - "-\toldusage = atomic_long_read(&memcg->memory.count);\n" - "+\toldusage = page_counter_read(&memcg->memory);\n" - " \n" - " \tdo {\n" - " \t\tif (signal_pending(current)) {\n" - "@@ -3692,23 +3705,23 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,\n" - " \t\t\tbreak;\n" - " \t\t}\n" - " \n" - "-\t\tmutex_lock(&set_limit_mutex);\n" - "+\t\tmutex_lock(&memcg_limit_mutex);\n" - " \t\tif (limit > memcg->memsw.limit) {\n" - "-\t\t\tmutex_unlock(&set_limit_mutex);\n" - "+\t\t\tmutex_unlock(&memcg_limit_mutex);\n" - " \t\t\tret = -EINVAL;\n" - " \t\t\tbreak;\n" - " \t\t}\n" - " \t\tif (limit > memcg->memory.limit)\n" - " \t\t\tenlarge = true;\n" - " \t\tret = page_counter_limit(&memcg->memory, limit);\n" - "-\t\tmutex_unlock(&set_limit_mutex);\n" - "+\t\tmutex_unlock(&memcg_limit_mutex);\n" - " \n" - " \t\tif (!ret)\n" - " \t\t\tbreak;\n" - " \n" - " \t\ttry_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, true);\n" - " \n" - "-\t\tcurusage = atomic_long_read(&memcg->memory.count);\n" - "+\t\tcurusage = page_counter_read(&memcg->memory);\n" - " \t\t/* Usage is reduced ? */\n" - " \t\tif (curusage >= oldusage)\n" - " \t\t\tretry_count--;\n" - "@@ -3735,7 +3748,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,\n" - " \tretry_count = MEM_CGROUP_RECLAIM_RETRIES *\n" - " \t\t mem_cgroup_count_children(memcg);\n" - " \n" - "-\toldusage = atomic_long_read(&memcg->memsw.count);\n" - "+\toldusage = page_counter_read(&memcg->memsw);\n" - " \n" - " \tdo {\n" - " \t\tif (signal_pending(current)) {\n" - "@@ -3743,23 +3756,23 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,\n" - " \t\t\tbreak;\n" - " \t\t}\n" - " \n" - "-\t\tmutex_lock(&set_limit_mutex);\n" - "+\t\tmutex_lock(&memcg_limit_mutex);\n" - " \t\tif (limit < memcg->memory.limit) {\n" - "-\t\t\tmutex_unlock(&set_limit_mutex);\n" - "+\t\t\tmutex_unlock(&memcg_limit_mutex);\n" - " \t\t\tret = -EINVAL;\n" - " \t\t\tbreak;\n" - " \t\t}\n" - " \t\tif (limit > memcg->memsw.limit)\n" - " \t\t\tenlarge = true;\n" - " \t\tret = page_counter_limit(&memcg->memsw, limit);\n" - "-\t\tmutex_unlock(&set_limit_mutex);\n" - "+\t\tmutex_unlock(&memcg_limit_mutex);\n" - " \n" - " \t\tif (!ret)\n" - " \t\t\tbreak;\n" - " \n" - " \t\ttry_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, false);\n" - " \n" - "-\t\tcurusage = atomic_long_read(&memcg->memsw.count);\n" - "+\t\tcurusage = page_counter_read(&memcg->memsw);\n" - " \t\t/* Usage is reduced ? */\n" - " \t\tif (curusage >= oldusage)\n" - " \t\t\tretry_count--;\n" - "@@ -3960,8 +3973,8 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)\n" - " \t\t * right after the check. RES_USAGE should be safe as we always\n" - " \t\t * charge before adding to the LRU.\n" - " \t\t */\n" - "-\t} while (atomic_long_read(&memcg->memory.count) -\n" - "-\t\t atomic_long_read(&memcg->kmem.count) > 0);\n" - "+\t} while (page_counter_read(&memcg->memory) -\n" - "+\t\t page_counter_read(&memcg->kmem) > 0);\n" - " }\n" - " \n" - " /*\n" - "@@ -4001,7 +4014,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)\n" - " \t/* we call try-to-free pages for make this cgroup empty */\n" - " \tlru_add_drain_all();\n" - " \t/* try to free all pages in this cgroup */\n" - "-\twhile (nr_retries && atomic_long_read(&memcg->memory.count)) {\n" - "+\twhile (nr_retries && page_counter_read(&memcg->memory)) {\n" - " \t\tint progress;\n" - " \n" - " \t\tif (signal_pending(current))\n" - "@@ -4098,9 +4111,9 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)\n" - " \t\t\tval += tree_stat(memcg, MEM_CGROUP_STAT_SWAP);\n" - " \t} else {\n" - " \t\tif (!swap)\n" - "-\t\t\tval = atomic_long_read(&memcg->memory.count);\n" - "+\t\t\tval = page_counter_read(&memcg->memory);\n" - " \t\telse\n" - "-\t\t\tval = atomic_long_read(&memcg->memsw.count);\n" - "+\t\t\tval = page_counter_read(&memcg->memsw);\n" - " \t}\n" - " \treturn val << PAGE_SHIFT;\n" - " }\n" - "@@ -4139,13 +4152,13 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,\n" - " \t\t\treturn mem_cgroup_usage(memcg, false);\n" - " \t\tif (counter == &memcg->memsw)\n" - " \t\t\treturn mem_cgroup_usage(memcg, true);\n" - "-\t\treturn (u64)atomic_long_read(&counter->count) * PAGE_SIZE;\n" - "+\t\treturn (u64)page_counter_read(counter) * PAGE_SIZE;\n" - " \tcase RES_LIMIT:\n" - " \t\treturn (u64)counter->limit * PAGE_SIZE;\n" - " \tcase RES_MAX_USAGE:\n" - " \t\treturn (u64)counter->watermark * PAGE_SIZE;\n" - " \tcase RES_FAILCNT:\n" - "-\t\treturn counter->limited;\n" - "+\t\treturn counter->failcnt;\n" - " \tcase RES_SOFT_LIMIT:\n" - " \t\treturn (u64)memcg->soft_limit * PAGE_SIZE;\n" - " \tdefault:\n" - "@@ -4234,10 +4247,12 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,\n" - " {\n" - " \tint ret;\n" - " \n" - "+\tmutex_lock(&memcg_limit_mutex);\n" - " \tif (!memcg_kmem_is_active(memcg))\n" - " \t\tret = memcg_activate_kmem(memcg, limit);\n" - " \telse\n" - " \t\tret = page_counter_limit(&memcg->kmem, limit);\n" - "+\tmutex_unlock(&memcg_limit_mutex);\n" - " \treturn ret;\n" - " }\n" - " \n" - "@@ -4255,7 +4270,7 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)\n" - " \t * after this point, because it has at least one child already.\n" - " \t */\n" - " \tif (memcg_kmem_is_active(parent))\n" - "-\t\tret = __memcg_activate_kmem(memcg, ULONG_MAX);\n" - "+\t\tret = __memcg_activate_kmem(memcg, PAGE_COUNTER_MAX);\n" - " \tmutex_unlock(&activate_kmem_mutex);\n" - " \treturn ret;\n" - " }\n" - "@@ -4331,10 +4346,10 @@ static ssize_t mem_cgroup_reset(struct kernfs_open_file *of, char *buf,\n" - " \n" - " \tswitch (MEMFILE_ATTR(of_cft(of)->private)) {\n" - " \tcase RES_MAX_USAGE:\n" - "-\t\tcounter->watermark = atomic_long_read(&counter->count);\n" - "+\t\tpage_counter_reset_watermark(counter);\n" - " \t\tbreak;\n" - " \tcase RES_FAILCNT:\n" - "-\t\tcounter->limited = 0;\n" - "+\t\tcounter->failcnt = 0;\n" - " \t\tbreak;\n" - " \tdefault:\n" - " \t\tBUG();\n" - "@@ -4934,7 +4949,7 @@ static void kmem_cgroup_css_offline(struct mem_cgroup *memcg)\n" - " \n" - " \tmemcg_kmem_mark_dead(memcg);\n" - " \n" - "-\tif (atomic_long_read(&memcg->kmem.count))\n" - "+\tif (page_counter_read(&memcg->kmem))\n" - " \t\treturn;\n" - " \n" - " \tif (memcg_kmem_test_and_clear_dead(memcg))\n" - "@@ -5603,7 +5618,7 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css)\n" - " \t * call_rcu()\n" - " \t * offline_css()\n" - " \t * reparent_charges()\n" - "-\t * page_counter_charge()\n" - "+\t * page_counter_try_charge()\n" - " \t * css_put()\n" - " \t * css_free()\n" - " \t * pc->mem_cgroup = dead memcg\n" - "diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c\n" - "index 9a448bdb19e9..272327134a1b 100644\n" - "--- a/net/ipv4/tcp_memcontrol.c\n" - "+++ b/net/ipv4/tcp_memcontrol.c\n" - "@@ -68,7 +68,7 @@ static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)\n" - " \t\tcg_proto->sysctl_mem[i] = min_t(long, nr_pages,\n" - " \t\t\t\t\t\tsysctl_tcp_mem[i]);\n" - " \n" - "-\tif (nr_pages == ULONG_MAX / PAGE_SIZE)\n" - "+\tif (nr_pages == PAGE_COUNTER_MAX)\n" - " \t\tclear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags);\n" - " \telse {\n" - " \t\t/*\n" - "@@ -106,6 +106,8 @@ enum {\n" - " \tRES_FAILCNT,\n" - " };\n" - " \n" - "+static DEFINE_MUTEX(tcp_limit_mutex);\n" - "+\n" - " static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,\n" - " \t\t\t\tchar *buf, size_t nbytes, loff_t off)\n" - " {\n" - "@@ -121,7 +123,9 @@ static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,\n" - " \t\tret = page_counter_memparse(buf, &nr_pages);\n" - " \t\tif (ret)\n" - " \t\t\tbreak;\n" - "+\t\tmutex_lock(&tcp_limit_mutex);\n" - " \t\tret = tcp_update_limit(memcg, nr_pages);\n" - "+\t\tmutex_unlock(&tcp_limit_mutex);\n" - " \t\tbreak;\n" - " \tdefault:\n" - " \t\tret = -EINVAL;\n" - "@@ -145,14 +149,15 @@ static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft)\n" - " \t\tbreak;\n" - " \tcase RES_USAGE:\n" - " \t\tif (!cg_proto)\n" - "-\t\t\treturn atomic_long_read(&tcp_memory_allocated);\n" - "-\t\tval = atomic_long_read(&cg_proto->memory_allocated.count);\n" - "+\t\t\tval = atomic_long_read(&tcp_memory_allocated);\n" - "+\t\telse\n" - "+\t\t\tval = page_counter_read(&cg_proto->memory_allocated);\n" - " \t\tval *= PAGE_SIZE;\n" - " \t\tbreak;\n" - " \tcase RES_FAILCNT:\n" - " \t\tif (!cg_proto)\n" - " \t\t\treturn 0;\n" - "-\t\tval = cg_proto->memory_allocated.limited;\n" - "+\t\tval = cg_proto->memory_allocated.failcnt;\n" - " \t\tbreak;\n" - " \tcase RES_MAX_USAGE:\n" - " \t\tif (!cg_proto)\n" - "@@ -179,11 +184,10 @@ static ssize_t tcp_cgroup_reset(struct kernfs_open_file *of,\n" - " \n" - " \tswitch (of_cft(of)->private) {\n" - " \tcase RES_MAX_USAGE:\n" - "-\t\tcg_proto->memory_allocated.watermark =\n" - "-\t\t\tatomic_long_read(&cg_proto->memory_allocated.count);\n" - "+\t\tpage_counter_reset_watermark(&cg_proto->memory_allocated);\n" - " \t\tbreak;\n" - " \tcase RES_FAILCNT:\n" - "-\t\tcg_proto->memory_allocated.limited = 0;\n" - "+\t\tcg_proto->memory_allocated.failcnt = 0;\n" - " \t\tbreak;\n" - " \t}\n" - " \n" - "-- \n" - "2.1.0\n" - "\n" - "\n" - "--\n" - "To unsubscribe, send a message with 'unsubscribe linux-mm' in\n" - "the body to majordomo@kvack.org. For more info on Linux MM,\n" - "see: http://www.linux-mm.org/ .\n" - "Don't email: <a href=mailto:\"dont@kvack.org\"> email@kvack.org </a>" + --- -89f67fcc0f7cd7d3c101e0f4628ef42b7213f688766a5c4803e345c654f5c7b2 +3dda00bc6d03373b5eab47b61048550d4de920f67e9cdada604e56e45e002421
diff --git a/a/1.txt b/N2/1.txt index 54985a3..c090594 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -451,7 +451,7 @@ Thanks for your thorough review, Vladimir! Here is the delta patch: --- -From 3601538347af756b9bfe05142ab21b5ae44f8cdd Mon Sep 17 00:00:00 2001 +>From 3601538347af756b9bfe05142ab21b5ae44f8cdd Mon Sep 17 00:00:00 2001 From: Johannes Weiner <hannes@cmpxchg.org> Date: Mon, 22 Sep 2014 13:54:24 -0400 Subject: [patch] mm: memcontrol: lockless page counters fix @@ -1089,10 +1089,3 @@ index 9a448bdb19e9..272327134a1b 100644 -- 2.1.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> diff --git a/a/content_digest b/N2/content_digest index dd677e0..2fb009b 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -465,7 +465,7 @@ "Here is the delta patch:\n" "\n" "---\n" - "From 3601538347af756b9bfe05142ab21b5ae44f8cdd Mon Sep 17 00:00:00 2001\n" + ">From 3601538347af756b9bfe05142ab21b5ae44f8cdd Mon Sep 17 00:00:00 2001\n" "From: Johannes Weiner <hannes@cmpxchg.org>\n" "Date: Mon, 22 Sep 2014 13:54:24 -0400\n" "Subject: [patch] mm: memcontrol: lockless page counters fix\n" @@ -1102,13 +1102,6 @@ " \t}\n" " \n" "-- \n" - "2.1.0\n" - "\n" - "\n" - "--\n" - "To unsubscribe, send a message with 'unsubscribe linux-mm' in\n" - "the body to majordomo@kvack.org. For more info on Linux MM,\n" - "see: http://www.linux-mm.org/ .\n" - "Don't email: <a href=mailto:\"dont@kvack.org\"> email@kvack.org </a>" + 2.1.0 -89f67fcc0f7cd7d3c101e0f4628ef42b7213f688766a5c4803e345c654f5c7b2 +a376983028772f94e302625bcef6b32d79a3ee4792d1e00ecd030831f1d7a8cd
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.