Patchwork [5/7] NUMA: add qmp command set-mpol to set memory policy for NUMA node

login
register
mail settings
Submitter Wanlong Gao
Date June 18, 2013, 8:09 a.m.
Message ID <1371542991-15911-6-git-send-email-gaowanlong@cn.fujitsu.com>
Download mbox | patch
Permalink /patch/252125/
State New
Headers show

Comments

Wanlong Gao - June 18, 2013, 8:09 a.m.
The QMP command let it be able to set node's memory policy
through the QMP protocol. The qmp-shell command is like:
    set-mpol nodeid=0 mpol=membind nodemask=0-1

Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
---
 cpus.c                  | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/sysemu.h |  1 +
 qapi-schema.json        | 13 +++++++++++
 qmp-commands.hx         | 35 ++++++++++++++++++++++++++++
 vl.c                    |  2 +-
 5 files changed, 111 insertions(+), 1 deletion(-)
Paolo Bonzini - June 18, 2013, 9:21 a.m.
Il 18/06/2013 10:09, Wanlong Gao ha scritto:
> The QMP command let it be able to set node's memory policy
> through the QMP protocol. The qmp-shell command is like:
>     set-mpol nodeid=0 mpol=membind nodemask=0-1
> 
> Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>

How would this work with mem-path?

Paolo

> ---
>  cpus.c                  | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
>  include/sysemu/sysemu.h |  1 +
>  qapi-schema.json        | 13 +++++++++++
>  qmp-commands.hx         | 35 ++++++++++++++++++++++++++++
>  vl.c                    |  2 +-
>  5 files changed, 111 insertions(+), 1 deletion(-)
> 
> diff --git a/cpus.c b/cpus.c
> index b868932..a2836e9 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -1431,3 +1431,64 @@ void qmp_inject_nmi(Error **errp)
>      error_set(errp, QERR_UNSUPPORTED);
>  #endif
>  }
> +
> +void qmp_set_mpol(int64_t nodeid, bool has_mpol, const char *mpol,
> +                  bool has_nodemask, const char *nodemask, Error **errp)
> +{
> +    unsigned int ret;
> +    unsigned int flags;
> +    DECLARE_BITMAP(host_mem, MAX_CPUMASK_BITS);
> +
> +    if (nodeid >= nb_numa_nodes) {
> +        error_setg(errp, "Only has '%d' NUMA nodes", nb_numa_nodes);
> +        return;
> +    }
> +
> +    bitmap_copy(host_mem, numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
> +    flags = numa_info[nodeid].flags;
> +
> +    numa_info[nodeid].flags = NODE_HOST_NONE;
> +    bitmap_zero(numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
> +
> +    if (!has_mpol) {
> +        if (set_node_mpol(nodeid) == -1) {
> +            goto error;
> +        }
> +        return;
> +    }
> +
> +    if (!strcmp(mpol, "membind")) {
> +        numa_info[nodeid].flags |= NODE_HOST_BIND;
> +    } else if (!strcmp(mpol, "interleave")) {
> +        numa_info[nodeid].flags |= NODE_HOST_INTERLEAVE;
> +    } else if (!strcmp(mpol, "preferred")) {
> +        numa_info[nodeid].flags |= NODE_HOST_PREFERRED;
> +    } else {
> +        error_setg(errp, "Invalid NUMA policy '%s'", mpol);
> +        goto error;
> +    }
> +
> +    if (!has_nodemask) {
> +        bitmap_fill(numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
> +    }
> +
> +    if (nodemask) {
> +        ret = numa_node_parse_mpol(nodemask, numa_info[nodeid].host_mem);
> +    }
> +    if (ret == 4) {
> +        goto error;
> +    } else if (ret & 1) {
> +        numa_info[nodeid].flags |= NODE_HOST_RELATIVE;
> +    }
> +
> +    if (set_node_mpol(nodeid) == -1) {
> +        goto error;
> +    }
> +
> +    return;
> +
> +error:
> +    bitmap_copy(numa_info[nodeid].host_mem, host_mem, MAX_CPUMASK_BITS);
> +    numa_info[nodeid].flags = flags;
> +    return;
> +}
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 993b8e0..7d804af 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -144,6 +144,7 @@ struct node_info {
>      unsigned int flags;
>  };
>  extern struct node_info numa_info[MAX_NODES];
> +extern unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm);
>  
>  #define MAX_OPTION_ROMS 16
>  typedef struct QEMUOptionRom {
> diff --git a/qapi-schema.json b/qapi-schema.json
> index a80ee40..403c703 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3608,3 +3608,16 @@
>              '*cpuid-input-ecx': 'int',
>              'cpuid-register': 'X86CPURegister32',
>              'features': 'int' } }
> +
> +# @set-mpol:
> +#
> +# Set the host memory binding policy for guest NUMA node.
> +#
> +# @node-id: The node ID of guest NUMA node to set memory policy to.
> +#
> +# @mpol: The memory policy string to set.
> +#
> +# Since: 1.6.0
> +##
> +{ 'command': 'set-mpol', 'data': {'nodeid': 'int', '*mpol': 'str',
> +                                  '*nodemask': 'str'} }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 8cea5e5..930c844 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2997,3 +2997,38 @@ Example:
>  <- { "return": {} }
>  
>  EQMP
> +
> +    {
> +        .name      = "set-mpol",
> +        .args_type = "nodeid:i,mpol:s?,nodemask:s?",
> +        .help      = "Set the host memory binding policy for guest NUMA node",
> +        .mhandler.cmd_new = qmp_marshal_input_set_mpol,
> +    },
> +
> +SQMP
> +set-mpol
> +------
> +
> +Set the host memory binding policy for guest NUMA node
> +
> +Arguments:
> +
> +- "nodeid": The nodeid of guest NUMA node to set memory policy to.
> +              (json-int)
> +- "mpol": The memory policy string to set.
> +           (json-string, optional)
> +- "nodemask": The node mask contained to mpol.
> +                (json-string, optional)
> +
> +Example:
> +
> +-> { "execute": "set-mpol", "arguments": { "nodeid": 0, "mpol": "membind",
> +                                           "nodemask": "0-1" }}
> +<- { "return": {} }
> +
> +Notes:
> +    1. If "mpol" is not set, the memory policy of this "nodeid" will be set
> +       to "default".
> +    2. If "nodemask" is not set, the node mask of this "mpol" will be set
> +       to "all".
> +EQMP
> diff --git a/vl.c b/vl.c
> index ada9fb2..73af85e 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1348,7 +1348,7 @@ error:
>      exit(1);
>  }
>  
> -static unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm)
> +unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm)
>  {
>      unsigned long long value, endvalue;
>      char *endptr;
>
Wanlong Gao - June 18, 2013, 9:44 a.m.
On 06/18/2013 05:21 PM, Paolo Bonzini wrote:
> Il 18/06/2013 10:09, Wanlong Gao ha scritto:
>> The QMP command let it be able to set node's memory policy
>> through the QMP protocol. The qmp-shell command is like:
>>     set-mpol nodeid=0 mpol=membind nodemask=0-1
>>
>> Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
> 
> How would this work with mem-path?

This can also set mempolicy for mem-path backed memory in
guest nodes. So we don't need to know if we are using
mem-path.

Thanks,
Wanlong Gao

> 
> Paolo
> 
>> ---
>>  cpus.c                  | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/sysemu/sysemu.h |  1 +
>>  qapi-schema.json        | 13 +++++++++++
>>  qmp-commands.hx         | 35 ++++++++++++++++++++++++++++
>>  vl.c                    |  2 +-
>>  5 files changed, 111 insertions(+), 1 deletion(-)
>>
>> diff --git a/cpus.c b/cpus.c
>> index b868932..a2836e9 100644
>> --- a/cpus.c
>> +++ b/cpus.c
>> @@ -1431,3 +1431,64 @@ void qmp_inject_nmi(Error **errp)
>>      error_set(errp, QERR_UNSUPPORTED);
>>  #endif
>>  }
>> +
>> +void qmp_set_mpol(int64_t nodeid, bool has_mpol, const char *mpol,
>> +                  bool has_nodemask, const char *nodemask, Error **errp)
>> +{
>> +    unsigned int ret;
>> +    unsigned int flags;
>> +    DECLARE_BITMAP(host_mem, MAX_CPUMASK_BITS);
>> +
>> +    if (nodeid >= nb_numa_nodes) {
>> +        error_setg(errp, "Only has '%d' NUMA nodes", nb_numa_nodes);
>> +        return;
>> +    }
>> +
>> +    bitmap_copy(host_mem, numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
>> +    flags = numa_info[nodeid].flags;
>> +
>> +    numa_info[nodeid].flags = NODE_HOST_NONE;
>> +    bitmap_zero(numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
>> +
>> +    if (!has_mpol) {
>> +        if (set_node_mpol(nodeid) == -1) {
>> +            goto error;
>> +        }
>> +        return;
>> +    }
>> +
>> +    if (!strcmp(mpol, "membind")) {
>> +        numa_info[nodeid].flags |= NODE_HOST_BIND;
>> +    } else if (!strcmp(mpol, "interleave")) {
>> +        numa_info[nodeid].flags |= NODE_HOST_INTERLEAVE;
>> +    } else if (!strcmp(mpol, "preferred")) {
>> +        numa_info[nodeid].flags |= NODE_HOST_PREFERRED;
>> +    } else {
>> +        error_setg(errp, "Invalid NUMA policy '%s'", mpol);
>> +        goto error;
>> +    }
>> +
>> +    if (!has_nodemask) {
>> +        bitmap_fill(numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
>> +    }
>> +
>> +    if (nodemask) {
>> +        ret = numa_node_parse_mpol(nodemask, numa_info[nodeid].host_mem);
>> +    }
>> +    if (ret == 4) {
>> +        goto error;
>> +    } else if (ret & 1) {
>> +        numa_info[nodeid].flags |= NODE_HOST_RELATIVE;
>> +    }
>> +
>> +    if (set_node_mpol(nodeid) == -1) {
>> +        goto error;
>> +    }
>> +
>> +    return;
>> +
>> +error:
>> +    bitmap_copy(numa_info[nodeid].host_mem, host_mem, MAX_CPUMASK_BITS);
>> +    numa_info[nodeid].flags = flags;
>> +    return;
>> +}
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index 993b8e0..7d804af 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -144,6 +144,7 @@ struct node_info {
>>      unsigned int flags;
>>  };
>>  extern struct node_info numa_info[MAX_NODES];
>> +extern unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm);
>>  
>>  #define MAX_OPTION_ROMS 16
>>  typedef struct QEMUOptionRom {
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index a80ee40..403c703 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -3608,3 +3608,16 @@
>>              '*cpuid-input-ecx': 'int',
>>              'cpuid-register': 'X86CPURegister32',
>>              'features': 'int' } }
>> +
>> +# @set-mpol:
>> +#
>> +# Set the host memory binding policy for guest NUMA node.
>> +#
>> +# @node-id: The node ID of guest NUMA node to set memory policy to.
>> +#
>> +# @mpol: The memory policy string to set.
>> +#
>> +# Since: 1.6.0
>> +##
>> +{ 'command': 'set-mpol', 'data': {'nodeid': 'int', '*mpol': 'str',
>> +                                  '*nodemask': 'str'} }
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index 8cea5e5..930c844 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -2997,3 +2997,38 @@ Example:
>>  <- { "return": {} }
>>  
>>  EQMP
>> +
>> +    {
>> +        .name      = "set-mpol",
>> +        .args_type = "nodeid:i,mpol:s?,nodemask:s?",
>> +        .help      = "Set the host memory binding policy for guest NUMA node",
>> +        .mhandler.cmd_new = qmp_marshal_input_set_mpol,
>> +    },
>> +
>> +SQMP
>> +set-mpol
>> +------
>> +
>> +Set the host memory binding policy for guest NUMA node
>> +
>> +Arguments:
>> +
>> +- "nodeid": The nodeid of guest NUMA node to set memory policy to.
>> +              (json-int)
>> +- "mpol": The memory policy string to set.
>> +           (json-string, optional)
>> +- "nodemask": The node mask contained to mpol.
>> +                (json-string, optional)
>> +
>> +Example:
>> +
>> +-> { "execute": "set-mpol", "arguments": { "nodeid": 0, "mpol": "membind",
>> +                                           "nodemask": "0-1" }}
>> +<- { "return": {} }
>> +
>> +Notes:
>> +    1. If "mpol" is not set, the memory policy of this "nodeid" will be set
>> +       to "default".
>> +    2. If "nodemask" is not set, the node mask of this "mpol" will be set
>> +       to "all".
>> +EQMP
>> diff --git a/vl.c b/vl.c
>> index ada9fb2..73af85e 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -1348,7 +1348,7 @@ error:
>>      exit(1);
>>  }
>>  
>> -static unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm)
>> +unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm)
>>  {
>>      unsigned long long value, endvalue;
>>      char *endptr;
>>
> 
>
Paolo Bonzini - June 18, 2013, 9:57 a.m.
Il 18/06/2013 11:44, Wanlong Gao ha scritto:
> On 06/18/2013 05:21 PM, Paolo Bonzini wrote:
>> Il 18/06/2013 10:09, Wanlong Gao ha scritto:
>>> The QMP command let it be able to set node's memory policy
>>> through the QMP protocol. The qmp-shell command is like:
>>>     set-mpol nodeid=0 mpol=membind nodemask=0-1
>>>
>>> Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
>>
>> How would this work with mem-path?
> 
> This can also set mempolicy for mem-path backed memory in
> guest nodes. So we don't need to know if we are using
> mem-path.

Cool, I didn't know this.  Thanks.

Paolo

Patch

diff --git a/cpus.c b/cpus.c
index b868932..a2836e9 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1431,3 +1431,64 @@  void qmp_inject_nmi(Error **errp)
     error_set(errp, QERR_UNSUPPORTED);
 #endif
 }
+
+void qmp_set_mpol(int64_t nodeid, bool has_mpol, const char *mpol,
+                  bool has_nodemask, const char *nodemask, Error **errp)
+{
+    unsigned int ret;
+    unsigned int flags;
+    DECLARE_BITMAP(host_mem, MAX_CPUMASK_BITS);
+
+    if (nodeid >= nb_numa_nodes) {
+        error_setg(errp, "Only has '%d' NUMA nodes", nb_numa_nodes);
+        return;
+    }
+
+    bitmap_copy(host_mem, numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
+    flags = numa_info[nodeid].flags;
+
+    numa_info[nodeid].flags = NODE_HOST_NONE;
+    bitmap_zero(numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
+
+    if (!has_mpol) {
+        if (set_node_mpol(nodeid) == -1) {
+            goto error;
+        }
+        return;
+    }
+
+    if (!strcmp(mpol, "membind")) {
+        numa_info[nodeid].flags |= NODE_HOST_BIND;
+    } else if (!strcmp(mpol, "interleave")) {
+        numa_info[nodeid].flags |= NODE_HOST_INTERLEAVE;
+    } else if (!strcmp(mpol, "preferred")) {
+        numa_info[nodeid].flags |= NODE_HOST_PREFERRED;
+    } else {
+        error_setg(errp, "Invalid NUMA policy '%s'", mpol);
+        goto error;
+    }
+
+    if (!has_nodemask) {
+        bitmap_fill(numa_info[nodeid].host_mem, MAX_CPUMASK_BITS);
+    }
+
+    if (nodemask) {
+        ret = numa_node_parse_mpol(nodemask, numa_info[nodeid].host_mem);
+    }
+    if (ret == 4) {
+        goto error;
+    } else if (ret & 1) {
+        numa_info[nodeid].flags |= NODE_HOST_RELATIVE;
+    }
+
+    if (set_node_mpol(nodeid) == -1) {
+        goto error;
+    }
+
+    return;
+
+error:
+    bitmap_copy(numa_info[nodeid].host_mem, host_mem, MAX_CPUMASK_BITS);
+    numa_info[nodeid].flags = flags;
+    return;
+}
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 993b8e0..7d804af 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -144,6 +144,7 @@  struct node_info {
     unsigned int flags;
 };
 extern struct node_info numa_info[MAX_NODES];
+extern unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm);
 
 #define MAX_OPTION_ROMS 16
 typedef struct QEMUOptionRom {
diff --git a/qapi-schema.json b/qapi-schema.json
index a80ee40..403c703 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3608,3 +3608,16 @@ 
             '*cpuid-input-ecx': 'int',
             'cpuid-register': 'X86CPURegister32',
             'features': 'int' } }
+
+# @set-mpol:
+#
+# Set the host memory binding policy for guest NUMA node.
+#
+# @node-id: The node ID of guest NUMA node to set memory policy to.
+#
+# @mpol: The memory policy string to set.
+#
+# Since: 1.6.0
+##
+{ 'command': 'set-mpol', 'data': {'nodeid': 'int', '*mpol': 'str',
+                                  '*nodemask': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8cea5e5..930c844 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2997,3 +2997,38 @@  Example:
 <- { "return": {} }
 
 EQMP
+
+    {
+        .name      = "set-mpol",
+        .args_type = "nodeid:i,mpol:s?,nodemask:s?",
+        .help      = "Set the host memory binding policy for guest NUMA node",
+        .mhandler.cmd_new = qmp_marshal_input_set_mpol,
+    },
+
+SQMP
+set-mpol
+------
+
+Set the host memory binding policy for guest NUMA node
+
+Arguments:
+
+- "nodeid": The nodeid of guest NUMA node to set memory policy to.
+              (json-int)
+- "mpol": The memory policy string to set.
+           (json-string, optional)
+- "nodemask": The node mask contained to mpol.
+                (json-string, optional)
+
+Example:
+
+-> { "execute": "set-mpol", "arguments": { "nodeid": 0, "mpol": "membind",
+                                           "nodemask": "0-1" }}
+<- { "return": {} }
+
+Notes:
+    1. If "mpol" is not set, the memory policy of this "nodeid" will be set
+       to "default".
+    2. If "nodemask" is not set, the node mask of this "mpol" will be set
+       to "all".
+EQMP
diff --git a/vl.c b/vl.c
index ada9fb2..73af85e 100644
--- a/vl.c
+++ b/vl.c
@@ -1348,7 +1348,7 @@  error:
     exit(1);
 }
 
-static unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm)
+unsigned int numa_node_parse_mpol(const char *str, unsigned long *bm)
 {
     unsigned long long value, endvalue;
     char *endptr;