]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
hypervisor/xen/tools: Remove the XENMEM_get_oustanding_pages and provide the data...
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Mon, 13 May 2013 19:29:11 +0000 (15:29 -0400)
committerIan Campbell <ian.campbell@citrix.com>
Tue, 14 May 2013 09:01:50 +0000 (10:01 +0100)
During the review of the patches it was noticed that there exists
a race wherein the 'free_memory' value consists of information from
two hypercalls. That is the XEN_SYSCTL_physinfo and XENMEM_get_outstanding_pages.

The free memory the host has available for guest is the difference between
the 'free_pages' (from XEN_SYSCTL_physinfo) and 'outstanding_pages'. As they
are two hypercalls many things can happen in between the execution of them.

This patch resolves this by eliminating the XENMEM_get_outstanding_pages
hypercall and providing the free_pages and outstanding_pages information
via the xc_phys_info structure.

It also removes the XSM hooks and adds locking as needed.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Reviewed-by: Tim Deegan <tim@xen.org>
Acked-by: Keir Fraser <keir.xen@gmail.com>
17 files changed:
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/libxl_types.idl
tools/libxl/xl_cmdimpl.c
xen/common/memory.c
xen/common/page_alloc.c
xen/common/sysctl.c
xen/include/public/memory.h
xen/include/public/sysctl.h
xen/include/xen/mm.h
xen/include/xsm/dummy.h
xen/include/xsm/xsm.h
xen/xsm/dummy.c
xen/xsm/flask/hooks.c
xen/xsm/flask/policy/access_vectors

index bb71ccaecf21ba8129c4f4e162366ae60b9805e8..3257e2af9490d94273c785fffaa959403f8af3ed 100644 (file)
@@ -873,15 +873,6 @@ int xc_domain_claim_pages(xc_interface *xch,
         err = errno = 0;
     return err;
 }
-unsigned long xc_domain_get_outstanding_pages(xc_interface *xch)
-{
-    long ret = do_memory_op(xch, XENMEM_get_outstanding_pages, NULL, 0);
-
-    /* Ignore it if the hypervisor does not support the call. */
-    if (ret == -1 && errno == ENOSYS)
-        ret = errno = 0;
-    return ret;
-}
 
 int xc_domain_populate_physmap(xc_interface *xch,
                                uint32_t domid,
index c024af439b601f22bebfa5e7c54af60f495fc78b..40ee8fce2a584149389e11fd888f62e00766a7f5 100644 (file)
@@ -1182,8 +1182,6 @@ int xc_domain_claim_pages(xc_interface *xch,
                                uint32_t domid,
                                unsigned long nr_pages);
 
-unsigned long xc_domain_get_outstanding_pages(xc_interface *xch);
-
 int xc_domain_memory_exchange_pages(xc_interface *xch,
                                     int domid,
                                     unsigned long nr_in_extents,
index bc91fd5abf6487432ecf4995c9154828d0e1f062..ee1fa9cf8c91cc7c462c5679fc3bc3cdb50554d4 100644 (file)
@@ -3942,6 +3942,7 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
     physinfo->total_pages = xcphysinfo.total_pages;
     physinfo->free_pages = xcphysinfo.free_pages;
     physinfo->scrub_pages = xcphysinfo.scrub_pages;
+    physinfo->outstanding_pages = xcphysinfo.outstanding_pages;
     l = xc_sharing_freed_pages(ctx->xch);
     if (l == -ENOSYS) {
         l = 0;
@@ -4105,20 +4106,6 @@ libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr)
     return ret;
 }
 
-uint64_t libxl_get_claiminfo(libxl_ctx *ctx)
-{
-    long l;
-
-    l = xc_domain_get_outstanding_pages(ctx->xch);
-    if (l < 0) {
-        LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_WARNING, l,
-                            "xc_domain_get_outstanding_pages failed.");
-        return ERROR_FAIL;
-    }
-    /* In pages */
-    return l;
-}
-
 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
 {
     union {
index ef96bce1a78417f2d3f68ca9c92b1d65df70ecd7..0bc005e0ee37e73d747e65de243faa61dedd051e 100644 (file)
@@ -624,7 +624,6 @@ int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid, uint32_t memory_k
 /* wait for the memory target of a domain to be reached */
 int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs);
 
-uint64_t libxl_get_claiminfo(libxl_ctx *ctx);
 int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass);
 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_type type);
 /* libxl_primary_console_exec finds the domid and console number
index ecf1f0bc4f5b456c4ea88eb13f7f9f3c8c0e5429..8262cba62312d1fbd66f567a8c26a74eeee4f350 100644 (file)
@@ -487,6 +487,7 @@ libxl_physinfo = Struct("physinfo", [
     ("total_pages", uint64),
     ("free_pages", uint64),
     ("scrub_pages", uint64),
+    ("outstanding_pages", uint64),
     ("sharing_freed_pages", uint64),
     ("sharing_used_frames", uint64),
 
index c1a969b80c0151d9314d89dbdd6fe689b877cd95..edf0325fdd59ab73bf0c58779dd06d5775336ca2 100644 (file)
@@ -4576,21 +4576,11 @@ static void output_physinfo(void)
     unsigned int i;
     libxl_bitmap cpumap;
     int n = 0;
-    long claims = 0;
 
     if (libxl_get_physinfo(ctx, &info) != 0) {
         fprintf(stderr, "libxl_physinfo failed.\n");
         return;
     }
-    /*
-     * Don't bother checking "claim_mode" as user might have turned it off
-     * and we have outstanding claims.
-     */
-    if ((claims = libxl_get_claiminfo(ctx)) < 0){
-        fprintf(stderr, "libxl_get_claiminfo failed. errno: %d (%s)\n",
-                errno, strerror(errno));
-        return;
-    }
     printf("nr_cpus                : %d\n", info.nr_cpus);
     printf("max_cpu_id             : %d\n", info.max_cpu_id);
     printf("nr_nodes               : %d\n", info.nr_nodes);
@@ -4610,15 +4600,15 @@ static void output_physinfo(void)
     if (vinfo) {
         i = (1 << 20) / vinfo->pagesize;
         printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
-        printf("free_memory            : %"PRIu64"\n", (info.free_pages - claims) / i);
+        printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
         printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
         printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
     }
     /*
      * Only if enabled (claim_mode=1) or there are outstanding claims.
      */
-    if (libxl_defbool_val(claim_mode) || claims)
-        printf("outstanding_claims     : %ld\n", claims / i);
+    if (libxl_defbool_val(claim_mode) || info.outstanding_pages)
+        printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
 
     if (!libxl_get_freecpus(ctx, &cpumap)) {
         libxl_for_each_bit(i, cpumap)
index 3239d53978f2d19432c16fc449e94ff52d05b448..06a0d0ac4cc335f6462f3ed0118e5728714b9dcb 100644 (file)
@@ -737,14 +737,6 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 
         break;
 
-    case XENMEM_get_outstanding_pages:
-        rc = xsm_xenmem_get_outstanding_pages(XSM_PRIV);
-
-        if ( !rc )
-            rc = get_outstanding_claims();
-
-        break;
-
     default:
         rc = arch_memory_op(op, arg);
         break;
index 203f77a4852952aac66cd7eb8e5d2a787a10b95b..2162ef14d41b737dfdcbecaa0b3b806487acee3d 100644 (file)
@@ -380,9 +380,12 @@ out:
     return ret;
 }
 
-long get_outstanding_claims(void)
+void get_outstanding_claims(uint64_t *free_pages, uint64_t *outstanding_pages)
 {
-    return outstanding_claims;
+    spin_lock(&heap_lock);
+    *outstanding_pages = outstanding_claims;
+    *free_pages =  avail_domheap_pages();
+    spin_unlock(&heap_lock);
 }
 
 static unsigned long init_node_heap(int node, unsigned long mfn,
index 31f9650ecc1c677ad75c06546f3f030a6c5dd6f6..117e095a35255f4c7ab0aa76458c39cc0b177148 100644 (file)
@@ -264,7 +264,8 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
         pi->max_node_id = MAX_NUMNODES-1;
         pi->max_cpu_id = nr_cpu_ids - 1;
         pi->total_pages = total_pages;
-        pi->free_pages = avail_domheap_pages();
+        /* Protected by lock */
+        get_outstanding_claims(&pi->free_pages, &pi->outstanding_pages);
         pi->scrub_pages = 0;
         pi->cpu_khz = cpu_khz;
         arch_do_physinfo(pi);
index 51d5254933e6d4e5eaea4ac27f9cd4e644924299..7a26dee0087962c8b23f8b2ed909b5a5ac8d7320 100644 (file)
@@ -459,13 +459,6 @@ DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
  * The zero value is appropiate.
  */
 
-/*
- * Get the number of pages currently claimed (but not yet "possessed")
- * across all domains.  The caller must be privileged but otherwise
- * the call never fails.
- */
-#define XENMEM_get_outstanding_pages        25
-
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
index 03710d896f63c9749bbb05f442f74ea03f640e5f..8437d31e18870ba8ba8630076b9ca650064d87e7 100644 (file)
@@ -34,7 +34,7 @@
 #include "xen.h"
 #include "domctl.h"
 
-#define XEN_SYSCTL_INTERFACE_VERSION 0x00000009
+#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000A
 
 /*
  * Read console content from Xen buffer ring.
@@ -101,6 +101,7 @@ struct xen_sysctl_physinfo {
     uint64_aligned_t total_pages;
     uint64_aligned_t free_pages;
     uint64_aligned_t scrub_pages;
+    uint64_aligned_t outstanding_pages;
     uint32_t hw_cap[8];
 
     /* XEN_SYSCTL_PHYSCAP_??? */
index efc45c78f1a1968ed7035b5ddfbdb6cdb6401474..4f5795c28beb4c36370ebddfe4c419d1c5059fbe 100644 (file)
@@ -59,7 +59,7 @@ void destroy_xen_mappings(unsigned long v, unsigned long e);
 /* Claim handling */
 unsigned long domain_adjust_tot_pages(struct domain *d, long pages);
 int domain_set_outstanding_pages(struct domain *d, unsigned long pages);
-long get_outstanding_claims(void);
+void get_outstanding_claims(uint64_t *free_pages, uint64_t *outstanding_pages);
 
 /* Domain suballocator. These functions are *not* interrupt-safe.*/
 void init_domheap_pages(paddr_t ps, paddr_t pe);
index a87205661dbccaca9042270cbd57ae63e5781d05..cc0a5a8301248f05a341fbf920644c896af30bef 100644 (file)
@@ -259,12 +259,6 @@ static XSM_INLINE int xsm_claim_pages(XSM_DEFAULT_ARG struct domain *d)
     return xsm_default_action(action, current->domain, d);
 }
 
-static XSM_INLINE int xsm_xenmem_get_outstanding_pages(XSM_DEFAULT_VOID)
-{
-    XSM_ASSERT_ACTION(XSM_PRIV);
-    return xsm_default_action(action, current->domain, NULL);
-}
-
 static XSM_INLINE int xsm_evtchn_unbound(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn,
                                          domid_t id2)
 {
index 58a4fbb1d1bb7d89f37fb13b38b121ca2646dff1..193945323e9a019382c1c1df17333a86eaf70f10 100644 (file)
@@ -93,7 +93,6 @@ struct xsm_operations {
     int (*add_to_physmap) (struct domain *d1, struct domain *d2);
     int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
     int (*claim_pages) (struct domain *d);
-    int (*xenmem_get_outstanding_pages) (void);
 
     int (*console_io) (struct domain *d, int cmd);
 
@@ -360,11 +359,6 @@ static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
     return xsm_ops->claim_pages(d);
 }
 
-static inline int xsm_xenmem_get_outstanding_pages(xsm_default_t def)
-{
-    return xsm_ops->xenmem_get_outstanding_pages();
-}
-
 static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
 {
     return xsm_ops->console_io(d, cmd);
index 937761f095eef6728fae81be0cf6218641471148..31e4f739b3baccf68e7337756b6bc655b8a7196d 100644 (file)
@@ -67,7 +67,6 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, memory_stat_reservation);
     set_to_dummy_if_null(ops, memory_pin_page);
     set_to_dummy_if_null(ops, claim_pages);
-    set_to_dummy_if_null(ops, xenmem_get_outstanding_pages);
 
     set_to_dummy_if_null(ops, console_io);
 
index bb10de3ae801d044a9df02f634b16b97da1e010e..fa0589a2d7343905f876d1d11bb27eafc2e8c028 100644 (file)
@@ -422,12 +422,6 @@ static int flask_claim_pages(struct domain *d)
     return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SETCLAIM);
 }
 
-static int flask_xenmem_get_outstanding_pages(void)
-{
-    return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN,
-                                XEN__HEAP, NULL);
-}
-
 static int flask_console_io(struct domain *d, int cmd)
 {
     u32 perm;
@@ -1504,7 +1498,6 @@ static struct xsm_operations flask_ops = {
     .memory_stat_reservation = flask_memory_stat_reservation,
     .memory_pin_page = flask_memory_pin_page,
     .claim_pages = flask_claim_pages,
-    .xenmem_get_outstanding_pages = flask_xenmem_get_outstanding_pages,
 
     .console_io = flask_console_io,
 
index 544c3bae0f90d28743350e0a26a343bdf511e2f7..5dfe13b016dd6a3c427504853a5b7b0d28fffe18 100644 (file)
@@ -54,7 +54,7 @@ class xen
     debug
 # XEN_SYSCTL_getcpuinfo, XENPF_get_cpu_version, XENPF_get_cpuinfo
     getcpuinfo
-# XEN_SYSCTL_availheap, XENMEM_get_outstanding_pages
+# XEN_SYSCTL_availheap
     heap
 # XEN_SYSCTL_get_pmstat, XEN_SYSCTL_pm_op, XENPF_set_processor_pminfo,
 # XENPF_core_parking