/** * struct node_access_nodes - Access class device to hold user visible * relationships to other nodes. * @dev: Device for this memory access class * @list_node: List element in the node's access list * @access: The access class rank * @coord: Heterogeneous memory performance coordinates
*/ struct node_access_nodes { struct device dev; struct list_head list_node; unsignedint access; #ifdef CONFIG_HMEM_REPORTING struct access_coordinate coord; #endif
}; #define to_access_nodes(dev) container_of(dev, struct node_access_nodes, dev)
/** * node_set_perf_attrs - Set the performance values for given access class * @nid: Node identifier to be set * @coord: Heterogeneous memory performance coordinates * @access: The access class the for the given attributes
*/ void node_set_perf_attrs(unsignedint nid, struct access_coordinate *coord, enum access_coordinate_class access)
{ struct node_access_nodes *c; struct node *node; int i;
if (WARN_ON_ONCE(!node_online(nid))) return;
node = node_devices[nid];
c = node_init_node_access(node, access); if (!c) return;
c->coord = *coord; for (i = 0; access_attrs[i] != NULL; i++) { if (sysfs_add_file_to_group(&c->dev.kobj, access_attrs[i], "initiators")) {
pr_info("failed to add performance attribute to node %d\n",
nid); break;
}
}
/* When setting CPU access coordinates, update mempolicy */ if (access == ACCESS_COORDINATE_CPU) { if (mempolicy_set_node_perf(nid, coord)) {
pr_info("failed to set mempolicy attrs for node %d\n",
nid);
}
}
}
EXPORT_SYMBOL_GPL(node_set_perf_attrs);
/** * struct node_cache_info - Internal tracking for memory node caches * @dev: Device represeting the cache level * @node: List element for tracking in the node * @cache_attrs:Attributes for this cache level
*/ struct node_cache_info { struct device dev; struct list_head node; struct node_cache_attrs cache_attrs;
}; #define to_cache_info(device) container_of(device, struct node_cache_info, dev)
static ssize_t node_read_vmstat(struct device *dev, struct device_attribute *attr, char *buf)
{ int nid = dev->id; struct pglist_data *pgdat = NODE_DATA(nid); int i; int len = 0;
for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
len += sysfs_emit_at(buf, len, "%s %lu\n",
zone_stat_name(i),
sum_zone_node_page_state(nid, i));
#ifdef CONFIG_NUMA
fold_vm_numa_events(); for (i = 0; i < NR_VM_NUMA_EVENT_ITEMS; i++)
len += sysfs_emit_at(buf, len, "%s %lu\n",
numa_stat_name(i),
sum_zone_numa_event_state(nid, i));
#endif for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) { unsignedlong pages = node_page_state_pages(pgdat, i);
if (vmstat_item_print_in_thp(i))
pages /= HPAGE_PMD_NR;
len += sysfs_emit_at(buf, len, "%s %lu\n", node_stat_name(i),
pages);
}
static ssize_t node_read_distance(struct device *dev, struct device_attribute *attr, char *buf)
{ int nid = dev->id; int len = 0; int i;
/* * buf is currently PAGE_SIZE in length and each node needs 4 chars * at the most (distance + space or newline).
*/
BUILD_BUG_ON(MAX_NUMNODES * 4 > PAGE_SIZE);
for_each_online_node(i) {
len += sysfs_emit_at(buf, len, "%s%d",
i ? " " : "", node_distance(nid, i));
}
/* * register_node - Setup a sysfs device for a node. * @num - Node number to use when creating the device. * * Initialize and register the node device.
*/ staticint register_node(struct node *node, int num)
{ int error;
/** * unregister_node - unregister a node device * @node: node going away * * Unregisters a node device @node. All the devices on the node must be * unregistered before calling this function.
*/ void unregister_node(struct node *node)
{
hugetlb_unregister_node(node);
compaction_unregister_node(node);
reclaim_unregister_node(node);
node_remove_accesses(node);
node_remove_caches(node);
device_unregister(&node->dev);
}
struct node *node_devices[MAX_NUMNODES];
/* * register cpu under node
*/ int register_cpu_under_node(unsignedint cpu, unsignedint nid)
{ int ret; struct device *obj;
if (!node_online(nid)) return 0;
obj = get_cpu_device(cpu); if (!obj) return 0;
ret = sysfs_create_link(&node_devices[nid]->dev.kobj,
&obj->kobj,
kobject_name(&obj->kobj)); if (ret) return ret;
/** * register_memory_node_under_compute_node - link memory node to its compute * node for a given access class. * @mem_nid: Memory node number * @cpu_nid: Cpu node number * @access: Access class to register * * Description: * For use with platforms that may have separate memory and compute nodes. * This function will export node relationships linking which memory * initiator nodes can access memory targets at a given ranked access * class.
*/ int register_memory_node_under_compute_node(unsignedint mem_nid, unsignedint cpu_nid, enum access_coordinate_class access)
{ struct node *init_node, *targ_node; struct node_access_nodes *initiator, *target; int ret;
if (!node_online(cpu_nid) || !node_online(mem_nid)) return -ENODEV;
ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
&mem_blk->dev.kobj,
kobject_name(&mem_blk->dev.kobj)); if (ret && ret != -EEXIST)
dev_err_ratelimited(&node_devices[nid]->dev, "can't create link to %s in sysfs (%d)\n",
kobject_name(&mem_blk->dev.kobj), ret);
ret = sysfs_create_link_nowarn(&mem_blk->dev.kobj,
&node_devices[nid]->dev.kobj,
kobject_name(&node_devices[nid]->dev.kobj)); if (ret && ret != -EEXIST)
dev_err_ratelimited(&mem_blk->dev, "can't create link to %s in sysfs (%d)\n",
kobject_name(&node_devices[nid]->dev.kobj),
ret);
}
/* * During hotplug we know that all pages in the memory block belong to the same * node.
*/ staticint register_mem_block_under_node_hotplug(struct memory_block *mem_blk, void *arg)
{ int nid = *(int *)arg;
/* * Unregister a memory block device under the node it spans. Memory blocks * with multiple nodes cannot be offlined and therefore also never be removed.
*/ void unregister_memory_block_under_nodes(struct memory_block *mem_blk)
{ if (mem_blk->nid == NUMA_NO_NODE) return;
ret = subsys_system_register(&node_subsys, cpu_root_attr_groups); if (ret)
panic("%s() failed to register subsystem: %d\n", __func__, ret);
/* * Create all node devices, which will properly link the node * to already created cpu devices.
*/
for_each_online_node(i) {
ret = register_one_node(i); if (ret)
panic("%s() failed to add node: %d\n", __func__, ret);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.