[libvirt] [PATCH v2] node_memory: Add new parameter field to tune the new sysfs knob

Daniel Veillard veillard at redhat.com
Mon Oct 15 06:55:40 UTC 2012


On Fri, Oct 12, 2012 at 04:25:42PM +0800, Osier Yang wrote:
> Upstream kernel introduced new sysfs knob "merge_across_nodes" to
> specify if pages from different numa nodes can be merged. When set
> to 0, only pages which physically reside in the memory area of
> same NUMA node can be merged. When set to 1, pages from all nodes
> can be merged.
> 
> This patch supports the tuning by adding new param field
> "shm_merge_across_nodes".
> ---
>  include/libvirt/libvirt.h.in |   12 ++++++++++++
>  src/nodeinfo.c               |   28 +++++++++++++++++++++++++---
>  tools/virsh-host.c           |   20 ++++++++++++++++++++
>  tools/virsh.pod              |    5 ++++-
>  4 files changed, 61 insertions(+), 4 deletions(-)
> 
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index a4e8ca9..1490558 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -4490,6 +4490,18 @@ typedef virMemoryParameter *virMemoryParameterPtr;
>   */
>  # define VIR_NODE_MEMORY_SHARED_FULL_SCANS         "shm_full_scans"
>  
> +/* VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES:
> + *
> + * Macro for typed parameter that represents whether pages from
> + * different NUMA nodes can be merged. The parameter has type int,
> + * when its value is 0, only pages which physically reside in the
> + * memory area of same NUMA node are merged; When its value is 1,
> + * pages from all nodes can be merged. Other values are reserved
> + * for future use.
> + */
> +# define VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES "shm_merge_across_nodes"
> +
> +
>  int virNodeGetMemoryParameters(virConnectPtr conn,
>                                 virTypedParameterPtr params,
>                                 int *nparams,
> diff --git a/src/nodeinfo.c b/src/nodeinfo.c
> index c0e60d8..8f96b8b 100644
> --- a/src/nodeinfo.c
> +++ b/src/nodeinfo.c
> @@ -1005,6 +1005,8 @@ nodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
>                                         VIR_TYPED_PARAM_UINT,
>                                         VIR_NODE_MEMORY_SHARED_SLEEP_MILLISECS,
>                                         VIR_TYPED_PARAM_UINT,
> +                                       VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES,
> +                                       VIR_TYPED_PARAM_UINT,
>                                         NULL) < 0)
>          return -1;
>  
> @@ -1025,6 +1027,13 @@ nodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
>              /* Out of memory */
>              if (ret == -2)
>                  return -1;
> +        } else if (STREQ(param->field,
> +                         VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES)) {
> +            ret = nodeSetMemoryParameterValue("merge_across_nodes", param);
> +
> +            /* Out of memory */
> +            if (ret == -2)
> +                return -1;
>          }
>      }
>  
> @@ -1060,8 +1069,9 @@ nodeGetMemoryParameterValue(const char *field,
>      if ((tmp = strchr(buf, '\n')))
>          *tmp = '\0';
>  
> -    if (STREQ(field, "pages_to_scan") ||
> -        STREQ(field, "sleep_millisecs"))
> +    if (STREQ(field, "pages_to_scan")   ||
> +        STREQ(field, "sleep_millisecs") ||
> +        STREQ(field, "merge_across_nodes"))
>          rc = virStrToLong_ui(buf, NULL, 10, (unsigned int *)value);
>      else if (STREQ(field, "pages_shared")    ||
>               STREQ(field, "pages_sharing")   ||
> @@ -1084,7 +1094,7 @@ cleanup:
>  }
>  #endif
>  
> -#define NODE_MEMORY_PARAMETERS_NUM 7
> +#define NODE_MEMORY_PARAMETERS_NUM 8
>  int
>  nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
>                          virTypedParameterPtr params ATTRIBUTE_UNUSED,
> @@ -1096,6 +1106,7 @@ nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
>  #ifdef __linux__
>      unsigned int pages_to_scan;
>      unsigned int sleep_millisecs;
> +    unsigned int merge_across_nodes;
>      unsigned long long pages_shared;
>      unsigned long long pages_sharing;
>      unsigned long long pages_unshared;
> @@ -1189,6 +1200,17 @@ nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
>  
>              break;
>  
> +        case 7:
> +            if (nodeGetMemoryParameterValue("merge_across_nodes",
> +                                            &merge_across_nodes) < 0)
> +                return -1;
> +
> +            if (virTypedParameterAssign(param, VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES,
> +                                        VIR_TYPED_PARAM_UINT, merge_across_nodes) < 0)
> +                return -1;
> +
> +            break;
> +
>          default:
>              break;
>          }
> diff --git a/tools/virsh-host.c b/tools/virsh-host.c
> index 5cf192d..106f5e9 100644
> --- a/tools/virsh-host.c
> +++ b/tools/virsh-host.c
> @@ -920,6 +920,8 @@ static const vshCmdOptDef opts_node_memory_tune[] = {
>      {"shm-sleep-millisecs", VSH_OT_INT, VSH_OFLAG_NONE,
>        N_("number of millisecs the shared memory service should "
>           "sleep before next scan")},
> +    {"shm-merge-across-nodes", VSH_OT_INT, VSH_OFLAG_NONE,
> +      N_("Specifies if pages from different numa nodes can be merged")},
>      {NULL, 0, 0, NULL}
>  };
>  
> @@ -931,6 +933,7 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
>      unsigned int flags = 0;
>      unsigned int shm_pages_to_scan = 0;
>      unsigned int shm_sleep_millisecs = 0;
> +    unsigned int shm_merge_across_nodes = 0;
>      bool ret = false;
>      int i = 0;
>  
> @@ -946,12 +949,21 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
>          return false;
>      }
>  
> +    if (vshCommandOptUInt(cmd, "shm-merge-across-nodes",
> +                          &shm_merge_across_nodes) < 0) {
> +        vshError(ctl, "%s", _("invalid shm-merge-across-nodes number"));
> +        return false;
> +    }
> +
>      if (shm_pages_to_scan)
>          nparams++;
>  
>      if (shm_sleep_millisecs)
>          nparams++;
>  
> +    if (shm_merge_across_nodes)
> +        nparams++;
> +
>      if (nparams == 0) {
>          /* Get the number of memory parameters */
>          if (virNodeGetMemoryParameters(ctl->conn, NULL, &nparams, flags) != 0) {
> @@ -1003,6 +1015,14 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
>                  goto error;
>          }
>  
> +        if (i < nparams && shm_merge_across_nodes) {
> +            if (virTypedParameterAssign(&params[i++],
> +                                        VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES,
> +                                        VIR_TYPED_PARAM_UINT,
> +                                        shm_merge_across_nodes) < 0)
> +                goto error;
> +        }
> +
>          if (virNodeSetMemoryParameters(ctl->conn, params, nparams, flags) != 0)
>              goto error;
>          else
> diff --git a/tools/virsh.pod b/tools/virsh.pod
> index 2d90b7b..0481e1f 100644
> --- a/tools/virsh.pod
> +++ b/tools/virsh.pod
> @@ -303,7 +303,10 @@ Allows you to display or set the node memory parameters.
>  I<shm-pages-to-scan> can be used to set the number of pages to scan
>  before the shared memory service goes to sleep; I<shm-sleep-millisecs>
>  can be used to set the number of millisecs the shared memory service should
> -sleep before next scan.
> +sleep before next scan; I<shm-merge-across-nodes> specifies if pages from
> +different numa nodes can be merged. When set to 0, only pages which physically
> +reside in the memory area of same NUMA node can be merged. When set to 1,
> +pages from all nodes can be merged. Default to 1.
>  
>  =item B<capabilities>
>  

  Okay, ACK,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list