direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @ 11135:88e6bd5e2b54

Whitespace clean-ups.

Signed-off-by: Steven Hand <steven@xensource.com>
author shand@kneesaa.uk.xensource.com
date Wed Aug 16 11:36:13 2006 +0100 (2006-08-16)
parents 2937703f0ed0
children 26576f1dbadb
line source
1 /* drivers/xen/blktap/xenbus.c
2 *
3 * Xenbus code for blktap
4 *
5 * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield
6 *
7 * Based on the blkback xenbus code:
8 *
9 * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
10 * Copyright (C) 2005 XenSource Ltd
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License version 2
14 * as published by the Free Software Foundation; or, when distributed
15 * separately from the Linux kernel or incorporated into other
16 * software packages, subject to the following license:
17 *
18 * Permission is hereby granted, free of charge, to any person obtaining a copy
19 * of this source file (the "Software"), to deal in the Software without
20 * restriction, including without limitation the rights to use, copy, modify,
21 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
22 * and to permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be included in
26 * all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34 * IN THE SOFTWARE.
35 */
37 #include <stdarg.h>
38 #include <linux/module.h>
39 #include <linux/kthread.h>
40 #include <xen/xenbus.h>
41 #include "common.h"
44 struct backend_info
45 {
46 struct xenbus_device *dev;
47 blkif_t *blkif;
48 struct xenbus_watch backend_watch;
49 int xenbus_id;
50 };
53 static void connect(struct backend_info *);
54 static int connect_ring(struct backend_info *);
55 static int blktap_remove(struct xenbus_device *dev);
56 static int blktap_probe(struct xenbus_device *dev,
57 const struct xenbus_device_id *id);
58 static void tap_backend_changed(struct xenbus_watch *, const char **,
59 unsigned int);
60 static void tap_frontend_changed(struct xenbus_device *dev,
61 enum xenbus_state frontend_state);
63 static int strsep_len(const char *str, char c, unsigned int len)
64 {
65 unsigned int i;
67 for (i = 0; str[i]; i++)
68 if (str[i] == c) {
69 if (len == 0)
70 return i;
71 len--;
72 }
73 return (len == 0) ? i : -ERANGE;
74 }
76 static long get_id(const char *str)
77 {
78 int len,end;
79 const char *ptr;
80 char *tptr, num[10];
82 len = strsep_len(str, '/', 2);
83 end = strlen(str);
84 if ( (len < 0) || (end < 0) ) return -1;
86 ptr = str + len + 1;
87 strncpy(num,ptr,end - len);
88 tptr = num + (end - (len + 1));
89 *tptr = '\0';
90 DPRINTK("Get_id called for %s (%s)\n",str,num);
92 return simple_strtol(num, NULL, 10);
93 }
95 static void tap_update_blkif_status(blkif_t *blkif)
96 {
97 int err;
99 /* Not ready to connect? */
100 if(!blkif->irq || !blkif->sectors) {
101 return;
102 }
104 /* Already connected? */
105 if (blkif->be->dev->state == XenbusStateConnected)
106 return;
108 /* Attempt to connect: exit if we fail to. */
109 connect(blkif->be);
110 if (blkif->be->dev->state != XenbusStateConnected)
111 return;
113 blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif,
114 "xvd %d",
115 blkif->domid);
117 if (IS_ERR(blkif->xenblkd)) {
118 err = PTR_ERR(blkif->xenblkd);
119 blkif->xenblkd = NULL;
120 xenbus_dev_fatal(blkif->be->dev, err, "start xenblkd");
121 WPRINTK("Error starting thread\n");
122 }
123 }
125 static int blktap_remove(struct xenbus_device *dev)
126 {
127 struct backend_info *be = dev->dev.driver_data;
129 if (be->backend_watch.node) {
130 unregister_xenbus_watch(&be->backend_watch);
131 kfree(be->backend_watch.node);
132 be->backend_watch.node = NULL;
133 }
134 if (be->blkif) {
135 if (be->blkif->xenblkd)
136 kthread_stop(be->blkif->xenblkd);
137 signal_tapdisk(be->blkif->dev_num);
138 tap_blkif_free(be->blkif);
139 be->blkif = NULL;
140 }
141 kfree(be);
142 dev->dev.driver_data = NULL;
143 return 0;
144 }
146 /**
147 * Entry point to this code when a new device is created. Allocate
148 * the basic structures, and watch the store waiting for the
149 * user-space program to tell us the physical device info. Switch to
150 * InitWait.
151 */
152 static int blktap_probe(struct xenbus_device *dev,
153 const struct xenbus_device_id *id)
154 {
155 int err;
156 struct backend_info *be = kzalloc(sizeof(struct backend_info),
157 GFP_KERNEL);
158 if (!be) {
159 xenbus_dev_fatal(dev, -ENOMEM,
160 "allocating backend structure");
161 return -ENOMEM;
162 }
164 be->dev = dev;
165 dev->dev.driver_data = be;
166 be->xenbus_id = get_id(dev->nodename);
168 be->blkif = tap_alloc_blkif(dev->otherend_id);
169 if (IS_ERR(be->blkif)) {
170 err = PTR_ERR(be->blkif);
171 be->blkif = NULL;
172 xenbus_dev_fatal(dev, err, "creating block interface");
173 goto fail;
174 }
176 /* setup back pointer */
177 be->blkif->be = be;
178 be->blkif->sectors = 0;
180 /* set a watch on disk info, waiting for userspace to update details*/
181 err = xenbus_watch_path2(dev, dev->nodename, "info",
182 &be->backend_watch, tap_backend_changed);
183 if (err)
184 goto fail;
186 err = xenbus_switch_state(dev, XenbusStateInitWait);
187 if (err)
188 goto fail;
189 return 0;
191 fail:
192 DPRINTK("blktap probe failed");
193 blktap_remove(dev);
194 return err;
195 }
198 /**
199 * Callback received when the user space code has placed the device
200 * information in xenstore.
201 */
202 static void tap_backend_changed(struct xenbus_watch *watch,
203 const char **vec, unsigned int len)
204 {
205 int err;
206 unsigned long info;
207 struct backend_info *be
208 = container_of(watch, struct backend_info, backend_watch);
209 struct xenbus_device *dev = be->dev;
211 /**
212 * Check to see whether userspace code has opened the image
213 * and written sector
214 * and disk info to xenstore
215 */
216 err = xenbus_gather(XBT_NIL, dev->nodename, "info", "%lu", &info,
217 NULL);
218 if (err) {
219 xenbus_dev_error(dev, err, "getting info");
220 return;
221 }
223 DPRINTK("Userspace update on disk info, %lu\n",info);
225 err = xenbus_gather(XBT_NIL, dev->nodename, "sectors", "%llu",
226 &be->blkif->sectors, NULL);
228 /* Associate tap dev with domid*/
229 be->blkif->dev_num = dom_to_devid(be->blkif->domid, be->xenbus_id,
230 be->blkif);
231 DPRINTK("Thread started for domid [%d], connecting disk\n",
232 be->blkif->dev_num);
234 tap_update_blkif_status(be->blkif);
235 }
237 /**
238 * Callback received when the frontend's state changes.
239 */
240 static void tap_frontend_changed(struct xenbus_device *dev,
241 enum xenbus_state frontend_state)
242 {
243 struct backend_info *be = dev->dev.driver_data;
244 int err;
246 DPRINTK("");
248 switch (frontend_state) {
249 case XenbusStateInitialising:
250 break;
252 case XenbusStateInitialised:
253 case XenbusStateConnected:
254 /* Ensure we connect even when two watches fire in
255 close successsion and we miss the intermediate value
256 of frontend_state. */
257 if (dev->state == XenbusStateConnected)
258 break;
260 err = connect_ring(be);
261 if (err)
262 break;
263 tap_update_blkif_status(be->blkif);
264 break;
266 case XenbusStateClosing:
267 xenbus_switch_state(dev, XenbusStateClosing);
268 break;
270 case XenbusStateClosed:
271 device_unregister(&dev->dev);
272 break;
274 case XenbusStateUnknown:
275 case XenbusStateInitWait:
276 default:
277 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
278 frontend_state);
279 break;
280 }
281 }
284 /**
285 * Switch to Connected state.
286 */
287 static void connect(struct backend_info *be)
288 {
289 int err;
291 struct xenbus_device *dev = be->dev;
293 err = xenbus_switch_state(dev, XenbusStateConnected);
294 if (err)
295 xenbus_dev_fatal(dev, err, "switching to Connected state",
296 dev->nodename);
298 return;
299 }
302 static int connect_ring(struct backend_info *be)
303 {
304 struct xenbus_device *dev = be->dev;
305 unsigned long ring_ref;
306 unsigned int evtchn;
307 int err;
309 DPRINTK("%s", dev->otherend);
311 err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu",
312 &ring_ref, "event-channel", "%u", &evtchn, NULL);
313 if (err) {
314 xenbus_dev_fatal(dev, err,
315 "reading %s/ring-ref and event-channel",
316 dev->otherend);
317 return err;
318 }
320 /* Map the shared frame, irq etc. */
321 err = tap_blkif_map(be->blkif, ring_ref, evtchn);
322 if (err) {
323 xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
324 ring_ref, evtchn);
325 return err;
326 }
328 return 0;
329 }
332 /* ** Driver Registration ** */
335 static struct xenbus_device_id blktap_ids[] = {
336 { "tap" },
337 { "" }
338 };
341 static struct xenbus_driver blktap = {
342 .name = "tap",
343 .owner = THIS_MODULE,
344 .ids = blktap_ids,
345 .probe = blktap_probe,
346 .remove = blktap_remove,
347 .otherend_changed = tap_frontend_changed
348 };
351 void tap_blkif_xenbus_init(void)
352 {
353 xenbus_register_backend(&blktap);
354 }