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