[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 1/5] xenbus_walk - walk XenStore keys, calling callback.
This is quite similar to 'pci_walk_bus.' We walk the XenStore keys, starting at the initial path, calling the callback with each key that has a value. If the callback returns a negative value we stop, clean up, and return the value back. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> --- drivers/xen/xenbus/xenbus_xs.c | 130 ++++++++++++++++++++++++++++++++++++++++ include/xen/xenbus.h | 2 + 2 files changed, 132 insertions(+), 0 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index eab33f1..6a03d22 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -67,6 +67,13 @@ struct xs_stored_msg { } u; }; +/* Temporary structure used by xenbus_walk to collect all of the + * paths in a stack for traversing. */ +struct xs_data_tuple { + struct list_head list; + char *path; +}; + struct xs_handle { /* A list of replies. Currently only one will ever be outstanding. */ struct list_head reply_list; @@ -111,6 +118,35 @@ static pid_t xenwatch_pid; static DEFINE_MUTEX(xenwatch_mutex); static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq); +static struct xs_data_tuple *add_tuple(struct list_head *list, char *path) +{ + struct xs_data_tuple *data; + + data = kzalloc(sizeof(struct xs_data_tuple), GFP_KERNEL); + if (!data) { + printk(KERN_ERR "%s: could not allocate memory\n", __func__); + return NULL; + } + + data->path = path; + list_add_tail(&data->list, list); + + return data; +} + +static int free_tuple(struct xs_data_tuple *data) +{ + + if (!data) + return 0; + + kfree(data->path); + + kfree(data); + return 0; +} + + static int get_error(const char *errorstring) { unsigned int i; @@ -367,6 +403,100 @@ void *xenbus_read(struct xenbus_transaction t, } EXPORT_SYMBOL_GPL(xenbus_read); + +/* + * A traverse of XenStore directory using a stack based + * implementation. For each file the callback function + * is called with: + * cb(path, filename, value, userdata); + * + * Zero return value continues the walk, while any other + * exits and returns the value. The value passed in the callback + * are automatically free-d. + * + */ +int xenbus_walk(char *start_path, + int (*cb)(char *, char *, char *, void *), + void *userdata) +{ + + struct list_head list; + struct xs_data_tuple *tuple, *tmp; + char **dir; + char *newpath, *val; + unsigned int i, dir_n; + int rc = 0; + + if (!cb) + return -ENONET; + + if (!xenstored_ready) + return -EBUSY; + + INIT_LIST_HEAD(&list); + + /* Item added to the top. */ + newpath = kasprintf(GFP_KERNEL, "%s", start_path); + if (!add_tuple(&list, newpath)) + goto err_start; + + tuple = list_entry(&list, struct xs_data_tuple, list); + while (!list_empty(&list) && !rc) { + /* Pop first element. */ + tuple = list_entry(list.next, struct xs_data_tuple, list); + if (!tuple) + goto err_while; + list_del(&tuple->list); + /* And start listening 'em. */ + dir = xenbus_directory(XBT_NIL, tuple->path, "", &dir_n); + if (IS_ERR(dir)) { + /* This will happen on XenStore directories we don't + * have access to. (Like for other domains).*/ + free_tuple(tuple); + continue; + } + for (i = 0; i < dir_n; i++) { + if (tuple->path && + tuple->path[strlen(tuple->path)-1] != '/') { + val = xenbus_read(XBT_NIL, tuple->path, dir[i], + NULL); + if (!IS_ERR(val)) { + /* Same thing as with xenbus_directory. + * Some values are protected.*/ + rc = cb(tuple->path, dir[i], + val, userdata); + kfree(val); + } + } + if (rc) + break; + newpath = kasprintf(GFP_KERNEL, "%s%s%s", tuple->path, + tuple->path[strlen(tuple->path)-1] == + '/' ? "" : "/", + dir[i]); + + if (!newpath) + goto err_loop; + if (!add_tuple(&list, newpath)) + goto err_loop; + } + kfree(dir); + free_tuple(tuple); + } + goto err_while; +err_loop: + kfree(dir); +err_start: + kfree(newpath); +err_while: + list_for_each_entry_safe(tuple, tmp, &list, list) { + list_del(&tuple->list); + free_tuple(tuple); + } + return rc; +} +EXPORT_SYMBOL_GPL(xenbus_walk); + /* Write the value of a single file. * Returns -err on failure. */ diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index 542ca7c..84dc8b0 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -229,4 +229,6 @@ const char *xenbus_strstate(enum xenbus_state state); int xenbus_dev_is_online(struct xenbus_device *dev); int xenbus_frontend_closed(struct xenbus_device *dev); +int xenbus_walk(char *start_path, int (*cb)(char *, char *, char *, void *), + void *userdata); #endif /* _XEN_XENBUS_H */ -- 1.6.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |