WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1/5] xenbus_walk - walk XenStore keys, calling callba

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1/5] xenbus_walk - walk XenStore keys, calling callback.
From: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Date: Thu, 5 Nov 2009 15:25:40 -0500
Cc: Jeremy Fitzhardinge <jeremy@xxxxxxxx>, Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Delivery-date: Thu, 05 Nov 2009 12:31:57 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1257452744-18243-1-git-send-email-konrad.wilk@xxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1257452744-18243-1-git-send-email-konrad.wilk@xxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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