[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [Xen-devel] [PATCH][RFC] permit domU userspace to watch xenstore



On Fri, 2006-08-04 at 13:48 -0700, Cihula, Joseph wrote:
> Michael,
...
> I realize that working code is worth more than a proposal, but perhaps
> you could see if the advantages of this approach might be worth a little
> re-coding.
> 

Thanks for the suggestions, I'll see what I can do to fit them in.

> Joe
> 
> On Wednesday, August 02, 2006 5:18 AM,  Michael LeMay <> wrote:
> 
> > Hello,
> > 
> > This patch allows userspace tools on a domU to setup a watch on
> > the xenstore.  It does this by intercepting XS_WATCH requests written
> > to /proc/xen/xenbus and then re-submitting the request to the
> > in-kernel 
> > xenstore interface, in
> > linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c.  When a callback
> > occurs, an in-kernel function is invoked, which then reconstructs a
> > response in the format expected by userspace, and sends this response
> > through /proc/xen/xenbus.
> > 
> > It was necessary to add some supporting infrastructure to
> > linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c, such as an
> > additional mutex to protect the response queue and a list of active
> > watches associated with each connection.
> > 
> > 
> > Signed-off-by: Michael LeMay <mdlemay@xxxxxxxxxxxxxx>
> > 
> > ---
> > 
> >  linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c |  114
> >  +++++++++++++++++++ 1 file changed, 114 insertions(+)
> > 
> > diff -r eb8083d63198 -r 0c8a22ad7e46
> > linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c ---
> > a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c      Tue Aug
> 01
> > 10:52:02 2006 -0400 +++
> >     b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c  Wed Aug
> 02
> >     08:20:06 2006 -0400 @@ -58,6 +58,9 @@ struct xenbus_dev_data {
> /*
> > In-progress transaction. */ struct list_head transactions; 
> > 
> > +   /* Active watches. */
> > +   struct list_head watches;
> > +
> >     /* Partial request. */
> >     unsigned int len;
> >     union {
> > @@ -70,6 +73,8 @@ struct xenbus_dev_data {
> >     char read_buffer[PAGE_SIZE];
> >     unsigned int read_cons, read_prod;
> >     wait_queue_head_t read_waitq;
> > +
> > +   struct mutex reply_mutex;
> >  };
> > 
> >  static struct proc_dir_entry *xenbus_dev_intf;
> > @@ -100,13 +105,59 @@ static void queue_reply(struct xenbus_de
> >  {
> >     int i;
> > 
> > +   mutex_lock(&u->reply_mutex);
> > +
> >     for (i = 0; i < len; i++, u->read_prod++)
> >             u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
> > 
> >     BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
> > 
> > +   mutex_unlock(&u->reply_mutex);
> > +
> >     wake_up(&u->read_waitq);
> >  }
> > +
> > +struct watch_adapter
> > +{
> > +   struct list_head list;
> > +   struct xenbus_watch watch;
> > +   struct xenbus_dev_data *dev_data;
> > +   char *token;
> > +};
> > +
> > +static void free_watch_adapter (struct watch_adapter *watch)
> > +{
> > +   kfree(watch->watch.node);
> > +   kfree(watch->token);
> > +   kfree(watch);
> > +}
> > +
> > +static void watch_fired(struct xenbus_watch *watch,
> > +                   const char **vec,
> > +                   unsigned int len)
> > +{
> > +   struct watch_adapter *adap =
> > +            container_of(watch, struct watch_adapter, watch);
> > +   struct xsd_sockmsg hdr;
> > +   const char *path, *token;
> > +   int path_len, tok_len, body_len;
> > +
> > +   path = vec[XS_WATCH_PATH];
> > +   token = adap->token;
> > +
> > +   path_len = strlen(path) + 1;
> > +   tok_len = strlen(token) + 1;
> > +   body_len = path_len + tok_len;
> > +
> > +   hdr.type = XS_WATCH_EVENT;
> > +   hdr.len = body_len;
> > +
> > +   queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
> > +   queue_reply(adap->dev_data, (char *)path, path_len);
> > +   queue_reply(adap->dev_data, (char *)token, tok_len);
> > +}
> > +
> > +static LIST_HEAD(watch_list);
> > 
> >  static ssize_t xenbus_dev_write(struct file *filp,
> >                             const char __user *ubuf,
> > @@ -116,6 +167,9 @@ static ssize_t xenbus_dev_write(struct f
> >     struct xenbus_dev_transaction *trans = NULL;
> >     uint32_t msg_type;
> >     void *reply;
> > +   char *path, *token;
> > +   struct watch_adapter *watch, *tmp_watch;
> > +   int err;
> > 
> >     if ((len + u->len) > sizeof(u->u.buffer))
> >             return -EINVAL;
> > @@ -169,6 +223,56 @@ static ssize_t xenbus_dev_write(struct f
> >             kfree(reply);
> >             break;
> > 
> > +   case XS_WATCH:
> > +   case XS_UNWATCH:
> > +           path = u->u.buffer + sizeof(u->u.msg);
> > +           token = memchr(path, 0, u->u.msg.len);
> > +           if (token == NULL)
> > +                   return -EILSEQ;
> > +           token++;
> > +
> > +           if (msg_type == XS_WATCH) {
> > +                   static const char * XS_WATCH_RESP = "OK";
> > +                   struct xsd_sockmsg hdr;
> > +
> > +                   watch = kmalloc(sizeof(*watch), GFP_KERNEL);
> > +                   watch->watch.node = kmalloc(strlen(path)+1,
> > +                                                    GFP_KERNEL);
> > +                   strcpy((char *)watch->watch.node, path);
> > +                   watch->watch.callback = watch_fired;
> > +                   watch->token = kmalloc(strlen(token)+1,
> GFP_KERNEL);
> > +                   strcpy(watch->token, token);
> > +                   watch->dev_data = u;
> > +
> > +                   err = register_xenbus_watch(&watch->watch);
> > +                   if (err) {
> > +                           free_watch_adapter(watch);
> > +                           return err;
> > +                   }
> > +
> > +                   list_add(&watch->list, &u->watches);
> > +
> > +                   hdr.type = XS_WATCH;
> > +                   hdr.len = strlen(XS_WATCH_RESP) + 1;
> > +                   queue_reply(u, (char *)&hdr, sizeof(hdr));
> > +                   queue_reply(u, (char *)XS_WATCH_RESP, hdr.len);
> > +           } else {
> > +                   list_for_each_entry_safe(watch, tmp_watch,
> > +                                                 &u->watches, list) {
> > +                           if (!strcmp(watch->token, token) &&
> > +                               !strcmp(watch->watch.node, path))
> > +                                   break;
> > +                           {
> > +
> unregister_xenbus_watch(&watch->watch);
> > +                                   list_del(&watch->list);
> > +                                   free_watch_adapter(watch);
> > +                                   break;
> > +                           }
> > +                   }
> > +           }
> > +
> > +           break;
> > +
> >     default:
> >             return -EINVAL;
> >     }
> > @@ -191,7 +295,10 @@ static int xenbus_dev_open(struct inode
> >             return -ENOMEM;
> > 
> >     INIT_LIST_HEAD(&u->transactions);
> > +   INIT_LIST_HEAD(&u->watches);
> >     init_waitqueue_head(&u->read_waitq);
> > +
> > +   mutex_init(&u->reply_mutex);
> > 
> >     filp->private_data = u;
> > 
> > @@ -202,11 +309,18 @@ static int xenbus_dev_release(struct ino
> >  {
> >     struct xenbus_dev_data *u = filp->private_data;
> >     struct xenbus_dev_transaction *trans, *tmp;
> > +   struct watch_adapter *watch, *tmp_watch;
> > 
> >     list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
> >             xenbus_transaction_end(trans->handle, 1);
> >             list_del(&trans->list);
> >             kfree(trans);
> > +   }
> > +
> > +   list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
> > +           unregister_xenbus_watch(&watch->watch);
> > +           list_del(&watch->list);
> > +           free_watch_adapter(watch);
> >     }
> > 
> >     kfree(u);
> > 
> > 
> > 
> > _______________________________________________
> > Xen-devel mailing list
> > Xen-devel@xxxxxxxxxxxxxxxxxxx
> > http://lists.xensource.com/xen-devel


_______________________________________________
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®.