direct-io.hg

view tools/libxc/xc_misc.c @ 12765:2dd4569e0640

[LIBXC] Add an error reporting API to the libxc library.

- An 'xc_error' struct is used to pass around error
details. Currently contains two members 'code' an enumeration of
error types, and 'message' a free text description of the specific
problem.

- The xc_get_last_error() method returns a const pointer to the
internal instance of this struct manged by libxc. By returning a
const pointer we can add extra members to the end of the struct at
any time without worrying about ABI of callers. This will let us
provide more fine-grained info if needed in the future.

- The xc_error instance is statically defined inside libxc and marked
__thread. This ensures that errors are recorded per-thread, and
that when dealing with errors we never need to call malloc - all
storage needed is statically allocated.

- The xc_clear_last_error() method resets any currently recorded
error details

- The xc_error_code_to_desc() method converts the integer error code
into a generic user facing messsage. eg "Invalid kernel". Together
with the 'message' field from xc_error, this provides the user
visible feedback. eg "Invalid kernel: Non PAE-kernel on PAE host."

- A callback can be registered with xc_set_error_handler to receive
notification whenever an error is recorded, rather than querying
for error details after the fact with xc_get_last_error

- If built with -DDEBUG set, a default error handler will be
registered which calls fprintf(stderr), thus maintaining current
behaviour of logging errors to stderr during developer builds.

- The python binding for libxc is updated to use xc_get_last_error
to pull out error details whenever appropriate, instead of
returning info based on 'errno'

- The xc_set_error method is private to libxc internals, and is used
for setting error details

- The ERROR and PERROR macros have been updated to call xc_set_error
automatically specifying XC_INTERNAL_ERROR as the error code. This
gives a generic error report for all current failure points

- Some uses of the ERROR macro have been replaced with explicit
calls to xc_set_error to enable finer grained error reporting. In
particular the code dealing with invalid kernel types uses this
to report about PAE/architecture/wordsize mismatches

The patch has been tested by calling xm create against a varietry of
config files defining invalid kernels of various kinds. It has also
been tested with libvirt talking to xend. In both cases the error
messages were propagated all the way back up the stack.

There is only one place where I need to do further work. The suspend
& restore APIs in Xend invoke external helper programs rather than
calling libxc directly. This means that error details are essentially
lost. Since there is already code in XenD which scans STDERR from
these programs I will investigate adapting this to extract actual
error messages from these helpers.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author kfraser@localhost.localdomain
date Thu Dec 07 11:36:26 2006 +0000 (2006-12-07)
parents f555a90bcc37
children 16f7f5ac80ed
line source
1 /******************************************************************************
2 * xc_misc.c
3 *
4 * Miscellaneous control interface functions.
5 */
7 #include "xc_private.h"
8 #include <xen/hvm/hvm_op.h>
10 int xc_readconsolering(int xc_handle,
11 char **pbuffer,
12 unsigned int *pnr_chars,
13 int clear)
14 {
15 int ret;
16 DECLARE_SYSCTL;
17 char *buffer = *pbuffer;
18 unsigned int nr_chars = *pnr_chars;
20 sysctl.cmd = XEN_SYSCTL_readconsole;
21 set_xen_guest_handle(sysctl.u.readconsole.buffer, buffer);
22 sysctl.u.readconsole.count = nr_chars;
23 sysctl.u.readconsole.clear = clear;
25 if ( (ret = lock_pages(buffer, nr_chars)) != 0 )
26 return ret;
28 if ( (ret = do_sysctl(xc_handle, &sysctl)) == 0 )
29 *pnr_chars = sysctl.u.readconsole.count;
31 unlock_pages(buffer, nr_chars);
33 return ret;
34 }
36 int xc_physinfo(int xc_handle,
37 xc_physinfo_t *put_info)
38 {
39 int ret;
40 DECLARE_SYSCTL;
42 sysctl.cmd = XEN_SYSCTL_physinfo;
44 if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
45 return ret;
47 memcpy(put_info, &sysctl.u.physinfo, sizeof(*put_info));
49 return 0;
50 }
52 int xc_sched_id(int xc_handle,
53 int *sched_id)
54 {
55 int ret;
56 DECLARE_SYSCTL;
58 sysctl.cmd = XEN_SYSCTL_sched_id;
60 if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
61 return ret;
63 *sched_id = sysctl.u.sched_id.sched_id;
65 return 0;
66 }
68 int xc_perfc_control(int xc_handle,
69 uint32_t opcode,
70 xc_perfc_desc_t *desc,
71 xc_perfc_val_t *val,
72 int *nbr_desc,
73 int *nbr_val)
74 {
75 int rc;
76 DECLARE_SYSCTL;
78 sysctl.cmd = XEN_SYSCTL_perfc_op;
79 sysctl.u.perfc_op.cmd = opcode;
80 set_xen_guest_handle(sysctl.u.perfc_op.desc, desc);
81 set_xen_guest_handle(sysctl.u.perfc_op.val, val);
83 rc = do_sysctl(xc_handle, &sysctl);
85 if (nbr_desc)
86 *nbr_desc = sysctl.u.perfc_op.nr_counters;
87 if (nbr_val)
88 *nbr_val = sysctl.u.perfc_op.nr_vals;
90 return rc;
91 }
93 int xc_hvm_set_pci_intx_level(
94 int xc_handle, domid_t dom,
95 uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
96 unsigned int level)
97 {
98 DECLARE_HYPERCALL;
99 struct xen_hvm_set_pci_intx_level arg;
100 int rc;
102 hypercall.op = __HYPERVISOR_hvm_op;
103 hypercall.arg[0] = HVMOP_set_pci_intx_level;
104 hypercall.arg[1] = (unsigned long)&arg;
106 arg.domid = dom;
107 arg.domain = domain;
108 arg.bus = bus;
109 arg.device = device;
110 arg.intx = intx;
111 arg.level = level;
113 if ( mlock(&arg, sizeof(arg)) != 0 )
114 {
115 PERROR("Could not lock memory");
116 return -1;
117 }
119 rc = do_xen_hypercall(xc_handle, &hypercall);
121 safe_munlock(&arg, sizeof(arg));
123 return rc;
124 }
126 int xc_hvm_set_isa_irq_level(
127 int xc_handle, domid_t dom,
128 uint8_t isa_irq,
129 unsigned int level)
130 {
131 DECLARE_HYPERCALL;
132 struct xen_hvm_set_isa_irq_level arg;
133 int rc;
135 hypercall.op = __HYPERVISOR_hvm_op;
136 hypercall.arg[0] = HVMOP_set_isa_irq_level;
137 hypercall.arg[1] = (unsigned long)&arg;
139 arg.domid = dom;
140 arg.isa_irq = isa_irq;
141 arg.level = level;
143 if ( mlock(&arg, sizeof(arg)) != 0 )
144 {
145 PERROR("Could not lock memory");
146 return -1;
147 }
149 rc = do_xen_hypercall(xc_handle, &hypercall);
151 safe_munlock(&arg, sizeof(arg));
153 return rc;
154 }
156 int xc_hvm_set_pci_link_route(
157 int xc_handle, domid_t dom, uint8_t link, uint8_t isa_irq)
158 {
159 DECLARE_HYPERCALL;
160 struct xen_hvm_set_pci_link_route arg;
161 int rc;
163 hypercall.op = __HYPERVISOR_hvm_op;
164 hypercall.arg[0] = HVMOP_set_pci_link_route;
165 hypercall.arg[1] = (unsigned long)&arg;
167 arg.domid = dom;
168 arg.link = link;
169 arg.isa_irq = isa_irq;
171 if ( mlock(&arg, sizeof(arg)) != 0 )
172 {
173 PERROR("Could not lock memory");
174 return -1;
175 }
177 rc = do_xen_hypercall(xc_handle, &hypercall);
179 safe_munlock(&arg, sizeof(arg));
181 return rc;
182 }
184 /*
185 * Local variables:
186 * mode: C
187 * c-set-style: "BSD"
188 * c-basic-offset: 4
189 * tab-width: 4
190 * indent-tabs-mode: nil
191 * End:
192 */