Message ID | 20201201082128.15239-16-jgross@suse.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | xen: support per-cpupool scheduling granularity | expand |
On 01.12.2020 09:21, Juergen Gross wrote: > Add /cpupool/<cpupool-id> directories to hypfs. Those are completely > dynamic, so the related hypfs access functions need to be implemented. > > Signed-off-by: Juergen Gross <jgross@suse.com> > --- > V2: > - added const (Jan Beulich) Any particular reason this doesn't extend to ... > @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { > .notifier_call = cpu_callback > }; > > +#ifdef CONFIG_HYPFS > +static const struct hypfs_entry *cpupool_pooldir_enter( > + const struct hypfs_entry *entry); > + > +static struct hypfs_funcs cpupool_pooldir_funcs = { ... this (similarly in the next patch)? Granted I didn't look at the hypfs patches yet, but I don't suppose these struct instances need to be writable. Jan
On 01.12.20 10:00, Jan Beulich wrote: > On 01.12.2020 09:21, Juergen Gross wrote: >> Add /cpupool/<cpupool-id> directories to hypfs. Those are completely >> dynamic, so the related hypfs access functions need to be implemented. >> >> Signed-off-by: Juergen Gross <jgross@suse.com> >> --- >> V2: >> - added const (Jan Beulich) > > Any particular reason this doesn't extend to ... > >> @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { >> .notifier_call = cpu_callback >> }; >> >> +#ifdef CONFIG_HYPFS >> +static const struct hypfs_entry *cpupool_pooldir_enter( >> + const struct hypfs_entry *entry); >> + >> +static struct hypfs_funcs cpupool_pooldir_funcs = { > > ... this (similarly in the next patch)? Granted I didn't look at > the hypfs patches yet, but I don't suppose these struct instances > need to be writable. No reason. I'll add const. Juergen
On 01.12.20 09:21, Juergen Gross wrote: > Add /cpupool/<cpupool-id> directories to hypfs. Those are completely > dynamic, so the related hypfs access functions need to be implemented. > > Signed-off-by: Juergen Gross <jgross@suse.com> > --- > V2: > - added const (Jan Beulich) > - call hypfs_add_dir() in helper (Dario Faggioli) > - switch locking to enter/exit callbacks > --- > docs/misc/hypfs-paths.pandoc | 9 +++ > xen/common/sched/cpupool.c | 122 +++++++++++++++++++++++++++++++++++ > 2 files changed, 131 insertions(+) > > diff --git a/docs/misc/hypfs-paths.pandoc b/docs/misc/hypfs-paths.pandoc > index 6c7b2f7ee3..aaca1cdf92 100644 > --- a/docs/misc/hypfs-paths.pandoc > +++ b/docs/misc/hypfs-paths.pandoc > @@ -175,6 +175,15 @@ The major version of Xen. > > The minor version of Xen. > > +#### /cpupool/ > + > +A directory of all current cpupools. > + > +#### /cpupool/*/ > + > +The individual cpupools. Each entry is a directory with the name being the > +cpupool-id (e.g. /cpupool/0/). > + > #### /params/ > > A directory of runtime parameters. > diff --git a/xen/common/sched/cpupool.c b/xen/common/sched/cpupool.c > index 0db7d77219..3e17fdf95b 100644 > --- a/xen/common/sched/cpupool.c > +++ b/xen/common/sched/cpupool.c > @@ -13,6 +13,8 @@ > > #include <xen/cpu.h> > #include <xen/cpumask.h> > +#include <xen/guest_access.h> > +#include <xen/hypfs.h> > #include <xen/init.h> > #include <xen/keyhandler.h> > #include <xen/lib.h> > @@ -33,6 +35,7 @@ static int cpupool_moving_cpu = -1; > static struct cpupool *cpupool_cpu_moving = NULL; > static cpumask_t cpupool_locked_cpus; > > +/* This lock nests inside sysctl or hypfs lock. */ > static DEFINE_SPINLOCK(cpupool_lock); > > static enum sched_gran __read_mostly opt_sched_granularity = SCHED_GRAN_cpu; > @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { > .notifier_call = cpu_callback > }; > > +#ifdef CONFIG_HYPFS > +static const struct hypfs_entry *cpupool_pooldir_enter( > + const struct hypfs_entry *entry); > + > +static struct hypfs_funcs cpupool_pooldir_funcs = { > + .enter = cpupool_pooldir_enter, > + .exit = hypfs_node_exit, > + .read = hypfs_read_dir, > + .write = hypfs_write_deny, > + .getsize = hypfs_getsize, > + .findentry = hypfs_dir_findentry, > +}; > + > +static HYPFS_VARDIR_INIT(cpupool_pooldir, "%u", &cpupool_pooldir_funcs); > + > +static const struct hypfs_entry *cpupool_pooldir_enter( > + const struct hypfs_entry *entry) > +{ > + return &cpupool_pooldir.e; > +} I have found a more generic way to handle entering a dyndir node, resulting in no need to have cpupool_pooldir_enter() and cpupool_pooldir_funcs. This will add some more lines to the previous patch, but less than saved here. Juergen
On 02.12.2020 16:46, Jürgen Groß wrote: > On 01.12.20 09:21, Juergen Gross wrote: >> @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { >> .notifier_call = cpu_callback >> }; >> >> +#ifdef CONFIG_HYPFS >> +static const struct hypfs_entry *cpupool_pooldir_enter( >> + const struct hypfs_entry *entry); >> + >> +static struct hypfs_funcs cpupool_pooldir_funcs = { >> + .enter = cpupool_pooldir_enter, >> + .exit = hypfs_node_exit, >> + .read = hypfs_read_dir, >> + .write = hypfs_write_deny, >> + .getsize = hypfs_getsize, >> + .findentry = hypfs_dir_findentry, >> +}; >> + >> +static HYPFS_VARDIR_INIT(cpupool_pooldir, "%u", &cpupool_pooldir_funcs); >> + >> +static const struct hypfs_entry *cpupool_pooldir_enter( >> + const struct hypfs_entry *entry) >> +{ >> + return &cpupool_pooldir.e; >> +} > I have found a more generic way to handle entering a dyndir node, > resulting in no need to have cpupool_pooldir_enter() and > cpupool_pooldir_funcs. > > This will add some more lines to the previous patch, but less than > saved here. Which may then mean it's not a good use of time to look at v2 patch 14, considering there's a lot of other stuff in need of looking at? Jan
On 03.12.20 15:46, Jan Beulich wrote: > On 02.12.2020 16:46, Jürgen Groß wrote: >> On 01.12.20 09:21, Juergen Gross wrote: >>> @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { >>> .notifier_call = cpu_callback >>> }; >>> >>> +#ifdef CONFIG_HYPFS >>> +static const struct hypfs_entry *cpupool_pooldir_enter( >>> + const struct hypfs_entry *entry); >>> + >>> +static struct hypfs_funcs cpupool_pooldir_funcs = { >>> + .enter = cpupool_pooldir_enter, >>> + .exit = hypfs_node_exit, >>> + .read = hypfs_read_dir, >>> + .write = hypfs_write_deny, >>> + .getsize = hypfs_getsize, >>> + .findentry = hypfs_dir_findentry, >>> +}; >>> + >>> +static HYPFS_VARDIR_INIT(cpupool_pooldir, "%u", &cpupool_pooldir_funcs); >>> + >>> +static const struct hypfs_entry *cpupool_pooldir_enter( >>> + const struct hypfs_entry *entry) >>> +{ >>> + return &cpupool_pooldir.e; >>> +} >> I have found a more generic way to handle entering a dyndir node, >> resulting in no need to have cpupool_pooldir_enter() and >> cpupool_pooldir_funcs. >> >> This will add some more lines to the previous patch, but less than >> saved here. > > Which may then mean it's not a good use of time to look at v2 patch > 14, considering there's a lot of other stuff in need of looking at? All of V2 patch 14 remains valid, there is just a generic enter function added in V3. Juergen
On 01.12.2020 09:21, Juergen Gross wrote: > @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { > .notifier_call = cpu_callback > }; > > +#ifdef CONFIG_HYPFS > +static const struct hypfs_entry *cpupool_pooldir_enter( > + const struct hypfs_entry *entry); > + > +static struct hypfs_funcs cpupool_pooldir_funcs = { Yet one more const missing? > + .enter = cpupool_pooldir_enter, > + .exit = hypfs_node_exit, > + .read = hypfs_read_dir, > + .write = hypfs_write_deny, > + .getsize = hypfs_getsize, > + .findentry = hypfs_dir_findentry, > +}; > + > +static HYPFS_VARDIR_INIT(cpupool_pooldir, "%u", &cpupool_pooldir_funcs); > + > +static const struct hypfs_entry *cpupool_pooldir_enter( > + const struct hypfs_entry *entry) > +{ > + return &cpupool_pooldir.e; > +} > + > +static int cpupool_dir_read(const struct hypfs_entry *entry, > + XEN_GUEST_HANDLE_PARAM(void) uaddr) > +{ > + int ret = 0; > + const struct cpupool *c; > + unsigned int size = 0; > + > + list_for_each_entry(c, &cpupool_list, list) > + { > + size += hypfs_dynid_entry_size(entry, c->cpupool_id); Why do you maintain size here? I can't spot any use. With this dropped the function then no longer depends on its "entry" parameter, which makes me wonder ... > + ret = hypfs_read_dyndir_id_entry(&cpupool_pooldir, c->cpupool_id, > + list_is_last(&c->list, &cpupool_list), > + &uaddr); > + if ( ret ) > + break; > + } > + > + return ret; > +} > + > +static unsigned int cpupool_dir_getsize(const struct hypfs_entry *entry) > +{ > + const struct cpupool *c; > + unsigned int size = 0; > + > + list_for_each_entry(c, &cpupool_list, list) > + size += hypfs_dynid_entry_size(entry, c->cpupool_id); ... why this one does. To be certain their results are consistent with one another, I think both should produce their results from the same data. > + return size; > +} > + > +static const struct hypfs_entry *cpupool_dir_enter( > + const struct hypfs_entry *entry) > +{ > + struct hypfs_dyndir_id *data; > + > + data = hypfs_alloc_dyndata(sizeof(*data)); I generally like the added type safety of the macro wrappers around _xmalloc(). I wonder if it wouldn't be a good idea to have such here as well, to avoid random mistakes like data = hypfs_alloc_dyndata(sizeof(data)); However I further notice that the struct allocated isn't cpupool specific at all. It would seem to me that such an allocation therefore doesn't belong here. Therefore I wonder whether ... > + if ( !data ) > + return ERR_PTR(-ENOMEM); > + data->id = CPUPOOLID_NONE; > + > + spin_lock(&cpupool_lock); ... these two properties (initial ID and lock) shouldn't e.g. be communicated via the template, allowing the enter/exit hooks to become generic for all ID templates. Yet in turn I notice that the "id" field only ever gets set, both in patch 14 and here. But yes, I've now spotted the consumers in patch 16. > + return entry; > +} > + > +static void cpupool_dir_exit(const struct hypfs_entry *entry) > +{ > + spin_unlock(&cpupool_lock); > + > + hypfs_free_dyndata(); > +} > + > +static struct hypfs_entry *cpupool_dir_findentry( > + const struct hypfs_entry_dir *dir, const char *name, unsigned int name_len) > +{ > + unsigned long id; > + const char *end; > + const struct cpupool *cpupool; > + > + id = simple_strtoul(name, &end, 10); > + if ( end != name + name_len ) > + return ERR_PTR(-ENOENT); > + > + cpupool = __cpupool_find_by_id(id, true); Silent truncation from unsigned long to unsigned int? > + if ( !cpupool ) > + return ERR_PTR(-ENOENT); > + > + return hypfs_gen_dyndir_entry_id(&cpupool_pooldir, id); > +} > + > +static struct hypfs_funcs cpupool_dir_funcs = { Yet another missing const? > + .enter = cpupool_dir_enter, > + .exit = cpupool_dir_exit, > + .read = cpupool_dir_read, > + .write = hypfs_write_deny, > + .getsize = cpupool_dir_getsize, > + .findentry = cpupool_dir_findentry, > +}; > + > +static HYPFS_VARDIR_INIT(cpupool_dir, "cpupool", &cpupool_dir_funcs); Why VARDIR? This isn't a template, is it? Or does VARDIR really serve multiple purposes? > +static void cpupool_hypfs_init(void) > +{ > + hypfs_add_dir(&hypfs_root, &cpupool_dir, true); > + hypfs_add_dyndir(&cpupool_dir, &cpupool_pooldir); > +} > +#else > + > +static void cpupool_hypfs_init(void) > +{ > +} > +#endif I think you want to be consistent with the use of blank lines next to #if / #else / #endif. In cases when they enclose multiple entities, I think it's generally better to have intervening blank lines everywhere. I also think in such cases commenting #else and #endif is helpful. But you're the maintainer of this code ... Jan
On 04.12.20 10:10, Jan Beulich wrote: > On 01.12.2020 09:21, Juergen Gross wrote: >> @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { >> .notifier_call = cpu_callback >> }; >> >> +#ifdef CONFIG_HYPFS >> +static const struct hypfs_entry *cpupool_pooldir_enter( >> + const struct hypfs_entry *entry); >> + >> +static struct hypfs_funcs cpupool_pooldir_funcs = { > > Yet one more const missing? Already fixed locally. > >> + .enter = cpupool_pooldir_enter, >> + .exit = hypfs_node_exit, >> + .read = hypfs_read_dir, >> + .write = hypfs_write_deny, >> + .getsize = hypfs_getsize, >> + .findentry = hypfs_dir_findentry, >> +}; >> + >> +static HYPFS_VARDIR_INIT(cpupool_pooldir, "%u", &cpupool_pooldir_funcs); >> + >> +static const struct hypfs_entry *cpupool_pooldir_enter( >> + const struct hypfs_entry *entry) >> +{ >> + return &cpupool_pooldir.e; >> +} >> + >> +static int cpupool_dir_read(const struct hypfs_entry *entry, >> + XEN_GUEST_HANDLE_PARAM(void) uaddr) >> +{ >> + int ret = 0; >> + const struct cpupool *c; >> + unsigned int size = 0; >> + >> + list_for_each_entry(c, &cpupool_list, list) >> + { >> + size += hypfs_dynid_entry_size(entry, c->cpupool_id); > > Why do you maintain size here? I can't spot any use. Oh, indeed. This is a remnant of an earlier variant. > > With this dropped the function then no longer depends on its > "entry" parameter, which makes me wonder ... > >> + ret = hypfs_read_dyndir_id_entry(&cpupool_pooldir, c->cpupool_id, >> + list_is_last(&c->list, &cpupool_list), >> + &uaddr); >> + if ( ret ) >> + break; >> + } >> + >> + return ret; >> +} >> + >> +static unsigned int cpupool_dir_getsize(const struct hypfs_entry *entry) >> +{ >> + const struct cpupool *c; >> + unsigned int size = 0; >> + >> + list_for_each_entry(c, &cpupool_list, list) >> + size += hypfs_dynid_entry_size(entry, c->cpupool_id); > > ... why this one does. To be certain their results are consistent > with one another, I think both should produce their results from > the same data. In the end they do. Creating a complete direntry just for obtaining its size is overkill, especially as hypfs_read_dyndir_id_entry() is not directly calculating the size, but copying the fixed and the variable parts in two portions. > >> + return size; >> +} >> + >> +static const struct hypfs_entry *cpupool_dir_enter( >> + const struct hypfs_entry *entry) >> +{ >> + struct hypfs_dyndir_id *data; >> + >> + data = hypfs_alloc_dyndata(sizeof(*data)); > > I generally like the added type safety of the macro wrappers > around _xmalloc(). I wonder if it wouldn't be a good idea to have > such here as well, to avoid random mistakes like > > data = hypfs_alloc_dyndata(sizeof(data)); Fine with me. > > However I further notice that the struct allocated isn't cpupool > specific at all. It would seem to me that such an allocation > therefore doesn't belong here. Therefore I wonder whether ... > >> + if ( !data ) >> + return ERR_PTR(-ENOMEM); >> + data->id = CPUPOOLID_NONE; >> + >> + spin_lock(&cpupool_lock); > > ... these two properties (initial ID and lock) shouldn't e.g. be > communicated via the template, allowing the enter/exit hooks to > become generic for all ID templates. The problem with the lock is that it is rather user specific. For domains this will be split (rcu_read_lock(&domlist_read_lock) for the /domain directory, and get_domain() for the per-domain level). And memory allocation might need other data as well, so this won't be the same structure for all cases. A two level dynamic directory (e.g. domain/vcpu) might want to allocate the needed dyndata for both levels already when entering /domain. > > Yet in turn I notice that the "id" field only ever gets set, both > in patch 14 and here. But yes, I've now spotted the consumers in > patch 16. > >> + return entry; >> +} >> + >> +static void cpupool_dir_exit(const struct hypfs_entry *entry) >> +{ >> + spin_unlock(&cpupool_lock); >> + >> + hypfs_free_dyndata(); >> +} >> + >> +static struct hypfs_entry *cpupool_dir_findentry( >> + const struct hypfs_entry_dir *dir, const char *name, unsigned int name_len) >> +{ >> + unsigned long id; >> + const char *end; >> + const struct cpupool *cpupool; >> + >> + id = simple_strtoul(name, &end, 10); >> + if ( end != name + name_len ) >> + return ERR_PTR(-ENOENT); >> + >> + cpupool = __cpupool_find_by_id(id, true); > > Silent truncation from unsigned long to unsigned int? Oh, indeed. Need to check against UINT_MAX. > >> + if ( !cpupool ) >> + return ERR_PTR(-ENOENT); >> + >> + return hypfs_gen_dyndir_entry_id(&cpupool_pooldir, id); >> +} >> + >> +static struct hypfs_funcs cpupool_dir_funcs = { > > Yet another missing const? Already fixed. > >> + .enter = cpupool_dir_enter, >> + .exit = cpupool_dir_exit, >> + .read = cpupool_dir_read, >> + .write = hypfs_write_deny, >> + .getsize = cpupool_dir_getsize, >> + .findentry = cpupool_dir_findentry, >> +}; >> + >> +static HYPFS_VARDIR_INIT(cpupool_dir, "cpupool", &cpupool_dir_funcs); > > Why VARDIR? This isn't a template, is it? Or does VARDIR really > serve multiple purposes? Basically it just takes an additional parameter for the function vector. Maybe I should rename it to HYPFS_DIR_INIT_FUNC()? > >> +static void cpupool_hypfs_init(void) >> +{ >> + hypfs_add_dir(&hypfs_root, &cpupool_dir, true); >> + hypfs_add_dyndir(&cpupool_dir, &cpupool_pooldir); >> +} >> +#else >> + >> +static void cpupool_hypfs_init(void) >> +{ >> +} >> +#endif > > I think you want to be consistent with the use of blank lines next > to #if / #else / #endif. In cases when they enclose multiple entities, > I think it's generally better to have intervening blank lines > everywhere. I also think in such cases commenting #else and #endif is > helpful. But you're the maintainer of this code ... I think I'll change it. Juergen
On 04.12.2020 12:08, Jürgen Groß wrote: > On 04.12.20 10:10, Jan Beulich wrote: >> On 01.12.2020 09:21, Juergen Gross wrote: >>> +static struct hypfs_funcs cpupool_dir_funcs = { >> >> Yet another missing const? > > Already fixed. > >> >>> + .enter = cpupool_dir_enter, >>> + .exit = cpupool_dir_exit, >>> + .read = cpupool_dir_read, >>> + .write = hypfs_write_deny, >>> + .getsize = cpupool_dir_getsize, >>> + .findentry = cpupool_dir_findentry, >>> +}; >>> + >>> +static HYPFS_VARDIR_INIT(cpupool_dir, "cpupool", &cpupool_dir_funcs); >> >> Why VARDIR? This isn't a template, is it? Or does VARDIR really >> serve multiple purposes? > > Basically it just takes an additional parameter for the function vector. > Maybe I should rename it to HYPFS_DIR_INIT_FUNC()? Maybe. Depends on what exactly the VAR is meant to stand for. Jan
diff --git a/docs/misc/hypfs-paths.pandoc b/docs/misc/hypfs-paths.pandoc index 6c7b2f7ee3..aaca1cdf92 100644 --- a/docs/misc/hypfs-paths.pandoc +++ b/docs/misc/hypfs-paths.pandoc @@ -175,6 +175,15 @@ The major version of Xen. The minor version of Xen. +#### /cpupool/ + +A directory of all current cpupools. + +#### /cpupool/*/ + +The individual cpupools. Each entry is a directory with the name being the +cpupool-id (e.g. /cpupool/0/). + #### /params/ A directory of runtime parameters. diff --git a/xen/common/sched/cpupool.c b/xen/common/sched/cpupool.c index 0db7d77219..3e17fdf95b 100644 --- a/xen/common/sched/cpupool.c +++ b/xen/common/sched/cpupool.c @@ -13,6 +13,8 @@ #include <xen/cpu.h> #include <xen/cpumask.h> +#include <xen/guest_access.h> +#include <xen/hypfs.h> #include <xen/init.h> #include <xen/keyhandler.h> #include <xen/lib.h> @@ -33,6 +35,7 @@ static int cpupool_moving_cpu = -1; static struct cpupool *cpupool_cpu_moving = NULL; static cpumask_t cpupool_locked_cpus; +/* This lock nests inside sysctl or hypfs lock. */ static DEFINE_SPINLOCK(cpupool_lock); static enum sched_gran __read_mostly opt_sched_granularity = SCHED_GRAN_cpu; @@ -1003,12 +1006,131 @@ static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; +#ifdef CONFIG_HYPFS +static const struct hypfs_entry *cpupool_pooldir_enter( + const struct hypfs_entry *entry); + +static struct hypfs_funcs cpupool_pooldir_funcs = { + .enter = cpupool_pooldir_enter, + .exit = hypfs_node_exit, + .read = hypfs_read_dir, + .write = hypfs_write_deny, + .getsize = hypfs_getsize, + .findentry = hypfs_dir_findentry, +}; + +static HYPFS_VARDIR_INIT(cpupool_pooldir, "%u", &cpupool_pooldir_funcs); + +static const struct hypfs_entry *cpupool_pooldir_enter( + const struct hypfs_entry *entry) +{ + return &cpupool_pooldir.e; +} + +static int cpupool_dir_read(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr) +{ + int ret = 0; + const struct cpupool *c; + unsigned int size = 0; + + list_for_each_entry(c, &cpupool_list, list) + { + size += hypfs_dynid_entry_size(entry, c->cpupool_id); + + ret = hypfs_read_dyndir_id_entry(&cpupool_pooldir, c->cpupool_id, + list_is_last(&c->list, &cpupool_list), + &uaddr); + if ( ret ) + break; + } + + return ret; +} + +static unsigned int cpupool_dir_getsize(const struct hypfs_entry *entry) +{ + const struct cpupool *c; + unsigned int size = 0; + + list_for_each_entry(c, &cpupool_list, list) + size += hypfs_dynid_entry_size(entry, c->cpupool_id); + + return size; +} + +static const struct hypfs_entry *cpupool_dir_enter( + const struct hypfs_entry *entry) +{ + struct hypfs_dyndir_id *data; + + data = hypfs_alloc_dyndata(sizeof(*data)); + if ( !data ) + return ERR_PTR(-ENOMEM); + data->id = CPUPOOLID_NONE; + + spin_lock(&cpupool_lock); + + return entry; +} + +static void cpupool_dir_exit(const struct hypfs_entry *entry) +{ + spin_unlock(&cpupool_lock); + + hypfs_free_dyndata(); +} + +static struct hypfs_entry *cpupool_dir_findentry( + const struct hypfs_entry_dir *dir, const char *name, unsigned int name_len) +{ + unsigned long id; + const char *end; + const struct cpupool *cpupool; + + id = simple_strtoul(name, &end, 10); + if ( end != name + name_len ) + return ERR_PTR(-ENOENT); + + cpupool = __cpupool_find_by_id(id, true); + + if ( !cpupool ) + return ERR_PTR(-ENOENT); + + return hypfs_gen_dyndir_entry_id(&cpupool_pooldir, id); +} + +static struct hypfs_funcs cpupool_dir_funcs = { + .enter = cpupool_dir_enter, + .exit = cpupool_dir_exit, + .read = cpupool_dir_read, + .write = hypfs_write_deny, + .getsize = cpupool_dir_getsize, + .findentry = cpupool_dir_findentry, +}; + +static HYPFS_VARDIR_INIT(cpupool_dir, "cpupool", &cpupool_dir_funcs); + +static void cpupool_hypfs_init(void) +{ + hypfs_add_dir(&hypfs_root, &cpupool_dir, true); + hypfs_add_dyndir(&cpupool_dir, &cpupool_pooldir); +} +#else + +static void cpupool_hypfs_init(void) +{ +} +#endif + static int __init cpupool_init(void) { unsigned int cpu; cpupool_gran_init(); + cpupool_hypfs_init(); + cpupool0 = cpupool_create(0, 0); BUG_ON(IS_ERR(cpupool0)); cpupool_put(cpupool0);
Add /cpupool/<cpupool-id> directories to hypfs. Those are completely dynamic, so the related hypfs access functions need to be implemented. Signed-off-by: Juergen Gross <jgross@suse.com> --- V2: - added const (Jan Beulich) - call hypfs_add_dir() in helper (Dario Faggioli) - switch locking to enter/exit callbacks --- docs/misc/hypfs-paths.pandoc | 9 +++ xen/common/sched/cpupool.c | 122 +++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+)