[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] The attached patch adds a new dom0_op, DOM0_GETDOMAININFOLIST. This



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID eef23f57f20e931a75481c2e2bce05cf2e9a19c6
# Parent  20ff6c7413d8dfb59d5c87d83887a3aaa2b86785

The attached patch adds a new dom0_op, DOM0_GETDOMAININFOLIST.  This
operation allows retrieval of the domain info structures for all domains
in one hypercall.

Using a small test program, on a system with 97 domains with
non-contiguous domain IDs, I found that with this hypercall I could
retrieve the full array of info structures 12840 times per second, an
improvement from 2380 times per second with the DOM0_GETDOMAININFO op.

The patch also adds a libxc wrapper for this new hypercall.

Signed-off-by: Josh Triplett <josht@xxxxxxxxxx>

diff -r 20ff6c7413d8 -r eef23f57f20e tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Fri Jul  8 08:48:46 2005
+++ b/tools/libxc/xc_domain.c   Fri Jul  8 09:06:04 2005
@@ -123,6 +123,33 @@
     if( !nr_doms ) return rc; 
 
     return nr_doms;
+}
+
+int xc_domain_getinfolist(int xc_handle,
+                          u32 first_domain,
+                          unsigned int max_domains,
+                          xc_domaininfo_t *info)
+{
+    int ret = 0;
+    dom0_op_t op;
+
+    if(mlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
+        return -1;
+    
+    op.cmd = DOM0_GETDOMAININFOLIST;
+    op.u.getdomaininfolist.first_domain = first_domain;
+    op.u.getdomaininfolist.max_domains  = max_domains;
+    op.u.getdomaininfolist.buffer       = info;
+
+    if(xc_dom0_op(xc_handle, &op) < 0)
+        ret = -1;
+    else
+        ret = op.u.getdomaininfolist.num_domains;
+    
+    if(munlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
+        ret = -1;
+    
+    return ret;
 }
 
 int xc_domain_get_vcpu_context(int xc_handle,
diff -r 20ff6c7413d8 -r eef23f57f20e tools/libxc/xc.h
--- a/tools/libxc/xc.h  Fri Jul  8 08:48:46 2005
+++ b/tools/libxc/xc.h  Fri Jul  8 09:06:04 2005
@@ -192,6 +192,24 @@
                       xc_dominfo_t *info);
 
 /**
+ * This function will return information about one or more domains, using a
+ * single hypercall.  The domain information will be stored into the supplied
+ * array of xc_domaininfo_t structures.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm first_domain the first domain to enumerate information from.
+ *                    Domains are currently enumerate in order of creation.
+ * @parm max_domains the number of elements in info
+ * @parm info an array of max_doms size that will contain the information for
+ *            the enumerated domains.
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_domain_getinfolist(int xc_handle,
+                          u32 first_domain,
+                          unsigned int max_domains,
+                          xc_domaininfo_t *info);
+
+/**
  * This function returns information about one domain.  This information is
  * more detailed than the information from xc_domain_getinfo().
  *
diff -r 20ff6c7413d8 -r eef23f57f20e xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Fri Jul  8 08:48:46 2005
+++ b/xen/include/public/dom0_ops.h     Fri Jul  8 09:06:04 2005
@@ -19,7 +19,7 @@
  * This makes sure that old versions of dom0 tools will stop working in a
  * well-defined way (rather than crashing the machine, for instance).
  */
-#define DOM0_INTERFACE_VERSION   0xAAAA100C
+#define DOM0_INTERFACE_VERSION   0xAAAA100D
 
 /************************************************************************/
 
@@ -356,6 +356,16 @@
     vcpu_guest_context_t *ctxt;       /* NB. IN/OUT variable. */
     u64     cpu_time;                 
 } dom0_getvcpucontext_t;
+
+#define DOM0_GETDOMAININFOLIST    38
+typedef struct {
+    /* IN variables. */
+    domid_t               first_domain;
+    memory_t              max_domains;
+    dom0_getdomaininfo_t *buffer;
+    /* OUT variables. */
+    memory_t              num_domains;
+} dom0_getdomaininfolist_t;
 
 typedef struct {
     u32 cmd;
@@ -389,6 +399,7 @@
         dom0_microcode_t         microcode;
         dom0_ioport_permission_t ioport_permission;
         dom0_getvcpucontext_t    getvcpucontext;
+        dom0_getdomaininfolist_t getdomaininfolist;
     } u;
 } dom0_op_t;
 
diff -r 20ff6c7413d8 -r eef23f57f20e xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c     Fri Jul  8 08:48:46 2005
+++ b/xen/common/dom0_ops.c     Fri Jul  8 09:06:04 2005
@@ -88,6 +88,60 @@
     return err;
 }
 
+static void getdomaininfo(struct domain *d, dom0_getdomaininfo_t *info)
+{
+    struct vcpu   *v;
+    u64 cpu_time = 0;
+    int vcpu_count = 0;
+    int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
+    
+    info->domain = d->domain_id;
+    
+    memset(&info->vcpu_to_cpu, -1, sizeof(info->vcpu_to_cpu));
+    memset(&info->cpumap, 0, sizeof(info->cpumap));
+    
+    /* 
+     * - domain is marked as paused or blocked only if all its vcpus 
+     *   are paused or blocked 
+     * - domain is marked as running if any of its vcpus is running
+     * - only map vcpus that aren't down.  Note, at some point we may
+     *   wish to demux the -1 value to indicate down vs. not-ever-booted
+     *   
+     */
+    for_each_vcpu ( d, v ) {
+        /* only map vcpus that are up */
+        if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
+            info->vcpu_to_cpu[v->vcpu_id] = v->processor;
+        info->cpumap[v->vcpu_id] = v->cpumap;
+        if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
+            flags &= ~DOMFLAGS_PAUSED;
+        if ( !(v->vcpu_flags & VCPUF_blocked) )
+            flags &= ~DOMFLAGS_BLOCKED;
+        if ( v->vcpu_flags & VCPUF_running )
+            flags |= DOMFLAGS_RUNNING;
+        if ( v->cpu_time > cpu_time )
+            cpu_time += v->cpu_time;
+        vcpu_count++;
+    }
+    
+    info->cpu_time = cpu_time;
+    info->n_vcpu = vcpu_count;
+    
+    info->flags = flags |
+        ((d->domain_flags & DOMF_dying)    ? DOMFLAGS_DYING    : 0) |
+        ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
+        d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
+
+    if (d->ssid != NULL)
+        info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
+    else    
+        info->ssidref = ACM_DEFAULT_SSID;
+    
+    info->tot_pages         = d->tot_pages;
+    info->max_pages         = d->max_pages;
+    info->shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT;
+}
+
 long do_dom0_op(dom0_op_t *u_dom0_op)
 {
     long ret = 0;
@@ -306,10 +360,6 @@
     case DOM0_GETDOMAININFO:
     { 
         struct domain *d;
-        struct vcpu   *v;
-        u64 cpu_time = 0;
-        int vcpu_count = 0;
-        int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
 
         read_lock(&domlist_lock);
 
@@ -328,59 +378,59 @@
 
         read_unlock(&domlist_lock);
 
-        op->u.getdomaininfo.domain = d->domain_id;
-
-        memset(&op->u.getdomaininfo.vcpu_to_cpu, -1,
-               sizeof(op->u.getdomaininfo.vcpu_to_cpu));
-        memset(&op->u.getdomaininfo.cpumap, 0,
-               sizeof(op->u.getdomaininfo.cpumap));
-
-        /* 
-         * - domain is marked as paused or blocked only if all its vcpus 
-         *   are paused or blocked 
-         * - domain is marked as running if any of its vcpus is running
-         * - only map vcpus that aren't down.  Note, at some point we may
-         *   wish to demux the -1 value to indicate down vs. not-ever-booted
-         *   
-         */
-        for_each_vcpu ( d, v ) {
-            /* only map vcpus that are up */
-            if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
-                op->u.getdomaininfo.vcpu_to_cpu[v->vcpu_id] = v->processor;
-            op->u.getdomaininfo.cpumap[v->vcpu_id]      = v->cpumap;
-            if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
-                flags &= ~DOMFLAGS_PAUSED;
-            if ( !(v->vcpu_flags & VCPUF_blocked) )
-                flags &= ~DOMFLAGS_BLOCKED;
-            if ( v->vcpu_flags & VCPUF_running )
-                flags |= DOMFLAGS_RUNNING;
-            if ( v->cpu_time > cpu_time )
-                cpu_time += v->cpu_time;
-            vcpu_count++;
-        }
-
-        op->u.getdomaininfo.cpu_time = cpu_time;
-        op->u.getdomaininfo.n_vcpu = vcpu_count;
-
-        op->u.getdomaininfo.flags = flags |
-            ((d->domain_flags & DOMF_dying)    ? DOMFLAGS_DYING    : 0) |
-            ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
-            d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
-
-        if (d->ssid != NULL)
-            op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain 
*)d->ssid)->ssidref;
-        else    
-            op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID;
-
-        op->u.getdomaininfo.tot_pages   = d->tot_pages;
-        op->u.getdomaininfo.max_pages   = d->max_pages;
-        op->u.getdomaininfo.shared_info_frame = 
-            __pa(d->shared_info) >> PAGE_SHIFT;
+        getdomaininfo(d, &op->u.getdomaininfo);
 
         if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )     
             ret = -EINVAL;
 
         put_domain(d);
+    }
+    break;
+
+    case DOM0_GETDOMAININFOLIST:
+    { 
+        struct domain *d;
+        dom0_getdomaininfo_t info;
+        dom0_getdomaininfo_t *buffer = op->u.getdomaininfolist.buffer;
+        u32 num_domains = 0;
+
+        read_lock(&domlist_lock);
+
+        for_each_domain ( d )
+        {
+            if ( d->domain_id < op->u.getdomaininfolist.first_domain )
+                continue;
+            if ( num_domains == op->u.getdomaininfolist.max_domains )
+                break;
+            if ( (d == NULL) || !get_domain(d) )
+            {
+                ret = -ESRCH;
+                break;
+            }
+
+            getdomaininfo(d, &info);
+
+            put_domain(d);
+
+            if ( copy_to_user(buffer, &info, sizeof(dom0_getdomaininfo_t)) )
+            {
+                ret = -EINVAL;
+                break;
+            }
+            
+            buffer++;
+            num_domains++;
+        }
+        
+        read_unlock(&domlist_lock);
+        
+        if ( ret != 0 )
+            break;
+        
+        op->u.getdomaininfolist.num_domains = num_domains;
+
+        if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
+            ret = -EINVAL;
     }
     break;
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.