|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4 of 9 RFC v2] 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 living in github. I have not examined the
changes in detail but it seems they are minor.
Function tap_ctl_list needs to be amended because minors are not retrieved
from sysfs (there's no sysfs blktap directory any more).
diff --git a/tools/blktap2/control/tap-ctl-list.c
b/tools/blktap3/control/tap-ctl-list.c
copy from tools/blktap2/control/tap-ctl-list.c
copy to tools/blktap3/control/tap-ctl-list.c
--- a/tools/blktap2/control/tap-ctl-list.c
+++ b/tools/blktap3/control/tap-ctl-list.c
@@ -34,23 +34,47 @@
#include <glob.h>
#include "tap-ctl.h"
-#include "blktap2.h"
-#include "list.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->minor = -1;
+ tl->state = -1;
+ tl->type = NULL;
+ tl->path = NULL;
+
+ return tl;
+}
static void
-free_list(tap_list_t *entry)
+_tap_list_free(tap_list_t * tl, struct tqh_tap_list *list)
{
- if (entry->type) {
- free(entry->type);
- entry->type = NULL;
+ if (tl->type) {
+ free(tl->type);
+ tl->type = NULL;
}
- if (entry->path) {
- free(entry->path);
- entry->path = NULL;
+ if (tl->path) {
+ free(tl->path);
+ tl->path = NULL;
}
- free(entry);
+ if (list)
+ TAILQ_REMOVE(list, tl, entry);
+
+ free(tl);
}
int
@@ -66,7 +90,7 @@ int
len = ptr - params;
*type = strndup(params, len);
- *path = strdup(params + len + 1);
+ *path = strdup(params + len + 1);
if (!*type || !*path) {
free(*type);
@@ -81,102 +105,26 @@ int
return 0;
}
-static int
-init_list(tap_list_t *entry,
- int tap_id, pid_t tap_pid, int vbd_minor, int vbd_state,
- const char *params)
+void
+tap_ctl_list_free(struct tqh_tap_list *list)
{
- int err = 0;
+ tap_list_t *tl, *n;
- entry->id = tap_id;
- entry->pid = tap_pid;
- entry->minor = vbd_minor;
- entry->state = vbd_state;
-
- if (params)
- err = _parse_params(params, &entry->type, &entry->path);
-
- return err;
-}
-
-void
-tap_ctl_free_list(tap_list_t **list)
-{
- tap_list_t **_entry;
-
- for (_entry = list; *_entry != NULL; ++_entry)
- free_list(*_entry);
-
- free(list);
-}
-
-static tap_list_t**
-tap_ctl_alloc_list(int n)
-{
- tap_list_t **list, *entry;
- size_t size;
- int i;
-
- size = sizeof(tap_list_t*) * (n+1);
- list = malloc(size);
- if (!list)
- goto fail;
-
- memset(list, 0, size);
-
- for (i = 0; i < n; ++i) {
- tap_list_t *entry;
-
- entry = malloc(sizeof(tap_list_t));
- if (!entry)
- goto fail;
-
- memset(entry, 0, sizeof(tap_list_t));
-
- list[i] = entry;
- }
-
- return list;
-
-fail:
- if (list)
- tap_ctl_free_list(list);
-
- return NULL;
-}
-
-static int
-tap_ctl_list_length(const tap_list_t **list)
-{
- const tap_list_t **_entry;
- int n;
-
- n = 0;
- for (_entry = list; *_entry != NULL; ++_entry)
- n++;
-
- return n;
-}
-
-static int
-_tap_minor_cmp(const void *a, const void *b)
-{
- return *(int*)a - *(int*)b;
+ tap_list_for_each_entry_safe(tl, n, list)
+ _tap_list_free(tl, list);
}
int
-_tap_ctl_find_minors(int **_minorv)
+_tap_ctl_find_tapdisks(struct tqh_tap_list *list)
{
- glob_t glbuf = { 0 };
+ glob_t glbuf = { 0 };
const char *pattern, *format;
- int *minorv = NULL, n_minors = 0;
- int err, i;
+ int err, i, n_taps = 0;
- pattern = BLKTAP2_SYSFS_DIR"/blktap*";
- format = BLKTAP2_SYSFS_DIR"/blktap%d";
+ pattern = BLKTAP3_CONTROL_DIR "/" BLKTAP3_CONTROL_SOCKET "*";
+ format = BLKTAP3_CONTROL_DIR "/" BLKTAP3_CONTROL_SOCKET "%d";
- n_minors = 0;
- minorv = NULL;
+ TAILQ_INIT(list);
err = glob(pattern, 0, NULL, &glbuf);
switch (err) {
@@ -186,337 +134,231 @@ int
case GLOB_ABORTED:
case GLOB_NOSPACE:
err = -errno;
- EPRINTF("%s: glob failed, err %d", pattern, err);
- goto fail;
- }
-
- minorv = malloc(sizeof(int) * glbuf.gl_pathc);
- if (!minorv) {
- 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;
- n = sscanf(glbuf.gl_pathv[i], format, &minorv[n_minors]);
+ tl = _tap_list_alloc();
+ if (!tl) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ n = sscanf(glbuf.gl_pathv[i], format, &tl->pid);
if (n != 1)
- continue;
+ goto skip;
- n_minors++;
+ 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);
}
- qsort(minorv, n_minors, sizeof(int), _tap_minor_cmp);
-
-done:
- *_minorv = minorv;
+ done:
err = 0;
-
-out:
- if (glbuf.gl_pathv)
- globfree(&glbuf);
-
- return err ? : n_minors;
-
-fail:
- if (minorv)
- free(minorv);
-
- goto out;
-}
-
-struct tapdisk {
- int id;
- pid_t pid;
- struct list_head list;
-};
-
-static int
-_tap_tapdisk_cmp(const void *a, const void *b)
-{
- return ((struct tapdisk*)a)->id - ((struct tapdisk*)b)->id;
-}
-
-int
-_tap_ctl_find_tapdisks(struct tapdisk **_tapv)
-{
- glob_t glbuf = { 0 };
- const char *pattern, *format;
- struct tapdisk *tapv = NULL;
- int err, i, n_taps = 0;
-
- pattern = BLKTAP2_CONTROL_DIR"/"BLKTAP2_CONTROL_SOCKET"*";
- format = BLKTAP2_CONTROL_DIR"/"BLKTAP2_CONTROL_SOCKET"%d";
-
- n_taps = 0;
- tapv = NULL;
-
- 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, err %d", pattern, err);
- goto fail;
- }
-
- tapv = malloc(sizeof(struct tapdisk) * glbuf.gl_pathc);
- if (!tapv) {
- err = -errno;
- goto fail;
- }
-
- for (i = 0; i < glbuf.gl_pathc; ++i) {
- struct tapdisk *tap;
- int n;
-
- tap = &tapv[n_taps];
-
- err = sscanf(glbuf.gl_pathv[i], format, &tap->id);
- if (err != 1)
- continue;
-
- tap->pid = tap_ctl_get_pid(tap->id);
- if (tap->pid < 0)
- continue;
-
- n_taps++;
- }
-
- qsort(tapv, n_taps, sizeof(struct tapdisk), _tap_tapdisk_cmp);
-
- for (i = 0; i < n_taps; ++i)
- INIT_LIST_HEAD(&tapv[i].list);
-
-done:
- *_tapv = tapv;
- err = 0;
-
-out:
+ out:
if (glbuf.gl_pathv)
globfree(&glbuf);
return err ? : n_taps;
-fail:
- if (tapv)
- free(tapv);
-
+ fail:
+ tap_ctl_list_free(list);
goto out;
}
-struct tapdisk_list {
- int minor;
- int state;
- char *params;
- struct list_head entry;
-};
-
-int
-_tap_ctl_list_tapdisk(int id, struct list_head *_list)
+/**
+ * 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;
- struct list_head list;
- struct tapdisk_list *tl, *next;
+ tap_list_t *tl;
int err, sfd;
- err = tap_ctl_connect_id(id, &sfd);
+ err = tap_ctl_connect_id(pid, &sfd);
if (err)
return err;
memset(&message, 0, sizeof(message));
- message.type = TAPDISK_MESSAGE_LIST;
+ message.type = TAPDISK_MESSAGE_LIST;
message.cookie = -1;
- err = tap_ctl_write_message(sfd, &message, 2);
+ err = tap_ctl_write_message(sfd, &message, &timeout);
if (err)
return err;
- INIT_LIST_HEAD(&list);
+ TAILQ_INIT(list);
+
do {
- err = tap_ctl_read_message(sfd, &message, 2);
+ err = tap_ctl_read_message(sfd, &message, &timeout);
if (err) {
err = -EPROTO;
- break;
+ goto fail;
}
if (message.u.list.count == 0)
break;
- tl = malloc(sizeof(struct tapdisk_list));
+ tl = _tap_list_alloc();
if (!tl) {
err = -ENOMEM;
- break;
+ goto fail;
}
- tl->minor = message.u.list.minor;
- tl->state = message.u.list.state;
+ tl->pid = pid;
+ tl->minor = message.u.list.minor;
+ tl->state = message.u.list.state;
+
if (message.u.list.path[0] != 0) {
- tl->params = strndup(message.u.list.path,
- sizeof(message.u.list.path));
- if (!tl->params) {
- err = -errno;
- break;
+ err = _parse_params(message.u.list.path, &tl->type,
&tl->path);
+ if (err) {
+ _tap_list_free(tl, NULL);
+ goto fail;
}
- } else
- tl->params = NULL;
+ }
- list_add(&tl->entry, &list);
+ TAILQ_INSERT_HEAD(list, tl, entry);
} while (1);
- if (err)
- list_for_each_entry_safe(tl, next, &list, entry) {
- list_del(&tl->entry);
- free(tl->params);
- free(tl);
- }
+ err = 0;
+ out:
+ close(sfd);
+ return 0;
- close(sfd);
- list_splice(&list, _list);
- return err;
-}
-
-void
-_tap_ctl_free_tapdisks(struct tapdisk *tapv, int n_taps)
-{
- struct tapdisk *tap;
-
- for (tap = tapv; tap < &tapv[n_taps]; ++tap) {
- struct tapdisk_list *tl, *next;
-
- list_for_each_entry_safe(tl, next, &tap->list, entry) {
- free(tl->params);
- free(tl);
- }
- }
-
- free(tapv);
+ fail:
+ tap_ctl_list_free(list);
+ goto out;
}
int
-_tap_list_join3(int n_minors, int *minorv, int n_taps, struct tapdisk *tapv,
- tap_list_t ***_list)
+tap_ctl_list(struct tqh_tap_list *list)
{
- tap_list_t **list, **_entry, *entry;
- int i, _m, err;
+ struct tqh_tap_list minors, tapdisks, vbds;
+ tap_list_t *t, *next_t, *v, *next_v, *m, *next_m;
+ int err;
- list = tap_ctl_alloc_list(n_minors + n_taps);
- if (!list) {
- err = -ENOMEM;
+ /*
+ * Find all minors, find all tapdisks, then list all minors
+ * they attached to. Output is a 3-way outer join.
+ */
+ TAILQ_INIT(&minors);
+
+ /*
+ * TODO There's no blktap sysfs entry anymore, get rid of minors and
+ * rationalise the rest of this function.
+ */
+#if 0
+ err = _tap_ctl_find_minors(&minors);
+ if (err < 0) {
+ EPRINTF("error finding minors: %s\n", strerror(err));
+ goto fail;
+ }
+#endif
+
+ err = _tap_ctl_find_tapdisks(&tapdisks);
+ if (err < 0) {
+ EPRINTF("error finding tapdisks: %s\n", strerror(err));
goto fail;
}
- _entry = list;
+ TAILQ_INIT(list);
- for (i = 0; i < n_taps; ++i) {
- struct tapdisk *tap = &tapv[i];
- struct tapdisk_list *tl;
+ tap_list_for_each_entry_safe(t, next_t, &tapdisks) {
- /* orphaned tapdisk */
- if (list_empty(&tap->list)) {
- err = init_list(*_entry++, tap->id, tap->pid, -1, -1,
NULL);
- if (err)
- goto fail;
+ err = _tap_ctl_list_tapdisk(t->pid, &vbds);
+
+ /*
+ * TODO Don't just swallow the error, print a warning, at least.
+ */
+ if (err || TAILQ_EMPTY(&vbds)) {
+ TAILQ_MOVE_TAIL(t, &tapdisks, list, entry);
continue;
}
- list_for_each_entry(tl, &tap->list, entry) {
+ tap_list_for_each_entry_safe(v, next_v, &vbds) {
- err = init_list(*_entry++,
- tap->id, tap->pid,
- tl->minor, tl->state, tl->params);
- if (err)
- goto fail;
+ tap_list_for_each_entry_safe(m, next_m, &minors)
+ if (m->minor == v->minor) {
+ _tap_list_free(m, &minors);
+ break;
+ }
- if (tl->minor >= 0) {
- /* clear minor */
- for (_m = 0; _m < n_minors; ++_m) {
- if (minorv[_m] == tl->minor) {
- minorv[_m] = -1;
- break;
- }
- }
- }
+ TAILQ_MOVE_TAIL(v, &vbds, list, entry);
}
+
+ _tap_list_free(t, &tapdisks);
}
/* orphaned minors */
- for (_m = 0; _m < n_minors; ++_m) {
- int minor = minorv[_m];
- if (minor >= 0) {
- err = init_list(*_entry++, -1, -1, minor, -1, NULL);
- if (err)
- goto fail;
- }
- }
-
- /* free extraneous list entries */
- for (; *_entry != NULL; ++entry) {
- free_list(*_entry);
- *_entry = NULL;
- }
-
- *_list = list;
+ TAILQ_CONCAT(list, &minors, entry);
return 0;
fail:
- if (list)
- tap_ctl_free_list(list);
+ tap_ctl_list_free(list);
+
+ tap_ctl_list_free(&vbds);
+ tap_ctl_list_free(&tapdisks);
+ tap_ctl_list_free(&minors);
return err;
}
int
-tap_ctl_list(tap_list_t ***list)
+tap_ctl_list_pid(pid_t pid, struct tqh_tap_list *list)
{
- int n_taps, n_minors, err, *minorv;
- struct tapdisk *tapv, *tap;
+ tap_list_t *t;
+ int err;
- n_taps = -1;
- n_minors = -1;
+ t = _tap_list_alloc();
+ if (!t)
+ return -ENOMEM;
- err = n_minors = _tap_ctl_find_minors(&minorv);
- if (err < 0)
- goto out;
-
- err = n_taps = _tap_ctl_find_tapdisks(&tapv);
- if (err < 0)
- goto out;
-
- for (tap = tapv; tap < &tapv[n_taps]; ++tap) {
- err = _tap_ctl_list_tapdisk(tap->id, &tap->list);
- if (err)
- goto out;
+ t->pid = tap_ctl_get_pid(pid);
+ if (t->pid < 0) {
+ _tap_list_free(t, NULL);
+ return 0;
}
- err = _tap_list_join3(n_minors, minorv, n_taps, tapv, list);
+ err = _tap_ctl_list_tapdisk(t->pid, list);
-out:
- if (n_taps > 0)
- _tap_ctl_free_tapdisks(tapv, n_taps);
+ if (err || TAILQ_EMPTY(list))
+ TAILQ_INSERT_TAIL(list, t, entry);
- if (n_minors > 0)
- free(minorv);
-
- return err;
+ return 0;
}
int
-tap_ctl_find(const char *type, const char *path, tap_list_t *tap)
+tap_ctl_find_minor(const char *type, const char *path)
{
- tap_list_t **list, **_entry;
- int ret = -ENOENT, err;
+ struct tqh_tap_list list = TAILQ_HEAD_INITIALIZER(list);
+ tap_list_t *entry;
+ int minor, err;
err = tap_ctl_list(&list);
if (err)
return err;
- for (_entry = list; *_entry != NULL; ++_entry) {
- tap_list_t *entry = *_entry;
+ minor = -1;
+
+ tap_list_for_each_entry(entry, &list) {
if (type && (!entry->type || strcmp(entry->type, type)))
continue;
@@ -524,13 +366,11 @@ tap_ctl_find(const char *type, const cha
if (path && (!entry->path || strcmp(entry->path, path)))
continue;
- *tap = *entry;
- tap->type = tap->path = NULL;
- ret = 0;
+ minor = entry->minor;
break;
}
- tap_ctl_free_list(list);
+ tap_ctl_list_free(&list);
- return ret;
+ return minor >= 0 ? minor : -ENOENT;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |