ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @ 10029:019411cc3ae5

Fix blkif and netif backend teardown -- do not remove devices from
sysfs (and hence trigger hotplug callbacks) until the devices really
are dead. This fixes a bug where the deferred code to free a blk
device was running concurrently with a hotplug-remove callback which
would try to reclaim the underlying storage. In some cases the race
would be lost and the hotplug script would fail.

Thanks to the Zhu Han at Intel for finding the root cause of this
long-term and annoying bug!

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed May 10 13:27:17 2006 +0100 (2006-05-10)
parents 24d25894f071
children 48c0f5489d44
line source
1 /* Xenbus code for blkif backend
2 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
3 Copyright (C) 2005 XenSource Ltd
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
20 #include <stdarg.h>
21 #include <linux/module.h>
22 #include <linux/kthread.h>
23 #include <xen/xenbus.h>
24 #include "common.h"
26 #undef DPRINTK
27 #define DPRINTK(fmt, args...) \
28 pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \
29 __FUNCTION__, __LINE__, ##args)
31 struct backend_info
32 {
33 struct xenbus_device *dev;
34 blkif_t *blkif;
35 struct xenbus_watch backend_watch;
36 unsigned major;
37 unsigned minor;
38 char *mode;
39 };
41 static void connect(struct backend_info *);
42 static int connect_ring(struct backend_info *);
43 static void backend_changed(struct xenbus_watch *, const char **,
44 unsigned int);
47 static void update_blkif_status(blkif_t *blkif)
48 {
49 int err;
51 /* Not ready to connect? */
52 if (!blkif->irq || !blkif->vbd.bdev)
53 return;
55 /* Already connected? */
56 if (blkif->be->dev->state == XenbusStateConnected)
57 return;
59 /* Attempt to connect: exit if we fail to. */
60 connect(blkif->be);
61 if (blkif->be->dev->state != XenbusStateConnected)
62 return;
64 blkif->xenblkd = kthread_run(blkif_schedule, blkif,
65 "xvd %d %02x:%02x",
66 blkif->domid,
67 blkif->be->major, blkif->be->minor);
68 if (IS_ERR(blkif->xenblkd)) {
69 err = PTR_ERR(blkif->xenblkd);
70 blkif->xenblkd = NULL;
71 xenbus_dev_error(blkif->be->dev, err, "start xenblkd");
72 }
73 }
76 static ssize_t show_physical_device(struct device *_dev,
77 struct device_attribute *attr, char *buf)
78 {
79 struct xenbus_device *dev = to_xenbus_device(_dev);
80 struct backend_info *be = dev->data;
81 return sprintf(buf, "%x:%x\n", be->major, be->minor);
82 }
83 DEVICE_ATTR(physical_device, S_IRUSR | S_IRGRP | S_IROTH,
84 show_physical_device, NULL);
87 static ssize_t show_mode(struct device *_dev, struct device_attribute *attr,
88 char *buf)
89 {
90 struct xenbus_device *dev = to_xenbus_device(_dev);
91 struct backend_info *be = dev->data;
92 return sprintf(buf, "%s\n", be->mode);
93 }
94 DEVICE_ATTR(mode, S_IRUSR | S_IRGRP | S_IROTH, show_mode, NULL);
97 static int blkback_remove(struct xenbus_device *dev)
98 {
99 struct backend_info *be = dev->data;
101 DPRINTK("");
103 if (be->backend_watch.node) {
104 unregister_xenbus_watch(&be->backend_watch);
105 kfree(be->backend_watch.node);
106 be->backend_watch.node = NULL;
107 }
108 if (be->blkif) {
109 if (be->blkif->xenblkd)
110 kthread_stop(be->blkif->xenblkd);
111 blkif_free(be->blkif);
112 be->blkif = NULL;
113 }
115 device_remove_file(&dev->dev, &dev_attr_physical_device);
116 device_remove_file(&dev->dev, &dev_attr_mode);
118 kfree(be);
119 dev->data = NULL;
120 return 0;
121 }
124 /**
125 * Entry point to this code when a new device is created. Allocate the basic
126 * structures, and watch the store waiting for the hotplug scripts to tell us
127 * the device's physical major and minor numbers. Switch to InitWait.
128 */
129 static int blkback_probe(struct xenbus_device *dev,
130 const struct xenbus_device_id *id)
131 {
132 int err;
133 struct backend_info *be = kzalloc(sizeof(struct backend_info),
134 GFP_KERNEL);
135 if (!be) {
136 xenbus_dev_fatal(dev, -ENOMEM,
137 "allocating backend structure");
138 return -ENOMEM;
139 }
140 be->dev = dev;
141 dev->data = be;
143 be->blkif = blkif_alloc(dev->otherend_id);
144 if (IS_ERR(be->blkif)) {
145 err = PTR_ERR(be->blkif);
146 be->blkif = NULL;
147 xenbus_dev_fatal(dev, err, "creating block interface");
148 goto fail;
149 }
151 /* setup back pointer */
152 be->blkif->be = be;
154 err = xenbus_watch_path2(dev, dev->nodename, "physical-device",
155 &be->backend_watch, backend_changed);
156 if (err)
157 goto fail;
159 err = xenbus_switch_state(dev, XenbusStateInitWait);
160 if (err)
161 goto fail;
163 return 0;
165 fail:
166 DPRINTK("failed");
167 blkback_remove(dev);
168 return err;
169 }
172 /**
173 * Callback received when the hotplug scripts have placed the physical-device
174 * node. Read it and the mode node, and create a vbd. If the frontend is
175 * ready, connect.
176 */
177 static void backend_changed(struct xenbus_watch *watch,
178 const char **vec, unsigned int len)
179 {
180 int err;
181 unsigned major;
182 unsigned minor;
183 struct backend_info *be
184 = container_of(watch, struct backend_info, backend_watch);
185 struct xenbus_device *dev = be->dev;
187 DPRINTK("");
189 err = xenbus_scanf(XBT_NULL, dev->nodename, "physical-device", "%x:%x",
190 &major, &minor);
191 if (XENBUS_EXIST_ERR(err)) {
192 /* Since this watch will fire once immediately after it is
193 registered, we expect this. Ignore it, and wait for the
194 hotplug scripts. */
195 return;
196 }
197 if (err != 2) {
198 xenbus_dev_fatal(dev, err, "reading physical-device");
199 return;
200 }
202 if ((be->major || be->minor) &&
203 ((be->major != major) || (be->minor != minor))) {
204 printk(KERN_WARNING
205 "blkback: changing physical device (from %x:%x to "
206 "%x:%x) not supported.\n", be->major, be->minor,
207 major, minor);
208 return;
209 }
211 be->mode = xenbus_read(XBT_NULL, dev->nodename, "mode", NULL);
212 if (IS_ERR(be->mode)) {
213 err = PTR_ERR(be->mode);
214 be->mode = NULL;
215 xenbus_dev_fatal(dev, err, "reading mode");
216 return;
217 }
219 if (be->major == 0 && be->minor == 0) {
220 /* Front end dir is a number, which is used as the handle. */
222 char *p = strrchr(dev->otherend, '/') + 1;
223 long handle = simple_strtoul(p, NULL, 0);
225 be->major = major;
226 be->minor = minor;
228 err = vbd_create(be->blkif, handle, major, minor,
229 (NULL == strchr(be->mode, 'w')));
230 if (err) {
231 be->major = 0;
232 be->minor = 0;
233 xenbus_dev_fatal(dev, err, "creating vbd structure");
234 return;
235 }
237 device_create_file(&dev->dev, &dev_attr_physical_device);
238 device_create_file(&dev->dev, &dev_attr_mode);
240 /* We're potentially connected now */
241 update_blkif_status(be->blkif);
242 }
243 }
246 /**
247 * Callback received when the frontend's state changes.
248 */
249 static void frontend_changed(struct xenbus_device *dev,
250 XenbusState frontend_state)
251 {
252 struct backend_info *be = dev->data;
253 int err;
255 DPRINTK("");
257 switch (frontend_state) {
258 case XenbusStateInitialising:
259 break;
261 case XenbusStateInitialised:
262 case XenbusStateConnected:
263 /* Ensure we connect even when two watches fire in
264 close successsion and we miss the intermediate value
265 of frontend_state. */
266 if (dev->state == XenbusStateConnected)
267 break;
269 err = connect_ring(be);
270 if (err)
271 break;
272 update_blkif_status(be->blkif);
273 break;
275 case XenbusStateClosing:
276 xenbus_switch_state(dev, XenbusStateClosing);
277 break;
279 case XenbusStateClosed:
280 device_unregister(&dev->dev);
281 break;
283 case XenbusStateUnknown:
284 case XenbusStateInitWait:
285 default:
286 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
287 frontend_state);
288 break;
289 }
290 }
293 /* ** Connection ** */
296 /**
297 * Write the physical details regarding the block device to the store, and
298 * switch to Connected state.
299 */
300 static void connect(struct backend_info *be)
301 {
302 xenbus_transaction_t xbt;
303 int err;
304 struct xenbus_device *dev = be->dev;
306 DPRINTK("%s", dev->otherend);
308 /* Supply the information about the device the frontend needs */
309 again:
310 err = xenbus_transaction_start(&xbt);
312 if (err) {
313 xenbus_dev_fatal(dev, err, "starting transaction");
314 return;
315 }
317 err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu",
318 vbd_size(&be->blkif->vbd));
319 if (err) {
320 xenbus_dev_fatal(dev, err, "writing %s/sectors",
321 dev->nodename);
322 goto abort;
323 }
325 /* FIXME: use a typename instead */
326 err = xenbus_printf(xbt, dev->nodename, "info", "%u",
327 vbd_info(&be->blkif->vbd));
328 if (err) {
329 xenbus_dev_fatal(dev, err, "writing %s/info",
330 dev->nodename);
331 goto abort;
332 }
333 err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
334 vbd_secsize(&be->blkif->vbd));
335 if (err) {
336 xenbus_dev_fatal(dev, err, "writing %s/sector-size",
337 dev->nodename);
338 goto abort;
339 }
341 err = xenbus_transaction_end(xbt, 0);
342 if (err == -EAGAIN)
343 goto again;
344 if (err)
345 xenbus_dev_fatal(dev, err, "ending transaction");
347 err = xenbus_switch_state(dev, XenbusStateConnected);
348 if (err)
349 xenbus_dev_fatal(dev, err, "switching to Connected state",
350 dev->nodename);
352 return;
353 abort:
354 xenbus_transaction_end(xbt, 1);
355 }
358 static int connect_ring(struct backend_info *be)
359 {
360 struct xenbus_device *dev = be->dev;
361 unsigned long ring_ref;
362 unsigned int evtchn;
363 int err;
365 DPRINTK("%s", dev->otherend);
367 err = xenbus_gather(XBT_NULL, dev->otherend, "ring-ref", "%lu", &ring_ref,
368 "event-channel", "%u", &evtchn, NULL);
369 if (err) {
370 xenbus_dev_fatal(dev, err,
371 "reading %s/ring-ref and event-channel",
372 dev->otherend);
373 return err;
374 }
376 /* Map the shared frame, irq etc. */
377 err = blkif_map(be->blkif, ring_ref, evtchn);
378 if (err) {
379 xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
380 ring_ref, evtchn);
381 return err;
382 }
384 return 0;
385 }
388 /* ** Driver Registration ** */
391 static struct xenbus_device_id blkback_ids[] = {
392 { "vbd" },
393 { "" }
394 };
397 static struct xenbus_driver blkback = {
398 .name = "vbd",
399 .owner = THIS_MODULE,
400 .ids = blkback_ids,
401 .probe = blkback_probe,
402 .remove = blkback_remove,
403 .otherend_changed = frontend_changed
404 };
407 void blkif_xenbus_init(void)
408 {
409 xenbus_register_backend(&blkback);
410 }
413 /*
414 * Local variables:
415 * c-file-style: "linux"
416 * indent-tabs-mode: t
417 * c-indent-level: 8
418 * c-basic-offset: 8
419 * tab-width: 8
420 * End:
421 */