aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorEric B Munson <emunson@mgebm.net>2011-01-13 18:47:27 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:49 -0500
commitadbe8726dc2a3805630d517270db17e3af86e526 (patch)
tree9558dc935030fa9eaec390ec56080d585b438f51 /mm
parent08d4a24659f1284f33e574211435aa12ce968477 (diff)
hugetlb: do not allow pagesize >= MAX_ORDER pool adjustment
Huge pages with order >= MAX_ORDER must be allocated at boot via the kernel command line, they cannot be allocated or freed once the kernel is up and running. Currently we allow values to be written to the sysfs and sysctl files controling pool size for these huge page sizes. This patch makes the store functions for nr_hugepages and nr_overcommit_hugepages return -EINVAL when the pool for a page size >= MAX_ORDER is changed. [akpm@linux-foundation.org: avoid multiple return paths in nr_hugepages_store_common()] [caiqian@redhat.com: add checking in hugetlb_overcommit_handler()] Signed-off-by: Eric B Munson <emunson@mgebm.net> Reported-by: CAI Qian <caiqian@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Michal Hocko <mhocko@suse.cz> Cc: Nishanth Aravamudan <nacc@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/hugetlb.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 363c4d22602a..ce8e5bb6f031 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1363,6 +1363,7 @@ static ssize_t nr_hugepages_show_common(struct kobject *kobj,
1363 1363
1364 return sprintf(buf, "%lu\n", nr_huge_pages); 1364 return sprintf(buf, "%lu\n", nr_huge_pages);
1365} 1365}
1366
1366static ssize_t nr_hugepages_store_common(bool obey_mempolicy, 1367static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
1367 struct kobject *kobj, struct kobj_attribute *attr, 1368 struct kobject *kobj, struct kobj_attribute *attr,
1368 const char *buf, size_t len) 1369 const char *buf, size_t len)
@@ -1375,11 +1376,16 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
1375 1376
1376 err = strict_strtoul(buf, 10, &count); 1377 err = strict_strtoul(buf, 10, &count);
1377 if (err) { 1378 if (err) {
1378 NODEMASK_FREE(nodes_allowed); 1379 err = 0; /* This seems wrong */
1379 return 0; 1380 goto out;
1380 } 1381 }
1381 1382
1382 h = kobj_to_hstate(kobj, &nid); 1383 h = kobj_to_hstate(kobj, &nid);
1384 if (h->order >= MAX_ORDER) {
1385 err = -EINVAL;
1386 goto out;
1387 }
1388
1383 if (nid == NUMA_NO_NODE) { 1389 if (nid == NUMA_NO_NODE) {
1384 /* 1390 /*
1385 * global hstate attribute 1391 * global hstate attribute
@@ -1405,6 +1411,9 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
1405 NODEMASK_FREE(nodes_allowed); 1411 NODEMASK_FREE(nodes_allowed);
1406 1412
1407 return len; 1413 return len;
1414out:
1415 NODEMASK_FREE(nodes_allowed);
1416 return err;
1408} 1417}
1409 1418
1410static ssize_t nr_hugepages_show(struct kobject *kobj, 1419static ssize_t nr_hugepages_show(struct kobject *kobj,
@@ -1447,6 +1456,7 @@ static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj,
1447 struct hstate *h = kobj_to_hstate(kobj, NULL); 1456 struct hstate *h = kobj_to_hstate(kobj, NULL);
1448 return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages); 1457 return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages);
1449} 1458}
1459
1450static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj, 1460static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
1451 struct kobj_attribute *attr, const char *buf, size_t count) 1461 struct kobj_attribute *attr, const char *buf, size_t count)
1452{ 1462{
@@ -1454,6 +1464,9 @@ static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
1454 unsigned long input; 1464 unsigned long input;
1455 struct hstate *h = kobj_to_hstate(kobj, NULL); 1465 struct hstate *h = kobj_to_hstate(kobj, NULL);
1456 1466
1467 if (h->order >= MAX_ORDER)
1468 return -EINVAL;
1469
1457 err = strict_strtoul(buf, 10, &input); 1470 err = strict_strtoul(buf, 10, &input);
1458 if (err) 1471 if (err)
1459 return 0; 1472 return 0;
@@ -1864,6 +1877,9 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
1864 if (!write) 1877 if (!write)
1865 tmp = h->max_huge_pages; 1878 tmp = h->max_huge_pages;
1866 1879
1880 if (write && h->order >= MAX_ORDER)
1881 return -EINVAL;
1882
1867 table->data = &tmp; 1883 table->data = &tmp;
1868 table->maxlen = sizeof(unsigned long); 1884 table->maxlen = sizeof(unsigned long);
1869 ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); 1885 ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);
@@ -1927,6 +1943,9 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
1927 if (!write) 1943 if (!write)
1928 tmp = h->nr_overcommit_huge_pages; 1944 tmp = h->nr_overcommit_huge_pages;
1929 1945
1946 if (write && h->order >= MAX_ORDER)
1947 return -EINVAL;
1948
1930 table->data = &tmp; 1949 table->data = &tmp;
1931 table->maxlen = sizeof(unsigned long); 1950 table->maxlen = sizeof(unsigned long);
1932 ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); 1951 ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);