[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 04 of 13 v5] blktap3/libblktapctl: Introduce listing running tapdisks functionality
This patch introduces tap-ctl-list.c, the file where listing tapdisks functionality is implemented. It is based on the existing blktap2 file with most changes coming from blktap2.5. I have not examined the changes in detail but it seems they are minor. Signed-off-by: Thanos Makatos <thanos.makatos@xxxxxxxxxx> --- Changed since v4: * Removed minor number. * Removed the message cookie from function _tap_ctl_find_tapdisks. * Removed the three-way merge between tapdisks, VBDs, and minor numbers from function _tap_ctl_find_tapdisks. diff --git a/tools/blktap3/control/tap-ctl-list.c b/tools/blktap3/control/tap-ctl-list.c new file mode 100644 --- /dev/null +++ b/tools/blktap3/control/tap-ctl-list.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2008, XenSource Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of XenSource Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <glob.h> + +#include "tap-ctl.h" +#include "blktap3.h" + +/** + * Allocates and initializes a tap_list_t. + */ +static tap_list_t * +_tap_list_alloc(void) +{ + const size_t sz = sizeof(tap_list_t); + tap_list_t *tl; + + tl = malloc(sz); + if (!tl) + return NULL; + + tl->pid = -1; + tl->state = -1; + tl->type = NULL; + tl->path = NULL; + + return tl; +} + +static void +_tap_list_free(tap_list_t * tl, struct tqh_tap_list *list) +{ + if (tl->type) { + free(tl->type); + tl->type = NULL; + } + + if (tl->path) { + free(tl->path); + tl->path = NULL; + } + + if (list) + TAILQ_REMOVE(list, tl, entry); + + free(tl); +} + +int +parse_params(const char *params, char **type, char **path) +{ + char *ptr; + size_t len; + + ptr = strchr(params, ':'); + if (!ptr) + return -EINVAL; + + len = ptr - params; + + *type = strndup(params, len); + *path = strdup(params + len + 1); + + if (!*type || !*path) { + free(*type); + *type = NULL; + + free(*path); + *path = NULL; + + return -errno; + } + + return 0; +} + +void +tap_ctl_list_free(struct tqh_tap_list *list) +{ + tap_list_t *tl, *n; + + tap_list_for_each_entry_safe(tl, n, list) + _tap_list_free(tl, list); +} + +/** + * Returns a list running tapdisks. tapdisks are searched for by looking for + * their control socket. + */ +static int +_tap_ctl_find_tapdisks(struct tqh_tap_list *list) +{ + glob_t glbuf = { 0 }; + const char *pattern, *format; + int err, i, n_taps = 0; + + pattern = BLKTAP3_CONTROL_DIR "/" BLKTAP3_CONTROL_SOCKET "*"; + format = BLKTAP3_CONTROL_DIR "/" BLKTAP3_CONTROL_SOCKET "%d"; + + TAILQ_INIT(list); + + err = glob(pattern, 0, NULL, &glbuf); + switch (err) { + case GLOB_NOMATCH: + goto done; + + case GLOB_ABORTED: + case GLOB_NOSPACE: + err = -errno; + EPRINTF("%s: glob failed: %s", pattern, strerror(err)); + goto fail; + } + + for (i = 0; i < glbuf.gl_pathc; ++i) { + tap_list_t *tl; + int n; + + tl = _tap_list_alloc(); + if (!tl) { + err = -ENOMEM; + goto fail; + } + + n = sscanf(glbuf.gl_pathv[i], format, &tl->pid); + if (n != 1) + goto skip; + + tl->pid = tap_ctl_get_pid(tl->pid); + if (tl->pid < 0) + goto skip; + + TAILQ_INSERT_TAIL(list, tl, entry); + n_taps++; + continue; + +skip: + _tap_list_free(tl, NULL); + } + +done: + err = 0; +out: + if (glbuf.gl_pathv) + globfree(&glbuf); + + return err ? : n_taps; + +fail: + tap_ctl_list_free(list); + goto out; +} + +/** + * Retrieves all the VBDs a tapdisk is serving. + * + * @param pid the process ID of the tapdisk whose VBDs should be retrieved + * @param list output parameter that receives the list of VBD + * @returns 0 on success, an error code otherwise + */ +static int +_tap_ctl_list_tapdisk(pid_t pid, struct tqh_tap_list *list) +{ + struct timeval timeout = {.tv_sec = 10,.tv_usec = 0 }; + tapdisk_message_t message; + tap_list_t *tl; + int err, sfd; + + err = tap_ctl_connect_id(pid, &sfd); + if (err) + return err; + + memset(&message, 0, sizeof(message)); + message.type = TAPDISK_MESSAGE_LIST; + + err = tap_ctl_write_message(sfd, &message, &timeout); + if (err) + return err; + + TAILQ_INIT(list); + + do { + err = tap_ctl_read_message(sfd, &message, &timeout); + if (err) { + err = -EPROTO; + goto fail; + } + + if (message.u.list.count == 0) + break; + + tl = _tap_list_alloc(); + if (!tl) { + err = -ENOMEM; + goto fail; + } + + tl->pid = pid; + tl->state = message.u.list.state; + + if (message.u.list.path[0] != 0) { + err = parse_params(message.u.list.path, &tl->type, &tl->path); + if (err) { + _tap_list_free(tl, NULL); + goto fail; + } + } + + TAILQ_INSERT_HEAD(list, tl, entry); + } while (1); + + err = 0; +out: + close(sfd); + return 0; + +fail: + tap_ctl_list_free(list); + goto out; +} + +int +tap_ctl_list(struct tqh_tap_list *list) +{ + struct tqh_tap_list tapdisks; + tap_list_t *tapdisk, *next_t; + int err; + + TAILQ_INIT(list); + + err = _tap_ctl_find_tapdisks(&tapdisks); + if (err < 0) { + EPRINTF("error finding tapdisks: %s\n", strerror(-err)); + goto out; + } + + tap_list_for_each_entry_safe(tapdisk, next_t, &tapdisks) { + struct tqh_tap_list vbds; + + err = _tap_ctl_list_tapdisk(tapdisk->pid, &vbds); + + if (!err) { + TAILQ_CONCAT(list, &vbds, entry); + } else { + EPRINTF("failed to get VBDs for tapdisk %d: %s\n", tapdisk->pid, + strerror(-err)); + /* TODO Return the error or just continue? */ + } + + _tap_list_free(tapdisk, &tapdisks); + } + +out: + tap_ctl_list_free(&tapdisks); + if (err) + tap_ctl_list_free(list); + return err; +} + +int +tap_ctl_list_pid(pid_t pid, struct tqh_tap_list *list) +{ + tap_list_t *t; + int err; + + t = _tap_list_alloc(); + if (!t) + return -ENOMEM; + + t->pid = tap_ctl_get_pid(pid); + if (t->pid < 0) { + _tap_list_free(t, NULL); + return 0; + } + + err = _tap_ctl_list_tapdisk(t->pid, list); + + if (err || TAILQ_EMPTY(list)) + TAILQ_INSERT_TAIL(list, t, entry); + + return 0; +} _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |