debuggers.hg

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c @ 6644:29808fef9148

merge?
author cl349@firebug.cl.cam.ac.uk
date Sat Sep 03 18:24:46 2005 +0000 (2005-09-03)
parents 87ea297c1d3a
children b6c98fe62e1a
line source
1 /*
2 * xenbus_dev.c
3 *
4 * Driver giving user-space access to the kernel's xenbus connection
5 * to xenstore.
6 *
7 * Copyright (c) 2005, Christian Limpach
8 *
9 * This file may be distributed separately from the Linux kernel, or
10 * incorporated into other software packages, subject to the following license:
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
31 #include <linux/config.h>
32 #include <linux/kernel.h>
33 #include <linux/errno.h>
34 #include <linux/uio.h>
35 #include <linux/notifier.h>
36 #include <linux/wait.h>
37 #include <linux/fs.h>
39 #include "xenstored.h"
40 #include "xenbus_comms.h"
42 #include <asm/uaccess.h>
43 #include <asm-xen/xenbus.h>
44 #include <asm-xen/linux-public/xenbus_dev.h>
45 #include <asm-xen/xen_proc.h>
47 struct xenbus_dev_data {
48 int in_transaction;
49 };
51 static struct proc_dir_entry *xenbus_dev_intf;
53 void *xs_talkv(enum xsd_sockmsg_type type, const struct kvec *iovec,
54 unsigned int num_vecs, unsigned int *len);
56 static int xenbus_dev_talkv(struct xenbus_dev_data *u, unsigned long data)
57 {
58 struct xenbus_dev_talkv xt;
59 unsigned int len;
60 void *resp, *base;
61 struct kvec *iovec;
62 int ret = -EFAULT, v = 0;
64 if (copy_from_user(&xt, (void *)data, sizeof(xt)))
65 return -EFAULT;
67 iovec = kmalloc(xt.num_vecs * sizeof(struct kvec), GFP_KERNEL);
68 if (iovec == NULL)
69 return -ENOMEM;
71 if (copy_from_user(iovec, xt.iovec,
72 xt.num_vecs * sizeof(struct kvec)))
73 goto out;
75 for (v = 0; v < xt.num_vecs; v++) {
76 base = iovec[v].iov_base;
77 iovec[v].iov_base = kmalloc(iovec[v].iov_len, GFP_KERNEL);
78 if (iovec[v].iov_base == NULL ||
79 copy_from_user(iovec[v].iov_base, base, iovec[v].iov_len))
80 {
81 if (iovec[v].iov_base)
82 kfree(iovec[v].iov_base);
83 else
84 ret = -ENOMEM;
85 v--;
86 goto out;
87 }
88 }
90 resp = xs_talkv(xt.type, iovec, xt.num_vecs, &len);
91 if (IS_ERR(resp)) {
92 ret = PTR_ERR(resp);
93 goto out;
94 }
96 switch (xt.type) {
97 case XS_TRANSACTION_START:
98 u->in_transaction = 1;
99 break;
100 case XS_TRANSACTION_END:
101 u->in_transaction = 0;
102 break;
103 default:
104 break;
105 }
107 ret = len;
108 if (len > xt.len)
109 len = xt.len;
111 if (copy_to_user(xt.buf, resp, len))
112 ret = -EFAULT;
114 kfree(resp);
115 out:
116 while (v-- > 0)
117 kfree(iovec[v].iov_base);
118 kfree(iovec);
119 return ret;
120 }
122 static int xenbus_dev_ioctl(struct inode *inode, struct file *filp,
123 unsigned int cmd, unsigned long data)
124 {
125 struct xenbus_dev_data *u = filp->private_data;
126 int ret = -ENOSYS;
128 switch (cmd) {
129 case IOCTL_XENBUS_DEV_TALKV:
130 ret = xenbus_dev_talkv(u, data);
131 break;
132 default:
133 ret = -EINVAL;
134 break;
135 }
136 return ret;
137 }
139 static int xenbus_dev_open(struct inode *inode, struct file *filp)
140 {
141 struct xenbus_dev_data *u;
143 u = kmalloc(sizeof(*u), GFP_KERNEL);
144 if (u == NULL)
145 return -ENOMEM;
147 memset(u, 0, sizeof(*u));
149 filp->private_data = u;
151 down(&xenbus_lock);
153 return 0;
154 }
156 static int xenbus_dev_release(struct inode *inode, struct file *filp)
157 {
158 struct xenbus_dev_data *u = filp->private_data;
160 if (u->in_transaction)
161 xenbus_transaction_end(1);
163 up(&xenbus_lock);
165 kfree(u);
167 return 0;
168 }
170 static struct file_operations xenbus_dev_file_ops = {
171 ioctl: xenbus_dev_ioctl,
172 open: xenbus_dev_open,
173 release: xenbus_dev_release
174 };
176 static int __init
177 xenbus_dev_init(void)
178 {
179 xenbus_dev_intf = create_xen_proc_entry("xenbus", 0400);
180 if (xenbus_dev_intf)
181 xenbus_dev_intf->proc_fops = &xenbus_dev_file_ops;
183 return 0;
184 }
186 __initcall(xenbus_dev_init);