direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @ 14377:817647aff01f

[BLKTAP] remove spurious error message
Signed-off-by: Jake Wires <jwires@xensource.com>
author Jake Wires <jwires@xensource.com>
date Wed Mar 14 14:18:51 2007 -0700 (2007-03-14)
parents f62a052384a5
children 0fd2bf14f38a
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 int group_added;
51 };
54 static void connect(struct backend_info *);
55 static int connect_ring(struct backend_info *);
56 static int blktap_remove(struct xenbus_device *dev);
57 static int blktap_probe(struct xenbus_device *dev,
58 const struct xenbus_device_id *id);
59 static void tap_backend_changed(struct xenbus_watch *, const char **,
60 unsigned int);
61 static void tap_frontend_changed(struct xenbus_device *dev,
62 enum xenbus_state frontend_state);
64 static int strsep_len(const char *str, char c, unsigned int len)
65 {
66 unsigned int i;
68 for (i = 0; str[i]; i++)
69 if (str[i] == c) {
70 if (len == 0)
71 return i;
72 len--;
73 }
74 return (len == 0) ? i : -ERANGE;
75 }
77 static long get_id(const char *str)
78 {
79 int len,end;
80 const char *ptr;
81 char *tptr, num[10];
83 len = strsep_len(str, '/', 2);
84 end = strlen(str);
85 if ( (len < 0) || (end < 0) ) return -1;
87 ptr = str + len + 1;
88 strncpy(num,ptr,end - len);
89 tptr = num + (end - (len + 1));
90 *tptr = '\0';
91 DPRINTK("Get_id called for %s (%s)\n",str,num);
93 return simple_strtol(num, NULL, 10);
94 }
96 static int blktap_name(blkif_t *blkif, char *buf)
97 {
98 char *devpath, *devname;
99 struct xenbus_device *dev = blkif->be->dev;
101 devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
102 if (IS_ERR(devpath))
103 return PTR_ERR(devpath);
105 if ((devname = strstr(devpath, "/dev/")) != NULL)
106 devname += strlen("/dev/");
107 else
108 devname = devpath;
110 snprintf(buf, TASK_COMM_LEN, "blktap.%d.%s", blkif->domid, devname);
111 kfree(devpath);
113 return 0;
114 }
116 /****************************************************************
117 * sysfs interface for VBD I/O requests
118 */
120 #define VBD_SHOW(name, format, args...) \
121 static ssize_t show_##name(struct device *_dev, \
122 struct device_attribute *attr, \
123 char *buf) \
124 { \
125 struct xenbus_device *dev = to_xenbus_device(_dev); \
126 struct backend_info *be = dev->dev.driver_data; \
127 \
128 return sprintf(buf, format, ##args); \
129 } \
130 DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
132 VBD_SHOW(tap_oo_req, "%d\n", be->blkif->st_oo_req);
133 VBD_SHOW(tap_rd_req, "%d\n", be->blkif->st_rd_req);
134 VBD_SHOW(tap_wr_req, "%d\n", be->blkif->st_wr_req);
135 VBD_SHOW(tap_rd_sect, "%d\n", be->blkif->st_rd_sect);
136 VBD_SHOW(tap_wr_sect, "%d\n", be->blkif->st_wr_sect);
138 static struct attribute *tapstat_attrs[] = {
139 &dev_attr_tap_oo_req.attr,
140 &dev_attr_tap_rd_req.attr,
141 &dev_attr_tap_wr_req.attr,
142 &dev_attr_tap_rd_sect.attr,
143 &dev_attr_tap_wr_sect.attr,
144 NULL
145 };
147 static struct attribute_group tapstat_group = {
148 .name = "statistics",
149 .attrs = tapstat_attrs,
150 };
152 int xentap_sysfs_addif(struct xenbus_device *dev)
153 {
154 int err;
155 struct backend_info *be = dev->dev.driver_data;
156 err = sysfs_create_group(&dev->dev.kobj, &tapstat_group);
157 if (!err)
158 be->group_added = 1;
159 return err;
160 }
162 void xentap_sysfs_delif(struct xenbus_device *dev)
163 {
164 sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
165 }
167 static int blktap_remove(struct xenbus_device *dev)
168 {
169 struct backend_info *be = dev->dev.driver_data;
171 if (be->backend_watch.node) {
172 unregister_xenbus_watch(&be->backend_watch);
173 kfree(be->backend_watch.node);
174 be->backend_watch.node = NULL;
175 }
176 if (be->blkif) {
177 if (be->blkif->xenblkd)
178 kthread_stop(be->blkif->xenblkd);
179 signal_tapdisk(be->blkif->dev_num);
180 tap_blkif_free(be->blkif);
181 be->blkif = NULL;
182 }
183 if (be->group_added)
184 xentap_sysfs_delif(be->dev);
185 kfree(be);
186 dev->dev.driver_data = NULL;
187 return 0;
188 }
190 static void tap_update_blkif_status(blkif_t *blkif)
191 {
192 int err;
193 char name[TASK_COMM_LEN];
195 /* Not ready to connect? */
196 if(!blkif->irq || !blkif->sectors) {
197 return;
198 }
200 /* Already connected? */
201 if (blkif->be->dev->state == XenbusStateConnected)
202 return;
204 /* Attempt to connect: exit if we fail to. */
205 connect(blkif->be);
206 if (blkif->be->dev->state != XenbusStateConnected)
207 return;
209 err = blktap_name(blkif, name);
210 if (err) {
211 xenbus_dev_error(blkif->be->dev, err, "get blktap dev name");
212 return;
213 }
215 err = xentap_sysfs_addif(blkif->be->dev);
216 if (err) {
217 xenbus_dev_fatal(blkif->be->dev, err,
218 "creating sysfs entries");
219 return;
220 }
222 blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, name);
223 if (IS_ERR(blkif->xenblkd)) {
224 err = PTR_ERR(blkif->xenblkd);
225 blkif->xenblkd = NULL;
226 xenbus_dev_fatal(blkif->be->dev, err, "start xenblkd");
227 WPRINTK("Error starting thread\n");
228 }
229 }
231 /**
232 * Entry point to this code when a new device is created. Allocate
233 * the basic structures, and watch the store waiting for the
234 * user-space program to tell us the physical device info. Switch to
235 * InitWait.
236 */
237 static int blktap_probe(struct xenbus_device *dev,
238 const struct xenbus_device_id *id)
239 {
240 int err;
241 struct backend_info *be = kzalloc(sizeof(struct backend_info),
242 GFP_KERNEL);
243 if (!be) {
244 xenbus_dev_fatal(dev, -ENOMEM,
245 "allocating backend structure");
246 return -ENOMEM;
247 }
249 be->dev = dev;
250 dev->dev.driver_data = be;
251 be->xenbus_id = get_id(dev->nodename);
253 be->blkif = tap_alloc_blkif(dev->otherend_id);
254 if (IS_ERR(be->blkif)) {
255 err = PTR_ERR(be->blkif);
256 be->blkif = NULL;
257 xenbus_dev_fatal(dev, err, "creating block interface");
258 goto fail;
259 }
261 /* setup back pointer */
262 be->blkif->be = be;
263 be->blkif->sectors = 0;
265 /* set a watch on disk info, waiting for userspace to update details*/
266 err = xenbus_watch_path2(dev, dev->nodename, "info",
267 &be->backend_watch, tap_backend_changed);
268 if (err)
269 goto fail;
271 err = xenbus_switch_state(dev, XenbusStateInitWait);
272 if (err)
273 goto fail;
274 return 0;
276 fail:
277 DPRINTK("blktap probe failed\n");
278 blktap_remove(dev);
279 return err;
280 }
283 /**
284 * Callback received when the user space code has placed the device
285 * information in xenstore.
286 */
287 static void tap_backend_changed(struct xenbus_watch *watch,
288 const char **vec, unsigned int len)
289 {
290 int err;
291 unsigned long info;
292 struct backend_info *be
293 = container_of(watch, struct backend_info, backend_watch);
294 struct xenbus_device *dev = be->dev;
296 /**
297 * Check to see whether userspace code has opened the image
298 * and written sector
299 * and disk info to xenstore
300 */
301 err = xenbus_gather(XBT_NIL, dev->nodename, "info", "%lu", &info,
302 NULL);
303 if (XENBUS_EXIST_ERR(err))
304 return;
305 if (err) {
306 xenbus_dev_error(dev, err, "getting info");
307 return;
308 }
310 DPRINTK("Userspace update on disk info, %lu\n",info);
312 err = xenbus_gather(XBT_NIL, dev->nodename, "sectors", "%llu",
313 &be->blkif->sectors, NULL);
315 /* Associate tap dev with domid*/
316 be->blkif->dev_num = dom_to_devid(be->blkif->domid, be->xenbus_id,
317 be->blkif);
318 DPRINTK("Thread started for domid [%d], connecting disk\n",
319 be->blkif->dev_num);
321 tap_update_blkif_status(be->blkif);
322 }
324 /**
325 * Callback received when the frontend's state changes.
326 */
327 static void tap_frontend_changed(struct xenbus_device *dev,
328 enum xenbus_state frontend_state)
329 {
330 struct backend_info *be = dev->dev.driver_data;
331 int err;
333 DPRINTK("\n");
335 switch (frontend_state) {
336 case XenbusStateInitialising:
337 if (dev->state == XenbusStateClosed) {
338 printk(KERN_INFO "%s: %s: prepare for reconnect\n",
339 __FUNCTION__, dev->nodename);
340 xenbus_switch_state(dev, XenbusStateInitWait);
341 }
342 break;
344 case XenbusStateInitialised:
345 case XenbusStateConnected:
346 /* Ensure we connect even when two watches fire in
347 close successsion and we miss the intermediate value
348 of frontend_state. */
349 if (dev->state == XenbusStateConnected)
350 break;
352 err = connect_ring(be);
353 if (err)
354 break;
355 tap_update_blkif_status(be->blkif);
356 break;
358 case XenbusStateClosing:
359 if (be->blkif->xenblkd) {
360 kthread_stop(be->blkif->xenblkd);
361 be->blkif->xenblkd = NULL;
362 }
363 xenbus_switch_state(dev, XenbusStateClosing);
364 break;
366 case XenbusStateClosed:
367 xenbus_switch_state(dev, XenbusStateClosed);
368 if (xenbus_dev_is_online(dev))
369 break;
370 /* fall through if not online */
371 case XenbusStateUnknown:
372 device_unregister(&dev->dev);
373 break;
375 default:
376 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
377 frontend_state);
378 break;
379 }
380 }
383 /**
384 * Switch to Connected state.
385 */
386 static void connect(struct backend_info *be)
387 {
388 int err;
390 struct xenbus_device *dev = be->dev;
392 err = xenbus_switch_state(dev, XenbusStateConnected);
393 if (err)
394 xenbus_dev_fatal(dev, err, "switching to Connected state",
395 dev->nodename);
397 return;
398 }
401 static int connect_ring(struct backend_info *be)
402 {
403 struct xenbus_device *dev = be->dev;
404 unsigned long ring_ref;
405 unsigned int evtchn;
406 char protocol[64];
407 int err;
409 DPRINTK("%s\n", dev->otherend);
411 err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu",
412 &ring_ref, "event-channel", "%u", &evtchn, NULL);
413 if (err) {
414 xenbus_dev_fatal(dev, err,
415 "reading %s/ring-ref and event-channel",
416 dev->otherend);
417 return err;
418 }
420 be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
421 err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
422 "%63s", protocol, NULL);
423 if (err)
424 strcpy(protocol, "unspecified, assuming native");
425 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
426 be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
427 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
428 be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
429 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
430 be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
431 else {
432 xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
433 return -1;
434 }
435 printk(KERN_INFO
436 "blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
437 ring_ref, evtchn, be->blkif->blk_protocol, protocol);
439 /* Map the shared frame, irq etc. */
440 err = tap_blkif_map(be->blkif, ring_ref, evtchn);
441 if (err) {
442 xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
443 ring_ref, evtchn);
444 return err;
445 }
447 return 0;
448 }
451 /* ** Driver Registration ** */
454 static struct xenbus_device_id blktap_ids[] = {
455 { "tap" },
456 { "" }
457 };
460 static struct xenbus_driver blktap = {
461 .name = "tap",
462 .owner = THIS_MODULE,
463 .ids = blktap_ids,
464 .probe = blktap_probe,
465 .remove = blktap_remove,
466 .otherend_changed = tap_frontend_changed
467 };
470 void tap_blkif_xenbus_init(void)
471 {
472 xenbus_register_backend(&blktap);
473 }