debuggers.hg

view linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @ 6649:f59e0163540e

Updates to blktap driver and user code.

Mostly this makes the tap code work again with all of the changes that
have happened to the block drivers recently. We now use a shared page
per VBD (to the driver), and handle control information through the
store. The taplib interfaces have changed to be based around per-vbd
data structures that you can attach arbitrary handlers for.

There is also initial code for a user-level blockback driver, which
aims to get around the use of loopbacks for file-based vbds. Still
plenty of work to do here -- this is a working incremental checkin and
I'm away from this for the next four weeks.

Signed-off-by: Andrew Warfield <andrew.warfield@cl.cam.ac.uk>
author akw27@arcadians.cl.cam.ac.uk
date Sun Sep 04 21:19:44 2005 +0000 (2005-09-04)
parents
children ac6605bceb9d 4d899a738d59 e7c7196fa329 b2f4823b6ff0
line source
1 /* Xenbus code for blkif tap
3 A Warfield.
5 Hastily modified from the oroginal backend code:
7 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
24 #include <stdarg.h>
25 #include <linux/module.h>
26 #include <asm-xen/xenbus.h>
27 #include "common.h"
29 struct backend_info
30 {
31 struct xenbus_device *dev;
33 /* our communications channel */
34 blkif_t *blkif;
36 long int frontend_id;
38 /* watch back end for changes */
39 struct xenbus_watch backend_watch;
41 /* watch front end for changes */
42 struct xenbus_watch watch;
43 char *frontpath;
44 };
46 static int blkback_remove(struct xenbus_device *dev)
47 {
48 struct backend_info *be = dev->data;
50 if (be->watch.node)
51 unregister_xenbus_watch(&be->watch);
52 unregister_xenbus_watch(&be->backend_watch);
53 if (be->blkif)
54 blkif_put(be->blkif);
55 if (be->frontpath)
56 kfree(be->frontpath);
57 kfree(be);
58 return 0;
59 }
61 /* Front end tells us frame. */
62 static void frontend_changed(struct xenbus_watch *watch, const char *node)
63 {
64 unsigned long ring_ref;
65 unsigned int evtchn;
66 int err;
67 struct backend_info *be
68 = container_of(watch, struct backend_info, watch);
70 /* If other end is gone, delete ourself. */
71 if (node && !xenbus_exists(be->frontpath, "")) {
72 xenbus_rm(be->dev->nodename, "");
73 device_unregister(&be->dev->dev);
74 return;
75 }
76 if (be->blkif == NULL || be->blkif->status == CONNECTED)
77 return;
79 err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
80 "event-channel", "%u", &evtchn, NULL);
81 if (err) {
82 xenbus_dev_error(be->dev, err,
83 "reading %s/ring-ref and event-channel",
84 be->frontpath);
85 return;
86 }
88 /* Map the shared frame, irq etc. */
89 err = blkif_map(be->blkif, ring_ref, evtchn);
90 if (err) {
91 xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
92 ring_ref, evtchn);
93 goto abort;
94 }
96 xenbus_dev_ok(be->dev);
98 return;
100 abort:
101 xenbus_transaction_end(1);
102 }
104 /*
105 Setup supplies physical device.
106 We provide event channel and device details to front end.
107 Frontend supplies shared frame and event channel.
108 */
109 static void backend_changed(struct xenbus_watch *watch, const char *node)
110 {
111 int err;
112 char *p;
113 long int handle;
114 struct backend_info *be
115 = container_of(watch, struct backend_info, backend_watch);
116 struct xenbus_device *dev = be->dev;
118 if (be->blkif == NULL) {
119 /* Front end dir is a number, which is used as the handle. */
120 p = strrchr(be->frontpath, '/') + 1;
121 handle = simple_strtoul(p, NULL, 0);
123 be->blkif = alloc_blkif(be->frontend_id);
124 if (IS_ERR(be->blkif)) {
125 err = PTR_ERR(be->blkif);
126 be->blkif = NULL;
127 xenbus_dev_error(dev, err, "creating block interface");
128 return;
129 }
131 /* Pass in NULL node to skip exist test. */
132 frontend_changed(&be->watch, NULL);
133 }
134 }
136 static int blkback_probe(struct xenbus_device *dev,
137 const struct xenbus_device_id *id)
138 {
139 struct backend_info *be;
140 char *frontend;
141 int err;
143 be = kmalloc(sizeof(*be), GFP_KERNEL);
144 if (!be) {
145 xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
146 return -ENOMEM;
147 }
148 memset(be, 0, sizeof(*be));
150 frontend = NULL;
151 err = xenbus_gather(dev->nodename,
152 "frontend-id", "%li", &be->frontend_id,
153 "frontend", NULL, &frontend,
154 NULL);
155 if (XENBUS_EXIST_ERR(err))
156 goto free_be;
157 if (err < 0) {
158 xenbus_dev_error(dev, err,
159 "reading %s/frontend or frontend-id",
160 dev->nodename);
161 goto free_be;
162 }
163 if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
164 /* If we can't get a frontend path and a frontend-id,
165 * then our bus-id is no longer valid and we need to
166 * destroy the backend device.
167 */
168 err = -ENOENT;
169 goto free_be;
170 }
172 be->dev = dev;
173 be->backend_watch.node = dev->nodename;
174 be->backend_watch.callback = backend_changed;
175 err = register_xenbus_watch(&be->backend_watch);
176 if (err) {
177 be->backend_watch.node = NULL;
178 xenbus_dev_error(dev, err, "adding backend watch on %s",
179 dev->nodename);
180 goto free_be;
181 }
183 be->frontpath = frontend;
184 be->watch.node = be->frontpath;
185 be->watch.callback = frontend_changed;
186 err = register_xenbus_watch(&be->watch);
187 if (err) {
188 be->watch.node = NULL;
189 xenbus_dev_error(dev, err,
190 "adding frontend watch on %s",
191 be->frontpath);
192 goto free_be;
193 }
195 dev->data = be;
197 backend_changed(&be->backend_watch, dev->nodename);
198 return 0;
200 free_be:
201 if (be->backend_watch.node)
202 unregister_xenbus_watch(&be->backend_watch);
203 if (frontend)
204 kfree(frontend);
205 kfree(be);
206 return err;
207 }
209 static struct xenbus_device_id blkback_ids[] = {
210 { "vbd" },
211 { "" }
212 };
214 static struct xenbus_driver blkback = {
215 .name = "vbd",
216 .owner = THIS_MODULE,
217 .ids = blkback_ids,
218 .probe = blkback_probe,
219 .remove = blkback_remove,
220 };
222 void blkif_xenbus_init(void)
223 {
224 xenbus_register_backend(&blkback);
225 }