Magellan Linux

Contents of /trunk/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 606 - (show annotations) (download)
Thu May 22 23:13:13 2008 UTC (15 years, 11 months ago) by niro
File size: 14237 byte(s)
-ver bump to 2.6.25-magellan-r1:
- linux-2.6.25.4
- fbcondecor-0.9.4
- squashfs-3.3
- unionfs-2.3.3
- tuxonice-3.0-rc7
- linux-phc-0.3.0
- acpi-dstd-0.9a
- reiser4
- xen-3.2.0
. ipw3945-1.2.2

1 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