Provide a new function libxl_domain_rename. It can check that the
domain being renamed has the expected name, to avoid races.
Use the new function to set the name during domain creation.
Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
---
tools/libxl/libxl.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++-
tools/libxl/libxl.h | 6 ++++
2 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 308273d..59859ab 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -82,7 +82,7 @@ int libxl_ctx_set_log(struct libxl_ctx *ctx,
libxl_log_callback log_callback, vo
int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
uint32_t *domid)
{
- int flags, ret, i;
+ int flags, ret, i, rc;
char *uuid_string;
char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
@@ -146,7 +146,8 @@ retry_transaction:
xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path,
strlen(vm_path));
xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path,
strlen(vss_path));
- xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", dom_path), info->name,
strlen(info->name));
+ rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
+ if (rc) return rc;
for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
@@ -175,6 +176,84 @@ retry_transaction:
return 0;
}
+int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
+ const char *old_name, const char *new_name,
+ xs_transaction_t trans) {
+ char *dom_path = 0;
+ const char *name_path;
+ char *got_old_name;
+ unsigned int got_old_len;
+ xs_transaction_t our_trans = 0;
+ int rc;
+
+ dom_path = libxl_xs_get_dompath(ctx, domid);
+ if (!dom_path) goto x_nomem;
+
+ name_path= libxl_sprintf(ctx, "%s/name", dom_path);
+ if (!name_path) goto x_nomem;
+
+ retry_transaction:
+ if (!trans) {
+ trans = our_trans = xs_transaction_start(ctx->xsh);
+ if (!our_trans) {
+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
+ "create xs transaction for domain (re)name");
+ goto x_fail;
+ }
+ }
+
+ if (old_name) {
+ got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
+ if (!got_old_name) {
+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, "check old name"
+ " for domain %"PRIu32" allegedly named `%s'",
+ domid, old_name);
+ goto x_fail;
+ }
+ if (strcmp(old_name, got_old_name)) {
+ XL_LOG(ctx, XL_LOG_ERROR, "domain %"PRIu32" allegedly named "
+ "`%s' is actually named `%s' - racing ?",
+ domid, old_name, got_old_name);
+ free(got_old_name);
+ goto x_fail;
+ }
+ free(got_old_name);
+ }
+ if (!xs_write(ctx->xsh, trans, name_path,
+ new_name, strlen(new_name))) {
+ XL_LOG(ctx, XL_LOG_ERROR, "failed to write new name `%s'"
+ " for domain %"PRIu32" previously named `%s'",
+ domid, new_name, old_name);
+ goto x_fail;
+ }
+
+ if (our_trans) {
+ if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
+ trans = our_trans = 0;
+ if (errno != EAGAIN) {
+ XL_LOG(ctx, XL_LOG_ERROR, "failed to commit new name `%s'"
+ " for domain %"PRIu32" previously named `%s'",
+ domid, new_name, old_name);
+ goto x_fail;
+ }
+ XL_LOG(ctx, XL_LOG_DEBUG, "need to retry rename transaction"
+ " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")",
+ domid, name_path, new_name);
+ goto retry_transaction;
+ }
+ our_trans = 0;
+ }
+
+ rc = 0;
+ x_rc:
+ if (dom_path) libxl_free(ctx, dom_path);
+ if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
+ return rc;
+
+ x_fail: rc = ERROR_FAIL; goto x_rc;
+ x_nomem: rc = ERROR_NOMEM; goto x_rc;
+}
+
int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info,
uint32_t domid, libxl_domain_build_state *state)
{
char **vments = NULL, **localents = NULL;
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 84e412a..2d76087 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -296,6 +296,12 @@ int libxl_free_waiter(libxl_waiter *waiter);
int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, xc_domaininfo_t *info);
int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, libxl_device_disk *disk);
+int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
+ const char *old_name, const char *new_name,
+ xs_transaction_t trans);
+ /* if old_name is NULL, any old name is OK; otherwise we check
+ * transactionally that the domain has the old old name; if
+ * trans is not 0 we use caller's transaction and caller must do retries */
int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid);
int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
--
1.5.6.5
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|