libxl: ao abort: Make datacopiers abortable
authorIan Jackson <ian.jackson@eu.citrix.com>
Tue, 10 Feb 2015 19:52:11 +0000 (19:52 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Fri, 26 Jun 2015 15:53:51 +0000 (16:53 +0100)
libxl__datacopier_* can now actually generate a callback with
rc==ABORTED.

This provides abort support during some corner cases, including (at
least) copying the device model data during the end of domain save.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
v2: New in this version of the series.

tools/libxl/libxl_aoutils.c
tools/libxl/libxl_internal.h

index 124582886dfa8191a7b26a1decdc7f72b01b4e37..0931eeeb1917e3e292032b775479342db4de2a80 100644 (file)
@@ -103,6 +103,7 @@ static void xswait_report_error(libxl__egc *egc, libxl__xswait_state *xswa,
 void libxl__datacopier_init(libxl__datacopier_state *dc)
 {
     assert(dc->ao);
+    libxl__ao_abortable_init(&dc->abrt);
     libxl__ev_fd_init(&dc->toread);
     libxl__ev_fd_init(&dc->towrite);
     LIBXL_TAILQ_INIT(&dc->bufs);
@@ -113,6 +114,7 @@ void libxl__datacopier_kill(libxl__datacopier_state *dc)
     STATE_AO_GC(dc->ao);
     libxl__datacopier_buf *buf, *tbuf;
 
+    libxl__ao_abortable_deregister(&dc->abrt);
     libxl__ev_fd_deregister(gc, &dc->toread);
     libxl__ev_fd_deregister(gc, &dc->towrite);
     LIBXL_TAILQ_FOREACH_SAFE(buf, &dc->bufs, entry, tbuf)
@@ -201,6 +203,15 @@ static int datacopier_pollhup_handled(libxl__egc *egc,
     return 0;
 }
 
+static void datacopier_abort(libxl__egc *egc, libxl__ao_abortable *abrt,
+                             int rc)
+{
+    libxl__datacopier_state *dc = CONTAINER_OF(abrt, *dc, abrt);
+    STATE_AO_GC(dc->ao);
+
+    datacopier_callback(egc, dc, rc, -1, 0);
+}
+
 static void datacopier_readable(libxl__egc *egc, libxl__ev_fd *ev,
                                 int fd, short events, short revents) {
     libxl__datacopier_state *dc = CONTAINER_OF(ev, *dc, toread);
@@ -359,6 +370,11 @@ int libxl__datacopier_start(libxl__datacopier_state *dc)
     assert(dc->readfd >= 0 || dc->writefd >= 0);
     assert(!(dc->readbuf && dc->bytes_to_read == -1));
 
+    dc->abrt.ao = ao;
+    dc->abrt.callback = datacopier_abort;
+    rc = libxl__ao_abortable_register(&dc->abrt);
+    if (rc) goto out;
+
     if (dc->readfd >= 0) {
         rc = libxl__ev_fd_register(gc, &dc->toread, datacopier_readable,
                                    dc->readfd, POLLIN);
index 140725199ba9d310432e83ec264edc10bfec0615..d52589ee85b4c60594e8c8b0daa58cb0e8714f1c 100644 (file)
@@ -2657,6 +2657,7 @@ struct libxl__datacopier_state {
                       fd. The buffer should be at least as large as the
                       bytes_to_read parameter, which should not be -1. */
     /* remaining fields are private to datacopier */
+    libxl__ao_abortable abrt;
     libxl__ev_fd toread, towrite;
     ssize_t used;
     LIBXL_TAILQ_HEAD(libxl__datacopier_bufs, libxl__datacopier_buf) bufs;