diff --git a/ocaml/libs/xenctrl-ext/xenctrlext.ml b/ocaml/libs/xenctrl-ext/xenctrlext.ml index 31360870fbc..419907ff268 100644 --- a/ocaml/libs/xenctrl-ext/xenctrlext.ml +++ b/ocaml/libs/xenctrl-ext/xenctrlext.ml @@ -124,7 +124,6 @@ end exception Not_available let domain_claim_pages handle domid ?(numa_node = NumaNode.none) nr_pages = - if numa_node <> NumaNode.none then raise Not_available ; stub_domain_claim_pages handle domid numa_node nr_pages let get_nr_nodes handle = diff --git a/ocaml/libs/xenctrl-ext/xenctrlext.mli b/ocaml/libs/xenctrl-ext/xenctrlext.mli index 11d6ad8ad66..1851b3d1b12 100644 --- a/ocaml/libs/xenctrl-ext/xenctrlext.mli +++ b/ocaml/libs/xenctrl-ext/xenctrlext.mli @@ -109,6 +109,14 @@ val get_nr_nodes : handle -> int (** Returns the count of NUMA nodes available in the system. *) module DomainNuma : sig + type domain_numainfo_node_pages = { + tot_pages_per_node: int64 array (* page=4k bytes *) + } + + external domain_get_numa_info_node_pages : + handle -> int -> domain_numainfo_node_pages + = "stub_xc_domain_numa_get_node_pages_wrapper" + type t = {optimised: bool; nodes: int; memory: int64 array (* bytes *)} val state : handle -> domid:int -> t diff --git a/ocaml/libs/xenctrl-ext/xenctrlext_stubs.c b/ocaml/libs/xenctrl-ext/xenctrlext_stubs.c index 5da78215acc..f4dd234b780 100644 --- a/ocaml/libs/xenctrl-ext/xenctrlext_stubs.c +++ b/ocaml/libs/xenctrl-ext/xenctrlext_stubs.c @@ -678,14 +678,15 @@ CAMLprim value stub_xenctrlext_domain_claim_pages(value xch_val, value domid_val value numa_node_val, value nr_pages_val) { CAMLparam4(xch_val, domid_val, numa_node_val, nr_pages_val); +#ifdef XEN_DOMCTL_NUMA_OP_GET_NODE_PAGES int retval, the_errno; xc_interface* xch = xch_of_val(xch_val); uint32_t domid = Int_val(domid_val); - // unsigned int numa_node = Int_val(numa_node_val); + unsigned int numa_node = Int_val(numa_node_val); unsigned long nr_pages = Long_val(nr_pages_val); caml_release_runtime_system(); - retval = xc_domain_claim_pages(xch, domid, /*numa_node,*/ nr_pages); + retval = xc_domain_claim_pages_node(xch, domid, numa_node, nr_pages); the_errno = errno; caml_acquire_runtime_system(); @@ -694,6 +695,9 @@ CAMLprim value stub_xenctrlext_domain_claim_pages(value xch_val, value domid_val "Error when trying to claim memory pages"); } CAMLreturn(Val_unit); +#else + raise_unix_errno_msg(ENOSYS, "xc_domain_claim_pages_node"); +#endif } #ifdef XEN_DOMCTL_NUMA_OP_GET_NODE_PAGES diff --git a/ocaml/xcp-rrdd/bin/rrdp-cpu/rrdp_cpu.ml b/ocaml/xcp-rrdd/bin/rrdp-cpu/rrdp_cpu.ml index 0cea2e90295..763aaaed5d8 100644 --- a/ocaml/xcp-rrdd/bin/rrdp-cpu/rrdp_cpu.ml +++ b/ocaml/xcp-rrdd/bin/rrdp-cpu/rrdp_cpu.ml @@ -80,6 +80,28 @@ let dss_vcpus xc doms = ) ] in + let nonaffine_vcpus_ds = + match ri.Xenctrl.Runstateinfo.V2.running with + | 0L -> + [] + | _ -> + [ + ( Rrd.VM uuid + , Ds.ds_make ~name:"numa_node_nonaffine_vcpus" + ~units:"(fraction)" + ~value: + (Rrd.VT_Float + (Int64.to_float ri.Xenctrl.Runstateinfo.V2.nonaffine + /. 1.0e9 + ) + ) + ~description: + "Fraction of vCPU time running outside of vCPU \ + soft-affinity" + ~ty:Rrd.Derive ~default:false ~min:0.0 ~max:1.0 () + ) + ] + in ( Rrd.VM uuid , Ds.ds_make ~name:"runstate_fullrun" ~units:"(fraction)" ~value: @@ -172,6 +194,7 @@ let dss_vcpus xc doms = ) :: dss @ runnable_vcpus_ds + @ nonaffine_vcpus_ds with _ -> dss in try cpus 0 dss with _ -> dss diff --git a/ocaml/xcp-rrdd/bin/rrdp-squeezed/dune b/ocaml/xcp-rrdd/bin/rrdp-squeezed/dune index 75c8e1f5ab5..ee5f217f137 100644 --- a/ocaml/xcp-rrdd/bin/rrdp-squeezed/dune +++ b/ocaml/xcp-rrdd/bin/rrdp-squeezed/dune @@ -13,6 +13,7 @@ xapi-log xapi-rrd xenctrl + xenctrl_ext xenstore xenstore.unix xenstore_transport diff --git a/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml b/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml index df49dca259f..951b7a8b1d5 100644 --- a/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml +++ b/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml @@ -252,6 +252,62 @@ let free_other uuid free = ~value:(Rrd.VT_Int64 free) ~ty:Rrd.Gauge ~min:0.0 ~default:true () ) +let dss_numa_info uuid domid = + try + let handle = Xenctrlext.get_handle () in + let host_nr_nodes = Xenctrlext.get_nr_nodes handle in + let vm_nodes = + Xenctrlext.DomainNuma.domain_get_numa_info_node_pages handle domid + in + let dss_memory_numa_nodes_of_vm (dss, nr_nodes_used_by_vm) + (node_id, tot_pages_per_node) = + (* + for each numa node used by the host, show the + corresponding amount of memory used by the vm + *) + let is_node_used_by_vm = tot_pages_per_node > 4096L in + let is_node_used_by_host = node_id < host_nr_nodes in + if is_node_used_by_host then + ( ( Rrd.VM uuid + , Ds.ds_make + ~name:(Printf.sprintf "memory_numa_node_%d" node_id) + ~units:"B" + ~description: + (Printf.sprintf "Memory from NUMA node %d used by VM" node_id) + ~value:(Rrd.VT_Int64 (Int64.mul tot_pages_per_node 4096L)) + ~min:0.0 ~ty:Rrd.Gauge ~default:false () + ) + :: dss + (* remember the number of nodes used by vm *) + , nr_nodes_used_by_vm + + + if is_node_used_by_vm then + 1 + else + 0 + ) + else + (dss, nr_nodes_used_by_vm) + in + let dss_numa_nodes_of_vm (dss, nr_nodes_used_by_vm) = + ( Rrd.VM uuid + , Ds.ds_make + ~name:(Printf.sprintf "numa_nodes") + ~units:"count" + ~description:(Printf.sprintf "Number of NUMA nodes used by VM") + ~value:(Rrd.VT_Int64 (Int64.of_int nr_nodes_used_by_vm)) + ~min:0.0 ~ty:Rrd.Gauge ~default:false () + ) + :: List.rev dss + in + vm_nodes.Xenctrlext.DomainNuma.tot_pages_per_node + |> Array.mapi (fun i x -> (i, x)) + |> Array.fold_left dss_memory_numa_nodes_of_vm ([], 0) + |> dss_numa_nodes_of_vm + with e -> + D.debug "dss_numa_info: %s" (Printexc.to_string e) ; + [] + let get_list f = Option.to_list (f ()) let generate_vm_sources domains = @@ -288,6 +344,7 @@ let generate_vm_sources domains = ~value:(Rrd.VT_Int64 memory) ~ty:Rrd.Gauge ~min:0.0 ~default:true () ) in + let get_list_numa_info = dss_numa_info uuid domid in (* CA-34383: Memory updates from paused domains serve no useful purpose. During a migrate such updates can also cause undesirable discontinuities in the observed value of memory_actual. Hence, we @@ -295,7 +352,7 @@ let generate_vm_sources domains = if dom.Xenctrl.paused then [] else - get_list target @ get_list free @ get_list total + get_list target @ get_list free @ get_list total @ get_list_numa_info in List.concat_map metrics_of domains diff --git a/ocaml/xenopsd/xc/domain.ml b/ocaml/xenopsd/xc/domain.ml index 1cdc9a87785..1dbc52c2cab 100644 --- a/ocaml/xenopsd/xc/domain.ml +++ b/ocaml/xenopsd/xc/domain.ml @@ -987,8 +987,6 @@ let numa_hierarchy = let numa_mutex = Mutex.create () -let numa_resources = ref None - let numa_init () = let xcext = Xenctrlext.get_handle () in let host = Lazy.force numa_hierarchy in @@ -1022,14 +1020,7 @@ let numa_placement domid ~vcpus ~cores ~memory affinity = (NUMA.nodes host) numa_meminfo in let vm = NUMARequest.make ~memory ~vcpus ~cores in - let nodea = - match !numa_resources with - | None -> - Array.of_seq nodes - | Some a -> - Array.map2 NUMAResource.min_memory (Array.of_seq nodes) a - in - numa_resources := Some nodea ; + let nodea = Array.of_seq nodes in let cpu_affinity, memory_plan = match Softaffinity.plan ~vm host nodea with | None ->