xen-vtx-unstable

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c @ 6774:4d899a738d59

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 15:05:49 2005 +0000 (2005-09-13)
parents 0fad07d67e75 b6c98fe62e1a
children e7c7196fa329 8ca0f98ba8e2
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 * Copyright (c) 2005, Rusty Russell, IBM Corporation
9 *
10 * This file may be distributed separately from the Linux kernel, or
11 * incorporated into other software packages, subject to the following license:
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this source file (the "Software"), to deal in the Software without
15 * restriction, including without limitation the rights to use, copy, modify,
16 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17 * and to permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * IN THE SOFTWARE.
30 */
32 #include <linux/config.h>
33 #include <linux/kernel.h>
34 #include <linux/errno.h>
35 #include <linux/uio.h>
36 #include <linux/notifier.h>
37 #include <linux/wait.h>
38 #include <linux/fs.h>
40 #include "xenbus_comms.h"
42 #include <asm/uaccess.h>
43 #include <asm-xen/xenbus.h>
44 #include <asm-xen/xen_proc.h>
45 #include <asm-xen/linux-public/xenstored.h>
47 struct xenbus_dev_data {
48 /* Are there bytes left to be read in this message? */
49 int bytes_left;
50 /* Are we still waiting for the reply to a message we wrote? */
51 int awaiting_reply;
52 /* Buffer for outgoing messages. */
53 unsigned int len;
54 union {
55 struct xsd_sockmsg msg;
56 char buffer[PAGE_SIZE];
57 } u;
58 };
60 static struct proc_dir_entry *xenbus_dev_intf;
62 /* Reply can be long (dir, getperm): don't buffer, just examine
63 * headers so we can discard rest if they die. */
64 static ssize_t xenbus_dev_read(struct file *filp,
65 char __user *ubuf,
66 size_t len, loff_t *ppos)
67 {
68 struct xenbus_dev_data *data = filp->private_data;
69 struct xsd_sockmsg msg;
70 int err;
72 /* Refill empty buffer? */
73 if (data->bytes_left == 0) {
74 if (len < sizeof(msg))
75 return -EINVAL;
77 err = xb_read(&msg, sizeof(msg));
78 if (err)
79 return err;
80 data->bytes_left = msg.len;
81 if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0)
82 return -EFAULT;
83 /* We can receive spurious XS_WATCH_EVENT messages. */
84 if (msg.type != XS_WATCH_EVENT)
85 data->awaiting_reply = 0;
86 return sizeof(msg);
87 }
89 /* Don't read over next header, or over temporary buffer. */
90 if (len > sizeof(data->u.buffer))
91 len = sizeof(data->u.buffer);
92 if (len > data->bytes_left)
93 len = data->bytes_left;
95 err = xb_read(data->u.buffer, len);
96 if (err)
97 return err;
99 data->bytes_left -= len;
100 if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0)
101 return -EFAULT;
102 return len;
103 }
105 /* We do v. basic sanity checking so they don't screw up kernel later. */
106 static ssize_t xenbus_dev_write(struct file *filp,
107 const char __user *ubuf,
108 size_t len, loff_t *ppos)
109 {
110 struct xenbus_dev_data *data = filp->private_data;
111 int err;
113 /* We gather data in buffer until we're ready to send it. */
114 if (len > data->len + sizeof(data->u))
115 return -EINVAL;
116 if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0)
117 return -EFAULT;
118 data->len += len;
119 if (data->len >= sizeof(data->u.msg) + data->u.msg.len) {
120 err = xb_write(data->u.buffer, data->len);
121 if (err)
122 return err;
123 data->len = 0;
124 data->awaiting_reply = 1;
125 }
126 return len;
127 }
129 static int xenbus_dev_open(struct inode *inode, struct file *filp)
130 {
131 struct xenbus_dev_data *u;
133 if (xen_start_info->store_evtchn == 0)
134 return -ENOENT;
136 /* Don't try seeking. */
137 nonseekable_open(inode, filp);
139 u = kmalloc(sizeof(*u), GFP_KERNEL);
140 if (u == NULL)
141 return -ENOMEM;
143 memset(u, 0, sizeof(*u));
145 filp->private_data = u;
147 down(&xenbus_lock);
149 return 0;
150 }
152 static int xenbus_dev_release(struct inode *inode, struct file *filp)
153 {
154 struct xenbus_dev_data *data = filp->private_data;
156 /* Discard any unread replies. */
157 while (data->bytes_left || data->awaiting_reply)
158 xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL);
160 /* Harmless if no transaction in progress. */
161 xenbus_transaction_end(1);
163 up(&xenbus_lock);
165 kfree(data);
167 return 0;
168 }
170 static struct file_operations xenbus_dev_file_ops = {
171 .read = xenbus_dev_read,
172 .write = xenbus_dev_write,
173 .open = xenbus_dev_open,
174 .release = xenbus_dev_release,
175 };
177 static int __init
178 xenbus_dev_init(void)
179 {
180 xenbus_dev_intf = create_xen_proc_entry("xenbus", 0400);
181 if (xenbus_dev_intf)
182 xenbus_dev_intf->proc_fops = &xenbus_dev_file_ops;
184 return 0;
185 }
187 __initcall(xenbus_dev_init);