[PATCH -V1 6/9] hugetlbfs: Switch to new region APIs

From: Aneesh Kumar K.V
Date: Mon Feb 20 2012 - 06:23:28 EST


From: "Aneesh Kumar K.V" <aneesh.kumar@xxxxxxxxxxxxxxxxxx>

Remove the old code which is not used

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx>
---
fs/hugetlbfs/Makefile | 2 +-
fs/hugetlbfs/hugetlb_cgroup.c | 135 +--------------------------
fs/hugetlbfs/region.c | 202 ++++++++++++++++++++++++++++++++++++++++
include/linux/hugetlb_cgroup.h | 17 +++-
mm/hugetlb.c | 163 +--------------------------------
5 files changed, 222 insertions(+), 297 deletions(-)
create mode 100644 fs/hugetlbfs/region.c

diff --git a/fs/hugetlbfs/Makefile b/fs/hugetlbfs/Makefile
index 986c778..3c544fe 100644
--- a/fs/hugetlbfs/Makefile
+++ b/fs/hugetlbfs/Makefile
@@ -4,5 +4,5 @@

obj-$(CONFIG_HUGETLBFS) += hugetlbfs.o

-hugetlbfs-objs := inode.o
+hugetlbfs-objs := inode.o region.o
hugetlbfs-$(CONFIG_CGROUP_HUGETLB_RES_CTLR) += hugetlb_cgroup.o
diff --git a/fs/hugetlbfs/hugetlb_cgroup.c b/fs/hugetlbfs/hugetlb_cgroup.c
index a75661d..a4c6786 100644
--- a/fs/hugetlbfs/hugetlb_cgroup.c
+++ b/fs/hugetlbfs/hugetlb_cgroup.c
@@ -18,6 +18,8 @@
#include <linux/hugetlb.h>
#include <linux/res_counter.h>
#include <linux/list.h>
+#include <linux/hugetlb_cgroup.h>
+

/* lifted from mem control */
#define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val))
@@ -32,136 +34,9 @@ struct hugetlb_cgroup {
struct res_counter memhuge[HUGE_MAX_HSTATE];
};

-struct file_region_with_data {
- struct list_head link;
- long from;
- long to;
- unsigned long data;
-};
-
struct cgroup_subsys hugetlb_subsys __read_mostly;
struct hugetlb_cgroup *root_h_cgroup __read_mostly;

-/*
- * A vairant of region_add that only merges regions only if data
- * match.
- */
-static long region_chg_with_same(struct list_head *head,
- long f, long t, unsigned long data)
-{
- long chg = 0;
- struct file_region_with_data *rg, *nrg, *trg;
-
- /* Locate the region we are before or in. */
- list_for_each_entry(rg, head, link)
- if (f <= rg->to)
- break;
- /*
- * If we are below the current region then a new region is required.
- * Subtle, allocate a new region at the position but make it zero
- * size such that we can guarantee to record the reservation.
- */
- if (&rg->link == head || t < rg->from) {
- nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
- if (!nrg)
- return -ENOMEM;
- nrg->from = f;
- nrg->to = f;
- nrg->data = data;
- INIT_LIST_HEAD(&nrg->link);
- list_add(&nrg->link, rg->link.prev);
- return t - f;
- }
- /*
- * f rg->from t rg->to
- */
- if (f < rg->from && data != rg->data) {
- /* we need to allocate a new region */
- nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
- if (!nrg)
- return -ENOMEM;
- nrg->from = f;
- nrg->to = f;
- nrg->data = data;
- INIT_LIST_HEAD(&nrg->link);
- list_add(&nrg->link, rg->link.prev);
- }
-
- /* Round our left edge to the current segment if it encloses us. */
- if (f > rg->from)
- f = rg->from;
- chg = t - f;
-
- /* Check for and consume any regions we now overlap with. */
- list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- if (rg->from > t)
- return chg;
- /*
- * rg->from f rg->to t
- */
- if (t > rg->to && data != rg->data) {
- /* we need to allocate a new region */
- nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
- if (!nrg)
- return -ENOMEM;
- nrg->from = rg->to;
- nrg->to = rg->to;
- nrg->data = data;
- INIT_LIST_HEAD(&nrg->link);
- list_add(&nrg->link, &rg->link);
- }
- /*
- * update charge
- */
- if (rg->to > t) {
- chg += rg->to - t;
- t = rg->to;
- }
- chg -= rg->to - rg->from;
- }
- return chg;
-}
-
-static void region_add_with_same(struct list_head *head,
- long f, long t, unsigned long data)
-{
- struct file_region_with_data *rg, *nrg, *trg;
-
- /* Locate the region we are before or in. */
- list_for_each_entry(rg, head, link)
- if (f <= rg->to)
- break;
-
- list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
-
- if (rg->from > t)
- return;
- if (&rg->link == head)
- return;
-
- /*FIXME!! this can possibly delete few regions */
- /* We need to worry only if we match data */
- if (rg->data == data) {
- if (f < rg->from)
- rg->from = f;
- if (t > rg->to) {
- /* if we are the last entry */
- if (rg->link.next == head) {
- rg->to = t;
- break;
- } else {
- nrg = list_entry(rg->link.next,
- typeof(*nrg), link);
- rg->to = nrg->from;
- }
- }
- }
- f = rg->to;
- }
-}
-
static inline
struct hugetlb_cgroup *css_to_hugetlbcgroup(struct cgroup_subsys_state *s)
{
@@ -355,7 +230,7 @@ long hugetlb_page_charge(struct list_head *head,
css_get(&h_cg->css);
rcu_read_unlock();

- chg = region_chg_with_same(head, f, t, (unsigned long)h_cg);
+ chg = region_chg(head, f, t, (unsigned long)h_cg);
if (chg < 0)
goto err_out;

@@ -400,7 +275,7 @@ void hugetlb_commit_page_charge(struct list_head *head, long f, long t)

rcu_read_lock();
h_cg = task_hugetlbcgroup(current);
- region_add_with_same(head, f, t, (unsigned long)h_cg);
+ region_add(head, f, t, (unsigned long)h_cg);
rcu_read_unlock();
return;
}
@@ -411,7 +286,7 @@ long hugetlb_truncate_cgroup(struct hstate *h,
long chg = 0, csize;
int idx = h - hstates;
struct hugetlb_cgroup *h_cg;
- struct file_region_with_data *rg, *trg;
+ struct file_region *rg, *trg;

/* Locate the region we are either in or before. */
list_for_each_entry(rg, head, link)
diff --git a/fs/hugetlbfs/region.c b/fs/hugetlbfs/region.c
new file mode 100644
index 0000000..d2445fb
--- /dev/null
+++ b/fs/hugetlbfs/region.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright IBM Corporation, 2012
+ * Author Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <linux/cgroup.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
+#include <linux/list.h>
+#include <linux/hugetlb_cgroup.h>
+
+/*
+ * Region tracking -- allows tracking of reservations and instantiated pages
+ * across the pages in a mapping.
+ *
+ * The region data structures are protected by a combination of the mmap_sem
+ * and the hugetlb_instantion_mutex. To access or modify a region the caller
+ * must either hold the mmap_sem for write, or the mmap_sem for read and
+ * the hugetlb_instantiation mutex:
+ *
+ * down_write(&mm->mmap_sem);
+ * or
+ * down_read(&mm->mmap_sem);
+ * mutex_lock(&hugetlb_instantiation_mutex);
+ */
+
+long region_chg(struct list_head *head, long f, long t, unsigned long data)
+{
+ long chg = 0;
+ struct file_region *rg, *nrg, *trg;
+
+ /* Locate the region we are before or in. */
+ list_for_each_entry(rg, head, link)
+ if (f <= rg->to)
+ break;
+ /*
+ * If we are below the current region then a new region is required.
+ * Subtle, allocate a new region at the position but make it zero
+ * size such that we can guarantee to record the reservation.
+ */
+ if (&rg->link == head || t < rg->from) {
+ nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
+ if (!nrg)
+ return -ENOMEM;
+ nrg->from = f;
+ nrg->to = f;
+ nrg->data = data;
+ INIT_LIST_HEAD(&nrg->link);
+ list_add(&nrg->link, rg->link.prev);
+ return t - f;
+ }
+ /*
+ * f rg->from t rg->to
+ */
+ if (f < rg->from && data != rg->data) {
+ /* we need to allocate a new region */
+ nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
+ if (!nrg)
+ return -ENOMEM;
+ nrg->from = f;
+ nrg->to = f;
+ nrg->data = data;
+ INIT_LIST_HEAD(&nrg->link);
+ list_add(&nrg->link, rg->link.prev);
+ }
+
+ /* Round our left edge to the current segment if it encloses us. */
+ if (f > rg->from)
+ f = rg->from;
+ chg = t - f;
+
+ /* Check for and consume any regions we now overlap with. */
+ list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+ if (&rg->link == head)
+ break;
+ if (rg->from > t)
+ return chg;
+ /*
+ * rg->from f rg->to t
+ */
+ if (t > rg->to && data != rg->data) {
+ /* we need to allocate a new region */
+ nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
+ if (!nrg)
+ return -ENOMEM;
+ nrg->from = rg->to;
+ nrg->to = rg->to;
+ nrg->data = data;
+ INIT_LIST_HEAD(&nrg->link);
+ list_add(&nrg->link, &rg->link);
+ }
+ /*
+ * update charge
+ */
+ if (rg->to > t) {
+ chg += rg->to - t;
+ t = rg->to;
+ }
+ chg -= rg->to - rg->from;
+ }
+ return chg;
+}
+
+void region_add(struct list_head *head, long f, long t, unsigned long data)
+{
+ struct file_region *rg, *nrg, *trg;
+
+ /* Locate the region we are before or in. */
+ list_for_each_entry(rg, head, link)
+ if (f <= rg->to)
+ break;
+
+ list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+
+ if (rg->from > t)
+ return;
+ if (&rg->link == head)
+ return;
+
+ /*FIXME!! this can possibly delete few regions */
+ /* We need to worry only if we match data */
+ if (rg->data == data) {
+ if (f < rg->from)
+ rg->from = f;
+ if (t > rg->to) {
+ /* if we are the last entry */
+ if (rg->link.next == head) {
+ rg->to = t;
+ break;
+ } else {
+ nrg = list_entry(rg->link.next,
+ typeof(*nrg), link);
+ rg->to = nrg->from;
+ }
+ }
+ }
+ f = rg->to;
+ }
+}
+
+long region_truncate(struct list_head *head, long end)
+{
+ struct file_region *rg, *trg;
+ long chg = 0;
+
+ /* Locate the region we are either in or before. */
+ list_for_each_entry(rg, head, link)
+ if (end <= rg->to)
+ break;
+ if (&rg->link == head)
+ return 0;
+
+ /* If we are in the middle of a region then adjust it. */
+ if (end > rg->from) {
+ chg = rg->to - end;
+ rg->to = end;
+ rg = list_entry(rg->link.next, typeof(*rg), link);
+ }
+
+ /* Drop any remaining regions. */
+ list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+ if (&rg->link == head)
+ break;
+ chg += rg->to - rg->from;
+ list_del(&rg->link);
+ kfree(rg);
+ }
+ return chg;
+}
+
+long region_count(struct list_head *head, long f, long t)
+{
+ struct file_region *rg;
+ long chg = 0;
+
+ /* Locate each segment we overlap with, and count that overlap. */
+ list_for_each_entry(rg, head, link) {
+ int seg_from;
+ int seg_to;
+
+ if (rg->to <= f)
+ continue;
+ if (rg->from >= t)
+ break;
+
+ seg_from = max(rg->from, f);
+ seg_to = min(rg->to, t);
+
+ chg += seg_to - seg_from;
+ }
+
+ return chg;
+}
diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h
index 1af9dd8..eaad86b 100644
--- a/include/linux/hugetlb_cgroup.h
+++ b/include/linux/hugetlb_cgroup.h
@@ -15,8 +15,16 @@
#ifndef _LINUX_HUGETLB_CGROUP_H
#define _LINUX_HUGETLB_CGROUP_H

-extern long region_add(struct list_head *head, long f, long t);
-extern long region_chg(struct list_head *head, long f, long t);
+struct file_region {
+ long from, to;
+ unsigned long data;
+ struct list_head link;
+};
+
+extern long region_chg(struct list_head *head, long f, long t,
+ unsigned long data);
+extern void region_add(struct list_head *head, long f, long t,
+ unsigned long data);
extern long region_truncate(struct list_head *head, long end);
extern long region_count(struct list_head *head, long f, long t);

@@ -40,7 +48,7 @@ extern void hugetlb_priv_page_uncharge(struct resv_map *map,
static inline long hugetlb_page_charge(struct list_head *head,
struct hstate *h, long f, long t)
{
- return region_chg(head, f, t);
+ return region_chg(head, f, t, 0);
}

static inline void hugetlb_page_uncharge(struct list_head *head,
@@ -52,8 +60,7 @@ static inline void hugetlb_page_uncharge(struct list_head *head,
static inline void hugetlb_commit_page_charge(struct list_head *head,
long f, long t)
{
- region_add(head, f, t);
- return;
+ return region_add(head, f, t, 0);
}

static inline long hugetlb_truncate_cgroup(struct hstate *h,
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index e1a0328..08555c6 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -59,165 +59,6 @@ static unsigned long __initdata default_hstate_size;
static DEFINE_SPINLOCK(hugetlb_lock);

/*
- * Region tracking -- allows tracking of reservations and instantiated pages
- * across the pages in a mapping.
- *
- * The region data structures are protected by a combination of the mmap_sem
- * and the hugetlb_instantion_mutex. To access or modify a region the caller
- * must either hold the mmap_sem for write, or the mmap_sem for read and
- * the hugetlb_instantiation mutex:
- *
- * down_write(&mm->mmap_sem);
- * or
- * down_read(&mm->mmap_sem);
- * mutex_lock(&hugetlb_instantiation_mutex);
- */
-struct file_region {
- struct list_head link;
- long from;
- long to;
-};
-
-long region_add(struct list_head *head, long f, long t)
-{
- struct file_region *rg, *nrg, *trg;
-
- /* Locate the region we are either in or before. */
- list_for_each_entry(rg, head, link)
- if (f <= rg->to)
- break;
-
- /* Round our left edge to the current segment if it encloses us. */
- if (f > rg->from)
- f = rg->from;
-
- /* Check for and consume any regions we now overlap with. */
- nrg = rg;
- list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- if (rg->from > t)
- break;
-
- /* If this area reaches higher then extend our area to
- * include it completely. If this is not the first area
- * which we intend to reuse, free it. */
- if (rg->to > t)
- t = rg->to;
- if (rg != nrg) {
- list_del(&rg->link);
- kfree(rg);
- }
- }
- nrg->from = f;
- nrg->to = t;
- return 0;
-}
-
-long region_chg(struct list_head *head, long f, long t)
-{
- struct file_region *rg, *nrg;
- long chg = 0;
-
- /* Locate the region we are before or in. */
- list_for_each_entry(rg, head, link)
- if (f <= rg->to)
- break;
-
- /* If we are below the current region then a new region is required.
- * Subtle, allocate a new region at the position but make it zero
- * size such that we can guarantee to record the reservation. */
- if (&rg->link == head || t < rg->from) {
- nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
- if (!nrg)
- return -ENOMEM;
- nrg->from = f;
- nrg->to = f;
- INIT_LIST_HEAD(&nrg->link);
- list_add(&nrg->link, rg->link.prev);
-
- return t - f;
- }
-
- /* Round our left edge to the current segment if it encloses us. */
- if (f > rg->from)
- f = rg->from;
- chg = t - f;
-
- /* Check for and consume any regions we now overlap with. */
- list_for_each_entry(rg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- if (rg->from > t)
- return chg;
-
- /* We overlap with this area, if it extends further than
- * us then we must extend ourselves. Account for its
- * existing reservation. */
- if (rg->to > t) {
- chg += rg->to - t;
- t = rg->to;
- }
- chg -= rg->to - rg->from;
- }
- return chg;
-}
-
-long region_truncate(struct list_head *head, long end)
-{
- struct file_region *rg, *trg;
- long chg = 0;
-
- /* Locate the region we are either in or before. */
- list_for_each_entry(rg, head, link)
- if (end <= rg->to)
- break;
- if (&rg->link == head)
- return 0;
-
- /* If we are in the middle of a region then adjust it. */
- if (end > rg->from) {
- chg = rg->to - end;
- rg->to = end;
- rg = list_entry(rg->link.next, typeof(*rg), link);
- }
-
- /* Drop any remaining regions. */
- list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- chg += rg->to - rg->from;
- list_del(&rg->link);
- kfree(rg);
- }
- return chg;
-}
-
-long region_count(struct list_head *head, long f, long t)
-{
- struct file_region *rg;
- long chg = 0;
-
- /* Locate each segment we overlap with, and count that overlap. */
- list_for_each_entry(rg, head, link) {
- int seg_from;
- int seg_to;
-
- if (rg->to <= f)
- continue;
- if (rg->from >= t)
- break;
-
- seg_from = max(rg->from, f);
- seg_to = min(rg->to, t);
-
- chg += seg_to - seg_from;
- }
-
- return chg;
-}
-
-/*
* Convert the address within this vma to the page offset within
* the mapping, in pagecache page units; huge pages here.
*/
@@ -1008,7 +849,7 @@ static long vma_needs_reservation(struct hstate *h,
pgoff_t idx = vma_hugecache_offset(h, vma, addr);
struct resv_map *reservations = vma_resv_map(vma);

- err = region_chg(&reservations->regions, idx, idx + 1);
+ err = region_chg(&reservations->regions, idx, idx + 1, 0);
if (err < 0)
return err;
return 0;
@@ -1052,7 +893,7 @@ static void vma_commit_reservation(struct hstate *h,
struct resv_map *reservations = vma_resv_map(vma);

/* Mark this page used in the map. */
- region_add(&reservations->regions, idx, idx + 1);
+ region_add(&reservations->regions, idx, idx + 1, 0);
}
}

--
1.7.9

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/