ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/netback/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 dadadf9aeee7
children 48c0f5489d44
line source
1 /* Xenbus code for netif 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 */
21 #include <stdarg.h>
22 #include <linux/module.h>
23 #include <xen/xenbus.h>
24 #include <xen/net_driver_util.h>
25 #include "common.h"
28 #if 0
29 #undef DPRINTK
30 #define DPRINTK(fmt, args...) \
31 printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
32 #endif
35 struct backend_info
36 {
37 struct xenbus_device *dev;
38 netif_t *netif;
39 struct xenbus_watch backend_watch;
40 XenbusState frontend_state;
41 };
44 static int connect_rings(struct backend_info *);
45 static void connect(struct backend_info *);
46 static void maybe_connect(struct backend_info *);
47 static void backend_changed(struct xenbus_watch *, const char **,
48 unsigned int);
51 static int netback_remove(struct xenbus_device *dev)
52 {
53 struct backend_info *be = dev->data;
55 if (be->backend_watch.node) {
56 unregister_xenbus_watch(&be->backend_watch);
57 kfree(be->backend_watch.node);
58 be->backend_watch.node = NULL;
59 }
60 if (be->netif) {
61 netif_disconnect(be->netif);
62 be->netif = NULL;
63 }
64 kfree(be);
65 dev->data = NULL;
66 return 0;
67 }
70 /**
71 * Entry point to this code when a new device is created. Allocate the basic
72 * structures, and watch the store waiting for the hotplug scripts to tell us
73 * the device's handle. Switch to InitWait.
74 */
75 static int netback_probe(struct xenbus_device *dev,
76 const struct xenbus_device_id *id)
77 {
78 int err;
79 struct backend_info *be = kzalloc(sizeof(struct backend_info),
80 GFP_KERNEL);
81 if (!be) {
82 xenbus_dev_fatal(dev, -ENOMEM,
83 "allocating backend structure");
84 return -ENOMEM;
85 }
87 be->dev = dev;
88 dev->data = be;
90 err = xenbus_watch_path2(dev, dev->nodename, "handle",
91 &be->backend_watch, backend_changed);
92 if (err)
93 goto fail;
95 err = xenbus_switch_state(dev, XenbusStateInitWait);
96 if (err) {
97 goto fail;
98 }
100 return 0;
102 fail:
103 DPRINTK("failed");
104 netback_remove(dev);
105 return err;
106 }
109 /**
110 * Handle the creation of the hotplug script environment. We add the script
111 * and vif variables to the environment, for the benefit of the vif-* hotplug
112 * scripts.
113 */
114 static int netback_uevent(struct xenbus_device *xdev, char **envp,
115 int num_envp, char *buffer, int buffer_size)
116 {
117 struct backend_info *be = xdev->data;
118 netif_t *netif = be->netif;
119 int i = 0, length = 0;
120 char *val;
122 DPRINTK("netback_uevent");
124 val = xenbus_read(XBT_NULL, xdev->nodename, "script", NULL);
125 if (IS_ERR(val)) {
126 int err = PTR_ERR(val);
127 xenbus_dev_fatal(xdev, err, "reading script");
128 return err;
129 }
130 else {
131 add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
132 &length, "script=%s", val);
133 kfree(val);
134 }
136 add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
137 "vif=%s", netif->dev->name);
139 envp[i] = NULL;
141 return 0;
142 }
145 /**
146 * Callback received when the hotplug scripts have placed the handle node.
147 * Read it, and create a netif structure. If the frontend is ready, connect.
148 */
149 static void backend_changed(struct xenbus_watch *watch,
150 const char **vec, unsigned int len)
151 {
152 int err;
153 long handle;
154 struct backend_info *be
155 = container_of(watch, struct backend_info, backend_watch);
156 struct xenbus_device *dev = be->dev;
158 DPRINTK("");
160 err = xenbus_scanf(XBT_NULL, dev->nodename, "handle", "%li", &handle);
161 if (XENBUS_EXIST_ERR(err)) {
162 /* Since this watch will fire once immediately after it is
163 registered, we expect this. Ignore it, and wait for the
164 hotplug scripts. */
165 return;
166 }
167 if (err != 1) {
168 xenbus_dev_fatal(dev, err, "reading handle");
169 return;
170 }
172 if (be->netif == NULL) {
173 u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
175 be->netif = netif_alloc(dev->otherend_id, handle, be_mac);
176 if (IS_ERR(be->netif)) {
177 err = PTR_ERR(be->netif);
178 be->netif = NULL;
179 xenbus_dev_fatal(dev, err, "creating interface");
180 return;
181 }
183 kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
185 maybe_connect(be);
186 }
187 }
190 /**
191 * Callback received when the frontend's state changes.
192 */
193 static void frontend_changed(struct xenbus_device *dev,
194 XenbusState frontend_state)
195 {
196 struct backend_info *be = dev->data;
198 DPRINTK("");
200 be->frontend_state = frontend_state;
202 switch (frontend_state) {
203 case XenbusStateInitialising:
204 case XenbusStateInitialised:
205 break;
207 case XenbusStateConnected:
208 maybe_connect(be);
209 break;
211 case XenbusStateClosing:
212 xenbus_switch_state(dev, XenbusStateClosing);
213 break;
215 case XenbusStateClosed:
216 if (be->netif != NULL)
217 kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
218 device_unregister(&dev->dev);
219 break;
221 case XenbusStateUnknown:
222 case XenbusStateInitWait:
223 default:
224 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
225 frontend_state);
226 break;
227 }
228 }
231 /* ** Connection ** */
234 static void maybe_connect(struct backend_info *be)
235 {
236 if (be->netif && (be->frontend_state == XenbusStateConnected))
237 connect(be);
238 }
240 static void xen_net_read_rate(struct xenbus_device *dev,
241 unsigned long *bytes, unsigned long *usec)
242 {
243 char *s, *e;
244 unsigned long b, u;
245 char *ratestr;
247 /* Default to unlimited bandwidth. */
248 *bytes = ~0UL;
249 *usec = 0;
251 ratestr = xenbus_read(XBT_NULL, dev->nodename, "rate", NULL);
252 if (IS_ERR(ratestr))
253 return;
255 s = ratestr;
256 b = simple_strtoul(s, &e, 10);
257 if ((s == e) || (*e != ','))
258 goto fail;
260 s = e + 1;
261 u = simple_strtoul(s, &e, 10);
262 if ((s == e) || (*e != '\0'))
263 goto fail;
265 *bytes = b;
266 *usec = u;
268 kfree(ratestr);
269 return;
271 fail:
272 WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n");
273 kfree(ratestr);
274 }
277 static void connect(struct backend_info *be)
278 {
279 int err;
280 struct xenbus_device *dev = be->dev;
282 err = connect_rings(be);
283 if (err)
284 return;
286 err = xen_net_read_mac(dev, be->netif->fe_dev_addr);
287 if (err) {
288 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
289 return;
290 }
292 xen_net_read_rate(dev, &be->netif->credit_bytes,
293 &be->netif->credit_usec);
294 be->netif->remaining_credit = be->netif->credit_bytes;
296 xenbus_switch_state(dev, XenbusStateConnected);
297 }
300 static int connect_rings(struct backend_info *be)
301 {
302 struct xenbus_device *dev = be->dev;
303 unsigned long tx_ring_ref, rx_ring_ref;
304 unsigned int evtchn;
305 int err;
307 DPRINTK("");
309 err = xenbus_gather(XBT_NULL, dev->otherend,
310 "tx-ring-ref", "%lu", &tx_ring_ref,
311 "rx-ring-ref", "%lu", &rx_ring_ref,
312 "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 = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
322 if (err) {
323 xenbus_dev_fatal(dev, err,
324 "mapping shared-frames %lu/%lu port %u",
325 tx_ring_ref, rx_ring_ref, evtchn);
326 return err;
327 }
328 return 0;
329 }
332 /* ** Driver Registration ** */
335 static struct xenbus_device_id netback_ids[] = {
336 { "vif" },
337 { "" }
338 };
341 static struct xenbus_driver netback = {
342 .name = "vif",
343 .owner = THIS_MODULE,
344 .ids = netback_ids,
345 .probe = netback_probe,
346 .remove = netback_remove,
347 .uevent = netback_uevent,
348 .otherend_changed = frontend_changed,
349 };
352 void netif_xenbus_init(void)
353 {
354 xenbus_register_backend(&netback);
355 }
358 /*
359 * Local variables:
360 * c-file-style: "linux"
361 * indent-tabs-mode: t
362 * c-indent-level: 8
363 * c-basic-offset: 8
364 * tab-width: 8
365 * End:
366 */