direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @ 8017:cbf7efa871ae

Minor tidy, no semantic change.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Nov 24 15:52:42 2005 +0000 (2005-11-24)
parents bf7c16e761fc
children 8c3ed250366c
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 */
21 #include <stdarg.h>
22 #include <linux/module.h>
23 #include <asm-xen/xenbus.h>
24 #include "common.h"
27 #if 0
28 #undef DPRINTK
29 #define DPRINTK(fmt, args...) \
30 printk("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
31 #endif
34 struct backend_info
35 {
36 struct xenbus_device *dev;
37 blkif_t *blkif;
38 struct xenbus_watch backend_watch;
40 long int pdev;
41 long int readonly;
42 };
45 static void maybe_connect(struct backend_info *);
46 static void connect(struct backend_info *);
47 static int connect_ring(struct backend_info *);
48 static void backend_changed(struct xenbus_watch *, const char **,
49 unsigned int);
52 static int blkback_remove(struct xenbus_device *dev)
53 {
54 struct backend_info *be = dev->data;
56 DPRINTK("");
58 if (be->backend_watch.node) {
59 unregister_xenbus_watch(&be->backend_watch);
60 kfree(be->backend_watch.node);
61 be->backend_watch.node = NULL;
62 }
63 if (be->blkif) {
64 blkif_put(be->blkif);
65 be->blkif = NULL;
66 }
67 kfree(be);
68 dev->data = NULL;
69 return 0;
70 }
73 /**
74 * Entry point to this code when a new device is created. Allocate the basic
75 * structures, and watch the store waiting for the hotplug scripts to tell us
76 * the device's physical-device. Switch to InitWait.
77 */
78 static int blkback_probe(struct xenbus_device *dev,
79 const struct xenbus_device_id *id)
80 {
81 int err;
82 struct backend_info *be = kmalloc(sizeof(struct backend_info),
83 GFP_KERNEL);
84 if (!be) {
85 xenbus_dev_fatal(dev, -ENOMEM,
86 "allocating backend structure");
87 return -ENOMEM;
88 }
89 memset(be, 0, sizeof(*be));
91 be->dev = dev;
92 dev->data = be;
94 be->blkif = alloc_blkif(dev->otherend_id);
95 if (IS_ERR(be->blkif)) {
96 err = PTR_ERR(be->blkif);
97 be->blkif = NULL;
98 xenbus_dev_fatal(dev, err, "creating block interface");
99 goto fail;
100 }
102 err = xenbus_watch_path2(dev, dev->nodename, "physical-device",
103 &be->backend_watch, backend_changed);
104 if (err)
105 goto fail;
107 err = xenbus_switch_state(dev, NULL, XenbusStateInitWait);
108 if (err)
109 goto fail;
111 return 0;
113 fail:
114 DPRINTK("failed");
115 blkback_remove(dev);
116 return err;
117 }
120 /**
121 * Callback received when the hotplug scripts have placed the physical-device
122 * node. Read it and the read-only node, and create a vbd. If the frontend
123 * is ready, connect.
124 */
125 static void backend_changed(struct xenbus_watch *watch,
126 const char **vec, unsigned int len)
127 {
128 int err;
129 char *p;
130 long pdev;
131 struct backend_info *be
132 = container_of(watch, struct backend_info, backend_watch);
133 struct xenbus_device *dev = be->dev;
135 DPRINTK("");
137 err = xenbus_scanf(NULL, dev->nodename,
138 "physical-device", "%li", &pdev);
139 if (XENBUS_EXIST_ERR(err)) {
140 /* Since this watch will fire once immediately after it is
141 registered, we expect this. Ignore it, and wait for the
142 hotplug scripts. */
143 return;
144 }
145 if (err != 1) {
146 xenbus_dev_fatal(dev, err, "reading physical-device");
147 return;
148 }
149 if (be->pdev && be->pdev != pdev) {
150 printk(KERN_WARNING
151 "blkback: changing physical-device (from %ld to %ld) "
152 "not supported.\n", be->pdev, pdev);
153 return;
154 }
156 /* If there's a read-only node, we're read only. */
157 p = xenbus_read(NULL, dev->nodename, "read-only", NULL);
158 if (!IS_ERR(p)) {
159 be->readonly = 1;
160 kfree(p);
161 }
163 if (be->pdev == 0L) {
164 /* Front end dir is a number, which is used as the handle. */
166 long handle;
168 p = strrchr(dev->otherend, '/') + 1;
169 handle = simple_strtoul(p, NULL, 0);
171 be->pdev = pdev;
173 err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
174 if (err) {
175 be->pdev = 0L;
176 xenbus_dev_fatal(dev, err,
177 "creating vbd structure");
178 return;
179 }
181 maybe_connect(be);
182 }
183 }
186 /**
187 * Callback received when the frontend's state changes.
188 */
189 static void frontend_changed(struct xenbus_device *dev,
190 XenbusState frontend_state)
191 {
192 struct backend_info *be = dev->data;
193 int err;
195 DPRINTK("");
197 switch (frontend_state) {
198 case XenbusStateInitialising:
199 case XenbusStateConnected:
200 break;
202 case XenbusStateInitialised:
203 err = connect_ring(be);
204 if (err) {
205 return;
206 }
207 maybe_connect(be);
208 break;
210 case XenbusStateClosing:
211 xenbus_switch_state(dev, NULL, XenbusStateClosing);
212 break;
214 case XenbusStateClosed:
215 device_unregister(&dev->dev);
216 break;
218 case XenbusStateUnknown:
219 case XenbusStateInitWait:
220 default:
221 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
222 frontend_state);
223 break;
224 }
225 }
228 /* ** Connection ** */
231 static void maybe_connect(struct backend_info *be)
232 {
233 if (be->pdev != 0L && be->blkif->status == CONNECTED)
234 connect(be);
235 }
238 /**
239 * Write the physical details regarding the block device to the store, and
240 * switch to Connected state.
241 */
242 static void connect(struct backend_info *be)
243 {
244 struct xenbus_transaction *xbt;
245 int err;
246 struct xenbus_device *dev = be->dev;
248 DPRINTK("%s", dev->otherend);
250 /* Supply the information about the device the frontend needs */
251 again:
252 xbt = xenbus_transaction_start();
254 if (IS_ERR(xbt)) {
255 err = PTR_ERR(xbt);
256 xenbus_dev_fatal(dev, err, "starting transaction");
257 return;
258 }
260 err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu",
261 vbd_size(&be->blkif->vbd));
262 if (err) {
263 xenbus_dev_fatal(dev, err, "writing %s/sectors",
264 dev->nodename);
265 goto abort;
266 }
268 /* FIXME: use a typename instead */
269 err = xenbus_printf(xbt, dev->nodename, "info", "%u",
270 vbd_info(&be->blkif->vbd));
271 if (err) {
272 xenbus_dev_fatal(dev, err, "writing %s/info",
273 dev->nodename);
274 goto abort;
275 }
276 err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
277 vbd_secsize(&be->blkif->vbd));
278 if (err) {
279 xenbus_dev_fatal(dev, err, "writing %s/sector-size",
280 dev->nodename);
281 goto abort;
282 }
284 err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
285 if (err)
286 goto abort;
288 err = xenbus_transaction_end(xbt, 0);
289 if (err == -EAGAIN)
290 goto again;
291 if (err)
292 xenbus_dev_fatal(dev, err, "ending transaction");
293 return;
294 abort:
295 xenbus_transaction_end(xbt, 1);
296 }
299 static int connect_ring(struct backend_info *be)
300 {
301 struct xenbus_device *dev = be->dev;
302 unsigned long ring_ref;
303 unsigned int evtchn;
304 int err;
306 DPRINTK("%s", dev->otherend);
308 err = xenbus_gather(NULL, dev->otherend, "ring-ref", "%lu", &ring_ref,
309 "event-channel", "%u", &evtchn, NULL);
310 if (err) {
311 xenbus_dev_fatal(dev, err,
312 "reading %s/ring-ref and event-channel",
313 dev->otherend);
314 return err;
315 }
317 /* Map the shared frame, irq etc. */
318 err = blkif_map(be->blkif, ring_ref, evtchn);
319 if (err) {
320 xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
321 ring_ref, evtchn);
322 return err;
323 }
325 return 0;
326 }
329 /* ** Driver Registration ** */
332 static struct xenbus_device_id blkback_ids[] = {
333 { "vbd" },
334 { "" }
335 };
338 static struct xenbus_driver blkback = {
339 .name = "vbd",
340 .owner = THIS_MODULE,
341 .ids = blkback_ids,
342 .probe = blkback_probe,
343 .remove = blkback_remove,
344 .otherend_changed = frontend_changed
345 };
348 void blkif_xenbus_init(void)
349 {
350 xenbus_register_backend(&blkback);
351 }
354 /*
355 * Local variables:
356 * c-file-style: "linux"
357 * indent-tabs-mode: t
358 * c-indent-level: 8
359 * c-basic-offset: 8
360 * tab-width: 8
361 * End:
362 */