ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @ 15179:0fd2bf14f38a

[BLKTAP] Ensure blktap doesn't try to re-create extant sysfs entries
Signed-off-by: Jake Wires <jwires@xensource.com>
author Jake Wires <jwires@xensource.com>
date Sat May 19 10:54:01 2007 -0700 (2007-05-19)
parents 817647aff01f
children
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 struct backend_info *be = dev->dev.driver_data;
165 sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
166 be->group_added = 0;
167 }
169 static int blktap_remove(struct xenbus_device *dev)
170 {
171 struct backend_info *be = dev->dev.driver_data;
173 if (be->backend_watch.node) {
174 unregister_xenbus_watch(&be->backend_watch);
175 kfree(be->backend_watch.node);
176 be->backend_watch.node = NULL;
177 }
178 if (be->blkif) {
179 if (be->blkif->xenblkd)
180 kthread_stop(be->blkif->xenblkd);
181 signal_tapdisk(be->blkif->dev_num);
182 tap_blkif_free(be->blkif);
183 be->blkif = NULL;
184 }
185 if (be->group_added)
186 xentap_sysfs_delif(be->dev);
187 kfree(be);
188 dev->dev.driver_data = NULL;
189 return 0;
190 }
192 static void tap_update_blkif_status(blkif_t *blkif)
193 {
194 int err;
195 char name[TASK_COMM_LEN];
197 /* Not ready to connect? */
198 if(!blkif->irq || !blkif->sectors) {
199 return;
200 }
202 /* Already connected? */
203 if (blkif->be->dev->state == XenbusStateConnected)
204 return;
206 /* Attempt to connect: exit if we fail to. */
207 connect(blkif->be);
208 if (blkif->be->dev->state != XenbusStateConnected)
209 return;
211 err = blktap_name(blkif, name);
212 if (err) {
213 xenbus_dev_error(blkif->be->dev, err, "get blktap dev name");
214 return;
215 }
217 if (!blkif->be->group_added) {
218 err = xentap_sysfs_addif(blkif->be->dev);
219 if (err) {
220 xenbus_dev_fatal(blkif->be->dev, err,
221 "creating sysfs entries");
222 return;
223 }
224 }
226 blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, name);
227 if (IS_ERR(blkif->xenblkd)) {
228 err = PTR_ERR(blkif->xenblkd);
229 blkif->xenblkd = NULL;
230 xenbus_dev_fatal(blkif->be->dev, err, "start xenblkd");
231 WPRINTK("Error starting thread\n");
232 }
233 }
235 /**
236 * Entry point to this code when a new device is created. Allocate
237 * the basic structures, and watch the store waiting for the
238 * user-space program to tell us the physical device info. Switch to
239 * InitWait.
240 */
241 static int blktap_probe(struct xenbus_device *dev,
242 const struct xenbus_device_id *id)
243 {
244 int err;
245 struct backend_info *be = kzalloc(sizeof(struct backend_info),
246 GFP_KERNEL);
247 if (!be) {
248 xenbus_dev_fatal(dev, -ENOMEM,
249 "allocating backend structure");
250 return -ENOMEM;
251 }
253 be->dev = dev;
254 dev->dev.driver_data = be;
255 be->xenbus_id = get_id(dev->nodename);
257 be->blkif = tap_alloc_blkif(dev->otherend_id);
258 if (IS_ERR(be->blkif)) {
259 err = PTR_ERR(be->blkif);
260 be->blkif = NULL;
261 xenbus_dev_fatal(dev, err, "creating block interface");
262 goto fail;
263 }
265 /* setup back pointer */
266 be->blkif->be = be;
267 be->blkif->sectors = 0;
269 /* set a watch on disk info, waiting for userspace to update details*/
270 err = xenbus_watch_path2(dev, dev->nodename, "info",
271 &be->backend_watch, tap_backend_changed);
272 if (err)
273 goto fail;
275 err = xenbus_switch_state(dev, XenbusStateInitWait);
276 if (err)
277 goto fail;
278 return 0;
280 fail:
281 DPRINTK("blktap probe failed\n");
282 blktap_remove(dev);
283 return err;
284 }
287 /**
288 * Callback received when the user space code has placed the device
289 * information in xenstore.
290 */
291 static void tap_backend_changed(struct xenbus_watch *watch,
292 const char **vec, unsigned int len)
293 {
294 int err;
295 unsigned long info;
296 struct backend_info *be
297 = container_of(watch, struct backend_info, backend_watch);
298 struct xenbus_device *dev = be->dev;
300 /**
301 * Check to see whether userspace code has opened the image
302 * and written sector
303 * and disk info to xenstore
304 */
305 err = xenbus_gather(XBT_NIL, dev->nodename, "info", "%lu", &info,
306 NULL);
307 if (XENBUS_EXIST_ERR(err))
308 return;
309 if (err) {
310 xenbus_dev_error(dev, err, "getting info");
311 return;
312 }
314 DPRINTK("Userspace update on disk info, %lu\n",info);
316 err = xenbus_gather(XBT_NIL, dev->nodename, "sectors", "%llu",
317 &be->blkif->sectors, NULL);
319 /* Associate tap dev with domid*/
320 be->blkif->dev_num = dom_to_devid(be->blkif->domid, be->xenbus_id,
321 be->blkif);
322 DPRINTK("Thread started for domid [%d], connecting disk\n",
323 be->blkif->dev_num);
325 tap_update_blkif_status(be->blkif);
326 }
328 /**
329 * Callback received when the frontend's state changes.
330 */
331 static void tap_frontend_changed(struct xenbus_device *dev,
332 enum xenbus_state frontend_state)
333 {
334 struct backend_info *be = dev->dev.driver_data;
335 int err;
337 DPRINTK("\n");
339 switch (frontend_state) {
340 case XenbusStateInitialising:
341 if (dev->state == XenbusStateClosed) {
342 printk(KERN_INFO "%s: %s: prepare for reconnect\n",
343 __FUNCTION__, dev->nodename);
344 xenbus_switch_state(dev, XenbusStateInitWait);
345 }
346 break;
348 case XenbusStateInitialised:
349 case XenbusStateConnected:
350 /* Ensure we connect even when two watches fire in
351 close successsion and we miss the intermediate value
352 of frontend_state. */
353 if (dev->state == XenbusStateConnected)
354 break;
356 err = connect_ring(be);
357 if (err)
358 break;
359 tap_update_blkif_status(be->blkif);
360 break;
362 case XenbusStateClosing:
363 if (be->blkif->xenblkd) {
364 kthread_stop(be->blkif->xenblkd);
365 be->blkif->xenblkd = NULL;
366 }
367 xenbus_switch_state(dev, XenbusStateClosing);
368 break;
370 case XenbusStateClosed:
371 xenbus_switch_state(dev, XenbusStateClosed);
372 if (xenbus_dev_is_online(dev))
373 break;
374 /* fall through if not online */
375 case XenbusStateUnknown:
376 device_unregister(&dev->dev);
377 break;
379 default:
380 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
381 frontend_state);
382 break;
383 }
384 }
387 /**
388 * Switch to Connected state.
389 */
390 static void connect(struct backend_info *be)
391 {
392 int err;
394 struct xenbus_device *dev = be->dev;
396 err = xenbus_switch_state(dev, XenbusStateConnected);
397 if (err)
398 xenbus_dev_fatal(dev, err, "switching to Connected state",
399 dev->nodename);
401 return;
402 }
405 static int connect_ring(struct backend_info *be)
406 {
407 struct xenbus_device *dev = be->dev;
408 unsigned long ring_ref;
409 unsigned int evtchn;
410 char protocol[64];
411 int err;
413 DPRINTK("%s\n", dev->otherend);
415 err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu",
416 &ring_ref, "event-channel", "%u", &evtchn, NULL);
417 if (err) {
418 xenbus_dev_fatal(dev, err,
419 "reading %s/ring-ref and event-channel",
420 dev->otherend);
421 return err;
422 }
424 be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
425 err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
426 "%63s", protocol, NULL);
427 if (err)
428 strcpy(protocol, "unspecified, assuming native");
429 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
430 be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
431 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
432 be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
433 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
434 be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
435 else {
436 xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
437 return -1;
438 }
439 printk(KERN_INFO
440 "blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
441 ring_ref, evtchn, be->blkif->blk_protocol, protocol);
443 /* Map the shared frame, irq etc. */
444 err = tap_blkif_map(be->blkif, ring_ref, evtchn);
445 if (err) {
446 xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
447 ring_ref, evtchn);
448 return err;
449 }
451 return 0;
452 }
455 /* ** Driver Registration ** */
458 static struct xenbus_device_id blktap_ids[] = {
459 { "tap" },
460 { "" }
461 };
464 static struct xenbus_driver blktap = {
465 .name = "tap",
466 .owner = THIS_MODULE,
467 .ids = blktap_ids,
468 .probe = blktap_probe,
469 .remove = blktap_remove,
470 .otherend_changed = tap_frontend_changed
471 };
474 void tap_blkif_xenbus_init(void)
475 {
476 xenbus_register_backend(&blktap);
477 }