diff options
author | Roger Pau Monne <roger.pau@entel.upc.edu> | 2011-11-02 17:06:04 +0000 |
---|---|---|
committer | Roger Pau Monne <roger.pau@entel.upc.edu> | 2011-11-02 17:06:04 +0000 |
commit | 331f2c59fdd7eaf575f7c3d75ce143d9aa6aaf7d (patch) | |
tree | 7e38de577e299bcc4e207a56a45fdf66b650fad7 /tools/libxl/libxl_device.c | |
parent | 93bf609a7782a612706e452a71913807ba28d22e (diff) | |
download | xen-331f2c59fdd7eaf575f7c3d75ce143d9aa6aaf7d.tar.gz xen-331f2c59fdd7eaf575f7c3d75ce143d9aa6aaf7d.tar.bz2 xen-331f2c59fdd7eaf575f7c3d75ce143d9aa6aaf7d.zip |
libxl: handle the return value of wait_for_dev_destroy select
Handle the return value of the select call inside wait_for_dev_destroy
properly, and return 0 if a device is removed, or ERROR_* if a timeout
or error happened. Use the return value of wait_for_dev_destroy inside
libxl__device_remove to properly return from that function.
Signed-off-by: Roger Pau Monne <roger.pau@entel.upc.edu>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl/libxl_device.c')
-rw-r--r-- | tools/libxl/libxl_device.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index 059545d495..a53fb70837 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -367,6 +367,10 @@ int libxl__device_disk_dev_number(const char *virtpath, int *pdisk, return -1; } +/* + * Returns 0 if a device is removed, ERROR_* if an error + * or timeout occurred. + */ static int wait_for_dev_destroy(libxl__gc *gc, struct timeval *tv) { libxl_ctx *ctx = libxl__gc_owner(gc); @@ -375,22 +379,41 @@ static int wait_for_dev_destroy(libxl__gc *gc, struct timeval *tv) fd_set rfds; char **l1 = NULL; +start: rc = 1; nfds = xs_fileno(ctx->xsh) + 1; FD_ZERO(&rfds); FD_SET(xs_fileno(ctx->xsh), &rfds); - if (select(nfds, &rfds, NULL, NULL, tv) > 0) { - l1 = xs_read_watch(ctx->xsh, &n); - if (l1 != NULL) { - char *state = libxl__xs_read(gc, XBT_NULL, l1[XS_WATCH_PATH]); - if (!state || atoi(state) == 6) { - xs_unwatch(ctx->xsh, l1[0], l1[1]); - xs_rm(ctx->xsh, XBT_NULL, l1[XS_WATCH_TOKEN]); - LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Destroyed device backend at %s", l1[XS_WATCH_TOKEN]); - rc = 0; + switch (select(nfds, &rfds, NULL, NULL, tv)) { + case -1: + if (errno == EINTR) + goto start; + rc = ERROR_FAIL; + break; + case 0: + rc = ERROR_TIMEDOUT; + break; + default: + l1 = xs_read_watch(ctx->xsh, &n); + if (l1 != NULL) { + char *state = libxl__xs_read(gc, XBT_NULL, + l1[XS_WATCH_PATH]); + if (!state || atoi(state) == 6) { + xs_unwatch(ctx->xsh, l1[0], l1[1]); + xs_rm(ctx->xsh, XBT_NULL, l1[XS_WATCH_TOKEN]); + LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, + "Destroyed device backend at %s", + l1[XS_WATCH_TOKEN]); + rc = 0; + } else { + /* State is not "disconnected", continue waiting... */ + goto start; + } + free(l1); + } else { + rc = ERROR_FAIL; } - free(l1); - } + break; } return rc; } @@ -436,7 +459,9 @@ retry_transaction: struct timeval tv; tv.tv_sec = LIBXL_DESTROY_TIMEOUT; tv.tv_usec = 0; - (void)wait_for_dev_destroy(gc, &tv); + rc = wait_for_dev_destroy(gc, &tv); + if (rc < 0) /* an error or timeout occurred, clear watches */ + xs_unwatch(ctx->xsh, state_path, be_path); xs_rm(ctx->xsh, XBT_NULL, libxl__device_frontend_path(gc, dev)); } else { rc = 1; /* Caller must wait_for_dev_destroy */ @@ -542,7 +567,8 @@ int libxl__devices_destroy(libxl__gc *gc, uint32_t domid, int force) tv.tv_sec = LIBXL_DESTROY_TIMEOUT; tv.tv_usec = 0; while (n_watches > 0) { - if (wait_for_dev_destroy(gc, &tv)) { + if (wait_for_dev_destroy(gc, &tv) < 0) { + /* function returned ERROR_* */ break; } else { n_watches--; |