debuggers.hg

view extras/mini-os/console/xencons_ring.c @ 20689:23bc248302df

mini-os: Fix memory leaks in blkfront, netfront, pcifront, etc.

The return value of Xenbus routines xenbus_transaction_start(),
xenbus_printf(), xenbus_transaction_end(), etc. is a pointer of error
message. This pointer should be passed to free() to release the
allocated memory when it is no longer needed.

Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Dec 14 09:51:07 2009 +0000 (2009-12-14)
parents e10d641b413f
children 4bde3bb310b4
line source
1 #include <mini-os/types.h>
2 #include <mini-os/wait.h>
3 #include <mini-os/mm.h>
4 #include <mini-os/hypervisor.h>
5 #include <mini-os/events.h>
6 #include <mini-os/os.h>
7 #include <mini-os/lib.h>
8 #include <mini-os/xenbus.h>
9 #include <xen/io/console.h>
10 #include <xen/io/protocols.h>
11 #include <xen/io/ring.h>
12 #include <mini-os/xmalloc.h>
13 #include <mini-os/gnttab.h>
15 DECLARE_WAIT_QUEUE_HEAD(console_queue);
17 static inline void notify_daemon(struct consfront_dev *dev)
18 {
19 /* Use evtchn: this is called early, before irq is set up. */
20 if (!dev)
21 notify_remote_via_evtchn(start_info.console.domU.evtchn);
22 else
23 notify_remote_via_evtchn(dev->evtchn);
24 }
26 static inline struct xencons_interface *xencons_interface(void)
27 {
28 return mfn_to_virt(start_info.console.domU.mfn);
29 }
31 int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len)
32 {
33 int sent = 0;
34 struct xencons_interface *intf;
35 XENCONS_RING_IDX cons, prod;
37 if (!dev)
38 intf = xencons_interface();
39 else
40 intf = dev->ring;
42 cons = intf->out_cons;
43 prod = intf->out_prod;
44 mb();
45 BUG_ON((prod - cons) > sizeof(intf->out));
47 while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
48 intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
50 wmb();
51 intf->out_prod = prod;
53 return sent;
54 }
56 int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len)
57 {
58 int sent;
60 sent = xencons_ring_send_no_notify(dev, data, len);
61 notify_daemon(dev);
63 return sent;
64 }
68 static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
69 {
70 #ifdef HAVE_LIBC
71 struct consfront_dev *dev = (struct consfront_dev *) data;
72 int fd = dev ? dev->fd : -1;
74 if (fd != -1)
75 files[fd].read = 1;
77 wake_up(&console_queue);
78 #else
79 struct xencons_interface *intf = xencons_interface();
80 XENCONS_RING_IDX cons, prod;
82 cons = intf->in_cons;
83 prod = intf->in_prod;
84 mb();
85 BUG_ON((prod - cons) > sizeof(intf->in));
87 while (cons != prod) {
88 xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
89 cons++;
90 }
92 mb();
93 intf->in_cons = cons;
95 notify_daemon(dev);
97 xencons_tx();
98 #endif
99 }
101 #ifdef HAVE_LIBC
102 int xencons_ring_avail(struct consfront_dev *dev)
103 {
104 struct xencons_interface *intf;
105 XENCONS_RING_IDX cons, prod;
107 if (!dev)
108 intf = xencons_interface();
109 else
110 intf = dev->ring;
112 cons = intf->in_cons;
113 prod = intf->in_prod;
114 mb();
115 BUG_ON((prod - cons) > sizeof(intf->in));
117 return prod - cons;
118 }
120 int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
121 {
122 struct xencons_interface *intf;
123 XENCONS_RING_IDX cons, prod;
124 unsigned filled = 0;
126 if (!dev)
127 intf = xencons_interface();
128 else
129 intf = dev->ring;
131 cons = intf->in_cons;
132 prod = intf->in_prod;
133 mb();
134 BUG_ON((prod - cons) > sizeof(intf->in));
136 while (filled < len && cons + filled != prod) {
137 data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in));
138 filled++;
139 }
141 mb();
142 intf->in_cons = cons + filled;
144 notify_daemon(dev);
146 return filled;
147 }
148 #endif
150 struct consfront_dev *xencons_ring_init(void)
151 {
152 int err;
153 struct consfront_dev *dev;
155 if (!start_info.console.domU.evtchn)
156 return 0;
158 dev = malloc(sizeof(struct consfront_dev));
159 memset(dev, 0, sizeof(struct consfront_dev));
160 dev->nodename = "device/console";
161 dev->dom = 0;
162 dev->backend = 0;
163 dev->ring_ref = 0;
165 #ifdef HAVE_LIBC
166 dev->fd = -1;
167 #endif
168 dev->evtchn = start_info.console.domU.evtchn;
169 dev->ring = (struct xencons_interface *) mfn_to_virt(start_info.console.domU.mfn);
171 err = bind_evtchn(dev->evtchn, handle_input, dev);
172 if (err <= 0) {
173 printk("XEN console request chn bind failed %i\n", err);
174 free(dev);
175 return NULL;
176 }
177 unmask_evtchn(dev->evtchn);
179 /* In case we have in-flight data after save/restore... */
180 notify_daemon(dev);
182 return dev;
183 }
185 void free_consfront(struct consfront_dev *dev)
186 {
187 mask_evtchn(dev->evtchn);
189 free(dev->backend);
191 gnttab_end_access(dev->ring_ref);
192 free_page(dev->ring);
194 unbind_evtchn(dev->evtchn);
196 free(dev->nodename);
197 free(dev);
198 }
200 struct consfront_dev *init_consfront(char *_nodename)
201 {
202 xenbus_transaction_t xbt;
203 char* err;
204 char* message=NULL;
205 int retry=0;
206 char* msg = NULL;
207 char nodename[256];
208 char path[256];
209 static int consfrontends = 1;
210 struct consfront_dev *dev;
211 int res;
213 if (!_nodename)
214 snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends);
215 else
216 strncpy(nodename, _nodename, sizeof(nodename));
218 printk("******************* CONSFRONT for %s **********\n\n\n", nodename);
220 consfrontends++;
221 dev = malloc(sizeof(*dev));
222 memset(dev, 0, sizeof(*dev));
223 dev->nodename = strdup(nodename);
224 #ifdef HAVE_LIBC
225 dev->fd = -1;
226 #endif
228 snprintf(path, sizeof(path), "%s/backend-id", nodename);
229 if ((res = xenbus_read_integer(path)) < 0)
230 return NULL;
231 else
232 dev->dom = res;
233 evtchn_alloc_unbound(dev->dom, handle_input, dev, &dev->evtchn);
235 dev->ring = (struct xencons_interface *) alloc_page();
236 memset(dev->ring, 0, PAGE_SIZE);
237 dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0);
239 dev->events = NULL;
241 again:
242 err = xenbus_transaction_start(&xbt);
243 if (err) {
244 printk("starting transaction\n");
245 free(err);
246 }
248 err = xenbus_printf(xbt, nodename, "ring-ref","%u",
249 dev->ring_ref);
250 if (err) {
251 message = "writing ring-ref";
252 goto abort_transaction;
253 }
254 err = xenbus_printf(xbt, nodename,
255 "port", "%u", dev->evtchn);
256 if (err) {
257 message = "writing event-channel";
258 goto abort_transaction;
259 }
260 err = xenbus_printf(xbt, nodename,
261 "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
262 if (err) {
263 message = "writing protocol";
264 goto abort_transaction;
265 }
267 err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu");
268 if (err) {
269 message = "writing type";
270 goto abort_transaction;
271 }
273 snprintf(path, sizeof(path), "%s/state", nodename);
274 err = xenbus_switch_state(xbt, path, XenbusStateConnected);
275 if (err) {
276 message = "switching state";
277 goto abort_transaction;
278 }
281 err = xenbus_transaction_end(xbt, 0, &retry);
282 if (err) free(err);
283 if (retry) {
284 goto again;
285 printk("completing transaction\n");
286 }
288 goto done;
290 abort_transaction:
291 free(err);
292 err = xenbus_transaction_end(xbt, 1, &retry);
293 goto error;
295 done:
297 snprintf(path, sizeof(path), "%s/backend", nodename);
298 msg = xenbus_read(XBT_NIL, path, &dev->backend);
299 if (msg) {
300 printk("Error %s when reading the backend path %s\n", msg, path);
301 goto error;
302 }
304 printk("backend at %s\n", dev->backend);
306 {
307 XenbusState state;
308 char path[strlen(dev->backend) + 1 + 19 + 1];
309 snprintf(path, sizeof(path), "%s/state", dev->backend);
311 xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
312 msg = NULL;
313 state = xenbus_read_integer(path);
314 while (msg == NULL && state < XenbusStateConnected)
315 msg = xenbus_wait_for_state_change(path, &state, &dev->events);
316 if (msg != NULL || state != XenbusStateConnected) {
317 printk("backend not available, state=%d\n", state);
318 xenbus_unwatch_path_token(XBT_NIL, path, path);
319 goto error;
320 }
321 }
322 unmask_evtchn(dev->evtchn);
324 printk("**************************\n");
326 return dev;
328 error:
329 free(msg);
330 free(err);
331 free_consfront(dev);
332 return NULL;
333 }
335 void xencons_resume(void)
336 {
337 (void)xencons_ring_init();
338 }