mirror of https://github.com/torvalds/linux.git
135 lines
3.1 KiB
C
135 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* HugeTLB sysfs interfaces.
|
|
* (C) Nadia Yvette Chambers, April 2004
|
|
*/
|
|
|
|
#include <linux/sysctl.h>
|
|
|
|
#include "hugetlb_internal.h"
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
static int proc_hugetlb_doulongvec_minmax(const struct ctl_table *table, int write,
|
|
void *buffer, size_t *length,
|
|
loff_t *ppos, unsigned long *out)
|
|
{
|
|
struct ctl_table dup_table;
|
|
|
|
/*
|
|
* In order to avoid races with __do_proc_doulongvec_minmax(), we
|
|
* can duplicate the @table and alter the duplicate of it.
|
|
*/
|
|
dup_table = *table;
|
|
dup_table.data = out;
|
|
|
|
return proc_doulongvec_minmax(&dup_table, write, buffer, length, ppos);
|
|
}
|
|
|
|
static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
|
|
const struct ctl_table *table, int write,
|
|
void *buffer, size_t *length, loff_t *ppos)
|
|
{
|
|
struct hstate *h = &default_hstate;
|
|
unsigned long tmp = h->max_huge_pages;
|
|
int ret;
|
|
|
|
if (!hugepages_supported())
|
|
return -EOPNOTSUPP;
|
|
|
|
ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos,
|
|
&tmp);
|
|
if (ret)
|
|
goto out;
|
|
|
|
if (write)
|
|
ret = __nr_hugepages_store_common(obey_mempolicy, h,
|
|
NUMA_NO_NODE, tmp, *length);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int hugetlb_sysctl_handler(const struct ctl_table *table, int write,
|
|
void *buffer, size_t *length, loff_t *ppos)
|
|
{
|
|
|
|
return hugetlb_sysctl_handler_common(false, table, write,
|
|
buffer, length, ppos);
|
|
}
|
|
|
|
#ifdef CONFIG_NUMA
|
|
static int hugetlb_mempolicy_sysctl_handler(const struct ctl_table *table, int write,
|
|
void *buffer, size_t *length, loff_t *ppos)
|
|
{
|
|
return hugetlb_sysctl_handler_common(true, table, write,
|
|
buffer, length, ppos);
|
|
}
|
|
#endif /* CONFIG_NUMA */
|
|
|
|
static int hugetlb_overcommit_handler(const struct ctl_table *table, int write,
|
|
void *buffer, size_t *length, loff_t *ppos)
|
|
{
|
|
struct hstate *h = &default_hstate;
|
|
unsigned long tmp;
|
|
int ret;
|
|
|
|
if (!hugepages_supported())
|
|
return -EOPNOTSUPP;
|
|
|
|
tmp = h->nr_overcommit_huge_pages;
|
|
|
|
if (write && hstate_is_gigantic_no_runtime(h))
|
|
return -EINVAL;
|
|
|
|
ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos,
|
|
&tmp);
|
|
if (ret)
|
|
goto out;
|
|
|
|
if (write) {
|
|
spin_lock_irq(&hugetlb_lock);
|
|
h->nr_overcommit_huge_pages = tmp;
|
|
spin_unlock_irq(&hugetlb_lock);
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static const struct ctl_table hugetlb_table[] = {
|
|
{
|
|
.procname = "nr_hugepages",
|
|
.data = NULL,
|
|
.maxlen = sizeof(unsigned long),
|
|
.mode = 0644,
|
|
.proc_handler = hugetlb_sysctl_handler,
|
|
},
|
|
#ifdef CONFIG_NUMA
|
|
{
|
|
.procname = "nr_hugepages_mempolicy",
|
|
.data = NULL,
|
|
.maxlen = sizeof(unsigned long),
|
|
.mode = 0644,
|
|
.proc_handler = &hugetlb_mempolicy_sysctl_handler,
|
|
},
|
|
#endif
|
|
{
|
|
.procname = "hugetlb_shm_group",
|
|
.data = &sysctl_hugetlb_shm_group,
|
|
.maxlen = sizeof(gid_t),
|
|
.mode = 0644,
|
|
.proc_handler = proc_dointvec,
|
|
},
|
|
{
|
|
.procname = "nr_overcommit_hugepages",
|
|
.data = NULL,
|
|
.maxlen = sizeof(unsigned long),
|
|
.mode = 0644,
|
|
.proc_handler = hugetlb_overcommit_handler,
|
|
},
|
|
};
|
|
|
|
void __init hugetlb_sysctl_init(void)
|
|
{
|
|
register_sysctl_init("vm", hugetlb_table);
|
|
}
|
|
#endif /* CONFIG_SYSCTL */
|