|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 04 of 13 v6] 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 |