aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2012-10-04 10:28:09 +0200
committerJan Beulich <jbeulich@suse.com>2012-10-04 10:28:09 +0200
commit2189af1fe6c7e3eaae086f67b44f4150b610c774 (patch)
treea08adaa5744a4807b1ee1208624188e9079e364d
parent8a26bdc7a41efd6dc0288824bc3fc4cc2fc7ac08 (diff)
downloadxen-2189af1fe6c7e3eaae086f67b44f4150b610c774.tar.gz
xen-2189af1fe6c7e3eaae086f67b44f4150b610c774.tar.bz2
xen-2189af1fe6c7e3eaae086f67b44f4150b610c774.zip
make domain_create() return a proper error code
While triggered by the XSA-9 fix, this really is of more general use; that fix just pointed out very sharply that the current situation with all domain creation failures reported to user (tools) space as -ENOMEM is very unfortunate (actively misleading users _and_ support personnel). Pull over the pointer <-> error code conversion infrastructure from Linux, and use it in domain_create() and all it callers. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org> xen-unstable changeset: 25808:4746414def65 xen-unstable date: Mon Sep 3 07:40:38 UTC 2012
-rw-r--r--xen/arch/x86/mm.c10
-rw-r--r--xen/arch/x86/setup.c3
-rw-r--r--xen/common/cpupool.c8
-rw-r--r--xen/common/domain.c28
-rw-r--r--xen/common/domctl.c7
-rw-r--r--xen/common/schedule.c4
-rw-r--r--xen/include/xen/err.h57
7 files changed, 92 insertions, 25 deletions
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 47b4985491..72872eeeda 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -91,7 +91,7 @@
#include <xen/mm.h>
#include <xen/domain.h>
#include <xen/sched.h>
-#include <xen/errno.h>
+#include <xen/err.h>
#include <xen/perfc.h>
#include <xen/irq.h>
#include <xen/softirq.h>
@@ -279,7 +279,7 @@ void __init arch_init_memory(void)
* their domain field set to dom_xen.
*/
dom_xen = domain_create(DOMID_XEN, DOMCRF_dummy, 0);
- BUG_ON(dom_xen == NULL);
+ BUG_ON(IS_ERR(dom_xen));
/*
* Initialise our DOMID_IO domain.
@@ -287,14 +287,14 @@ void __init arch_init_memory(void)
* array. Mappings occur at the priv of the caller.
*/
dom_io = domain_create(DOMID_IO, DOMCRF_dummy, 0);
- BUG_ON(dom_io == NULL);
+ BUG_ON(IS_ERR(dom_io));
/*
- * Initialise our DOMID_IO domain.
+ * Initialise our COW domain.
* This domain owns sharable pages.
*/
dom_cow = domain_create(DOMID_COW, DOMCRF_dummy, 0);
- BUG_ON(dom_cow == NULL);
+ BUG_ON(IS_ERR(dom_cow));
/* First 1MB of RAM is historically marked as I/O. */
for ( i = 0; i < 0x100; i++ )
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index d4f746b747..602a92235c 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1,6 +1,7 @@
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
+#include <xen/err.h>
#include <xen/sched.h>
#include <xen/sched-if.h>
#include <xen/domain.h>
@@ -1277,7 +1278,7 @@ void __init __start_xen(unsigned long mbi_p)
/* Create initial domain 0. */
dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
- if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
+ if ( IS_ERR(dom0) || (alloc_dom0_vcpu0() == NULL) )
panic("Error creating domain 0\n");
dom0->is_privileged = 1;
diff --git a/xen/common/cpupool.c b/xen/common/cpupool.c
index cafb4be792..6e0a546725 100644
--- a/xen/common/cpupool.c
+++ b/xen/common/cpupool.c
@@ -355,14 +355,18 @@ out:
int cpupool_add_domain(struct domain *d, int poolid)
{
struct cpupool *c;
- int rc = 1;
+ int rc;
int n_dom = 0;
if ( poolid == CPUPOOLID_NONE )
return 0;
spin_lock(&cpupool_lock);
c = cpupool_find_by_id(poolid);
- if ( (c != NULL) && cpus_weight(c->cpu_valid) )
+ if ( c == NULL )
+ rc = -ESRCH;
+ else if ( !cpus_weight(c->cpu_valid) )
+ rc = -ENODEV;
+ else
{
c->n_dom++;
n_dom = c->n_dom;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index b8c48a7ab0..98e36eee55 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -9,7 +9,7 @@
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/ctype.h>
-#include <xen/errno.h>
+#include <xen/err.h>
#include <xen/sched.h>
#include <xen/domain.h>
#include <xen/mm.h>
@@ -217,17 +217,17 @@ struct domain *domain_create(
struct domain *d, **pd;
enum { INIT_xsm = 1u<<0, INIT_watchdog = 1u<<1, INIT_rangeset = 1u<<2,
INIT_evtchn = 1u<<3, INIT_gnttab = 1u<<4, INIT_arch = 1u<<5 };
- int init_status = 0;
+ int err, init_status = 0;
int poolid = CPUPOOLID_NONE;
if ( (d = alloc_domain_struct()) == NULL )
- return NULL;
+ return ERR_PTR(-ENOMEM);
d->domain_id = domid;
lock_profile_register_struct(LOCKPROF_TYPE_PERDOM, d, domid, "Domain");
- if ( xsm_alloc_security_domain(d) != 0 )
+ if ( (err = xsm_alloc_security_domain(d)) != 0 )
goto fail;
init_status |= INIT_xsm;
@@ -261,14 +261,14 @@ struct domain *domain_create(
d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex);
d->irq_caps = rangeset_new(d, "Interrupts", 0);
if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) )
- goto fail;
+ goto nomem;
if ( domcr_flags & DOMCRF_dummy )
return d;
if ( !is_idle_domain(d) )
{
- if ( xsm_domain_create(d, ssidref) != 0 )
+ if ( (err = xsm_domain_create(d, ssidref)) != 0 )
goto fail;
d->is_paused_by_controller = 1;
@@ -285,29 +285,29 @@ struct domain *domain_create(
d->pirq_mask = xmalloc_array(
unsigned long, BITS_TO_LONGS(d->nr_pirqs));
if ( (d->pirq_to_evtchn == NULL) || (d->pirq_mask == NULL) )
- goto fail;
+ goto nomem;
memset(d->pirq_to_evtchn, 0, d->nr_pirqs * sizeof(*d->pirq_to_evtchn));
bitmap_zero(d->pirq_mask, d->nr_pirqs);
- if ( evtchn_init(d) != 0 )
+ if ( (err = evtchn_init(d)) != 0 )
goto fail;
init_status |= INIT_evtchn;
- if ( grant_table_create(d) != 0 )
+ if ( (err = grant_table_create(d)) != 0 )
goto fail;
init_status |= INIT_gnttab;
poolid = 0;
}
- if ( arch_domain_create(d, domcr_flags) != 0 )
+ if ( (err = arch_domain_create(d, domcr_flags)) != 0 )
goto fail;
init_status |= INIT_arch;
- if ( cpupool_add_domain(d, poolid) != 0 )
+ if ( (err = cpupool_add_domain(d, poolid)) != 0 )
goto fail;
- if ( sched_init_domain(d) != 0 )
+ if ( (err = sched_init_domain(d)) != 0 )
goto fail;
if ( !is_idle_domain(d) )
@@ -326,6 +326,8 @@ struct domain *domain_create(
return d;
+ nomem:
+ err = -ENOMEM;
fail:
d->is_dying = DOMDYING_dead;
atomic_set(&d->refcnt, DOMAIN_DESTROYED);
@@ -347,7 +349,7 @@ struct domain *domain_create(
xfree(d->pirq_mask);
xfree(d->pirq_to_evtchn);
free_domain_struct(d);
- return NULL;
+ return ERR_PTR(err);
}
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index f45c62e93c..981cb1a6df 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -9,6 +9,7 @@
#include <xen/config.h>
#include <xen/types.h>
#include <xen/lib.h>
+#include <xen/err.h>
#include <xen/mm.h>
#include <xen/sched.h>
#include <xen/sched-if.h>
@@ -435,10 +436,12 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_oos_off )
domcr_flags |= DOMCRF_oos_off;
- ret = -ENOMEM;
d = domain_create(dom, domcr_flags, op->u.createdomain.ssidref);
- if ( d == NULL )
+ if ( IS_ERR(d) )
+ {
+ ret = PTR_ERR(d);
break;
+ }
ret = 0;
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index e06e44e690..be39b20bbd 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -28,7 +28,7 @@
#include <xen/softirq.h>
#include <xen/trace.h>
#include <xen/mm.h>
-#include <xen/errno.h>
+#include <xen/err.h>
#include <xen/guest_access.h>
#include <xen/multicall.h>
#include <xen/cpu.h>
@@ -1357,7 +1357,7 @@ void __init scheduler_init(void)
panic("scheduler returned error on init\n");
idle_domain = domain_create(DOMID_IDLE, 0, 0);
- BUG_ON(idle_domain == NULL);
+ BUG_ON(IS_ERR(idle_domain));
idle_domain->vcpu = idle_vcpu;
idle_domain->max_vcpus = NR_CPUS;
if ( alloc_vcpu(idle_domain, 0, 0) == NULL )
diff --git a/xen/include/xen/err.h b/xen/include/xen/err.h
new file mode 100644
index 0000000000..2f29b57d28
--- /dev/null
+++ b/xen/include/xen/err.h
@@ -0,0 +1,57 @@
+#if !defined(__XEN_ERR_H__) && !defined(__ASSEMBLY__)
+#define __XEN_ERR_H__
+
+#include <xen/compiler.h>
+#include <xen/errno.h>
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This could be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define MAX_ERRNO 4095
+
+#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void *__must_check ERR_PTR(long error)
+{
+ return (void *)error;
+}
+
+static inline long __must_check PTR_ERR(const void *ptr)
+{
+ return (long)ptr;
+}
+
+static inline long __must_check IS_ERR(const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+static inline long __must_check IS_ERR_OR_NULL(const void *ptr)
+{
+ return !ptr || IS_ERR_VALUE((unsigned long)ptr);
+}
+
+/**
+ * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type
+ * @ptr: The pointer to cast.
+ *
+ * Explicitly cast an error-valued pointer to another pointer type in such a
+ * way as to make it clear that's what's going on.
+ */
+static inline void * __must_check ERR_CAST(const void *ptr)
+{
+ /* cast away the const */
+ return (void *)ptr;
+}
+
+static inline int __must_check PTR_RET(const void *ptr)
+{
+ return IS_ERR(ptr) ? PTR_ERR(ptr) : 0;
+}
+
+#endif /* __XEN_ERR_H__ */