[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 11/15] tools/helpers: Add get_overlay
From: Vikram Garhwal <fnu.vikram@xxxxxxxxxx> This user level application copies the overlay dtbo shared by dom0 while doing overlay node assignment operation. It uses xenstore to communicate with dom0. More information on the protocol is writtien in docs/misc/overlay.txt file. Signed-off-by: Vikram Garhwal <fnu.vikram@xxxxxxxxxx> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx> Signed-off-by: Henry Wang <xin.wang2@xxxxxxx> --- tools/helpers/Makefile | 8 + tools/helpers/get_overlay.c | 393 ++++++++++++++++++++++++++++++++++++ 2 files changed, 401 insertions(+) create mode 100644 tools/helpers/get_overlay.c diff --git a/tools/helpers/Makefile b/tools/helpers/Makefile index 09590eb5b6..dfe17ef269 100644 --- a/tools/helpers/Makefile +++ b/tools/helpers/Makefile @@ -12,6 +12,7 @@ TARGETS += init-xenstore-domain endif ifeq ($(CONFIG_ARM),y) TARGETS += init-dom0less +TARGETS += get_overlay endif endif @@ -39,6 +40,9 @@ $(INIT_DOM0LESS_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(INIT_DOM0LESS_OBJS): CFLAGS += $(CFLAGS_libxenevtchn) init-dom0less: LDLIBS += $(call xenlibs-ldlibs,ctrl evtchn toollog store light guest foreignmemory) +SHARE_OVERLAY_OBJS = get_overlay.o +$(SHARE_OVERLAY_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxenstore) $(CFLAGS_libxenctrl) + .PHONY: all all: $(TARGETS) @@ -51,6 +55,10 @@ init-xenstore-domain: $(INIT_XENSTORE_DOMAIN_OBJS) init-dom0less: $(INIT_DOM0LESS_OBJS) $(CC) $(LDFLAGS) -o $@ $(INIT_DOM0LESS_OBJS) $(LDLIBS) $(APPEND_LDFLAGS) +get_overlay: $(SHARE_OVERLAY_OBJS) + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenvchan) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxengnttab) $(APPEND_LDFLAGS) + + .PHONY: install install: all $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN) diff --git a/tools/helpers/get_overlay.c b/tools/helpers/get_overlay.c new file mode 100644 index 0000000000..ca3007570e --- /dev/null +++ b/tools/helpers/get_overlay.c @@ -0,0 +1,393 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <xenstore.h> +#include <libxenvchan.h> +#include <xengnttab.h> + +#define PAGE_SIZE 4096 + +static int xs_create_overlay_node(int domain, const char *xs_base, + struct xs_handle *xs) +{ + int ret = -1; + struct xs_permissions perms[2]; + char buf[64]; + char ref[16]; + char *domid_str = NULL; + int overlay_size = 0; + + xs_transaction_t xs_trans = XBT_NULL; + + domid_str = xs_read(xs, XBT_NULL, "domid", NULL); + + if (!domid_str) + return ret; + + /* owner domain is us */ + perms[0].id = atoi(domid_str); + /* permissions for domains not listed = none. */ + perms[0].perms = XS_PERM_NONE; + /* other domains i.e. domain provided by user gets r/w permissions. */ + perms[1].id = domain; + perms[1].perms = XS_PERM_READ | XS_PERM_WRITE; + +retry_transaction: + + xs_trans = xs_transaction_start(xs); + if (!xs_trans) + goto fail_xs_transaction; + + /* Create overlay-size node. */ + snprintf(ref, sizeof(ref), "%d", overlay_size); + snprintf(buf, sizeof(buf), "%s/overlay-size", xs_base); + + if (!xs_write(xs, xs_trans, buf, ref, strlen(ref))) + goto fail_xs_transaction; + if (!xs_set_permissions(xs, xs_trans, buf, perms, 2)) + goto fail_xs_transaction; + + /* Create domU status node. */ + snprintf(ref, sizeof(ref), "%s", "waiting"); + snprintf(buf, sizeof(buf), "%s/receiver-status", xs_base); + + if (!xs_write(xs, xs_trans, buf, ref, strlen(ref))) + goto fail_xs_transaction; + if (!xs_set_permissions(xs, xs_trans, buf, perms, 2)) + goto fail_xs_transaction; + + /* Create dom0 status node. */ + snprintf(ref, sizeof(ref), "%s", "not_ready"); + snprintf(buf, sizeof(buf), "%s/sender-status", xs_base); + + if (!xs_write(xs, xs_trans, buf, ref, strlen(ref))) + goto fail_xs_transaction; + if (!xs_set_permissions(xs, xs_trans, buf, perms, 2)) + goto fail_xs_transaction; + + if (!xs_transaction_end(xs, xs_trans, 0)) { + if (errno == EAGAIN) + goto retry_transaction; + else + goto fail_xs_transaction; + } else + ret = 0; + +fail_xs_transaction: + free(domid_str); + + return ret; +} + +static int get_overlay_size(struct xs_handle *xs, int domain, + const char *xs_path) +{ + char buf[128]; + char *ref; + unsigned int len; + int dt_size = 0; + + snprintf(buf, sizeof(buf), "%s/overlay-size", xs_path); + + ref = xs_read(xs, XBT_NULL, buf, &len); + + if (!ref) + return dt_size; + + dt_size = atoi(ref); + + free(ref); + + return dt_size; +} + +static uint32_t get_num_pages(int dtbo_size) +{ + int num_pages = 1; + + while (dtbo_size > PAGE_SIZE) { + dtbo_size = dtbo_size - PAGE_SIZE; + num_pages++; + } + + return num_pages; +} + +static void *create_shared_buffer(int domain, uint32_t *refs, uint32_t pages, + xengntshr_handle *gntshr) +{ + return xengntshr_share_pages(gntshr, domain, pages, refs, 1); +} + +static bool wait_for_status(struct xs_handle *xs, int fd, char *status_path, + const char *status) +{ + unsigned int num_strings; + char *buf = NULL; + char **vec = NULL; + bool ret = false; + unsigned int len; + int rc = 0; + fd_set set; + + while (1) + { + FD_ZERO(&set); + FD_SET(fd, &set); + + rc = select(fd + 1, &set, NULL, NULL, NULL); + /* Poll for data: Blocking. */ + if (rc <= 0) + break; + + if (FD_ISSET(fd, &set)) { + /* + * num_strings will be set to the number of elements in vec + * (2 - the watched path and the overlay_watch) + */ + vec = xs_read_watch(xs, &num_strings); + if (!vec) { + break; + } + + /* do a read. */ + buf = xs_read(xs, XBT_NULL, status_path, &len); + if (buf) { + if (!strcmp(buf, status)) { + ret = true; + break; + } + } + } + } + + free(vec); + free(buf); + + return ret; +} + +static bool write_page_ref(struct xs_handle *xs, uint32_t *page_ref, + uint32_t num_pages, char *path) +{ + xs_transaction_t xs_trans = XBT_NULL; + char buf[128]; + char *ref = NULL; + char tmp[16]; + int i = 0; + bool rc = false; + + /* Caller will free this. */ + ref = (char *)calloc(num_pages * 16, sizeof(char)); /* For each number. */ + if (ref == NULL) { + fprintf(stderr, "Memory calloc for ref failed\n"); + return rc; + } + +retry_transaction: + xs_trans = xs_transaction_start(xs); + if (!xs_trans) + goto out; + + for (i = 0; i < num_pages; i++) { + snprintf(tmp, sizeof(tmp), "%d,", page_ref[i]); + strcat(ref, tmp); + } + + snprintf(buf, sizeof(buf), "%s/page-ref", path); + + if (!xs_write(xs, xs_trans, buf, ref, strlen(ref))) + goto out; + + snprintf(buf, sizeof(buf), "%s/num-pages", path); + snprintf(tmp, sizeof(tmp), "%u", num_pages); + if (!xs_write(xs, xs_trans, buf, tmp, strlen(tmp))) + goto out; + + if (!xs_transaction_end(xs, xs_trans, 0)) { + if (errno == EAGAIN) + goto retry_transaction; + else + goto out; + } + + rc = true; + +out: + if (ref) + free(ref); + + return rc; +} + +static bool write_status(struct xs_handle *xs, const char *status, + const char *status_path) +{ + xs_transaction_t xs_trans = XBT_NULL; + +retry_transaction: + xs_trans = xs_transaction_start(xs); + if (!xs_trans) + return false; + + if (!xs_write(xs, xs_trans, status_path, status, strlen(status))) + return false; + + if (!xs_transaction_end(xs, xs_trans, 0)) { + if (errno == EAGAIN) + goto retry_transaction; + else + return false; + } + + return true; +} + +int main(int argc, char **argv) +{ + void *buffer = NULL; + int domain ; + uint32_t *page_refs = NULL; + FILE *fptr; + int dtbo_size = 0; + const char *path = "data/overlay"; + char receiver_status_path[64] = { }; + char sender_status_path[64] = { }; + struct xs_handle *xs = NULL; + int rc = 0; + int fd = 0; + uint32_t num_pages = 0; + xengntshr_handle *gntshr; + + if (argc < 2) { + fprintf(stderr,"Please enter domain_id.\n"); + return 0; + } + + domain = atoi(argv[1]); + + xs = xs_open(0); + if (xs == NULL) { + fprintf(stderr, "Xenstore open for domain%d failed\n", domain); + goto out; + } + + rc = xs_create_overlay_node(domain, path, xs); + if (rc) { + fprintf(stderr,"Creating overlay nodes failed\n"); + goto out; + } + + strcpy(receiver_status_path, path); + strcat(receiver_status_path, "/receiver-status"); + + strcpy(sender_status_path, path); + strcat(sender_status_path, "/sender-status"); + + /* + * Watch a node for changes (poll on fd to detect). + * When the node changes, fd will become readable. + */ + rc = xs_watch(xs, sender_status_path, "overlay_watch"); + if (rc == 0) { + fprintf(stderr, "Creating watch failed\n"); + goto out; + } + + /* We are notified of read availability on the watch via the + * file descriptor. + */ + fd = xs_fileno(xs); + + /* Wait for ready. */ + if (!wait_for_status(xs, fd, sender_status_path, "ready")) { + fprintf(stderr, "dom0 not ready.\n"); + goto out; + } + + dtbo_size = get_overlay_size(xs, domain, path); + if (dtbo_size == 0) { + fprintf(stderr,"Overlay data size is zero. Exiting the application\n"); + goto out; + } + + gntshr = xengntshr_open(NULL, 0); + if (!gntshr) { + fprintf(stderr,"Error in opening gntshr\n"); + goto out; + } + + num_pages = get_num_pages(dtbo_size); + + page_refs =(uint32_t *)malloc(num_pages * sizeof(int)); + if (page_refs == NULL) { + fprintf(stderr, "Allocating page_ref array failed\n"); + goto out; + } + + /* Allocate memory for data size and share with domain. */ + buffer = create_shared_buffer(domain, page_refs, num_pages, + gntshr); + if (buffer == NULL) { + fprintf(stderr,"Buffer allocation failed\n"); + goto out; + } + + /* Created the buffer and got page_ref. Share the page_ref with domain. */ + if (!write_page_ref(xs, page_refs, num_pages, path)) { + fprintf(stderr,"Writing page ref failed\n"); + goto out; + } + + /* Write the status "page_ref". */ + if (!write_status(xs, "page_ref", receiver_status_path)) { + fprintf(stderr,"Writing status DONE failed\n"); + goto out; + } + + /* Wait for done. This means other domain done copying the dtb to buffer. */ + if (!wait_for_status(xs, fd, sender_status_path, "done")) { + fprintf(stderr, "dom0 status not done\n"); + goto out; + } + + if ((fptr = fopen("overlay.dtbo","wb")) == NULL) { + fprintf(stderr,"Error! opening file"); + goto out; + } + + printf("Writing to file overlay.dtbo.\n"); + + fwrite(buffer, dtbo_size, 1, fptr); + + printf("Done writing to file overlay.dtbo \n"); + +out: + if (fptr) + fclose(fptr); + + if (page_refs) + free(page_refs); + + if (xs) { + close(fd); + + xs_unwatch(xs, path, "overlay_watch"); + + xs_close(xs); + } + + if (buffer) + xengntshr_unshare(gntshr, buffer, num_pages); + + if (gntshr) + xengntshr_close(gntshr); + + return 0; +} -- 2.34.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |