Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/hugetlb: extract sysfs into hugetlb_sysfs.c

Patch series "mm/hugetlb: refactor sysfs/sysctl interfaces", v5.

hugetlb.c has grown significantly and become difficult to maintain. This
patch series extracts the sysfs and sysctl interface code into separate
dedicated files to improve code organization.

The refactoring includes:
- Patch 1: Extract sysfs interface into mm/hugetlb_sysfs.c
- Patch 2: Extract sysctl interface into mm/hugetlb_sysctl.c

No functional changes are introduced in this series. The code is moved
as-is, with only minor formatting adjustments for code style consistency.
This should make future maintenance and enhancements to the hugetlb
subsystem easier.

Testing: The patch series has been compile-tested and maintains the same
functionality as the original code.


This patch (of 2):

Currently, hugetlb.c contains both core management logic and sysfs
interface implementations, making it difficult to maintain. This patch
extracts the sysfs-related code into a dedicated file to improve code
organization.

The following components are moved to mm/hugetlb_sysfs.c:
- sysfs attribute definitions and handlers
- sysfs kobject management functions
- NUMA per-node hstate attribute registration

Several inline helper functions and macros are moved to
mm/hugetlb_internal.h:
- hstate_is_gigantic_no_runtime()
- next_node_allowed()
- get_valid_node_allowed()
- hstate_next_node_to_alloc()
- hstate_next_node_to_free()
- for_each_node_mask_to_alloc/to_free macros

To support code sharing, these functions are changed from static to
exported symbols:
- remove_hugetlb_folio()
- add_hugetlb_folio()
- init_new_hugetlb_folio()
- prep_and_add_allocated_folios()
- demote_pool_huge_page()
- __nr_hugepages_store_common()

The Makefile is updated to compile hugetlb_sysfs.o when CONFIG_HUGETLBFS
is enabled. This maintains all existing functionality while improving
maintainability by separating concerns.

MAINTAINERS is updated to add new file hugetlb_sysfs.c.

Link: https://lkml.kernel.org/r/cover.1762398359.git.zhuhui@kylinos.cn
Link: https://lkml.kernel.org/r/656a03dff7e2bb20e24e841ede81fdca01d21410.1762398359.git.zhuhui@kylinos.cn
Signed-off-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Hui Zhu <zhuhui@kylinos.cn>
Cc: David Hildenbrand <david@redhat.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: SeongJae Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Hui Zhu and committed by
Andrew Morton
ecd6703f 98be1554

+626 -586
+1
MAINTAINERS
··· 11540 11540 F: mm/hugetlb_cgroup.c 11541 11541 F: mm/hugetlb_cma.c 11542 11542 F: mm/hugetlb_cma.h 11543 + F: mm/hugetlb_sysfs.c 11543 11544 F: mm/hugetlb_vmemmap.c 11544 11545 F: mm/hugetlb_vmemmap.h 11545 11546 F: tools/testing/selftests/cgroup/test_hugetlb_memcg.c
+1 -1
mm/Makefile
··· 78 78 obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o 79 79 obj-$(CONFIG_ZSWAP) += zswap.o 80 80 obj-$(CONFIG_HAS_DMA) += dmapool.o 81 - obj-$(CONFIG_HUGETLBFS) += hugetlb.o 81 + obj-$(CONFIG_HUGETLBFS) += hugetlb.o hugetlb_sysfs.o 82 82 ifdef CONFIG_CMA 83 83 obj-$(CONFIG_HUGETLBFS) += hugetlb_cma.o 84 84 endif
+11 -585
mm/hugetlb.c
··· 19 19 #include <linux/mutex.h> 20 20 #include <linux/memblock.h> 21 21 #include <linux/minmax.h> 22 - #include <linux/sysfs.h> 23 22 #include <linux/slab.h> 24 23 #include <linux/sched/mm.h> 25 24 #include <linux/mmdebug.h> ··· 45 46 #include <asm/setup.h> 46 47 47 48 #include <linux/io.h> 48 - #include <linux/hugetlb.h> 49 - #include <linux/hugetlb_cgroup.h> 50 49 #include <linux/node.h> 51 50 #include <linux/page_owner.h> 52 51 #include "internal.h" 53 52 #include "hugetlb_vmemmap.h" 54 53 #include "hugetlb_cma.h" 54 + #include "hugetlb_internal.h" 55 55 #include <linux/page-isolation.h> 56 56 57 57 int hugetlb_max_hstate __read_mostly; ··· 130 132 } 131 133 132 134 folio_put(folio); 133 - } 134 - 135 - /* 136 - * Check if the hstate represents gigantic pages but gigantic page 137 - * runtime support is not available. This is a common condition used to 138 - * skip operations that cannot be performed on gigantic pages when runtime 139 - * support is disabled. 140 - */ 141 - static inline bool hstate_is_gigantic_no_runtime(struct hstate *h) 142 - { 143 - return hstate_is_gigantic(h) && !gigantic_page_runtime_supported(); 144 135 } 145 136 146 137 static inline bool subpool_is_free(struct hugepage_subpool *spool) ··· 1418 1431 return NULL; 1419 1432 } 1420 1433 1421 - /* 1422 - * common helper functions for hstate_next_node_to_{alloc|free}. 1423 - * We may have allocated or freed a huge page based on a different 1424 - * nodes_allowed previously, so h->next_node_to_{alloc|free} might 1425 - * be outside of *nodes_allowed. Ensure that we use an allowed 1426 - * node for alloc or free. 1427 - */ 1428 - static int next_node_allowed(int nid, nodemask_t *nodes_allowed) 1429 - { 1430 - nid = next_node_in(nid, *nodes_allowed); 1431 - VM_BUG_ON(nid >= MAX_NUMNODES); 1432 - 1433 - return nid; 1434 - } 1435 - 1436 - static int get_valid_node_allowed(int nid, nodemask_t *nodes_allowed) 1437 - { 1438 - if (!node_isset(nid, *nodes_allowed)) 1439 - nid = next_node_allowed(nid, nodes_allowed); 1440 - return nid; 1441 - } 1442 - 1443 - /* 1444 - * returns the previously saved node ["this node"] from which to 1445 - * allocate a persistent huge page for the pool and advance the 1446 - * next node from which to allocate, handling wrap at end of node 1447 - * mask. 1448 - */ 1449 - static int hstate_next_node_to_alloc(int *next_node, 1450 - nodemask_t *nodes_allowed) 1451 - { 1452 - int nid; 1453 - 1454 - VM_BUG_ON(!nodes_allowed); 1455 - 1456 - nid = get_valid_node_allowed(*next_node, nodes_allowed); 1457 - *next_node = next_node_allowed(nid, nodes_allowed); 1458 - 1459 - return nid; 1460 - } 1461 - 1462 - /* 1463 - * helper for remove_pool_hugetlb_folio() - return the previously saved 1464 - * node ["this node"] from which to free a huge page. Advance the 1465 - * next node id whether or not we find a free huge page to free so 1466 - * that the next attempt to free addresses the next node. 1467 - */ 1468 - static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed) 1469 - { 1470 - int nid; 1471 - 1472 - VM_BUG_ON(!nodes_allowed); 1473 - 1474 - nid = get_valid_node_allowed(h->next_nid_to_free, nodes_allowed); 1475 - h->next_nid_to_free = next_node_allowed(nid, nodes_allowed); 1476 - 1477 - return nid; 1478 - } 1479 - 1480 - #define for_each_node_mask_to_alloc(next_node, nr_nodes, node, mask) \ 1481 - for (nr_nodes = nodes_weight(*mask); \ 1482 - nr_nodes > 0 && \ 1483 - ((node = hstate_next_node_to_alloc(next_node, mask)) || 1); \ 1484 - nr_nodes--) 1485 - 1486 - #define for_each_node_mask_to_free(hs, nr_nodes, node, mask) \ 1487 - for (nr_nodes = nodes_weight(*mask); \ 1488 - nr_nodes > 0 && \ 1489 - ((node = hstate_next_node_to_free(hs, mask)) || 1); \ 1490 - nr_nodes--) 1491 - 1492 1434 #ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE 1493 1435 #ifdef CONFIG_CONTIG_ALLOC 1494 1436 static struct folio *alloc_gigantic_folio(int order, gfp_t gfp_mask, ··· 1473 1557 * 1474 1558 * Must be called with hugetlb lock held. 1475 1559 */ 1476 - static void remove_hugetlb_folio(struct hstate *h, struct folio *folio, 1477 - bool adjust_surplus) 1560 + void remove_hugetlb_folio(struct hstate *h, struct folio *folio, 1561 + bool adjust_surplus) 1478 1562 { 1479 1563 int nid = folio_nid(folio); 1480 1564 ··· 1509 1593 h->nr_huge_pages_node[nid]--; 1510 1594 } 1511 1595 1512 - static void add_hugetlb_folio(struct hstate *h, struct folio *folio, 1513 - bool adjust_surplus) 1596 + void add_hugetlb_folio(struct hstate *h, struct folio *folio, 1597 + bool adjust_surplus) 1514 1598 { 1515 1599 int nid = folio_nid(folio); 1516 1600 ··· 1841 1925 h->nr_huge_pages_node[folio_nid(folio)]++; 1842 1926 } 1843 1927 1844 - static void init_new_hugetlb_folio(struct folio *folio) 1928 + void init_new_hugetlb_folio(struct folio *folio) 1845 1929 { 1846 1930 __folio_set_hugetlb(folio); 1847 1931 INIT_LIST_HEAD(&folio->lru); ··· 1953 2037 return folio; 1954 2038 } 1955 2039 1956 - static void prep_and_add_allocated_folios(struct hstate *h, 1957 - struct list_head *folio_list) 2040 + void prep_and_add_allocated_folios(struct hstate *h, 2041 + struct list_head *folio_list) 1958 2042 { 1959 2043 unsigned long flags; 1960 2044 struct folio *folio, *tmp_f; ··· 4009 4093 return rc; 4010 4094 } 4011 4095 4012 - static long demote_pool_huge_page(struct hstate *src, nodemask_t *nodes_allowed, 4013 - unsigned long nr_to_demote) 4096 + long demote_pool_huge_page(struct hstate *src, nodemask_t *nodes_allowed, 4097 + unsigned long nr_to_demote) 4014 4098 __must_hold(&hugetlb_lock) 4015 4099 { 4016 4100 int nr_nodes, node; ··· 4078 4162 return -EBUSY; 4079 4163 } 4080 4164 4081 - #define HSTATE_ATTR_RO(_name) \ 4082 - static struct kobj_attribute _name##_attr = __ATTR_RO(_name) 4083 - 4084 - #define HSTATE_ATTR_WO(_name) \ 4085 - static struct kobj_attribute _name##_attr = __ATTR_WO(_name) 4086 - 4087 - #define HSTATE_ATTR(_name) \ 4088 - static struct kobj_attribute _name##_attr = __ATTR_RW(_name) 4089 - 4090 - static struct kobject *hugepages_kobj; 4091 - static struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; 4092 - 4093 - static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp); 4094 - 4095 - static struct hstate *kobj_to_hstate(struct kobject *kobj, int *nidp) 4096 - { 4097 - int i; 4098 - 4099 - for (i = 0; i < HUGE_MAX_HSTATE; i++) 4100 - if (hstate_kobjs[i] == kobj) { 4101 - if (nidp) 4102 - *nidp = NUMA_NO_NODE; 4103 - return &hstates[i]; 4104 - } 4105 - 4106 - return kobj_to_node_hstate(kobj, nidp); 4107 - } 4108 - 4109 - static ssize_t nr_hugepages_show_common(struct kobject *kobj, 4110 - struct kobj_attribute *attr, char *buf) 4111 - { 4112 - struct hstate *h; 4113 - unsigned long nr_huge_pages; 4114 - int nid; 4115 - 4116 - h = kobj_to_hstate(kobj, &nid); 4117 - if (nid == NUMA_NO_NODE) 4118 - nr_huge_pages = h->nr_huge_pages; 4119 - else 4120 - nr_huge_pages = h->nr_huge_pages_node[nid]; 4121 - 4122 - return sysfs_emit(buf, "%lu\n", nr_huge_pages); 4123 - } 4124 - 4125 - static ssize_t __nr_hugepages_store_common(bool obey_mempolicy, 4165 + ssize_t __nr_hugepages_store_common(bool obey_mempolicy, 4126 4166 struct hstate *h, int nid, 4127 4167 unsigned long count, size_t len) 4128 4168 { ··· 4109 4237 err = set_max_huge_pages(h, count, nid, n_mask); 4110 4238 4111 4239 return err ? err : len; 4112 - } 4113 - 4114 - static ssize_t nr_hugepages_store_common(bool obey_mempolicy, 4115 - struct kobject *kobj, const char *buf, 4116 - size_t len) 4117 - { 4118 - struct hstate *h; 4119 - unsigned long count; 4120 - int nid; 4121 - int err; 4122 - 4123 - err = kstrtoul(buf, 10, &count); 4124 - if (err) 4125 - return err; 4126 - 4127 - h = kobj_to_hstate(kobj, &nid); 4128 - return __nr_hugepages_store_common(obey_mempolicy, h, nid, count, len); 4129 - } 4130 - 4131 - static ssize_t nr_hugepages_show(struct kobject *kobj, 4132 - struct kobj_attribute *attr, char *buf) 4133 - { 4134 - return nr_hugepages_show_common(kobj, attr, buf); 4135 - } 4136 - 4137 - static ssize_t nr_hugepages_store(struct kobject *kobj, 4138 - struct kobj_attribute *attr, const char *buf, size_t len) 4139 - { 4140 - return nr_hugepages_store_common(false, kobj, buf, len); 4141 - } 4142 - HSTATE_ATTR(nr_hugepages); 4143 - 4144 - #ifdef CONFIG_NUMA 4145 - 4146 - /* 4147 - * hstate attribute for optionally mempolicy-based constraint on persistent 4148 - * huge page alloc/free. 4149 - */ 4150 - static ssize_t nr_hugepages_mempolicy_show(struct kobject *kobj, 4151 - struct kobj_attribute *attr, 4152 - char *buf) 4153 - { 4154 - return nr_hugepages_show_common(kobj, attr, buf); 4155 - } 4156 - 4157 - static ssize_t nr_hugepages_mempolicy_store(struct kobject *kobj, 4158 - struct kobj_attribute *attr, const char *buf, size_t len) 4159 - { 4160 - return nr_hugepages_store_common(true, kobj, buf, len); 4161 - } 4162 - HSTATE_ATTR(nr_hugepages_mempolicy); 4163 - #endif 4164 - 4165 - 4166 - static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj, 4167 - struct kobj_attribute *attr, char *buf) 4168 - { 4169 - struct hstate *h = kobj_to_hstate(kobj, NULL); 4170 - return sysfs_emit(buf, "%lu\n", h->nr_overcommit_huge_pages); 4171 - } 4172 - 4173 - static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj, 4174 - struct kobj_attribute *attr, const char *buf, size_t count) 4175 - { 4176 - int err; 4177 - unsigned long input; 4178 - struct hstate *h = kobj_to_hstate(kobj, NULL); 4179 - 4180 - if (hstate_is_gigantic_no_runtime(h)) 4181 - return -EINVAL; 4182 - 4183 - err = kstrtoul(buf, 10, &input); 4184 - if (err) 4185 - return err; 4186 - 4187 - spin_lock_irq(&hugetlb_lock); 4188 - h->nr_overcommit_huge_pages = input; 4189 - spin_unlock_irq(&hugetlb_lock); 4190 - 4191 - return count; 4192 - } 4193 - HSTATE_ATTR(nr_overcommit_hugepages); 4194 - 4195 - static ssize_t free_hugepages_show(struct kobject *kobj, 4196 - struct kobj_attribute *attr, char *buf) 4197 - { 4198 - struct hstate *h; 4199 - unsigned long free_huge_pages; 4200 - int nid; 4201 - 4202 - h = kobj_to_hstate(kobj, &nid); 4203 - if (nid == NUMA_NO_NODE) 4204 - free_huge_pages = h->free_huge_pages; 4205 - else 4206 - free_huge_pages = h->free_huge_pages_node[nid]; 4207 - 4208 - return sysfs_emit(buf, "%lu\n", free_huge_pages); 4209 - } 4210 - HSTATE_ATTR_RO(free_hugepages); 4211 - 4212 - static ssize_t resv_hugepages_show(struct kobject *kobj, 4213 - struct kobj_attribute *attr, char *buf) 4214 - { 4215 - struct hstate *h = kobj_to_hstate(kobj, NULL); 4216 - return sysfs_emit(buf, "%lu\n", h->resv_huge_pages); 4217 - } 4218 - HSTATE_ATTR_RO(resv_hugepages); 4219 - 4220 - static ssize_t surplus_hugepages_show(struct kobject *kobj, 4221 - struct kobj_attribute *attr, char *buf) 4222 - { 4223 - struct hstate *h; 4224 - unsigned long surplus_huge_pages; 4225 - int nid; 4226 - 4227 - h = kobj_to_hstate(kobj, &nid); 4228 - if (nid == NUMA_NO_NODE) 4229 - surplus_huge_pages = h->surplus_huge_pages; 4230 - else 4231 - surplus_huge_pages = h->surplus_huge_pages_node[nid]; 4232 - 4233 - return sysfs_emit(buf, "%lu\n", surplus_huge_pages); 4234 - } 4235 - HSTATE_ATTR_RO(surplus_hugepages); 4236 - 4237 - static ssize_t demote_store(struct kobject *kobj, 4238 - struct kobj_attribute *attr, const char *buf, size_t len) 4239 - { 4240 - unsigned long nr_demote; 4241 - unsigned long nr_available; 4242 - nodemask_t nodes_allowed, *n_mask; 4243 - struct hstate *h; 4244 - int err; 4245 - int nid; 4246 - 4247 - err = kstrtoul(buf, 10, &nr_demote); 4248 - if (err) 4249 - return err; 4250 - h = kobj_to_hstate(kobj, &nid); 4251 - 4252 - if (nid != NUMA_NO_NODE) { 4253 - init_nodemask_of_node(&nodes_allowed, nid); 4254 - n_mask = &nodes_allowed; 4255 - } else { 4256 - n_mask = &node_states[N_MEMORY]; 4257 - } 4258 - 4259 - /* Synchronize with other sysfs operations modifying huge pages */ 4260 - mutex_lock(&h->resize_lock); 4261 - spin_lock_irq(&hugetlb_lock); 4262 - 4263 - while (nr_demote) { 4264 - long rc; 4265 - 4266 - /* 4267 - * Check for available pages to demote each time thorough the 4268 - * loop as demote_pool_huge_page will drop hugetlb_lock. 4269 - */ 4270 - if (nid != NUMA_NO_NODE) 4271 - nr_available = h->free_huge_pages_node[nid]; 4272 - else 4273 - nr_available = h->free_huge_pages; 4274 - nr_available -= h->resv_huge_pages; 4275 - if (!nr_available) 4276 - break; 4277 - 4278 - rc = demote_pool_huge_page(h, n_mask, nr_demote); 4279 - if (rc < 0) { 4280 - err = rc; 4281 - break; 4282 - } 4283 - 4284 - nr_demote -= rc; 4285 - } 4286 - 4287 - spin_unlock_irq(&hugetlb_lock); 4288 - mutex_unlock(&h->resize_lock); 4289 - 4290 - if (err) 4291 - return err; 4292 - return len; 4293 - } 4294 - HSTATE_ATTR_WO(demote); 4295 - 4296 - static ssize_t demote_size_show(struct kobject *kobj, 4297 - struct kobj_attribute *attr, char *buf) 4298 - { 4299 - struct hstate *h = kobj_to_hstate(kobj, NULL); 4300 - unsigned long demote_size = (PAGE_SIZE << h->demote_order) / SZ_1K; 4301 - 4302 - return sysfs_emit(buf, "%lukB\n", demote_size); 4303 - } 4304 - 4305 - static ssize_t demote_size_store(struct kobject *kobj, 4306 - struct kobj_attribute *attr, 4307 - const char *buf, size_t count) 4308 - { 4309 - struct hstate *h, *demote_hstate; 4310 - unsigned long demote_size; 4311 - unsigned int demote_order; 4312 - 4313 - demote_size = (unsigned long)memparse(buf, NULL); 4314 - 4315 - demote_hstate = size_to_hstate(demote_size); 4316 - if (!demote_hstate) 4317 - return -EINVAL; 4318 - demote_order = demote_hstate->order; 4319 - if (demote_order < HUGETLB_PAGE_ORDER) 4320 - return -EINVAL; 4321 - 4322 - /* demote order must be smaller than hstate order */ 4323 - h = kobj_to_hstate(kobj, NULL); 4324 - if (demote_order >= h->order) 4325 - return -EINVAL; 4326 - 4327 - /* resize_lock synchronizes access to demote size and writes */ 4328 - mutex_lock(&h->resize_lock); 4329 - h->demote_order = demote_order; 4330 - mutex_unlock(&h->resize_lock); 4331 - 4332 - return count; 4333 - } 4334 - HSTATE_ATTR(demote_size); 4335 - 4336 - static struct attribute *hstate_attrs[] = { 4337 - &nr_hugepages_attr.attr, 4338 - &nr_overcommit_hugepages_attr.attr, 4339 - &free_hugepages_attr.attr, 4340 - &resv_hugepages_attr.attr, 4341 - &surplus_hugepages_attr.attr, 4342 - #ifdef CONFIG_NUMA 4343 - &nr_hugepages_mempolicy_attr.attr, 4344 - #endif 4345 - NULL, 4346 - }; 4347 - 4348 - static const struct attribute_group hstate_attr_group = { 4349 - .attrs = hstate_attrs, 4350 - }; 4351 - 4352 - static struct attribute *hstate_demote_attrs[] = { 4353 - &demote_size_attr.attr, 4354 - &demote_attr.attr, 4355 - NULL, 4356 - }; 4357 - 4358 - static const struct attribute_group hstate_demote_attr_group = { 4359 - .attrs = hstate_demote_attrs, 4360 - }; 4361 - 4362 - static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent, 4363 - struct kobject **hstate_kobjs, 4364 - const struct attribute_group *hstate_attr_group) 4365 - { 4366 - int retval; 4367 - int hi = hstate_index(h); 4368 - 4369 - hstate_kobjs[hi] = kobject_create_and_add(h->name, parent); 4370 - if (!hstate_kobjs[hi]) 4371 - return -ENOMEM; 4372 - 4373 - retval = sysfs_create_group(hstate_kobjs[hi], hstate_attr_group); 4374 - if (retval) { 4375 - kobject_put(hstate_kobjs[hi]); 4376 - hstate_kobjs[hi] = NULL; 4377 - return retval; 4378 - } 4379 - 4380 - if (h->demote_order) { 4381 - retval = sysfs_create_group(hstate_kobjs[hi], 4382 - &hstate_demote_attr_group); 4383 - if (retval) { 4384 - pr_warn("HugeTLB unable to create demote interfaces for %s\n", h->name); 4385 - sysfs_remove_group(hstate_kobjs[hi], hstate_attr_group); 4386 - kobject_put(hstate_kobjs[hi]); 4387 - hstate_kobjs[hi] = NULL; 4388 - return retval; 4389 - } 4390 - } 4391 - 4392 - return 0; 4393 - } 4394 - 4395 - #ifdef CONFIG_NUMA 4396 - static bool hugetlb_sysfs_initialized __ro_after_init; 4397 - 4398 - /* 4399 - * node_hstate/s - associate per node hstate attributes, via their kobjects, 4400 - * with node devices in node_devices[] using a parallel array. The array 4401 - * index of a node device or _hstate == node id. 4402 - * This is here to avoid any static dependency of the node device driver, in 4403 - * the base kernel, on the hugetlb module. 4404 - */ 4405 - struct node_hstate { 4406 - struct kobject *hugepages_kobj; 4407 - struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; 4408 - }; 4409 - static struct node_hstate node_hstates[MAX_NUMNODES]; 4410 - 4411 - /* 4412 - * A subset of global hstate attributes for node devices 4413 - */ 4414 - static struct attribute *per_node_hstate_attrs[] = { 4415 - &nr_hugepages_attr.attr, 4416 - &free_hugepages_attr.attr, 4417 - &surplus_hugepages_attr.attr, 4418 - NULL, 4419 - }; 4420 - 4421 - static const struct attribute_group per_node_hstate_attr_group = { 4422 - .attrs = per_node_hstate_attrs, 4423 - }; 4424 - 4425 - /* 4426 - * kobj_to_node_hstate - lookup global hstate for node device hstate attr kobj. 4427 - * Returns node id via non-NULL nidp. 4428 - */ 4429 - static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp) 4430 - { 4431 - int nid; 4432 - 4433 - for (nid = 0; nid < nr_node_ids; nid++) { 4434 - struct node_hstate *nhs = &node_hstates[nid]; 4435 - int i; 4436 - for (i = 0; i < HUGE_MAX_HSTATE; i++) 4437 - if (nhs->hstate_kobjs[i] == kobj) { 4438 - if (nidp) 4439 - *nidp = nid; 4440 - return &hstates[i]; 4441 - } 4442 - } 4443 - 4444 - BUG(); 4445 - return NULL; 4446 - } 4447 - 4448 - /* 4449 - * Unregister hstate attributes from a single node device. 4450 - * No-op if no hstate attributes attached. 4451 - */ 4452 - void hugetlb_unregister_node(struct node *node) 4453 - { 4454 - struct hstate *h; 4455 - struct node_hstate *nhs = &node_hstates[node->dev.id]; 4456 - 4457 - if (!nhs->hugepages_kobj) 4458 - return; /* no hstate attributes */ 4459 - 4460 - for_each_hstate(h) { 4461 - int idx = hstate_index(h); 4462 - struct kobject *hstate_kobj = nhs->hstate_kobjs[idx]; 4463 - 4464 - if (!hstate_kobj) 4465 - continue; 4466 - if (h->demote_order) 4467 - sysfs_remove_group(hstate_kobj, &hstate_demote_attr_group); 4468 - sysfs_remove_group(hstate_kobj, &per_node_hstate_attr_group); 4469 - kobject_put(hstate_kobj); 4470 - nhs->hstate_kobjs[idx] = NULL; 4471 - } 4472 - 4473 - kobject_put(nhs->hugepages_kobj); 4474 - nhs->hugepages_kobj = NULL; 4475 - } 4476 - 4477 - 4478 - /* 4479 - * Register hstate attributes for a single node device. 4480 - * No-op if attributes already registered. 4481 - */ 4482 - void hugetlb_register_node(struct node *node) 4483 - { 4484 - struct hstate *h; 4485 - struct node_hstate *nhs = &node_hstates[node->dev.id]; 4486 - int err; 4487 - 4488 - if (!hugetlb_sysfs_initialized) 4489 - return; 4490 - 4491 - if (nhs->hugepages_kobj) 4492 - return; /* already allocated */ 4493 - 4494 - nhs->hugepages_kobj = kobject_create_and_add("hugepages", 4495 - &node->dev.kobj); 4496 - if (!nhs->hugepages_kobj) 4497 - return; 4498 - 4499 - for_each_hstate(h) { 4500 - err = hugetlb_sysfs_add_hstate(h, nhs->hugepages_kobj, 4501 - nhs->hstate_kobjs, 4502 - &per_node_hstate_attr_group); 4503 - if (err) { 4504 - pr_err("HugeTLB: Unable to add hstate %s for node %d\n", 4505 - h->name, node->dev.id); 4506 - hugetlb_unregister_node(node); 4507 - break; 4508 - } 4509 - } 4510 - } 4511 - 4512 - /* 4513 - * hugetlb init time: register hstate attributes for all registered node 4514 - * devices of nodes that have memory. All on-line nodes should have 4515 - * registered their associated device by this time. 4516 - */ 4517 - static void __init hugetlb_register_all_nodes(void) 4518 - { 4519 - int nid; 4520 - 4521 - for_each_online_node(nid) 4522 - hugetlb_register_node(node_devices[nid]); 4523 - } 4524 - #else /* !CONFIG_NUMA */ 4525 - 4526 - static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp) 4527 - { 4528 - BUG(); 4529 - if (nidp) 4530 - *nidp = -1; 4531 - return NULL; 4532 - } 4533 - 4534 - static void hugetlb_register_all_nodes(void) { } 4535 - 4536 - #endif 4537 - 4538 - static void __init hugetlb_sysfs_init(void) 4539 - { 4540 - struct hstate *h; 4541 - int err; 4542 - 4543 - hugepages_kobj = kobject_create_and_add("hugepages", mm_kobj); 4544 - if (!hugepages_kobj) 4545 - return; 4546 - 4547 - for_each_hstate(h) { 4548 - err = hugetlb_sysfs_add_hstate(h, hugepages_kobj, 4549 - hstate_kobjs, &hstate_attr_group); 4550 - if (err) 4551 - pr_err("HugeTLB: Unable to add hstate %s\n", h->name); 4552 - } 4553 - 4554 - #ifdef CONFIG_NUMA 4555 - hugetlb_sysfs_initialized = true; 4556 - #endif 4557 - hugetlb_register_all_nodes(); 4558 4240 } 4559 4241 4560 4242 #ifdef CONFIG_SYSCTL
+111
mm/hugetlb_internal.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Internal HugeTLB definitions. 4 + * (C) Nadia Yvette Chambers, April 2004 5 + */ 6 + 7 + #ifndef _LINUX_HUGETLB_INTERNAL_H 8 + #define _LINUX_HUGETLB_INTERNAL_H 9 + 10 + #include <linux/hugetlb.h> 11 + #include <linux/hugetlb_cgroup.h> 12 + 13 + /* 14 + * Check if the hstate represents gigantic pages but gigantic page 15 + * runtime support is not available. This is a common condition used to 16 + * skip operations that cannot be performed on gigantic pages when runtime 17 + * support is disabled. 18 + */ 19 + static inline bool hstate_is_gigantic_no_runtime(struct hstate *h) 20 + { 21 + return hstate_is_gigantic(h) && !gigantic_page_runtime_supported(); 22 + } 23 + 24 + /* 25 + * common helper functions for hstate_next_node_to_{alloc|free}. 26 + * We may have allocated or freed a huge page based on a different 27 + * nodes_allowed previously, so h->next_node_to_{alloc|free} might 28 + * be outside of *nodes_allowed. Ensure that we use an allowed 29 + * node for alloc or free. 30 + */ 31 + static inline int next_node_allowed(int nid, nodemask_t *nodes_allowed) 32 + { 33 + nid = next_node_in(nid, *nodes_allowed); 34 + VM_BUG_ON(nid >= MAX_NUMNODES); 35 + 36 + return nid; 37 + } 38 + 39 + static inline int get_valid_node_allowed(int nid, nodemask_t *nodes_allowed) 40 + { 41 + if (!node_isset(nid, *nodes_allowed)) 42 + nid = next_node_allowed(nid, nodes_allowed); 43 + return nid; 44 + } 45 + 46 + /* 47 + * returns the previously saved node ["this node"] from which to 48 + * allocate a persistent huge page for the pool and advance the 49 + * next node from which to allocate, handling wrap at end of node 50 + * mask. 51 + */ 52 + static inline int hstate_next_node_to_alloc(int *next_node, 53 + nodemask_t *nodes_allowed) 54 + { 55 + int nid; 56 + 57 + VM_BUG_ON(!nodes_allowed); 58 + 59 + nid = get_valid_node_allowed(*next_node, nodes_allowed); 60 + *next_node = next_node_allowed(nid, nodes_allowed); 61 + 62 + return nid; 63 + } 64 + 65 + /* 66 + * helper for remove_pool_hugetlb_folio() - return the previously saved 67 + * node ["this node"] from which to free a huge page. Advance the 68 + * next node id whether or not we find a free huge page to free so 69 + * that the next attempt to free addresses the next node. 70 + */ 71 + static inline int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed) 72 + { 73 + int nid; 74 + 75 + VM_BUG_ON(!nodes_allowed); 76 + 77 + nid = get_valid_node_allowed(h->next_nid_to_free, nodes_allowed); 78 + h->next_nid_to_free = next_node_allowed(nid, nodes_allowed); 79 + 80 + return nid; 81 + } 82 + 83 + #define for_each_node_mask_to_alloc(next_node, nr_nodes, node, mask) \ 84 + for (nr_nodes = nodes_weight(*mask); \ 85 + nr_nodes > 0 && \ 86 + ((node = hstate_next_node_to_alloc(next_node, mask)) || 1); \ 87 + nr_nodes--) 88 + 89 + #define for_each_node_mask_to_free(hs, nr_nodes, node, mask) \ 90 + for (nr_nodes = nodes_weight(*mask); \ 91 + nr_nodes > 0 && \ 92 + ((node = hstate_next_node_to_free(hs, mask)) || 1); \ 93 + nr_nodes--) 94 + 95 + extern void remove_hugetlb_folio(struct hstate *h, struct folio *folio, 96 + bool adjust_surplus); 97 + extern void add_hugetlb_folio(struct hstate *h, struct folio *folio, 98 + bool adjust_surplus); 99 + extern void init_new_hugetlb_folio(struct folio *folio); 100 + extern void prep_and_add_allocated_folios(struct hstate *h, 101 + struct list_head *folio_list); 102 + extern long demote_pool_huge_page(struct hstate *src, 103 + nodemask_t *nodes_allowed, 104 + unsigned long nr_to_demote); 105 + extern ssize_t __nr_hugepages_store_common(bool obey_mempolicy, 106 + struct hstate *h, int nid, 107 + unsigned long count, size_t len); 108 + 109 + extern void hugetlb_sysfs_init(void) __init; 110 + 111 + #endif /* _LINUX_HUGETLB_INTERNAL_H */
+502
mm/hugetlb_sysfs.c
··· 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/swap.h> 8 + #include <linux/page_owner.h> 9 + #include <linux/page-isolation.h> 10 + 11 + #include "hugetlb_vmemmap.h" 12 + #include "hugetlb_internal.h" 13 + 14 + #define HSTATE_ATTR_RO(_name) \ 15 + static struct kobj_attribute _name##_attr = __ATTR_RO(_name) 16 + 17 + #define HSTATE_ATTR_WO(_name) \ 18 + static struct kobj_attribute _name##_attr = __ATTR_WO(_name) 19 + 20 + #define HSTATE_ATTR(_name) \ 21 + static struct kobj_attribute _name##_attr = __ATTR_RW(_name) 22 + 23 + static struct kobject *hugepages_kobj; 24 + static struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; 25 + 26 + static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp); 27 + 28 + static struct hstate *kobj_to_hstate(struct kobject *kobj, int *nidp) 29 + { 30 + int i; 31 + 32 + for (i = 0; i < HUGE_MAX_HSTATE; i++) 33 + if (hstate_kobjs[i] == kobj) { 34 + if (nidp) 35 + *nidp = NUMA_NO_NODE; 36 + return &hstates[i]; 37 + } 38 + 39 + return kobj_to_node_hstate(kobj, nidp); 40 + } 41 + 42 + static ssize_t nr_hugepages_show_common(struct kobject *kobj, 43 + struct kobj_attribute *attr, char *buf) 44 + { 45 + struct hstate *h; 46 + unsigned long nr_huge_pages; 47 + int nid; 48 + 49 + h = kobj_to_hstate(kobj, &nid); 50 + if (nid == NUMA_NO_NODE) 51 + nr_huge_pages = h->nr_huge_pages; 52 + else 53 + nr_huge_pages = h->nr_huge_pages_node[nid]; 54 + 55 + return sysfs_emit(buf, "%lu\n", nr_huge_pages); 56 + } 57 + 58 + static ssize_t nr_hugepages_store_common(bool obey_mempolicy, 59 + struct kobject *kobj, const char *buf, 60 + size_t len) 61 + { 62 + struct hstate *h; 63 + unsigned long count; 64 + int nid; 65 + int err; 66 + 67 + err = kstrtoul(buf, 10, &count); 68 + if (err) 69 + return err; 70 + 71 + h = kobj_to_hstate(kobj, &nid); 72 + return __nr_hugepages_store_common(obey_mempolicy, h, nid, count, len); 73 + } 74 + 75 + static ssize_t nr_hugepages_show(struct kobject *kobj, 76 + struct kobj_attribute *attr, char *buf) 77 + { 78 + return nr_hugepages_show_common(kobj, attr, buf); 79 + } 80 + 81 + static ssize_t nr_hugepages_store(struct kobject *kobj, 82 + struct kobj_attribute *attr, const char *buf, size_t len) 83 + { 84 + return nr_hugepages_store_common(false, kobj, buf, len); 85 + } 86 + HSTATE_ATTR(nr_hugepages); 87 + 88 + #ifdef CONFIG_NUMA 89 + 90 + /* 91 + * hstate attribute for optionally mempolicy-based constraint on persistent 92 + * huge page alloc/free. 93 + */ 94 + static ssize_t nr_hugepages_mempolicy_show(struct kobject *kobj, 95 + struct kobj_attribute *attr, 96 + char *buf) 97 + { 98 + return nr_hugepages_show_common(kobj, attr, buf); 99 + } 100 + 101 + static ssize_t nr_hugepages_mempolicy_store(struct kobject *kobj, 102 + struct kobj_attribute *attr, const char *buf, size_t len) 103 + { 104 + return nr_hugepages_store_common(true, kobj, buf, len); 105 + } 106 + HSTATE_ATTR(nr_hugepages_mempolicy); 107 + #endif 108 + 109 + 110 + static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj, 111 + struct kobj_attribute *attr, char *buf) 112 + { 113 + struct hstate *h = kobj_to_hstate(kobj, NULL); 114 + return sysfs_emit(buf, "%lu\n", h->nr_overcommit_huge_pages); 115 + } 116 + 117 + static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj, 118 + struct kobj_attribute *attr, const char *buf, size_t count) 119 + { 120 + int err; 121 + unsigned long input; 122 + struct hstate *h = kobj_to_hstate(kobj, NULL); 123 + 124 + if (hstate_is_gigantic_no_runtime(h)) 125 + return -EINVAL; 126 + 127 + err = kstrtoul(buf, 10, &input); 128 + if (err) 129 + return err; 130 + 131 + spin_lock_irq(&hugetlb_lock); 132 + h->nr_overcommit_huge_pages = input; 133 + spin_unlock_irq(&hugetlb_lock); 134 + 135 + return count; 136 + } 137 + HSTATE_ATTR(nr_overcommit_hugepages); 138 + 139 + static ssize_t free_hugepages_show(struct kobject *kobj, 140 + struct kobj_attribute *attr, char *buf) 141 + { 142 + struct hstate *h; 143 + unsigned long free_huge_pages; 144 + int nid; 145 + 146 + h = kobj_to_hstate(kobj, &nid); 147 + if (nid == NUMA_NO_NODE) 148 + free_huge_pages = h->free_huge_pages; 149 + else 150 + free_huge_pages = h->free_huge_pages_node[nid]; 151 + 152 + return sysfs_emit(buf, "%lu\n", free_huge_pages); 153 + } 154 + HSTATE_ATTR_RO(free_hugepages); 155 + 156 + static ssize_t resv_hugepages_show(struct kobject *kobj, 157 + struct kobj_attribute *attr, char *buf) 158 + { 159 + struct hstate *h = kobj_to_hstate(kobj, NULL); 160 + return sysfs_emit(buf, "%lu\n", h->resv_huge_pages); 161 + } 162 + HSTATE_ATTR_RO(resv_hugepages); 163 + 164 + static ssize_t surplus_hugepages_show(struct kobject *kobj, 165 + struct kobj_attribute *attr, char *buf) 166 + { 167 + struct hstate *h; 168 + unsigned long surplus_huge_pages; 169 + int nid; 170 + 171 + h = kobj_to_hstate(kobj, &nid); 172 + if (nid == NUMA_NO_NODE) 173 + surplus_huge_pages = h->surplus_huge_pages; 174 + else 175 + surplus_huge_pages = h->surplus_huge_pages_node[nid]; 176 + 177 + return sysfs_emit(buf, "%lu\n", surplus_huge_pages); 178 + } 179 + HSTATE_ATTR_RO(surplus_hugepages); 180 + 181 + static ssize_t demote_store(struct kobject *kobj, 182 + struct kobj_attribute *attr, const char *buf, size_t len) 183 + { 184 + unsigned long nr_demote; 185 + unsigned long nr_available; 186 + nodemask_t nodes_allowed, *n_mask; 187 + struct hstate *h; 188 + int err; 189 + int nid; 190 + 191 + err = kstrtoul(buf, 10, &nr_demote); 192 + if (err) 193 + return err; 194 + h = kobj_to_hstate(kobj, &nid); 195 + 196 + if (nid != NUMA_NO_NODE) { 197 + init_nodemask_of_node(&nodes_allowed, nid); 198 + n_mask = &nodes_allowed; 199 + } else { 200 + n_mask = &node_states[N_MEMORY]; 201 + } 202 + 203 + /* Synchronize with other sysfs operations modifying huge pages */ 204 + mutex_lock(&h->resize_lock); 205 + spin_lock_irq(&hugetlb_lock); 206 + 207 + while (nr_demote) { 208 + long rc; 209 + 210 + /* 211 + * Check for available pages to demote each time thorough the 212 + * loop as demote_pool_huge_page will drop hugetlb_lock. 213 + */ 214 + if (nid != NUMA_NO_NODE) 215 + nr_available = h->free_huge_pages_node[nid]; 216 + else 217 + nr_available = h->free_huge_pages; 218 + nr_available -= h->resv_huge_pages; 219 + if (!nr_available) 220 + break; 221 + 222 + rc = demote_pool_huge_page(h, n_mask, nr_demote); 223 + if (rc < 0) { 224 + err = rc; 225 + break; 226 + } 227 + 228 + nr_demote -= rc; 229 + } 230 + 231 + spin_unlock_irq(&hugetlb_lock); 232 + mutex_unlock(&h->resize_lock); 233 + 234 + if (err) 235 + return err; 236 + return len; 237 + } 238 + HSTATE_ATTR_WO(demote); 239 + 240 + static ssize_t demote_size_show(struct kobject *kobj, 241 + struct kobj_attribute *attr, char *buf) 242 + { 243 + struct hstate *h = kobj_to_hstate(kobj, NULL); 244 + unsigned long demote_size = (PAGE_SIZE << h->demote_order) / SZ_1K; 245 + 246 + return sysfs_emit(buf, "%lukB\n", demote_size); 247 + } 248 + 249 + static ssize_t demote_size_store(struct kobject *kobj, 250 + struct kobj_attribute *attr, 251 + const char *buf, size_t count) 252 + { 253 + struct hstate *h, *demote_hstate; 254 + unsigned long demote_size; 255 + unsigned int demote_order; 256 + 257 + demote_size = (unsigned long)memparse(buf, NULL); 258 + 259 + demote_hstate = size_to_hstate(demote_size); 260 + if (!demote_hstate) 261 + return -EINVAL; 262 + demote_order = demote_hstate->order; 263 + if (demote_order < HUGETLB_PAGE_ORDER) 264 + return -EINVAL; 265 + 266 + /* demote order must be smaller than hstate order */ 267 + h = kobj_to_hstate(kobj, NULL); 268 + if (demote_order >= h->order) 269 + return -EINVAL; 270 + 271 + /* resize_lock synchronizes access to demote size and writes */ 272 + mutex_lock(&h->resize_lock); 273 + h->demote_order = demote_order; 274 + mutex_unlock(&h->resize_lock); 275 + 276 + return count; 277 + } 278 + HSTATE_ATTR(demote_size); 279 + 280 + static struct attribute *hstate_attrs[] = { 281 + &nr_hugepages_attr.attr, 282 + &nr_overcommit_hugepages_attr.attr, 283 + &free_hugepages_attr.attr, 284 + &resv_hugepages_attr.attr, 285 + &surplus_hugepages_attr.attr, 286 + #ifdef CONFIG_NUMA 287 + &nr_hugepages_mempolicy_attr.attr, 288 + #endif 289 + NULL, 290 + }; 291 + 292 + static const struct attribute_group hstate_attr_group = { 293 + .attrs = hstate_attrs, 294 + }; 295 + 296 + static struct attribute *hstate_demote_attrs[] = { 297 + &demote_size_attr.attr, 298 + &demote_attr.attr, 299 + NULL, 300 + }; 301 + 302 + static const struct attribute_group hstate_demote_attr_group = { 303 + .attrs = hstate_demote_attrs, 304 + }; 305 + 306 + static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent, 307 + struct kobject **hstate_kobjs, 308 + const struct attribute_group *hstate_attr_group) 309 + { 310 + int retval; 311 + int hi = hstate_index(h); 312 + 313 + hstate_kobjs[hi] = kobject_create_and_add(h->name, parent); 314 + if (!hstate_kobjs[hi]) 315 + return -ENOMEM; 316 + 317 + retval = sysfs_create_group(hstate_kobjs[hi], hstate_attr_group); 318 + if (retval) { 319 + kobject_put(hstate_kobjs[hi]); 320 + hstate_kobjs[hi] = NULL; 321 + return retval; 322 + } 323 + 324 + if (h->demote_order) { 325 + retval = sysfs_create_group(hstate_kobjs[hi], 326 + &hstate_demote_attr_group); 327 + if (retval) { 328 + pr_warn("HugeTLB unable to create demote interfaces for %s\n", h->name); 329 + sysfs_remove_group(hstate_kobjs[hi], hstate_attr_group); 330 + kobject_put(hstate_kobjs[hi]); 331 + hstate_kobjs[hi] = NULL; 332 + return retval; 333 + } 334 + } 335 + 336 + return 0; 337 + } 338 + 339 + #ifdef CONFIG_NUMA 340 + static bool hugetlb_sysfs_initialized __ro_after_init; 341 + 342 + /* 343 + * node_hstate/s - associate per node hstate attributes, via their kobjects, 344 + * with node devices in node_devices[] using a parallel array. The array 345 + * index of a node device or _hstate == node id. 346 + * This is here to avoid any static dependency of the node device driver, in 347 + * the base kernel, on the hugetlb module. 348 + */ 349 + struct node_hstate { 350 + struct kobject *hugepages_kobj; 351 + struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; 352 + }; 353 + static struct node_hstate node_hstates[MAX_NUMNODES]; 354 + 355 + /* 356 + * A subset of global hstate attributes for node devices 357 + */ 358 + static struct attribute *per_node_hstate_attrs[] = { 359 + &nr_hugepages_attr.attr, 360 + &free_hugepages_attr.attr, 361 + &surplus_hugepages_attr.attr, 362 + NULL, 363 + }; 364 + 365 + static const struct attribute_group per_node_hstate_attr_group = { 366 + .attrs = per_node_hstate_attrs, 367 + }; 368 + 369 + /* 370 + * kobj_to_node_hstate - lookup global hstate for node device hstate attr kobj. 371 + * Returns node id via non-NULL nidp. 372 + */ 373 + static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp) 374 + { 375 + int nid; 376 + 377 + for (nid = 0; nid < nr_node_ids; nid++) { 378 + struct node_hstate *nhs = &node_hstates[nid]; 379 + int i; 380 + for (i = 0; i < HUGE_MAX_HSTATE; i++) 381 + if (nhs->hstate_kobjs[i] == kobj) { 382 + if (nidp) 383 + *nidp = nid; 384 + return &hstates[i]; 385 + } 386 + } 387 + 388 + BUG(); 389 + return NULL; 390 + } 391 + 392 + /* 393 + * Unregister hstate attributes from a single node device. 394 + * No-op if no hstate attributes attached. 395 + */ 396 + void hugetlb_unregister_node(struct node *node) 397 + { 398 + struct hstate *h; 399 + struct node_hstate *nhs = &node_hstates[node->dev.id]; 400 + 401 + if (!nhs->hugepages_kobj) 402 + return; /* no hstate attributes */ 403 + 404 + for_each_hstate(h) { 405 + int idx = hstate_index(h); 406 + struct kobject *hstate_kobj = nhs->hstate_kobjs[idx]; 407 + 408 + if (!hstate_kobj) 409 + continue; 410 + if (h->demote_order) 411 + sysfs_remove_group(hstate_kobj, &hstate_demote_attr_group); 412 + sysfs_remove_group(hstate_kobj, &per_node_hstate_attr_group); 413 + kobject_put(hstate_kobj); 414 + nhs->hstate_kobjs[idx] = NULL; 415 + } 416 + 417 + kobject_put(nhs->hugepages_kobj); 418 + nhs->hugepages_kobj = NULL; 419 + } 420 + 421 + 422 + /* 423 + * Register hstate attributes for a single node device. 424 + * No-op if attributes already registered. 425 + */ 426 + void hugetlb_register_node(struct node *node) 427 + { 428 + struct hstate *h; 429 + struct node_hstate *nhs = &node_hstates[node->dev.id]; 430 + int err; 431 + 432 + if (!hugetlb_sysfs_initialized) 433 + return; 434 + 435 + if (nhs->hugepages_kobj) 436 + return; /* already allocated */ 437 + 438 + nhs->hugepages_kobj = kobject_create_and_add("hugepages", 439 + &node->dev.kobj); 440 + if (!nhs->hugepages_kobj) 441 + return; 442 + 443 + for_each_hstate(h) { 444 + err = hugetlb_sysfs_add_hstate(h, nhs->hugepages_kobj, 445 + nhs->hstate_kobjs, 446 + &per_node_hstate_attr_group); 447 + if (err) { 448 + pr_err("HugeTLB: Unable to add hstate %s for node %d\n", 449 + h->name, node->dev.id); 450 + hugetlb_unregister_node(node); 451 + break; 452 + } 453 + } 454 + } 455 + 456 + /* 457 + * hugetlb init time: register hstate attributes for all registered node 458 + * devices of nodes that have memory. All on-line nodes should have 459 + * registered their associated device by this time. 460 + */ 461 + static void __init hugetlb_register_all_nodes(void) 462 + { 463 + int nid; 464 + 465 + for_each_online_node(nid) 466 + hugetlb_register_node(node_devices[nid]); 467 + } 468 + #else /* !CONFIG_NUMA */ 469 + 470 + static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp) 471 + { 472 + BUG(); 473 + if (nidp) 474 + *nidp = -1; 475 + return NULL; 476 + } 477 + 478 + static void hugetlb_register_all_nodes(void) { } 479 + 480 + #endif 481 + 482 + void __init hugetlb_sysfs_init(void) 483 + { 484 + struct hstate *h; 485 + int err; 486 + 487 + hugepages_kobj = kobject_create_and_add("hugepages", mm_kobj); 488 + if (!hugepages_kobj) 489 + return; 490 + 491 + for_each_hstate(h) { 492 + err = hugetlb_sysfs_add_hstate(h, hugepages_kobj, 493 + hstate_kobjs, &hstate_attr_group); 494 + if (err) 495 + pr_err("HugeTLB: Unable to add hstate %s\n", h->name); 496 + } 497 + 498 + #ifdef CONFIG_NUMA 499 + hugetlb_sysfs_initialized = true; 500 + #endif 501 + hugetlb_register_all_nodes(); 502 + }