aboutsummaryrefslogtreecommitdiffstats
path: root/mm/hugetlb.c
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@shadowen.org>2008-07-24 00:27:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:16 -0400
commit9682290484370ce68ba23cd2ec2838e301934199 (patch)
tree435dbd415ed2324d9f8e768425cf26704365cf3c /mm/hugetlb.c
parentcdfd4325c0d878679bd6a3ba8285b71d9980e3c0 (diff)
hugetlb: move reservation region support earlier
The following patch will require use of the reservation regions support. Move this earlier in the file. No changes have been made to this code. Signed-off-by: Andy Whitcroft <apw@shadowen.org> Cc: Mel Gorman <mel@csn.ul.ie> Acked-by: Adam Litke <agl@us.ibm.com> Cc: Johannes Weiner <hannes@saeurebad.de> Cc: Andy Whitcroft <apw@shadowen.org> Cc: William Lee Irwin III <wli@holomorphy.com> Cc: Hugh Dickins <hugh@veritas.com> Cc: Michael Kerrisk <mtk.manpages@googlemail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r--mm/hugetlb.c246
1 files changed, 125 insertions, 121 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 3e873f0101fb..05bc9af4fca9 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -41,6 +41,131 @@ static int hugetlb_next_nid;
41static DEFINE_SPINLOCK(hugetlb_lock); 41static DEFINE_SPINLOCK(hugetlb_lock);
42 42
43/* 43/*
44 * Region tracking -- allows tracking of reservations and instantiated pages
45 * across the pages in a mapping.
46 */
47struct file_region {
48 struct list_head link;
49 long from;
50 long to;
51};
52
53static long region_add(struct list_head *head, long f, long t)
54{
55 struct file_region *rg, *nrg, *trg;
56
57 /* Locate the region we are either in or before. */
58 list_for_each_entry(rg, head, link)
59 if (f <= rg->to)
60 break;
61
62 /* Round our left edge to the current segment if it encloses us. */
63 if (f > rg->from)
64 f = rg->from;
65
66 /* Check for and consume any regions we now overlap with. */
67 nrg = rg;
68 list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
69 if (&rg->link == head)
70 break;
71 if (rg->from > t)
72 break;
73
74 /* If this area reaches higher then extend our area to
75 * include it completely. If this is not the first area
76 * which we intend to reuse, free it. */
77 if (rg->to > t)
78 t = rg->to;
79 if (rg != nrg) {
80 list_del(&rg->link);
81 kfree(rg);
82 }
83 }
84 nrg->from = f;
85 nrg->to = t;
86 return 0;
87}
88
89static long region_chg(struct list_head *head, long f, long t)
90{
91 struct file_region *rg, *nrg;
92 long chg = 0;
93
94 /* Locate the region we are before or in. */
95 list_for_each_entry(rg, head, link)
96 if (f <= rg->to)
97 break;
98
99 /* If we are below the current region then a new region is required.
100 * Subtle, allocate a new region at the position but make it zero
101 * size such that we can guarantee to record the reservation. */
102 if (&rg->link == head || t < rg->from) {
103 nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
104 if (!nrg)
105 return -ENOMEM;
106 nrg->from = f;
107 nrg->to = f;
108 INIT_LIST_HEAD(&nrg->link);
109 list_add(&nrg->link, rg->link.prev);
110
111 return t - f;
112 }
113
114 /* Round our left edge to the current segment if it encloses us. */
115 if (f > rg->from)
116 f = rg->from;
117 chg = t - f;
118
119 /* Check for and consume any regions we now overlap with. */
120 list_for_each_entry(rg, rg->link.prev, link) {
121 if (&rg->link == head)
122 break;
123 if (rg->from > t)
124 return chg;
125
126 /* We overlap with this area, if it extends futher than
127 * us then we must extend ourselves. Account for its
128 * existing reservation. */
129 if (rg->to > t) {
130 chg += rg->to - t;
131 t = rg->to;
132 }
133 chg -= rg->to - rg->from;
134 }
135 return chg;
136}
137
138static long region_truncate(struct list_head *head, long end)
139{
140 struct file_region *rg, *trg;
141 long chg = 0;
142
143 /* Locate the region we are either in or before. */
144 list_for_each_entry(rg, head, link)
145 if (end <= rg->to)
146 break;
147 if (&rg->link == head)
148 return 0;
149
150 /* If we are in the middle of a region then adjust it. */
151 if (end > rg->from) {
152 chg = rg->to - end;
153 rg->to = end;
154 rg = list_entry(rg->link.next, typeof(*rg), link);
155 }
156
157 /* Drop any remaining regions. */
158 list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
159 if (&rg->link == head)
160 break;
161 chg += rg->to - rg->from;
162 list_del(&rg->link);
163 kfree(rg);
164 }
165 return chg;
166}
167
168/*
44 * Convert the address within this vma to the page offset within 169 * Convert the address within this vma to the page offset within
45 * the mapping, in base page units. 170 * the mapping, in base page units.
46 */ 171 */
@@ -1429,127 +1554,6 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
1429 flush_tlb_range(vma, start, end); 1554 flush_tlb_range(vma, start, end);
1430} 1555}
1431 1556
1432struct file_region {
1433 struct list_head link;
1434 long from;
1435 long to;
1436};
1437
1438static long region_add(struct list_head *head, long f, long t)
1439{
1440 struct file_region *rg, *nrg, *trg;
1441
1442 /* Locate the region we are either in or before. */
1443 list_for_each_entry(rg, head, link)
1444 if (f <= rg->to)
1445 break;
1446
1447 /* Round our left edge to the current segment if it encloses us. */
1448 if (f > rg->from)
1449 f = rg->from;
1450
1451 /* Check for and consume any regions we now overlap with. */
1452 nrg = rg;
1453 list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
1454 if (&rg->link == head)
1455 break;
1456 if (rg->from > t)
1457 break;
1458
1459 /* If this area reaches higher then extend our area to
1460 * include it completely. If this is not the first area
1461 * which we intend to reuse, free it. */
1462 if (rg->to > t)
1463 t = rg->to;
1464 if (rg != nrg) {
1465 list_del(&rg->link);
1466 kfree(rg);
1467 }
1468 }
1469 nrg->from = f;
1470 nrg->to = t;
1471 return 0;
1472}
1473
1474static long region_chg(struct list_head *head, long f, long t)
1475{
1476 struct file_region *rg, *nrg;
1477 long chg = 0;
1478
1479 /* Locate the region we are before or in. */
1480 list_for_each_entry(rg, head, link)
1481 if (f <= rg->to)
1482 break;
1483
1484 /* If we are below the current region then a new region is required.
1485 * Subtle, allocate a new region at the position but make it zero
1486 * size such that we can guarantee to record the reservation. */
1487 if (&rg->link == head || t < rg->from) {
1488 nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
1489 if (!nrg)
1490 return -ENOMEM;
1491 nrg->from = f;
1492 nrg->to = f;
1493 INIT_LIST_HEAD(&nrg->link);
1494 list_add(&nrg->link, rg->link.prev);
1495
1496 return t - f;
1497 }
1498
1499 /* Round our left edge to the current segment if it encloses us. */
1500 if (f > rg->from)
1501 f = rg->from;
1502 chg = t - f;
1503
1504 /* Check for and consume any regions we now overlap with. */
1505 list_for_each_entry(rg, rg->link.prev, link) {
1506 if (&rg->link == head)
1507 break;
1508 if (rg->from > t)
1509 return chg;
1510
1511 /* We overlap with this area, if it extends futher than
1512 * us then we must extend ourselves. Account for its
1513 * existing reservation. */
1514 if (rg->to > t) {
1515 chg += rg->to - t;
1516 t = rg->to;
1517 }
1518 chg -= rg->to - rg->from;
1519 }
1520 return chg;
1521}
1522
1523static long region_truncate(struct list_head *head, long end)
1524{
1525 struct file_region *rg, *trg;
1526 long chg = 0;
1527
1528 /* Locate the region we are either in or before. */
1529 list_for_each_entry(rg, head, link)
1530 if (end <= rg->to)
1531 break;
1532 if (&rg->link == head)
1533 return 0;
1534
1535 /* If we are in the middle of a region then adjust it. */
1536 if (end > rg->from) {
1537 chg = rg->to - end;
1538 rg->to = end;
1539 rg = list_entry(rg->link.next, typeof(*rg), link);
1540 }
1541
1542 /* Drop any remaining regions. */
1543 list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
1544 if (&rg->link == head)
1545 break;
1546 chg += rg->to - rg->from;
1547 list_del(&rg->link);
1548 kfree(rg);
1549 }
1550 return chg;
1551}
1552
1553int hugetlb_reserve_pages(struct inode *inode, 1557int hugetlb_reserve_pages(struct inode *inode,
1554 long from, long to, 1558 long from, long to,
1555 struct vm_area_struct *vma) 1559 struct vm_area_struct *vma)