xen/libxc-pass-errno-to-callers-of-xc_domain_save.patch

648 lines
27 KiB
Diff
Raw Normal View History

From b7fc90f3d4f0d61281312c5d05859ee2de8fc8be Mon Sep 17 00:00:00 2001
From: Olaf Hering <olaf@aepfle.de>
Date: Mon, 10 Feb 2014 12:47:26 +0100
Subject: libxc: pass errno to callers of xc_domain_save
Callers of xc_domain_save use errno to print diagnostics if the call
fails. But xc_domain_save does not preserve the actual errno in case of
a failure.
This change preserves errno in all cases where code jumps to the label
"out". In addition a new label "exit" is added to catch also code which
used to do just "return 1".
Now libxl_save_helper:complete can print the actual error string.
Note: some of the functions used in xc_domain_save do not use errno to
indicate a reason. In these cases the errno remains undefined as it used
to be without this change.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/libxc/xc_domain_save.c | 88 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 82 insertions(+), 6 deletions(-)
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 42c4752..f32ac81 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -806,6 +806,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
xc_dominfo_t info;
DECLARE_DOMCTL;
+ int errnoval = 0;
int rc = 1, frc, i, j, last_iter = 0, iter = 0;
int live = (flags & XCFLAGS_LIVE);
int debug = (flags & XCFLAGS_DEBUG);
@@ -898,8 +899,8 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( hvm && !callbacks->switch_qemu_logdirty )
{
ERROR("No switch_qemu_logdirty callback provided.");
- errno = EINVAL;
- return 1;
+ errnoval = EINVAL;
+ goto exit;
}
outbuf_init(xch, &ob_pagebuf, OUTBUF_SIZE);
@@ -913,14 +914,16 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( !get_platform_info(xch, dom,
&ctx->max_mfn, &ctx->hvirt_start, &ctx->pt_levels, &dinfo->guest_width) )
{
+ errnoval = errno;
ERROR("Unable to get platform info.");
- return 1;
+ goto exit;
}
if ( xc_domain_getinfo(xch, dom, 1, &info) != 1 )
{
+ errnoval = errno;
PERROR("Could not get domain info");
- return 1;
+ goto exit;
}
shared_info_frame = info.shared_info_frame;
@@ -932,6 +935,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
PROT_READ, shared_info_frame);
if ( !live_shinfo )
{
+ errnoval = errno;
PERROR("Couldn't map live_shinfo");
goto out;
}
@@ -942,6 +946,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( dinfo->p2m_size > ~XEN_DOMCTL_PFINFO_LTAB_MASK )
{
+ errnoval = E2BIG;
ERROR("Cannot save this big a guest");
goto out;
}
@@ -967,6 +972,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( frc < 0 )
{
+ errnoval = errno;
PERROR("Couldn't enable shadow mode (rc %d) (errno %d)", frc, errno );
goto out;
}
@@ -975,6 +981,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Enable qemu-dm logging dirty pages to xen */
if ( hvm && callbacks->switch_qemu_logdirty(dom, 1, callbacks->data) )
{
+ errnoval = errno;
PERROR("Couldn't enable qemu log-dirty mode (errno %d)", errno);
goto out;
}
@@ -985,6 +992,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( suspend_and_state(callbacks->suspend, callbacks->data, xch,
io_fd, dom, &info) )
{
+ errnoval = errno;
ERROR("Domain appears not to have suspended");
goto out;
}
@@ -994,6 +1002,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
{
if (!(compress_ctx = xc_compression_create_context(xch, dinfo->p2m_size)))
{
+ errnoval = errno;
ERROR("Failed to create compression context");
goto out;
}
@@ -1012,6 +1021,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( !to_send || !to_fix || !to_skip )
{
+ errnoval = ENOMEM;
ERROR("Couldn't allocate to_send array");
goto out;
}
@@ -1024,12 +1034,14 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
hvm_buf_size = xc_domain_hvm_getcontext(xch, dom, 0, 0);
if ( hvm_buf_size == -1 )
{
+ errnoval = errno;
PERROR("Couldn't get HVM context size from Xen");
goto out;
}
hvm_buf = malloc(hvm_buf_size);
if ( !hvm_buf )
{
+ errnoval = ENOMEM;
ERROR("Couldn't allocate memory");
goto out;
}
@@ -1043,7 +1055,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (pfn_type == NULL) || (pfn_batch == NULL) || (pfn_err == NULL) )
{
ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays");
- errno = ENOMEM;
+ errnoval = ENOMEM;
goto out;
}
memset(pfn_type, 0,
@@ -1052,6 +1064,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Setup the mfn_to_pfn table mapping */
if ( !(ctx->live_m2p = xc_map_m2p(xch, ctx->max_mfn, PROT_READ, &ctx->m2p_mfn0)) )
{
+ errnoval = errno;
PERROR("Failed to map live M2P table");
goto out;
}
@@ -1059,6 +1072,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Start writing out the saved-domain record. */
if ( write_exact(io_fd, &dinfo->p2m_size, sizeof(unsigned long)) )
{
+ errnoval = errno;
PERROR("write: p2m_size");
goto out;
}
@@ -1071,6 +1085,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
ctx->live_p2m = map_and_save_p2m_table(xch, io_fd, dom, ctx, live_shinfo);
if ( ctx->live_p2m == NULL )
{
+ errnoval = errno;
PERROR("Failed to map/save the p2m frame list");
goto out;
}
@@ -1097,12 +1112,14 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
tmem_saved = xc_tmem_save(xch, dom, io_fd, live, XC_SAVE_ID_TMEM);
if ( tmem_saved == -1 )
{
+ errnoval = errno;
PERROR("Error when writing to state file (tmem)");
goto out;
}
if ( !live && save_tsc_info(xch, dom, io_fd) < 0 )
{
+ errnoval = errno;
PERROR("Error when writing to state file (tsc)");
goto out;
}
@@ -1143,6 +1160,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
dinfo->p2m_size, NULL, 0, NULL);
if ( frc != dinfo->p2m_size )
{
+ errnoval = errno;
ERROR("Error peeking shadow bitmap");
goto out;
}
@@ -1257,6 +1275,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
xch, dom, PROT_READ, pfn_type, pfn_err, batch);
if ( region_base == NULL )
{
+ errnoval = errno;
PERROR("map batch failed");
goto out;
}
@@ -1264,6 +1283,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Get page types */
if ( xc_get_pfn_type_batch(xch, dom, batch, pfn_type) )
{
+ errnoval = errno;
PERROR("get_pfn_type_batch failed");
goto out;
}
@@ -1332,6 +1352,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( wrexact(io_fd, &batch, sizeof(unsigned int)) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (2)");
goto out;
}
@@ -1341,6 +1362,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
((unsigned long *)pfn_type)[j] = pfn_type[j];
if ( wrexact(io_fd, pfn_type, sizeof(unsigned long)*batch) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (3)");
goto out;
}
@@ -1368,6 +1390,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
(char*)region_base+(PAGE_SIZE*(j-run)),
PAGE_SIZE*run) != PAGE_SIZE*run )
{
+ errnoval = errno;
PERROR("Error when writing to state file (4a)"
" (errno %d)", errno);
goto out;
@@ -1396,6 +1419,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( race && !live )
{
+ errnoval = errno;
ERROR("Fatal PT race (pfn %lx, type %08lx)", pfn,
pagetype);
goto out;
@@ -1409,6 +1433,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
pfn, 1 /* raw page */);
if (c_err == -2) /* OOB PFN */
{
+ errnoval = errno;
ERROR("Could not add pagetable page "
"(pfn:%" PRIpfn "to page buffer\n", pfn);
goto out;
@@ -1428,6 +1453,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
*/
if (wrcompressed(io_fd) < 0)
{
+ errnoval = errno;
ERROR("Error when writing compressed"
" data (4b)\n");
goto out;
@@ -1437,6 +1463,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
else if ( wruncached(io_fd, live, page,
PAGE_SIZE) != PAGE_SIZE )
{
+ errnoval = errno;
PERROR("Error when writing to state file (4b)"
" (errno %d)", errno);
goto out;
@@ -1456,6 +1483,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if (c_err == -2) /* OOB PFN */
{
+ errnoval = errno;
ERROR("Could not add page "
"(pfn:%" PRIpfn "to page buffer\n", pfn);
goto out;
@@ -1465,6 +1493,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
{
if (wrcompressed(io_fd) < 0)
{
+ errnoval = errno;
ERROR("Error when writing compressed"
" data (4c)\n");
goto out;
@@ -1483,6 +1512,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
(char*)region_base+(PAGE_SIZE*(j-run)),
PAGE_SIZE*run) != PAGE_SIZE*run )
{
+ errnoval = errno;
PERROR("Error when writing to state file (4c)"
" (errno %d)", errno);
goto out;
@@ -1520,6 +1550,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* send "-1" to put receiver into debug mode */
if ( wrexact(io_fd, &id, sizeof(int)) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (6)");
goto out;
}
@@ -1542,6 +1573,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( suspend_and_state(callbacks->suspend, callbacks->data,
xch, io_fd, dom, &info) )
{
+ errnoval = errno;
ERROR("Domain appears not to have suspended");
goto out;
}
@@ -1550,12 +1582,14 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (tmem_saved > 0) &&
(xc_tmem_save_extra(xch,dom,io_fd,XC_SAVE_ID_TMEM_EXTRA) == -1) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (tmem)");
goto out;
}
if ( save_tsc_info(xch, dom, io_fd) < 0 )
{
+ errnoval = errno;
PERROR("Error when writing to state file (tsc)");
goto out;
}
@@ -1567,6 +1601,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
XEN_DOMCTL_SHADOW_OP_CLEAN, HYPERCALL_BUFFER(to_send),
dinfo->p2m_size, NULL, 0, &shadow_stats) != dinfo->p2m_size )
{
+ errnoval = errno;
PERROR("Error flushing shadow PT");
goto out;
}
@@ -1598,6 +1633,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( info.max_vcpu_id >= XC_SR_MAX_VCPUS )
{
+ errnoval = E2BIG;
ERROR("Too many VCPUS in guest!");
goto out;
}
@@ -1614,6 +1650,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( wrexact(io_fd, &chunk, offsetof(struct chunk, vcpumap)
+ vcpumap_sz(info.max_vcpu_id)) )
{
+ errnoval = errno;
PERROR("Error when writing to state file");
goto out;
}
@@ -1633,6 +1670,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the generation id buffer location for guest");
goto out;
}
@@ -1645,6 +1683,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the ident_pt for EPT guest");
goto out;
}
@@ -1657,6 +1696,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the paging ring pfn for guest");
goto out;
}
@@ -1669,6 +1709,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the access ring pfn for guest");
goto out;
}
@@ -1681,6 +1722,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the sharing ring pfn for guest");
goto out;
}
@@ -1693,6 +1735,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the vm86 TSS for guest");
goto out;
}
@@ -1705,6 +1748,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the console pfn for guest");
goto out;
}
@@ -1716,6 +1760,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ((chunk.data != 0) && wrexact(io_fd, &chunk, sizeof(chunk)))
{
+ errnoval = errno;
PERROR("Error when writing the firmware ioport version");
goto out;
}
@@ -1728,6 +1773,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (chunk.data != 0) &&
wrexact(io_fd, &chunk, sizeof(chunk)) )
{
+ errnoval = errno;
PERROR("Error when writing the viridian flag");
goto out;
}
@@ -1741,6 +1787,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( callbacks->toolstack_save(dom, &buf, &len, callbacks->data) < 0 )
{
+ errnoval = errno;
PERROR("Error calling toolstack_save");
goto out;
}
@@ -1759,6 +1806,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
i = XC_SAVE_ID_LAST_CHECKPOINT;
if ( wrexact(io_fd, &i, sizeof(int)) )
{
+ errnoval = errno;
PERROR("Error when writing last checkpoint chunk");
goto out;
}
@@ -1778,6 +1826,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
i = XC_SAVE_ID_ENABLE_COMPRESSION;
if ( wrexact(io_fd, &i, sizeof(int)) )
{
+ errnoval = errno;
PERROR("Error when writing enable_compression marker");
goto out;
}
@@ -1787,6 +1836,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
i = 0;
if ( wrexact(io_fd, &i, sizeof(int)) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (6')");
goto out;
}
@@ -1805,6 +1855,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
(unsigned long *)&magic_pfns[2]);
if ( wrexact(io_fd, magic_pfns, sizeof(magic_pfns)) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (7)");
goto out;
}
@@ -1813,18 +1864,21 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (rec_size = xc_domain_hvm_getcontext(xch, dom, hvm_buf,
hvm_buf_size)) == -1 )
{
+ errnoval = errno;
PERROR("HVM:Could not get hvm buffer");
goto out;
}
if ( wrexact(io_fd, &rec_size, sizeof(uint32_t)) )
{
+ errnoval = errno;
PERROR("error write hvm buffer size");
goto out;
}
if ( wrexact(io_fd, hvm_buf, rec_size) )
{
+ errnoval = errno;
PERROR("write HVM info failed!");
goto out;
}
@@ -1849,6 +1903,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( wrexact(io_fd, &j, sizeof(unsigned int)) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (6a)");
goto out;
}
@@ -1863,6 +1918,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
{
if ( wrexact(io_fd, &pfntab, sizeof(unsigned long)*j) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (6b)");
goto out;
}
@@ -1873,6 +1929,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( xc_vcpu_getcontext(xch, dom, 0, &ctxt) )
{
+ errnoval = errno;
PERROR("Could not get vcpu context");
goto out;
}
@@ -1888,6 +1945,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
mfn = GET_FIELD(&ctxt, user_regs.edx);
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
+ errnoval = ERANGE;
ERROR("Suspend record is not in range of pseudophys map");
goto out;
}
@@ -1900,6 +1958,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( (i != 0) && xc_vcpu_getcontext(xch, dom, i, &ctxt) )
{
+ errnoval = errno;
PERROR("No context for VCPU%d", i);
goto out;
}
@@ -1910,6 +1969,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
mfn = GET_FIELD(&ctxt, gdt_frames[j]);
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
+ errnoval = ERANGE;
ERROR("GDT frame is not in range of pseudophys map");
goto out;
}
@@ -1920,6 +1980,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(
GET_FIELD(&ctxt, ctrlreg[3]))) )
{
+ errnoval = ERANGE;
ERROR("PT base is not in range of pseudophys map");
goto out;
}
@@ -1931,6 +1992,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
{
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(ctxt.x64.ctrlreg[1])) )
{
+ errnoval = ERANGE;
ERROR("PT base is not in range of pseudophys map");
goto out;
}
@@ -1943,6 +2005,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
? sizeof(ctxt.x64)
: sizeof(ctxt.x32))) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (1)");
goto out;
}
@@ -1953,11 +2016,13 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
domctl.u.ext_vcpucontext.vcpu = i;
if ( xc_domctl(xch, &domctl) < 0 )
{
+ errnoval = errno;
PERROR("No extended context for VCPU%d", i);
goto out;
}
if ( wrexact(io_fd, &domctl.u.ext_vcpucontext, 128) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (2)");
goto out;
}
@@ -1971,6 +2036,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
domctl.u.vcpuextstate.size = 0;
if ( xc_domctl(xch, &domctl) < 0 )
{
+ errnoval = errno;
PERROR("No eXtended states (XSAVE) for VCPU%d", i);
goto out;
}
@@ -1982,6 +2048,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
buffer = xc_hypercall_buffer_alloc(xch, buffer, domctl.u.vcpuextstate.size);
if ( !buffer )
{
+ errnoval = errno;
PERROR("Insufficient memory for getting eXtended states for"
"VCPU%d", i);
goto out;
@@ -1989,6 +2056,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
set_xen_guest_handle(domctl.u.vcpuextstate.buffer, buffer);
if ( xc_domctl(xch, &domctl) < 0 )
{
+ errnoval = errno;
PERROR("No eXtended states (XSAVE) for VCPU%d", i);
xc_hypercall_buffer_free(xch, buffer);
goto out;
@@ -2000,6 +2068,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
sizeof(domctl.u.vcpuextstate.size)) ||
wrexact(io_fd, buffer, domctl.u.vcpuextstate.size) )
{
+ errnoval = errno;
PERROR("Error when writing to state file VCPU extended state");
xc_hypercall_buffer_free(xch, buffer);
goto out;
@@ -2015,6 +2084,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
arch.pfn_to_mfn_frame_list_list, 0);
if ( wrexact(io_fd, page, PAGE_SIZE) )
{
+ errnoval = errno;
PERROR("Error when writing to state file (1)");
goto out;
}
@@ -2022,6 +2092,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Flush last write and check for errors. */
if ( fsync(io_fd) && errno != EINVAL )
{
+ errnoval = errno;
PERROR("Error when flushing state file");
goto out;
}
@@ -2043,6 +2114,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
ob = &ob_pagebuf;
if (wrcompressed(io_fd) < 0)
{
+ errnoval = errno;
ERROR("Error when writing compressed data, after postcopy\n");
rc = 1;
goto out;
@@ -2051,6 +2123,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( wrexact(io_fd, ob_tailbuf.buf, ob_tailbuf.pos) )
{
rc = 1;
+ errnoval = errno;
PERROR("Error when copying tailbuf into outbuf");
goto out;
}
@@ -2079,6 +2152,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( suspend_and_state(callbacks->suspend, callbacks->data, xch,
io_fd, dom, &info) )
{
+ errnoval = errno;
ERROR("Domain appears not to have suspended");
goto out;
}
@@ -2130,7 +2204,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
free(hvm_buf);
outbuf_free(&ob_pagebuf);
- DPRINTF("Save exit of domid %u with rc=%d\n", dom, rc);
+exit:
+ DPRINTF("Save exit of domid %u with rc=%d, errno=%d\n", dom, rc, errnoval);
+ errno = errnoval;
return !!rc;
}