lkml.org 
[lkml]   [2022]   [Jun]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 06/12] mm/demotion: Expose memory tier details via sysfs
    Date
    This patch adds /sys/devices/system/memtier/ where all memory tier
    related details can be found. All created memory tiers will be
    listed there as /sys/devices/system/memtier/memtierN/

    The nodes which are part of a specific memory tier can be listed
    via /sys/devices/system/memtier/memtierN/nodelist

    /sys/devices/system/memtier/max_tier shows the max tier ID value
    supported.

    /sys/devices/system/memtier/default_tier shows the memory tier to which
    NUMA nodes get added by default if not assigned a specific memory tier.

    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
    ---
    mm/memory-tiers.c | 93 ++++++++++++++++++++++++++++++++++++++++++++---
    1 file changed, 87 insertions(+), 6 deletions(-)

    diff --git a/mm/memory-tiers.c b/mm/memory-tiers.c
    index 0596f0b11065..4acf7570ae1b 100644
    --- a/mm/memory-tiers.c
    +++ b/mm/memory-tiers.c
    @@ -13,14 +13,15 @@

    struct memory_tier {
    struct list_head list;
    + struct device dev;
    nodemask_t nodelist;
    - int id;
    };

    struct demotion_nodes {
    nodemask_t preferred;
    };

    +#define to_memory_tier(device) container_of(device, struct memory_tier, dev)
    static void establish_migration_targets(void);
    static DEFINE_MUTEX(memory_tier_lock);
    static LIST_HEAD(memory_tiers);
    @@ -86,6 +87,42 @@ static LIST_HEAD(memory_tiers);
    */
    static struct demotion_nodes *node_demotion __read_mostly;

    +static struct bus_type memory_tier_subsys = {
    + .name = "memtier",
    + .dev_name = "memtier",
    +};
    +
    +static ssize_t nodelist_show(struct device *dev,
    + struct device_attribute *attr, char *buf)
    +{
    + struct memory_tier *memtier = to_memory_tier(dev);
    +
    + return sysfs_emit(buf, "%*pbl\n",
    + nodemask_pr_args(&memtier->nodelist));
    +}
    +static DEVICE_ATTR_RO(nodelist);
    +
    +static struct attribute *memory_tier_dev_attrs[] = {
    + &dev_attr_nodelist.attr,
    + NULL
    +};
    +
    +static const struct attribute_group memory_tier_dev_group = {
    + .attrs = memory_tier_dev_attrs,
    +};
    +
    +static const struct attribute_group *memory_tier_dev_groups[] = {
    + &memory_tier_dev_group,
    + NULL
    +};
    +
    +static void memory_tier_device_release(struct device *dev)
    +{
    + struct memory_tier *tier = to_memory_tier(dev);
    +
    + kfree(tier);
    +}
    +
    static void insert_memory_tier(struct memory_tier *memtier)
    {
    struct list_head *ent;
    @@ -95,7 +132,7 @@ static void insert_memory_tier(struct memory_tier *memtier)

    list_for_each(ent, &memory_tiers) {
    tmp_memtier = list_entry(ent, struct memory_tier, list);
    - if (tmp_memtier->id < memtier->id) {
    + if (tmp_memtier->dev.id < memtier->dev.id) {
    list_add_tail(&memtier->list, ent);
    return;
    }
    @@ -105,6 +142,7 @@ static void insert_memory_tier(struct memory_tier *memtier)

    static struct memory_tier *register_memory_tier(unsigned int tier)
    {
    + int error;
    struct memory_tier *memtier;

    if (tier > MAX_MEMORY_TIER_ID)
    @@ -114,17 +152,26 @@ static struct memory_tier *register_memory_tier(unsigned int tier)
    if (!memtier)
    return ERR_PTR(-ENOMEM);

    - memtier->id = tier;
    + memtier->dev.id = tier;
    + memtier->dev.bus = &memory_tier_subsys;
    + memtier->dev.release = memory_tier_device_release;
    + memtier->dev.groups = memory_tier_dev_groups;

    insert_memory_tier(memtier);

    + error = device_register(&memtier->dev);
    + if (error) {
    + list_del(&memtier->list);
    + put_device(&memtier->dev);
    + return ERR_PTR(error);
    + }
    return memtier;
    }

    static void unregister_memory_tier(struct memory_tier *memtier)
    {
    list_del(&memtier->list);
    - kfree(memtier);
    + device_unregister(&memtier->dev);
    }

    static struct memory_tier *__node_get_memory_tier(int node)
    @@ -143,7 +190,7 @@ static struct memory_tier *__get_memory_tier_from_id(int id)
    struct memory_tier *memtier;

    list_for_each_entry(memtier, &memory_tiers, list) {
    - if (memtier->id == id)
    + if (memtier->dev.id == id)
    return memtier;
    }
    return NULL;
    @@ -181,7 +228,7 @@ int node_create_and_set_memory_tier(int node, int tier)
    goto out;
    }

    - if (current_tier->id == tier)
    + if (current_tier->dev.id == tier)
    goto out;

    node_clear(node, current_tier->nodelist);
    @@ -426,10 +473,44 @@ static void __init migrate_on_reclaim_init(void)
    hotplug_memory_notifier(migrate_on_reclaim_callback, 100);
    }

    +static ssize_t
    +max_tier_show(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    + return sysfs_emit(buf, "%d\n", MAX_MEMORY_TIER_ID);
    +}
    +static DEVICE_ATTR_RO(max_tier);
    +
    +static ssize_t
    +default_tier_show(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    + return sysfs_emit(buf, "memtier%d\n", default_memtier);
    +}
    +static DEVICE_ATTR_RO(default_tier);
    +
    +static struct attribute *memory_tier_attrs[] = {
    + &dev_attr_max_tier.attr,
    + &dev_attr_default_tier.attr,
    + NULL
    +};
    +
    +static const struct attribute_group memory_tier_attr_group = {
    + .attrs = memory_tier_attrs,
    +};
    +
    +static const struct attribute_group *memory_tier_attr_groups[] = {
    + &memory_tier_attr_group,
    + NULL,
    +};
    +
    static int __init memory_tier_init(void)
    {
    + int ret;
    struct memory_tier *memtier;

    + ret = subsys_system_register(&memory_tier_subsys, memory_tier_attr_groups);
    + if (ret)
    + pr_err("%s() failed to register subsystem: %d\n", __func__, ret);
    +
    /*
    * Register only default memory tier to hide all empty
    * memory tier from sysfs. Since this is early during
    --
    2.36.1
    \
     
     \ /
      Last update: 2022-06-22 10:29    [W:4.186 / U:0.228 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site