[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.