]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - mm/memcontrol.c
memcg: change defines to an enum
[mirror_ubuntu-bionic-kernel.git] / mm / memcontrol.c
index 12307b3838fb37c37bda30c913b7ef6ea0a39734..c7b0b1b803a5c1ec81787b0193130de5edd0758a 100644 (file)
@@ -59,6 +59,8 @@
 #include <trace/events/vmscan.h>
 
 struct cgroup_subsys mem_cgroup_subsys __read_mostly;
+EXPORT_SYMBOL(mem_cgroup_subsys);
+
 #define MEM_CGROUP_RECLAIM_RETRIES     5
 static struct mem_cgroup *root_mem_cgroup __read_mostly;
 
@@ -386,9 +388,12 @@ enum charge_type {
 };
 
 /* for encoding cft->private value on file */
-#define _MEM                   (0)
-#define _MEMSWAP               (1)
-#define _OOM_TYPE              (2)
+enum res_type {
+       _MEM,
+       _MEMSWAP,
+       _OOM_TYPE,
+};
+
 #define MEMFILE_PRIVATE(x, val)        ((x) << 16 | (val))
 #define MEMFILE_TYPE(val)      ((val) >> 16 & 0xffff)
 #define MEMFILE_ATTR(val)      ((val) & 0xffff)
@@ -800,7 +805,7 @@ static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,
        int nid;
        u64 total = 0;
 
-       for_each_node_state(nid, N_HIGH_MEMORY)
+       for_each_node_state(nid, N_MEMORY)
                total += mem_cgroup_node_nr_lru_pages(memcg, nid, lru_mask);
        return total;
 }
@@ -1015,13 +1020,10 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
             iter != NULL;                              \
             iter = mem_cgroup_iter(NULL, iter, NULL))
 
-void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
+void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 {
        struct mem_cgroup *memcg;
 
-       if (!mm)
-               return;
-
        rcu_read_lock();
        memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
        if (unlikely(!memcg))
@@ -1040,7 +1042,7 @@ void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 out:
        rcu_read_unlock();
 }
-EXPORT_SYMBOL(mem_cgroup_count_vm_event);
+EXPORT_SYMBOL(__mem_cgroup_count_vm_event);
 
 /**
  * mem_cgroup_zone_lruvec - get the lru list vector for a zone and memcg
@@ -1644,9 +1646,9 @@ static void mem_cgroup_may_update_nodemask(struct mem_cgroup *memcg)
                return;
 
        /* make a nodemask where this memcg uses memory from */
-       memcg->scan_nodes = node_states[N_HIGH_MEMORY];
+       memcg->scan_nodes = node_states[N_MEMORY];
 
-       for_each_node_mask(nid, node_states[N_HIGH_MEMORY]) {
+       for_each_node_mask(nid, node_states[N_MEMORY]) {
 
                if (!test_mem_cgroup_node_reclaimable(memcg, nid, false))
                        node_clear(nid, memcg->scan_nodes);
@@ -1717,7 +1719,7 @@ static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
        /*
         * Check rest of nodes.
         */
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                if (node_isset(nid, memcg->scan_nodes))
                        continue;
                if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
@@ -2061,20 +2063,28 @@ struct memcg_stock_pcp {
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
 static DEFINE_MUTEX(percpu_charge_mutex);
 
-/*
- * Try to consume stocked charge on this cpu. If success, one page is consumed
- * from local stock and true is returned. If the stock is 0 or charges from a
- * cgroup which is not current target, returns false. This stock will be
- * refilled.
+/**
+ * consume_stock: Try to consume stocked charge on this cpu.
+ * @memcg: memcg to consume from.
+ * @nr_pages: how many pages to charge.
+ *
+ * The charges will only happen if @memcg matches the current cpu's memcg
+ * stock, and at least @nr_pages are available in that stock.  Failure to
+ * service an allocation will refill the stock.
+ *
+ * returns true if successful, false otherwise.
  */
-static bool consume_stock(struct mem_cgroup *memcg)
+static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
 {
        struct memcg_stock_pcp *stock;
        bool ret = true;
 
+       if (nr_pages > CHARGE_BATCH)
+               return false;
+
        stock = &get_cpu_var(memcg_stock);
-       if (memcg == stock->cached && stock->nr_pages)
-               stock->nr_pages--;
+       if (memcg == stock->cached && stock->nr_pages >= nr_pages)
+               stock->nr_pages -= nr_pages;
        else /* need to call res_counter_charge */
                ret = false;
        put_cpu_var(memcg_stock);
@@ -2251,7 +2261,8 @@ enum {
 };
 
 static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
-                               unsigned int nr_pages, bool oom_check)
+                               unsigned int nr_pages, unsigned int min_pages,
+                               bool oom_check)
 {
        unsigned long csize = nr_pages * PAGE_SIZE;
        struct mem_cgroup *mem_over_limit;
@@ -2274,18 +2285,18 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
        } else
                mem_over_limit = mem_cgroup_from_res_counter(fail_res, res);
        /*
-        * nr_pages can be either a huge page (HPAGE_PMD_NR), a batch
-        * of regular pages (CHARGE_BATCH), or a single regular page (1).
-        *
         * Never reclaim on behalf of optional batching, retry with a
         * single page instead.
         */
-       if (nr_pages == CHARGE_BATCH)
+       if (nr_pages > min_pages)
                return CHARGE_RETRY;
 
        if (!(gfp_mask & __GFP_WAIT))
                return CHARGE_WOULDBLOCK;
 
+       if (gfp_mask & __GFP_NORETRY)
+               return CHARGE_NOMEM;
+
        ret = mem_cgroup_reclaim(mem_over_limit, gfp_mask, flags);
        if (mem_cgroup_margin(mem_over_limit) >= nr_pages)
                return CHARGE_RETRY;
@@ -2298,7 +2309,7 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
         * unlikely to succeed so close to the limit, and we fall back
         * to regular pages anyway in case of failure.
         */
-       if (nr_pages == 1 && ret)
+       if (nr_pages <= (1 << PAGE_ALLOC_COSTLY_ORDER) && ret)
                return CHARGE_RETRY;
 
        /*
@@ -2372,7 +2383,7 @@ again:
                memcg = *ptr;
                if (mem_cgroup_is_root(memcg))
                        goto done;
-               if (nr_pages == 1 && consume_stock(memcg))
+               if (consume_stock(memcg, nr_pages))
                        goto done;
                css_get(&memcg->css);
        } else {
@@ -2397,7 +2408,7 @@ again:
                        rcu_read_unlock();
                        goto done;
                }
-               if (nr_pages == 1 && consume_stock(memcg)) {
+               if (consume_stock(memcg, nr_pages)) {
                        /*
                         * It seems dagerous to access memcg without css_get().
                         * But considering how consume_stok works, it's not
@@ -2432,7 +2443,8 @@ again:
                        nr_oom_retries = MEM_CGROUP_RECLAIM_RETRIES;
                }
 
-               ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, oom_check);
+               ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, nr_pages,
+                   oom_check);
                switch (ret) {
                case CHARGE_OK:
                        break;
@@ -3290,15 +3302,18 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
                                  struct mem_cgroup **memcgp)
 {
        struct mem_cgroup *memcg = NULL;
+       unsigned int nr_pages = 1;
        struct page_cgroup *pc;
        enum charge_type ctype;
 
        *memcgp = NULL;
 
-       VM_BUG_ON(PageTransHuge(page));
        if (mem_cgroup_disabled())
                return;
 
+       if (PageTransHuge(page))
+               nr_pages <<= compound_order(page);
+
        pc = lookup_page_cgroup(page);
        lock_page_cgroup(pc);
        if (PageCgroupUsed(pc)) {
@@ -3360,7 +3375,7 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
         * charged to the res_counter since we plan on replacing the
         * old one and only one page is going to be left afterwards.
         */
-       __mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false);
+       __mem_cgroup_commit_charge(memcg, newpage, nr_pages, ctype, false);
 }
 
 /* remove redundant charge if migration failed*/
@@ -3776,7 +3791,7 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)
                lru_add_drain_all();
                drain_all_stock_sync(memcg);
                mem_cgroup_start_move(memcg);
-               for_each_node_state(node, N_HIGH_MEMORY) {
+               for_each_node_state(node, N_MEMORY) {
                        for (zid = 0; zid < MAX_NR_ZONES; zid++) {
                                enum lru_list lru;
                                for_each_lru(lru) {
@@ -3940,7 +3955,8 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
        char str[64];
        u64 val;
-       int type, name, len;
+       int name, len;
+       enum res_type type;
 
        type = MEMFILE_TYPE(cft->private);
        name = MEMFILE_ATTR(cft->private);
@@ -3976,7 +3992,8 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
                            const char *buffer)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-       int type, name;
+       enum res_type type;
+       int name;
        unsigned long long val;
        int ret;
 
@@ -4052,7 +4069,8 @@ out:
 static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-       int type, name;
+       int name;
+       enum res_type type;
 
        type = MEMFILE_TYPE(event);
        name = MEMFILE_ATTR(event);
@@ -4122,7 +4140,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
        seq_printf(m, "total=%lu", total_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL);
                seq_printf(m, " N%d=%lu", nid, node_nr);
        }
@@ -4130,7 +4148,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        file_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_FILE);
        seq_printf(m, "file=%lu", file_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
                                LRU_ALL_FILE);
                seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4139,7 +4157,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        anon_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_ANON);
        seq_printf(m, "anon=%lu", anon_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
                                LRU_ALL_ANON);
                seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4148,7 +4166,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
        unevictable_nr = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
        seq_printf(m, "unevictable=%lu", unevictable_nr);
-       for_each_node_state(nid, N_HIGH_MEMORY) {
+       for_each_node_state(nid, N_MEMORY) {
                node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
                                BIT(LRU_UNEVICTABLE));
                seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4388,7 +4406,7 @@ static int mem_cgroup_usage_register_event(struct cgroup *cgrp,
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
        struct mem_cgroup_thresholds *thresholds;
        struct mem_cgroup_threshold_ary *new;
-       int type = MEMFILE_TYPE(cft->private);
+       enum res_type type = MEMFILE_TYPE(cft->private);
        u64 threshold, usage;
        int i, size, ret;
 
@@ -4471,7 +4489,7 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
        struct mem_cgroup_thresholds *thresholds;
        struct mem_cgroup_threshold_ary *new;
-       int type = MEMFILE_TYPE(cft->private);
+       enum res_type type = MEMFILE_TYPE(cft->private);
        u64 usage;
        int i, j, size;
 
@@ -4549,7 +4567,7 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
        struct mem_cgroup_eventfd_list *event;
-       int type = MEMFILE_TYPE(cft->private);
+       enum res_type type = MEMFILE_TYPE(cft->private);
 
        BUG_ON(type != _OOM_TYPE);
        event = kmalloc(sizeof(*event), GFP_KERNEL);
@@ -4574,7 +4592,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
        struct mem_cgroup_eventfd_list *ev, *tmp;
-       int type = MEMFILE_TYPE(cft->private);
+       enum res_type type = MEMFILE_TYPE(cft->private);
 
        BUG_ON(type != _OOM_TYPE);