1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HugeTLB sysfs interfaces. 4 * (C) Nadia Yvette Chambers, April 2004 5 */ 6 7 #include <linux/sysctl.h> 8 9 #include "hugetlb_internal.h" 10 11 int movable_gigantic_pages; 12 13 #ifdef CONFIG_SYSCTL 14 static int proc_hugetlb_doulongvec_minmax(const struct ctl_table *table, int write, 15 void *buffer, size_t *length, 16 loff_t *ppos, unsigned long *out) 17 { 18 struct ctl_table dup_table; 19 20 /* 21 * In order to avoid races with __do_proc_doulongvec_minmax(), we 22 * can duplicate the @table and alter the duplicate of it. 23 */ 24 dup_table = *table; 25 dup_table.data = out; 26 27 return proc_doulongvec_minmax(&dup_table, write, buffer, length, ppos); 28 } 29 30 static int hugetlb_sysctl_handler_common(bool obey_mempolicy, 31 const struct ctl_table *table, int write, 32 void *buffer, size_t *length, loff_t *ppos) 33 { 34 struct hstate *h = &default_hstate; 35 unsigned long tmp = h->max_huge_pages; 36 int ret; 37 38 if (!hugepages_supported()) 39 return -EOPNOTSUPP; 40 41 ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos, 42 &tmp); 43 if (ret) 44 goto out; 45 46 if (write) 47 ret = __nr_hugepages_store_common(obey_mempolicy, h, 48 NUMA_NO_NODE, tmp, *length); 49 out: 50 return ret; 51 } 52 53 static int hugetlb_sysctl_handler(const struct ctl_table *table, int write, 54 void *buffer, size_t *length, loff_t *ppos) 55 { 56 57 return hugetlb_sysctl_handler_common(false, table, write, 58 buffer, length, ppos); 59 } 60 61 #ifdef CONFIG_NUMA 62 static int hugetlb_mempolicy_sysctl_handler(const struct ctl_table *table, int write, 63 void *buffer, size_t *length, loff_t *ppos) 64 { 65 return hugetlb_sysctl_handler_common(true, table, write, 66 buffer, length, ppos); 67 } 68 #endif /* CONFIG_NUMA */ 69 70 static int hugetlb_overcommit_handler(const struct ctl_table *table, int write, 71 void *buffer, size_t *length, loff_t *ppos) 72 { 73 struct hstate *h = &default_hstate; 74 unsigned long tmp; 75 int ret; 76 77 if (!hugepages_supported()) 78 return -EOPNOTSUPP; 79 80 tmp = h->nr_overcommit_huge_pages; 81 82 if (write && hstate_is_gigantic_no_runtime(h)) 83 return -EINVAL; 84 85 ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos, 86 &tmp); 87 if (ret) 88 goto out; 89 90 if (write) { 91 spin_lock_irq(&hugetlb_lock); 92 h->nr_overcommit_huge_pages = tmp; 93 spin_unlock_irq(&hugetlb_lock); 94 } 95 out: 96 return ret; 97 } 98 99 static const struct ctl_table hugetlb_table[] = { 100 { 101 .procname = "nr_hugepages", 102 .data = NULL, 103 .maxlen = sizeof(unsigned long), 104 .mode = 0644, 105 .proc_handler = hugetlb_sysctl_handler, 106 }, 107 #ifdef CONFIG_NUMA 108 { 109 .procname = "nr_hugepages_mempolicy", 110 .data = NULL, 111 .maxlen = sizeof(unsigned long), 112 .mode = 0644, 113 .proc_handler = &hugetlb_mempolicy_sysctl_handler, 114 }, 115 #endif 116 { 117 .procname = "hugetlb_shm_group", 118 .data = &sysctl_hugetlb_shm_group, 119 .maxlen = sizeof(gid_t), 120 .mode = 0644, 121 .proc_handler = proc_dointvec, 122 }, 123 { 124 .procname = "nr_overcommit_hugepages", 125 .data = NULL, 126 .maxlen = sizeof(unsigned long), 127 .mode = 0644, 128 .proc_handler = hugetlb_overcommit_handler, 129 }, 130 #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION 131 { 132 .procname = "movable_gigantic_pages", 133 .data = &movable_gigantic_pages, 134 .maxlen = sizeof(int), 135 .mode = 0644, 136 .proc_handler = proc_dointvec, 137 }, 138 #endif 139 }; 140 141 void __init hugetlb_sysctl_init(void) 142 { 143 register_sysctl_init("vm", hugetlb_table); 144 } 145 #endif /* CONFIG_SYSCTL */ 146