[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |