[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


 


Rackspace

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