xen-vtx-unstable

view linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @ 6796:0d8c0db04258

Don't return failure when trying to delete a non-existent node.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 21:52:24 2005 +0000 (2005-09-13)
parents feff6bf0417e
children
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 blkif_put(be->blkif);
182 be->blkif = NULL;
183 xenbus_dev_error(dev, err, "creating vbd structure");
184 return;
185 }
187 /* Pass in NULL node to skip exist test. */
188 frontend_changed(&be->watch, NULL);
189 }
190 }
192 static int blkback_probe(struct xenbus_device *dev,
193 const struct xenbus_device_id *id)
194 {
195 struct backend_info *be;
196 char *frontend;
197 int err;
199 be = kmalloc(sizeof(*be), GFP_KERNEL);
200 if (!be) {
201 xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
202 return -ENOMEM;
203 }
204 memset(be, 0, sizeof(*be));
206 frontend = NULL;
207 err = xenbus_gather(dev->nodename,
208 "frontend-id", "%li", &be->frontend_id,
209 "frontend", NULL, &frontend,
210 NULL);
211 if (XENBUS_EXIST_ERR(err))
212 goto free_be;
213 if (err < 0) {
214 xenbus_dev_error(dev, err,
215 "reading %s/frontend or frontend-id",
216 dev->nodename);
217 goto free_be;
218 }
219 if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
220 /* If we can't get a frontend path and a frontend-id,
221 * then our bus-id is no longer valid and we need to
222 * destroy the backend device.
223 */
224 err = -ENOENT;
225 goto free_be;
226 }
228 be->dev = dev;
229 be->backend_watch.node = dev->nodename;
230 be->backend_watch.callback = backend_changed;
231 err = register_xenbus_watch(&be->backend_watch);
232 if (err) {
233 be->backend_watch.node = NULL;
234 xenbus_dev_error(dev, err, "adding backend watch on %s",
235 dev->nodename);
236 goto free_be;
237 }
239 be->frontpath = frontend;
240 be->watch.node = be->frontpath;
241 be->watch.callback = frontend_changed;
242 err = register_xenbus_watch(&be->watch);
243 if (err) {
244 be->watch.node = NULL;
245 xenbus_dev_error(dev, err,
246 "adding frontend watch on %s",
247 be->frontpath);
248 goto free_be;
249 }
251 dev->data = be;
253 backend_changed(&be->backend_watch, dev->nodename);
254 return 0;
256 free_be:
257 if (be->backend_watch.node)
258 unregister_xenbus_watch(&be->backend_watch);
259 if (frontend)
260 kfree(frontend);
261 kfree(be);
262 return err;
263 }
265 static struct xenbus_device_id blkback_ids[] = {
266 { "vbd" },
267 { "" }
268 };
270 static struct xenbus_driver blkback = {
271 .name = "vbd",
272 .owner = THIS_MODULE,
273 .ids = blkback_ids,
274 .probe = blkback_probe,
275 .remove = blkback_remove,
276 };
278 void blkif_xenbus_init(void)
279 {
280 xenbus_register_backend(&blkback);
281 }