On Fri, Apr 22, 2022 at 12:55 PM Jagdish Gediya <jvgediya@xxxxxxxxxxxxx> wrote: > > Kernel prepares per-node demotion target list based on > node_states[N_DEMOTION_TARGETS], If enabled through sysfs, > demotion kicks in during reclaim, and pages get migrated > according to demotion target list prepared by kernel. > > It is helpful to know demotion target list prepared by > kernel to understand the demotion behaviour, so add > interface /sys/devices/system/node/nodeX/demotion_targets > to view per-node demotion targets via sysfs. > > Signed-off-by: Jagdish Gediya <jvgediya@xxxxxxxxxxxxx> > --- > drivers/base/node.c | 10 ++++++++++ > include/linux/migrate.h | 1 + > mm/migrate.c | 17 +++++++++++++++++ > 3 files changed, 28 insertions(+) > > diff --git a/drivers/base/node.c b/drivers/base/node.c > index e03eedbc421b..92326219aac2 100644 > --- a/drivers/base/node.c > +++ b/drivers/base/node.c > @@ -561,11 +561,21 @@ static ssize_t node_read_distance(struct device *dev, > } > static DEVICE_ATTR(distance, 0444, node_read_distance, NULL); > > +static ssize_t demotion_targets_show(struct device *dev, > + struct device_attribute *attr, char *buf) > +{ > + nodemask_t demotion_targets = node_get_demotion_targets(dev->id); > + > + return sysfs_emit(buf, "%*pbl\n", nodemask_pr_args(&demotion_targets)); > +} > +static DEVICE_ATTR_RO(demotion_targets); > + > static struct attribute *node_dev_attrs[] = { > &dev_attr_meminfo.attr, > &dev_attr_numastat.attr, > &dev_attr_distance.attr, > &dev_attr_vmstat.attr, > + &dev_attr_demotion_targets.attr, > NULL > }; > > diff --git a/include/linux/migrate.h b/include/linux/migrate.h > index 90e75d5a54d6..072019441a24 100644 > --- a/include/linux/migrate.h > +++ b/include/linux/migrate.h > @@ -173,6 +173,7 @@ int migrate_vma_setup(struct migrate_vma *args); > void migrate_vma_pages(struct migrate_vma *migrate); > void migrate_vma_finalize(struct migrate_vma *migrate); > int next_demotion_node(int node); > +nodemask_t node_get_demotion_targets(int node); I think a stub implementation for !CONFIG_MIGRATION is also needed. > #else /* CONFIG_MIGRATION disabled: */ > > diff --git a/mm/migrate.c b/mm/migrate.c > index 5b92a09fbe4a..da864831bc0c 100644 > --- a/mm/migrate.c > +++ b/mm/migrate.c > @@ -2187,6 +2187,23 @@ struct demotion_nodes { > > static struct demotion_nodes *node_demotion __read_mostly; > > +nodemask_t node_get_demotion_targets(int node) > +{ > + nodemask_t demotion_targets = NODE_MASK_NONE; > + unsigned short target_nr; > + > + if (!node_demotion) > + return NODE_MASK_NONE; > + > + rcu_read_lock(); > + target_nr = READ_ONCE(node_demotion[node].nr); > + for (int i = 0; i < target_nr; i++) > + node_set(READ_ONCE(node_demotion[node].nodes[i]), demotion_targets); > + rcu_read_unlock(); > + > + return demotion_targets; > +} > + > /** > * next_demotion_node() - Get the next node in the demotion path > * @node: The starting node to lookup the next node > -- > 2.35.1 >