hugetlb: check the return value of string conversion in sysctl handler
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / memcontrol.c
index 356d496..741206f 100644 (file)
@@ -1027,10 +1027,6 @@ mem_cgroup_get_reclaim_stat_from_page(struct page *page)
 {
        struct page_cgroup *pc;
        struct mem_cgroup_per_zone *mz;
-       int page_size = PAGE_SIZE;
-
-       if (PageTransHuge(page))
-               page_size <<= compound_order(page);
 
        if (mem_cgroup_disabled())
                return NULL;
@@ -1091,7 +1087,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                case 0:
                        list_move(&page->lru, dst);
                        mem_cgroup_del_lru(page);
-                       nr_taken++;
+                       nr_taken += hpage_nr_pages(page);
                        break;
                case -EBUSY:
                        /* we don't affect global LRU but rotate in our LRU */
@@ -2094,23 +2090,10 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
  * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be
  * USED state. If already USED, uncharge and return.
  */
-
-static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
-                                      struct page_cgroup *pc,
-                                      enum charge_type ctype,
-                                      int page_size)
+static void ____mem_cgroup_commit_charge(struct mem_cgroup *mem,
+                                        struct page_cgroup *pc,
+                                        enum charge_type ctype)
 {
-       /* try_charge() can return NULL to *memcg, taking care of it. */
-       if (!mem)
-               return;
-
-       lock_page_cgroup(pc);
-       if (unlikely(PageCgroupUsed(pc))) {
-               unlock_page_cgroup(pc);
-               mem_cgroup_cancel_charge(mem, page_size);
-               return;
-       }
-
        pc->mem_cgroup = mem;
        /*
         * We access a page_cgroup asynchronously without lock_page_cgroup().
@@ -2135,6 +2118,33 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
        }
 
        mem_cgroup_charge_statistics(mem, pc, true);
+}
+
+static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
+                                      struct page_cgroup *pc,
+                                      enum charge_type ctype,
+                                      int page_size)
+{
+       int i;
+       int count = page_size >> PAGE_SHIFT;
+
+       /* try_charge() can return NULL to *memcg, taking care of it. */
+       if (!mem)
+               return;
+
+       lock_page_cgroup(pc);
+       if (unlikely(PageCgroupUsed(pc))) {
+               unlock_page_cgroup(pc);
+               mem_cgroup_cancel_charge(mem, page_size);
+               return;
+       }
+
+       /*
+        * we don't need page_cgroup_lock about tail pages, becase they are not
+        * accessed by any other context at this point.
+        */
+       for (i = 0; i < count; i++)
+               ____mem_cgroup_commit_charge(mem, pc + i, ctype);
 
        unlock_page_cgroup(pc);
        /*
@@ -2272,8 +2282,10 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
        int ret;
        int page_size = PAGE_SIZE;
 
-       if (PageTransHuge(page))
+       if (PageTransHuge(page)) {
                page_size <<= compound_order(page);
+               VM_BUG_ON(!PageTransHuge(page));
+       }
 
        pc = lookup_page_cgroup(page);
        /* can happen at boot */
@@ -2532,6 +2544,8 @@ direct_uncharge:
 static struct mem_cgroup *
 __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 {
+       int i;
+       int count;
        struct page_cgroup *pc;
        struct mem_cgroup *mem = NULL;
        int page_size = PAGE_SIZE;
@@ -2542,9 +2556,12 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
        if (PageSwapCache(page))
                return NULL;
 
-       if (PageTransHuge(page))
+       if (PageTransHuge(page)) {
                page_size <<= compound_order(page);
+               VM_BUG_ON(!PageTransHuge(page));
+       }
 
+       count = page_size >> PAGE_SHIFT;
        /*
         * Check if our page_cgroup is valid
         */
@@ -2577,7 +2594,8 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
                break;
        }
 
-       mem_cgroup_charge_statistics(mem, pc, false);
+       for (i = 0; i < count; i++)
+               mem_cgroup_charge_statistics(mem, pc + i, false);
 
        ClearPageCgroupUsed(pc);
        /*