[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 04 of 15 v4] 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). Signed-off-by: Thanos Makatos <thanos.makatos@xxxxxxxxxx> 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 |