]> 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 6c055929c8cc3250f895ca7e264fdeb0a8d4a934..c7b0b1b803a5c1ec81787b0193130de5edd0758a 100644 (file)
@@ -388,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)
@@ -2060,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);
@@ -2250,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;
@@ -2273,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;
@@ -2297,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;
 
        /*
@@ -2371,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 {
@@ -2396,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
@@ -2431,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;
@@ -3289,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)) {
@@ -3359,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*/
@@ -3939,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);
@@ -3975,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;
 
@@ -4051,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);
@@ -4387,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;
 
@@ -4470,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;
 
@@ -4548,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);
@@ -4573,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);