Magellan Linux

Annotation of /tags/kernel26-xen-2_6_25_r1-fedora9-patches/kernel26-xen/patches-2.6.25-r1/1014-2.6.25-xen-Add-proc-xen-xenbus.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 608 - (hide annotations) (download)
Fri May 23 12:17:32 2008 UTC (16 years, 1 month ago) by (unknown author)
File size: 14237 byte(s)
This commit was manufactured by cvs2svn to create tag
'kernel26-xen-2_6_25_r1-fedora9-patches'.
1 niro 606 From 8b4585c4677d8e9e58a1e156b113494abd74c541 Mon Sep 17 00:00:00 2001
2     From: Mark McLoughlin <markmc@redhat.com>
3     Date: Mon, 4 Feb 2008 22:04:36 +0000
4     Subject: [PATCH] xen: Add /proc/xen/xenbus
5    
6     This interface is used by userspace programs to talk to
7     xenstored.
8    
9     Since xenstored makes itself available to Dom0 userspace
10     via a socket this should only really be useful in Domu,
11     but it turns out that Dom0 apps historically default
12     to using /proc/xen/xenbus rather than the socket.
13    
14     Signed-off-by: Mark McLoughlin <markmc@redhat.com>
15     ---
16     drivers/xen/xenbus/xenbus_comms.h | 1 -
17     drivers/xen/xenbus/xenbus_probe.c | 2 +
18     drivers/xen/xenbus/xenbus_xs.c | 1 +
19     drivers/xen/xenctrl/Makefile | 1 +
20     drivers/xen/xenctrl/main.c | 6 +
21     drivers/xen/xenctrl/xenbus.c | 398 +++++++++++++++++++++++++++++++++++++
22     drivers/xen/xenctrl/xenctrl.h | 6 +
23     include/xen/xenbus.h | 2 +
24     8 files changed, 416 insertions(+), 1 deletions(-)
25     create mode 100644 drivers/xen/xenctrl/xenbus.c
26    
27     diff --git a/drivers/xen/xenbus/xenbus_comms.h b/drivers/xen/xenbus/xenbus_comms.h
28     index c21db75..fcc9b29 100644
29     --- a/drivers/xen/xenbus/xenbus_comms.h
30     +++ b/drivers/xen/xenbus/xenbus_comms.h
31     @@ -41,6 +41,5 @@ int xb_data_to_read(void);
32     int xb_wait_for_data_to_read(void);
33     int xs_input_avail(void);
34     extern struct xenstore_domain_interface *xen_store_interface;
35     -extern int xen_store_evtchn;
36    
37     #endif /* _XENBUS_COMMS_H */
38     diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
39     index 57ceb53..c811581 100644
40     --- a/drivers/xen/xenbus/xenbus_probe.c
41     +++ b/drivers/xen/xenbus/xenbus_probe.c
42     @@ -56,6 +56,8 @@
43     #include "xenbus_probe.h"
44    
45     int xen_store_evtchn;
46     +EXPORT_SYMBOL_GPL(xen_store_evtchn);
47     +
48     struct xenstore_domain_interface *xen_store_interface;
49     static unsigned long xen_store_mfn;
50    
51     diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
52     index 227d53b..810e24a 100644
53     --- a/drivers/xen/xenbus/xenbus_xs.c
54     +++ b/drivers/xen/xenbus/xenbus_xs.c
55     @@ -184,6 +184,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
56    
57     return ret;
58     }
59     +EXPORT_SYMBOL(xenbus_dev_request_and_reply);
60    
61     /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
62     static void *xs_talkv(struct xenbus_transaction t,
63     diff --git a/drivers/xen/xenctrl/Makefile b/drivers/xen/xenctrl/Makefile
64     index 8a706cb..23dafa3 100644
65     --- a/drivers/xen/xenctrl/Makefile
66     +++ b/drivers/xen/xenctrl/Makefile
67     @@ -4,3 +4,4 @@ xenctrl-objs =
68     xenctrl-objs += main.o
69     xenctrl-objs += capabilities.o
70     xenctrl-objs += privcmd.o
71     +xenctrl-objs += xenbus.o
72     diff --git a/drivers/xen/xenctrl/main.c b/drivers/xen/xenctrl/main.c
73     index d1fe6ef..b0cf61b 100644
74     --- a/drivers/xen/xenctrl/main.c
75     +++ b/drivers/xen/xenctrl/main.c
76     @@ -59,8 +59,13 @@ static int __init xenctrl_init(void)
77     if (ret)
78     goto fail2;
79    
80     + ret = xenbus_create_proc_entry();
81     + if (ret)
82     + goto fail3;
83     +
84     return 0;
85    
86     + fail3: privcmd_remove_proc_entry();
87     fail2: capabilities_remove_proc_entry();
88     fail1: remove_proc_entry("xen", NULL);
89     return ret;
90     @@ -68,6 +73,7 @@ static int __init xenctrl_init(void)
91    
92     static void __exit xenctrl_exit(void)
93     {
94     + xenbus_remove_proc_entry();
95     privcmd_remove_proc_entry();
96     capabilities_remove_proc_entry();
97     remove_proc_entry("xen", NULL);
98     diff --git a/drivers/xen/xenctrl/xenbus.c b/drivers/xen/xenctrl/xenbus.c
99     new file mode 100644
100     index 0000000..57d5501
101     --- /dev/null
102     +++ b/drivers/xen/xenctrl/xenbus.c
103     @@ -0,0 +1,398 @@
104     +/*
105     + * xenbus.c
106     + *
107     + * /proc/xen/xenbus gives user-space access to the kernel's xenbus
108     + * connection to xenstore.
109     + *
110     + * Copyright (c) 2005, Christian Limpach
111     + * Copyright (c) 2005, Rusty Russell, IBM Corporation
112     + *
113     + * This program is free software; you can redistribute it and/or
114     + * modify it under the terms of the GNU General Public License version 2
115     + * as published by the Free Software Foundation; or, when distributed
116     + * separately from the Linux kernel or incorporated into other
117     + * software packages, subject to the following license:
118     + *
119     + * Permission is hereby granted, free of charge, to any person obtaining a copy
120     + * of this source file (the "Software"), to deal in the Software without
121     + * restriction, including without limitation the rights to use, copy, modify,
122     + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
123     + * and to permit persons to whom the Software is furnished to do so, subject to
124     + * the following conditions:
125     + *
126     + * The above copyright notice and this permission notice shall be included in
127     + * all copies or substantial portions of the Software.
128     + *
129     + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
130     + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131     + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
132     + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
133     + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
134     + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
135     + * IN THE SOFTWARE.
136     + */
137     +
138     +#include <linux/proc_fs.h>
139     +#include <linux/module.h>
140     +#include <linux/uaccess.h>
141     +#include <linux/poll.h>
142     +
143     +#include <xen/xenbus.h>
144     +
145     +struct xenbus_dev_transaction {
146     + struct list_head list;
147     + struct xenbus_transaction handle;
148     +};
149     +
150     +struct read_buffer {
151     + struct list_head list;
152     + unsigned int cons;
153     + unsigned int len;
154     + char msg[];
155     +};
156     +
157     +struct xenbus_dev_data {
158     + /* In-progress transaction. */
159     + struct list_head transactions;
160     +
161     + /* Active watches. */
162     + struct list_head watches;
163     +
164     + /* Partial request. */
165     + unsigned int len;
166     + union {
167     + struct xsd_sockmsg msg;
168     + char buffer[PAGE_SIZE];
169     + } u;
170     +
171     + /* Response queue. */
172     + struct list_head read_buffers;
173     + wait_queue_head_t read_waitq;
174     +
175     + struct mutex reply_mutex;
176     +};
177     +
178     +static ssize_t xenbus_dev_read(struct file *filp,
179     + char __user *ubuf,
180     + size_t len, loff_t *ppos)
181     +{
182     + struct xenbus_dev_data *u = filp->private_data;
183     + struct read_buffer *rb;
184     + int i, ret;
185     +
186     + mutex_lock(&u->reply_mutex);
187     + while (list_empty(&u->read_buffers)) {
188     + mutex_unlock(&u->reply_mutex);
189     + ret = wait_event_interruptible(u->read_waitq,
190     + !list_empty(&u->read_buffers));
191     + if (ret)
192     + return ret;
193     + mutex_lock(&u->reply_mutex);
194     + }
195     +
196     + rb = list_entry(u->read_buffers.next, struct read_buffer, list);
197     + for (i = 0; i < len;) {
198     + put_user(rb->msg[rb->cons], ubuf + i);
199     + i++;
200     + rb->cons++;
201     + if (rb->cons == rb->len) {
202     + list_del(&rb->list);
203     + kfree(rb);
204     + if (list_empty(&u->read_buffers))
205     + break;
206     + rb = list_entry(u->read_buffers.next,
207     + struct read_buffer, list);
208     + }
209     + }
210     + mutex_unlock(&u->reply_mutex);
211     +
212     + return i;
213     +}
214     +
215     +static void queue_reply(struct xenbus_dev_data *u,
216     + char *data, unsigned int len)
217     +{
218     + struct read_buffer *rb;
219     +
220     + if (len == 0)
221     + return;
222     +
223     + rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
224     + BUG_ON(rb == NULL);
225     +
226     + rb->cons = 0;
227     + rb->len = len;
228     +
229     + memcpy(rb->msg, data, len);
230     +
231     + list_add_tail(&rb->list, &u->read_buffers);
232     +
233     + wake_up(&u->read_waitq);
234     +}
235     +
236     +struct watch_adapter
237     +{
238     + struct list_head list;
239     + struct xenbus_watch watch;
240     + struct xenbus_dev_data *dev_data;
241     + char *token;
242     +};
243     +
244     +static void free_watch_adapter(struct watch_adapter *watch)
245     +{
246     + kfree(watch->watch.node);
247     + kfree(watch->token);
248     + kfree(watch);
249     +}
250     +
251     +static void watch_fired(struct xenbus_watch *watch,
252     + const char **vec,
253     + unsigned int len)
254     +{
255     + struct watch_adapter *adap =
256     + container_of(watch, struct watch_adapter, watch);
257     + struct xsd_sockmsg hdr;
258     + const char *path, *token;
259     + int path_len, tok_len, body_len;
260     +
261     + path = vec[XS_WATCH_PATH];
262     + token = adap->token;
263     +
264     + path_len = strlen(path) + 1;
265     + tok_len = strlen(token) + 1;
266     + body_len = path_len + tok_len;
267     +
268     + hdr.type = XS_WATCH_EVENT;
269     + hdr.len = body_len;
270     +
271     + mutex_lock(&adap->dev_data->reply_mutex);
272     + queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
273     + queue_reply(adap->dev_data, (char *)path, path_len);
274     + queue_reply(adap->dev_data, (char *)token, tok_len);
275     + mutex_unlock(&adap->dev_data->reply_mutex);
276     +}
277     +
278     +static LIST_HEAD(watch_list);
279     +
280     +static ssize_t xenbus_dev_write(struct file *filp,
281     + const char __user *ubuf,
282     + size_t len, loff_t *ppos)
283     +{
284     + struct xenbus_dev_data *u = filp->private_data;
285     + struct xenbus_dev_transaction *trans = NULL;
286     + uint32_t msg_type;
287     + void *reply;
288     + char *path, *token;
289     + struct watch_adapter *watch, *tmp_watch;
290     + int err, rc = len;
291     +
292     + if ((len + u->len) > sizeof(u->u.buffer)) {
293     + rc = -EINVAL;
294     + goto out;
295     + }
296     +
297     + if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0) {
298     + rc = -EFAULT;
299     + goto out;
300     + }
301     +
302     + u->len += len;
303     + if ((u->len < sizeof(u->u.msg)) ||
304     + (u->len < (sizeof(u->u.msg) + u->u.msg.len)))
305     + return rc;
306     +
307     + msg_type = u->u.msg.type;
308     +
309     + switch (msg_type) {
310     + case XS_TRANSACTION_START:
311     + case XS_TRANSACTION_END:
312     + case XS_DIRECTORY:
313     + case XS_READ:
314     + case XS_GET_PERMS:
315     + case XS_RELEASE:
316     + case XS_GET_DOMAIN_PATH:
317     + case XS_WRITE:
318     + case XS_MKDIR:
319     + case XS_RM:
320     + case XS_SET_PERMS:
321     + if (msg_type == XS_TRANSACTION_START) {
322     + trans = kmalloc(sizeof(*trans), GFP_KERNEL);
323     + if (!trans) {
324     + rc = -ENOMEM;
325     + goto out;
326     + }
327     + }
328     +
329     + reply = xenbus_dev_request_and_reply(&u->u.msg);
330     + if (IS_ERR(reply)) {
331     + kfree(trans);
332     + rc = PTR_ERR(reply);
333     + goto out;
334     + }
335     +
336     + if (msg_type == XS_TRANSACTION_START) {
337     + trans->handle.id = simple_strtoul(reply, NULL, 0);
338     + list_add(&trans->list, &u->transactions);
339     + } else if (msg_type == XS_TRANSACTION_END) {
340     + list_for_each_entry(trans, &u->transactions, list)
341     + if (trans->handle.id == u->u.msg.tx_id)
342     + break;
343     + BUG_ON(&trans->list == &u->transactions);
344     + list_del(&trans->list);
345     + kfree(trans);
346     + }
347     + mutex_lock(&u->reply_mutex);
348     + queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
349     + queue_reply(u, (char *)reply, u->u.msg.len);
350     + mutex_unlock(&u->reply_mutex);
351     + kfree(reply);
352     + break;
353     +
354     + case XS_WATCH:
355     + case XS_UNWATCH: {
356     + static const char *XS_RESP = "OK";
357     + struct xsd_sockmsg hdr;
358     +
359     + path = u->u.buffer + sizeof(u->u.msg);
360     + token = memchr(path, 0, u->u.msg.len);
361     + if (token == NULL) {
362     + rc = -EILSEQ;
363     + goto out;
364     + }
365     + token++;
366     +
367     + if (msg_type == XS_WATCH) {
368     + watch = kmalloc(sizeof(*watch), GFP_KERNEL);
369     + watch->watch.node = kmalloc(strlen(path)+1,
370     + GFP_KERNEL);
371     + strcpy((char *)watch->watch.node, path);
372     + watch->watch.callback = watch_fired;
373     + watch->token = kmalloc(strlen(token)+1, GFP_KERNEL);
374     + strcpy(watch->token, token);
375     + watch->dev_data = u;
376     +
377     + err = register_xenbus_watch(&watch->watch);
378     + if (err) {
379     + free_watch_adapter(watch);
380     + rc = err;
381     + goto out;
382     + }
383     +
384     + list_add(&watch->list, &u->watches);
385     + } else {
386     + list_for_each_entry_safe(watch, tmp_watch,
387     + &u->watches, list) {
388     + if (!strcmp(watch->token, token) &&
389     + !strcmp(watch->watch.node, path))
390     + {
391     + unregister_xenbus_watch(&watch->watch);
392     + list_del(&watch->list);
393     + free_watch_adapter(watch);
394     + break;
395     + }
396     + }
397     + }
398     +
399     + hdr.type = msg_type;
400     + hdr.len = strlen(XS_RESP) + 1;
401     + mutex_lock(&u->reply_mutex);
402     + queue_reply(u, (char *)&hdr, sizeof(hdr));
403     + queue_reply(u, (char *)XS_RESP, hdr.len);
404     + mutex_unlock(&u->reply_mutex);
405     + break;
406     + }
407     +
408     + default:
409     + rc = -EINVAL;
410     + break;
411     + }
412     +
413     + out:
414     + u->len = 0;
415     + return rc;
416     +}
417     +
418     +static int xenbus_dev_open(struct inode *inode, struct file *filp)
419     +{
420     + struct xenbus_dev_data *u;
421     +
422     + if (xen_store_evtchn == 0)
423     + return -ENOENT;
424     +
425     + nonseekable_open(inode, filp);
426     +
427     + u = kzalloc(sizeof(*u), GFP_KERNEL);
428     + if (u == NULL)
429     + return -ENOMEM;
430     +
431     + INIT_LIST_HEAD(&u->transactions);
432     + INIT_LIST_HEAD(&u->watches);
433     + INIT_LIST_HEAD(&u->read_buffers);
434     + init_waitqueue_head(&u->read_waitq);
435     +
436     + mutex_init(&u->reply_mutex);
437     +
438     + filp->private_data = u;
439     +
440     + return 0;
441     +}
442     +
443     +static int xenbus_dev_release(struct inode *inode, struct file *filp)
444     +{
445     + struct xenbus_dev_data *u = filp->private_data;
446     + struct xenbus_dev_transaction *trans, *tmp;
447     + struct watch_adapter *watch, *tmp_watch;
448     +
449     + list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
450     + xenbus_transaction_end(trans->handle, 1);
451     + list_del(&trans->list);
452     + kfree(trans);
453     + }
454     +
455     + list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
456     + unregister_xenbus_watch(&watch->watch);
457     + list_del(&watch->list);
458     + free_watch_adapter(watch);
459     + }
460     +
461     + kfree(u);
462     +
463     + return 0;
464     +}
465     +
466     +static unsigned int xenbus_dev_poll(struct file *file, poll_table *wait)
467     +{
468     + struct xenbus_dev_data *u = file->private_data;
469     +
470     + poll_wait(file, &u->read_waitq, wait);
471     + if (!list_empty(&u->read_buffers))
472     + return POLLIN | POLLRDNORM;
473     + return 0;
474     +}
475     +
476     +static const struct file_operations xenbus_dev_file_ops = {
477     + .read = xenbus_dev_read,
478     + .write = xenbus_dev_write,
479     + .open = xenbus_dev_open,
480     + .release = xenbus_dev_release,
481     + .poll = xenbus_dev_poll,
482     +};
483     +
484     +int __init xenbus_create_proc_entry(void)
485     +{
486     + struct proc_dir_entry *entry;
487     +
488     + entry = create_proc_entry("xen/xenbus", 0400, NULL);
489     + if (!entry)
490     + return -ENOMEM;
491     +
492     + entry->owner = THIS_MODULE;
493     + entry->proc_fops = &xenbus_dev_file_ops;
494     +
495     + return 0;
496     +}
497     +
498     +void __exit xenbus_remove_proc_entry(void)
499     +{
500     + remove_proc_entry("xen/xenbus", NULL);
501     +}
502     diff --git a/drivers/xen/xenctrl/xenctrl.h b/drivers/xen/xenctrl/xenctrl.h
503     index a35209a..e585c4b 100644
504     --- a/drivers/xen/xenctrl/xenctrl.h
505     +++ b/drivers/xen/xenctrl/xenctrl.h
506     @@ -43,3 +43,9 @@ void capabilities_remove_proc_entry(void) __exit;
507     */
508     int privcmd_create_proc_entry(void) __init;
509     void privcmd_remove_proc_entry(void) __exit;
510     +
511     +/*
512     + * xenbus.c
513     + */
514     +int xenbus_create_proc_entry(void) __init;
515     +void xenbus_remove_proc_entry(void) __exit;
516     diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
517     index 6369d89..a3fef9d 100644
518     --- a/include/xen/xenbus.h
519     +++ b/include/xen/xenbus.h
520     @@ -232,4 +232,6 @@ const char *xenbus_strstate(enum xenbus_state state);
521     int xenbus_dev_is_online(struct xenbus_device *dev);
522     int xenbus_frontend_closed(struct xenbus_device *dev);
523    
524     +extern int xen_store_evtchn;
525     +
526     #endif /* _XEN_XENBUS_H */
527     --
528     1.5.4.1
529