ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @ 6766:219d96d545fc

merge?
author cl349@firebug.cl.cam.ac.uk
date Mon Sep 12 20:00:41 2005 +0000 (2005-09-12)
parents 968541972a7c 9ead08216805
children 4d899a738d59 8ca0f98ba8e2
line source
1 /* Xenbus code for blkif backend
2 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 #include <stdarg.h>
19 #include <linux/module.h>
20 #include <asm-xen/xenbus.h>
21 #include "common.h"
23 struct backend_info
24 {
25 struct xenbus_device *dev;
27 /* our communications channel */
28 blkif_t *blkif;
30 long int frontend_id;
31 long int pdev;
32 long int readonly;
34 /* watch back end for changes */
35 struct xenbus_watch backend_watch;
37 /* watch front end for changes */
38 struct xenbus_watch watch;
39 char *frontpath;
40 };
42 static int blkback_remove(struct xenbus_device *dev)
43 {
44 struct backend_info *be = dev->data;
46 if (be->watch.node)
47 unregister_xenbus_watch(&be->watch);
48 unregister_xenbus_watch(&be->backend_watch);
49 if (be->blkif)
50 blkif_put(be->blkif);
51 if (be->frontpath)
52 kfree(be->frontpath);
53 kfree(be);
54 return 0;
55 }
57 /* Front end tells us frame. */
58 static void frontend_changed(struct xenbus_watch *watch, const char *node)
59 {
60 unsigned long ring_ref;
61 unsigned int evtchn;
62 int err;
63 struct backend_info *be
64 = container_of(watch, struct backend_info, watch);
66 /* If other end is gone, delete ourself. */
67 if (node && !xenbus_exists(be->frontpath, "")) {
68 device_unregister(&be->dev->dev);
69 return;
70 }
71 if (be->blkif == NULL || be->blkif->status == CONNECTED)
72 return;
74 err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
75 "event-channel", "%u", &evtchn, NULL);
76 if (err) {
77 xenbus_dev_error(be->dev, err,
78 "reading %s/ring-ref and event-channel",
79 be->frontpath);
80 return;
81 }
83 /* Supply the information about the device the frontend needs */
84 err = xenbus_transaction_start(be->dev->nodename);
85 if (err) {
86 xenbus_dev_error(be->dev, err, "starting transaction");
87 return;
88 }
90 err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
91 vbd_size(&be->blkif->vbd));
92 if (err) {
93 xenbus_dev_error(be->dev, err, "writing %s/sectors",
94 be->dev->nodename);
95 goto abort;
96 }
98 /* FIXME: use a typename instead */
99 err = xenbus_printf(be->dev->nodename, "info", "%u",
100 vbd_info(&be->blkif->vbd));
101 if (err) {
102 xenbus_dev_error(be->dev, err, "writing %s/info",
103 be->dev->nodename);
104 goto abort;
105 }
106 err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
107 vbd_secsize(&be->blkif->vbd));
108 if (err) {
109 xenbus_dev_error(be->dev, err, "writing %s/sector-size",
110 be->dev->nodename);
111 goto abort;
112 }
114 /* Map the shared frame, irq etc. */
115 err = blkif_map(be->blkif, ring_ref, evtchn);
116 if (err) {
117 xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
118 ring_ref, evtchn);
119 goto abort;
120 }
122 xenbus_transaction_end(0);
123 xenbus_dev_ok(be->dev);
125 return;
127 abort:
128 xenbus_transaction_end(1);
129 }
131 /*
132 Setup supplies physical device.
133 We provide event channel and device details to front end.
134 Frontend supplies shared frame and event channel.
135 */
136 static void backend_changed(struct xenbus_watch *watch, const char *node)
137 {
138 int err;
139 char *p;
140 long int handle, pdev;
141 struct backend_info *be
142 = container_of(watch, struct backend_info, backend_watch);
143 struct xenbus_device *dev = be->dev;
145 err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
146 if (XENBUS_EXIST_ERR(err))
147 return;
148 if (err < 0) {
149 xenbus_dev_error(dev, err, "reading physical-device");
150 return;
151 }
152 if (be->pdev && be->pdev != pdev) {
153 printk(KERN_WARNING
154 "changing physical-device not supported\n");
155 return;
156 }
157 be->pdev = pdev;
159 /* If there's a read-only node, we're read only. */
160 p = xenbus_read(dev->nodename, "read-only", NULL);
161 if (!IS_ERR(p)) {
162 be->readonly = 1;
163 kfree(p);
164 }
166 if (be->blkif == NULL) {
167 /* Front end dir is a number, which is used as the handle. */
168 p = strrchr(be->frontpath, '/') + 1;
169 handle = simple_strtoul(p, NULL, 0);
171 be->blkif = alloc_blkif(be->frontend_id);
172 if (IS_ERR(be->blkif)) {
173 err = PTR_ERR(be->blkif);
174 be->blkif = NULL;
175 xenbus_dev_error(dev, err, "creating block interface");
176 return;
177 }
179 err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
180 if (err) {
181 xenbus_dev_error(dev, err, "creating vbd structure");
182 return;
183 }
185 /* Pass in NULL node to skip exist test. */
186 frontend_changed(&be->watch, NULL);
187 }
188 }
190 static int blkback_probe(struct xenbus_device *dev,
191 const struct xenbus_device_id *id)
192 {
193 struct backend_info *be;
194 char *frontend;
195 int err;
197 be = kmalloc(sizeof(*be), GFP_KERNEL);
198 if (!be) {
199 xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
200 return -ENOMEM;
201 }
202 memset(be, 0, sizeof(*be));
204 frontend = NULL;
205 err = xenbus_gather(dev->nodename,
206 "frontend-id", "%li", &be->frontend_id,
207 "frontend", NULL, &frontend,
208 NULL);
209 if (XENBUS_EXIST_ERR(err))
210 goto free_be;
211 if (err < 0) {
212 xenbus_dev_error(dev, err,
213 "reading %s/frontend or frontend-id",
214 dev->nodename);
215 goto free_be;
216 }
217 if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
218 /* If we can't get a frontend path and a frontend-id,
219 * then our bus-id is no longer valid and we need to
220 * destroy the backend device.
221 */
222 err = -ENOENT;
223 goto free_be;
224 }
226 be->dev = dev;
227 be->backend_watch.node = dev->nodename;
228 be->backend_watch.callback = backend_changed;
229 err = register_xenbus_watch(&be->backend_watch);
230 if (err) {
231 be->backend_watch.node = NULL;
232 xenbus_dev_error(dev, err, "adding backend watch on %s",
233 dev->nodename);
234 goto free_be;
235 }
237 be->frontpath = frontend;
238 be->watch.node = be->frontpath;
239 be->watch.callback = frontend_changed;
240 err = register_xenbus_watch(&be->watch);
241 if (err) {
242 be->watch.node = NULL;
243 xenbus_dev_error(dev, err,
244 "adding frontend watch on %s",
245 be->frontpath);
246 goto free_be;
247 }
249 dev->data = be;
251 backend_changed(&be->backend_watch, dev->nodename);
252 return 0;
254 free_be:
255 if (be->backend_watch.node)
256 unregister_xenbus_watch(&be->backend_watch);
257 if (frontend)
258 kfree(frontend);
259 kfree(be);
260 return err;
261 }
263 static struct xenbus_device_id blkback_ids[] = {
264 { "vbd" },
265 { "" }
266 };
268 static struct xenbus_driver blkback = {
269 .name = "vbd",
270 .owner = THIS_MODULE,
271 .ids = blkback_ids,
272 .probe = blkback_probe,
273 .remove = blkback_remove,
274 };
276 void blkif_xenbus_init(void)
277 {
278 xenbus_register_backend(&blkback);
279 }