*/
        struct page_counter hugepage[HUGE_MAX_HSTATE];
 
+       /*
+        * the counter to account for hugepage reservations from hugetlb.
+        */
+       struct page_counter rsvd_hugepage[HUGE_MAX_HSTATE];
+
        atomic_long_t events[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS];
        atomic_long_t events_local[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS];
 
 
 static struct hugetlb_cgroup *root_h_cgroup __read_mostly;
 
+static inline struct page_counter *
+hugetlb_cgroup_counter_from_cgroup(struct hugetlb_cgroup *h_cg, int idx,
+                                  bool rsvd)
+{
+       if (rsvd)
+               return &h_cg->rsvd_hugepage[idx];
+       return &h_cg->hugepage[idx];
+}
+
 static inline
 struct hugetlb_cgroup *hugetlb_cgroup_from_css(struct cgroup_subsys_state *s)
 {
 
 enum {
        RES_USAGE,
+       RES_RSVD_USAGE,
        RES_LIMIT,
+       RES_RSVD_LIMIT,
        RES_MAX_USAGE,
+       RES_RSVD_MAX_USAGE,
        RES_FAILCNT,
+       RES_RSVD_FAILCNT,
 };
 
 static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css,
                                   struct cftype *cft)
 {
        struct page_counter *counter;
+       struct page_counter *rsvd_counter;
        struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
 
        counter = &h_cg->hugepage[MEMFILE_IDX(cft->private)];
+       rsvd_counter = &h_cg->rsvd_hugepage[MEMFILE_IDX(cft->private)];
 
        switch (MEMFILE_ATTR(cft->private)) {
        case RES_USAGE:
                return (u64)page_counter_read(counter) * PAGE_SIZE;
+       case RES_RSVD_USAGE:
+               return (u64)page_counter_read(rsvd_counter) * PAGE_SIZE;
        case RES_LIMIT:
                return (u64)counter->max * PAGE_SIZE;
+       case RES_RSVD_LIMIT:
+               return (u64)rsvd_counter->max * PAGE_SIZE;
        case RES_MAX_USAGE:
                return (u64)counter->watermark * PAGE_SIZE;
+       case RES_RSVD_MAX_USAGE:
+               return (u64)rsvd_counter->watermark * PAGE_SIZE;
        case RES_FAILCNT:
                return counter->failcnt;
+       case RES_RSVD_FAILCNT:
+               return rsvd_counter->failcnt;
        default:
                BUG();
        }
                           1 << huge_page_order(&hstates[idx]));
 
        switch (MEMFILE_ATTR(cft->private)) {
+       case RES_RSVD_USAGE:
+               counter = &h_cg->rsvd_hugepage[idx];
+               /* Fall through. */
        case RES_USAGE:
                val = (u64)page_counter_read(counter);
                seq_printf(seq, "%llu\n", val * PAGE_SIZE);
                break;
+       case RES_RSVD_LIMIT:
+               counter = &h_cg->rsvd_hugepage[idx];
+               /* Fall through. */
        case RES_LIMIT:
                val = (u64)counter->max;
                if (val == limit)
        int ret, idx;
        unsigned long nr_pages;
        struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
+       bool rsvd = false;
 
        if (hugetlb_cgroup_is_root(h_cg)) /* Can't set limit on root */
                return -EINVAL;
        nr_pages = round_down(nr_pages, 1 << huge_page_order(&hstates[idx]));
 
        switch (MEMFILE_ATTR(of_cft(of)->private)) {
+       case RES_RSVD_LIMIT:
+               rsvd = true;
+               /* Fall through. */
        case RES_LIMIT:
                mutex_lock(&hugetlb_limit_mutex);
-               ret = page_counter_set_max(&h_cg->hugepage[idx], nr_pages);
+               ret = page_counter_set_max(
+                       hugetlb_cgroup_counter_from_cgroup(h_cg, idx, rsvd),
+                       nr_pages);
                mutex_unlock(&hugetlb_limit_mutex);
                break;
        default:
                                    char *buf, size_t nbytes, loff_t off)
 {
        int ret = 0;
-       struct page_counter *counter;
+       struct page_counter *counter, *rsvd_counter;
        struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
 
        counter = &h_cg->hugepage[MEMFILE_IDX(of_cft(of)->private)];
+       rsvd_counter = &h_cg->rsvd_hugepage[MEMFILE_IDX(of_cft(of)->private)];
 
        switch (MEMFILE_ATTR(of_cft(of)->private)) {
        case RES_MAX_USAGE:
                page_counter_reset_watermark(counter);
                break;
+       case RES_RSVD_MAX_USAGE:
+               page_counter_reset_watermark(rsvd_counter);
+               break;
        case RES_FAILCNT:
                counter->failcnt = 0;
                break;
+       case RES_RSVD_FAILCNT:
+               rsvd_counter->failcnt = 0;
+               break;
        default:
                ret = -EINVAL;
                break;
        struct hstate *h = &hstates[idx];
 
        /* format the size */
-       mem_fmt(buf, 32, huge_page_size(h));
+       mem_fmt(buf, sizeof(buf), huge_page_size(h));
 
        /* Add the limit file */
        cft = &h->cgroup_files_dfl[0];
        cft->write = hugetlb_cgroup_write_dfl;
        cft->flags = CFTYPE_NOT_ON_ROOT;
 
-       /* Add the current usage file */
+       /* Add the reservation limit file */
        cft = &h->cgroup_files_dfl[1];
+       snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.max", buf);
+       cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_LIMIT);
+       cft->seq_show = hugetlb_cgroup_read_u64_max;
+       cft->write = hugetlb_cgroup_write_dfl;
+       cft->flags = CFTYPE_NOT_ON_ROOT;
+
+       /* Add the current usage file */
+       cft = &h->cgroup_files_dfl[2];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.current", buf);
        cft->private = MEMFILE_PRIVATE(idx, RES_USAGE);
        cft->seq_show = hugetlb_cgroup_read_u64_max;
        cft->flags = CFTYPE_NOT_ON_ROOT;
 
+       /* Add the current reservation usage file */
+       cft = &h->cgroup_files_dfl[3];
+       snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.current", buf);
+       cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_USAGE);
+       cft->seq_show = hugetlb_cgroup_read_u64_max;
+       cft->flags = CFTYPE_NOT_ON_ROOT;
+
        /* Add the events file */
-       cft = &h->cgroup_files_dfl[2];
+       cft = &h->cgroup_files_dfl[4];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.events", buf);
        cft->private = MEMFILE_PRIVATE(idx, 0);
        cft->seq_show = hugetlb_events_show;
        cft->flags = CFTYPE_NOT_ON_ROOT;
 
        /* Add the events.local file */
-       cft = &h->cgroup_files_dfl[3];
+       cft = &h->cgroup_files_dfl[5];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.events.local", buf);
        cft->private = MEMFILE_PRIVATE(idx, 0);
        cft->seq_show = hugetlb_events_local_show;
        cft->flags = CFTYPE_NOT_ON_ROOT;
 
        /* NULL terminate the last cft */
-       cft = &h->cgroup_files_dfl[4];
+       cft = &h->cgroup_files_dfl[6];
        memset(cft, 0, sizeof(*cft));
 
        WARN_ON(cgroup_add_dfl_cftypes(&hugetlb_cgrp_subsys,
        struct hstate *h = &hstates[idx];
 
        /* format the size */
-       mem_fmt(buf, 32, huge_page_size(h));
+       mem_fmt(buf, sizeof(buf), huge_page_size(h));
 
        /* Add the limit file */
        cft = &h->cgroup_files_legacy[0];
        cft->read_u64 = hugetlb_cgroup_read_u64;
        cft->write = hugetlb_cgroup_write_legacy;
 
-       /* Add the usage file */
+       /* Add the reservation limit file */
        cft = &h->cgroup_files_legacy[1];
+       snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.limit_in_bytes", buf);
+       cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_LIMIT);
+       cft->read_u64 = hugetlb_cgroup_read_u64;
+       cft->write = hugetlb_cgroup_write_legacy;
+
+       /* Add the usage file */
+       cft = &h->cgroup_files_legacy[2];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.usage_in_bytes", buf);
        cft->private = MEMFILE_PRIVATE(idx, RES_USAGE);
        cft->read_u64 = hugetlb_cgroup_read_u64;
 
+       /* Add the reservation usage file */
+       cft = &h->cgroup_files_legacy[3];
+       snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.usage_in_bytes", buf);
+       cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_USAGE);
+       cft->read_u64 = hugetlb_cgroup_read_u64;
+
        /* Add the MAX usage file */
-       cft = &h->cgroup_files_legacy[2];
+       cft = &h->cgroup_files_legacy[4];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max_usage_in_bytes", buf);
        cft->private = MEMFILE_PRIVATE(idx, RES_MAX_USAGE);
        cft->write = hugetlb_cgroup_reset;
        cft->read_u64 = hugetlb_cgroup_read_u64;
 
+       /* Add the MAX reservation usage file */
+       cft = &h->cgroup_files_legacy[5];
+       snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.max_usage_in_bytes", buf);
+       cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_MAX_USAGE);
+       cft->write = hugetlb_cgroup_reset;
+       cft->read_u64 = hugetlb_cgroup_read_u64;
+
        /* Add the failcntfile */
-       cft = &h->cgroup_files_legacy[3];
+       cft = &h->cgroup_files_legacy[6];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.failcnt", buf);
-       cft->private  = MEMFILE_PRIVATE(idx, RES_FAILCNT);
+       cft->private = MEMFILE_PRIVATE(idx, RES_FAILCNT);
+       cft->write = hugetlb_cgroup_reset;
+       cft->read_u64 = hugetlb_cgroup_read_u64;
+
+       /* Add the reservation failcntfile */
+       cft = &h->cgroup_files_legacy[7];
+       snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.failcnt", buf);
+       cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_FAILCNT);
        cft->write = hugetlb_cgroup_reset;
        cft->read_u64 = hugetlb_cgroup_read_u64;
 
        /* NULL terminate the last cft */
-       cft = &h->cgroup_files_legacy[4];
+       cft = &h->cgroup_files_legacy[8];
        memset(cft, 0, sizeof(*cft));
 
        WARN_ON(cgroup_add_legacy_cftypes(&hugetlb_cgrp_subsys,