ia64/xen-unstable

view tools/ioemu/block.c @ 7238:971e7c7411b3

Raise an exception if an error appears on the pipes to our children, and make
sure that the child's pipes are closed even under that exception. Move the
handling of POLLHUP to the end of the loop, so that we guarantee to read any
remaining data from the child if POLLHUP and POLLIN appear at the same time.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Thu Oct 06 10:13:11 2005 +0100 (2005-10-06)
parents 3c759ba83f7c
children f7b43e5c42b9
line source
1 /*
2 * QEMU System Emulator block driver
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
25 #include "block_int.h"
27 static BlockDriverState *bdrv_first;
28 static BlockDriver *first_drv;
30 void bdrv_register(BlockDriver *bdrv)
31 {
32 bdrv->next = first_drv;
33 first_drv = bdrv;
34 }
36 /* create a new block device (by default it is empty) */
37 BlockDriverState *bdrv_new(const char *device_name)
38 {
39 BlockDriverState **pbs, *bs;
41 bs = qemu_mallocz(sizeof(BlockDriverState));
42 if(!bs)
43 return NULL;
44 pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
45 if (device_name[0] != '\0') {
46 /* insert at the end */
47 pbs = &bdrv_first;
48 while (*pbs != NULL)
49 pbs = &(*pbs)->next;
50 *pbs = bs;
51 }
52 return bs;
53 }
55 BlockDriver *bdrv_find_format(const char *format_name)
56 {
57 BlockDriver *drv1;
58 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
59 if (!strcmp(drv1->format_name, format_name))
60 return drv1;
61 }
62 return NULL;
63 }
65 int bdrv_create(BlockDriver *drv,
66 const char *filename, int64_t size_in_sectors,
67 const char *backing_file, int flags)
68 {
69 if (!drv->bdrv_create)
70 return -ENOTSUP;
71 return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
72 }
74 static BlockDriver *find_image_format(const char *filename)
75 {
76 int fd, ret, score, score_max;
77 BlockDriver *drv1, *drv;
78 uint8_t buf[1024];
80 fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
81 if (fd < 0)
82 return NULL;
83 ret = read(fd, buf, sizeof(buf));
84 if (ret < 0) {
85 close(fd);
86 return NULL;
87 }
88 close(fd);
90 drv = NULL;
91 score_max = 0;
92 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
93 score = drv1->bdrv_probe(buf, ret, filename);
94 if (score > score_max) {
95 score_max = score;
96 drv = drv1;
97 }
98 }
99 return drv;
100 }
102 int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
103 {
104 return bdrv_open2(bs, filename, snapshot, NULL);
105 }
107 int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
108 BlockDriver *drv)
109 {
110 int ret;
112 bs->read_only = 0;
113 bs->is_temporary = 0;
114 bs->encrypted = 0;
116 pstrcpy(bs->filename, sizeof(bs->filename), filename);
117 if (!drv) {
118 drv = find_image_format(filename);
119 if (!drv)
120 return -1;
121 }
122 bs->drv = drv;
123 bs->opaque = qemu_mallocz(drv->instance_size);
124 if (bs->opaque == NULL && drv->instance_size > 0)
125 return -1;
127 ret = drv->bdrv_open(bs, filename);
128 if (ret < 0) {
129 qemu_free(bs->opaque);
130 return -1;
131 }
132 #ifndef _WIN32
133 if (bs->is_temporary) {
134 unlink(filename);
135 }
136 #endif
137 if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
138 /* if there is a backing file, use it */
139 bs->backing_hd = bdrv_new("");
140 if (!bs->backing_hd) {
141 fail:
142 bdrv_close(bs);
143 return -1;
144 }
145 if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
146 goto fail;
147 }
149 bs->inserted = 1;
151 /* call the change callback */
152 if (bs->change_cb)
153 bs->change_cb(bs->change_opaque);
155 return 0;
156 }
158 void bdrv_close(BlockDriverState *bs)
159 {
160 if (bs->inserted) {
161 if (bs->backing_hd)
162 bdrv_delete(bs->backing_hd);
163 bs->drv->bdrv_close(bs);
164 qemu_free(bs->opaque);
165 #ifdef _WIN32
166 if (bs->is_temporary) {
167 unlink(bs->filename);
168 }
169 #endif
170 bs->opaque = NULL;
171 bs->drv = NULL;
172 bs->inserted = 0;
174 /* call the change callback */
175 if (bs->change_cb)
176 bs->change_cb(bs->change_opaque);
177 }
178 }
180 void bdrv_delete(BlockDriverState *bs)
181 {
182 /* XXX: remove the driver list */
183 bdrv_close(bs);
184 qemu_free(bs);
185 }
187 /* commit COW file into the raw image */
188 int bdrv_commit(BlockDriverState *bs)
189 {
190 int64_t i;
191 int n, j;
192 unsigned char sector[512];
194 if (!bs->inserted)
195 return -ENOENT;
197 if (bs->read_only) {
198 return -EACCES;
199 }
201 if (!bs->backing_hd) {
202 return -ENOTSUP;
203 }
205 for (i = 0; i < bs->total_sectors;) {
206 if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
207 for(j = 0; j < n; j++) {
208 if (bdrv_read(bs, i, sector, 1) != 0) {
209 return -EIO;
210 }
212 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
213 return -EIO;
214 }
215 i++;
216 }
217 } else {
218 i += n;
219 }
220 }
221 return 0;
222 }
224 /* return -1 if error */
225 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
226 uint8_t *buf, int nb_sectors)
227 {
228 int ret, n;
229 BlockDriver *drv = bs->drv;
231 if (!bs->inserted)
232 return -1;
234 while (nb_sectors > 0) {
235 if (sector_num == 0 && bs->boot_sector_enabled) {
236 memcpy(buf, bs->boot_sector_data, 512);
237 n = 1;
238 } else if (bs->backing_hd) {
239 if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
240 ret = drv->bdrv_read(bs, sector_num, buf, n);
241 if (ret < 0)
242 return -1;
243 } else {
244 /* read from the base image */
245 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
246 if (ret < 0)
247 return -1;
248 }
249 } else {
250 ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
251 if (ret < 0)
252 return -1;
253 /* no need to loop */
254 break;
255 }
256 nb_sectors -= n;
257 sector_num += n;
258 buf += n * 512;
259 }
260 return 0;
261 }
263 /* return -1 if error */
264 int bdrv_write(BlockDriverState *bs, int64_t sector_num,
265 const uint8_t *buf, int nb_sectors)
266 {
267 if (!bs->inserted)
268 return -1;
269 if (bs->read_only)
270 return -1;
271 return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
272 }
274 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
275 {
276 *nb_sectors_ptr = bs->total_sectors;
277 }
279 /* force a given boot sector. */
280 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
281 {
282 bs->boot_sector_enabled = 1;
283 if (size > 512)
284 size = 512;
285 memcpy(bs->boot_sector_data, data, size);
286 memset(bs->boot_sector_data + size, 0, 512 - size);
287 }
289 void bdrv_set_geometry_hint(BlockDriverState *bs,
290 int cyls, int heads, int secs)
291 {
292 bs->cyls = cyls;
293 bs->heads = heads;
294 bs->secs = secs;
295 }
297 void bdrv_set_type_hint(BlockDriverState *bs, int type)
298 {
299 bs->type = type;
300 bs->removable = ((type == BDRV_TYPE_CDROM ||
301 type == BDRV_TYPE_FLOPPY));
302 }
304 void bdrv_get_geometry_hint(BlockDriverState *bs,
305 int *pcyls, int *pheads, int *psecs)
306 {
307 *pcyls = bs->cyls;
308 *pheads = bs->heads;
309 *psecs = bs->secs;
310 }
312 int bdrv_get_type_hint(BlockDriverState *bs)
313 {
314 return bs->type;
315 }
317 int bdrv_is_removable(BlockDriverState *bs)
318 {
319 return bs->removable;
320 }
322 int bdrv_is_read_only(BlockDriverState *bs)
323 {
324 return bs->read_only;
325 }
327 int bdrv_is_inserted(BlockDriverState *bs)
328 {
329 return bs->inserted;
330 }
332 int bdrv_is_locked(BlockDriverState *bs)
333 {
334 return bs->locked;
335 }
337 void bdrv_set_locked(BlockDriverState *bs, int locked)
338 {
339 bs->locked = locked;
340 }
342 void bdrv_set_change_cb(BlockDriverState *bs,
343 void (*change_cb)(void *opaque), void *opaque)
344 {
345 bs->change_cb = change_cb;
346 bs->change_opaque = opaque;
347 }
349 int bdrv_is_encrypted(BlockDriverState *bs)
350 {
351 if (bs->backing_hd && bs->backing_hd->encrypted)
352 return 1;
353 return bs->encrypted;
354 }
356 int bdrv_set_key(BlockDriverState *bs, const char *key)
357 {
358 int ret;
359 if (bs->backing_hd && bs->backing_hd->encrypted) {
360 ret = bdrv_set_key(bs->backing_hd, key);
361 if (ret < 0)
362 return ret;
363 if (!bs->encrypted)
364 return 0;
365 }
366 if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
367 return -1;
368 return bs->drv->bdrv_set_key(bs, key);
369 }
371 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
372 {
373 if (!bs->inserted || !bs->drv) {
374 buf[0] = '\0';
375 } else {
376 pstrcpy(buf, buf_size, bs->drv->format_name);
377 }
378 }
380 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
381 void *opaque)
382 {
383 BlockDriver *drv;
385 for (drv = first_drv; drv != NULL; drv = drv->next) {
386 it(opaque, drv->format_name);
387 }
388 }
390 BlockDriverState *bdrv_find(const char *name)
391 {
392 BlockDriverState *bs;
394 for (bs = bdrv_first; bs != NULL; bs = bs->next) {
395 if (!strcmp(name, bs->device_name))
396 return bs;
397 }
398 return NULL;
399 }
401 void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
402 {
403 BlockDriverState *bs;
405 for (bs = bdrv_first; bs != NULL; bs = bs->next) {
406 it(opaque, bs->device_name);
407 }
408 }
410 const char *bdrv_get_device_name(BlockDriverState *bs)
411 {
412 return bs->device_name;
413 }
415 void bdrv_info(void)
416 {
417 BlockDriverState *bs;
419 for (bs = bdrv_first; bs != NULL; bs = bs->next) {
420 term_printf("%s:", bs->device_name);
421 term_printf(" type=");
422 switch(bs->type) {
423 case BDRV_TYPE_HD:
424 term_printf("hd");
425 break;
426 case BDRV_TYPE_CDROM:
427 term_printf("cdrom");
428 break;
429 case BDRV_TYPE_FLOPPY:
430 term_printf("floppy");
431 break;
432 }
433 term_printf(" removable=%d", bs->removable);
434 if (bs->removable) {
435 term_printf(" locked=%d", bs->locked);
436 }
437 if (bs->inserted) {
438 term_printf(" file=%s", bs->filename);
439 if (bs->backing_file[0] != '\0')
440 term_printf(" backing_file=%s", bs->backing_file);
441 term_printf(" ro=%d", bs->read_only);
442 term_printf(" drv=%s", bs->drv->format_name);
443 if (bs->encrypted)
444 term_printf(" encrypted");
445 } else {
446 term_printf(" [not inserted]");
447 }
448 term_printf("\n");
449 }
450 }
453 /**************************************************************/
454 /* RAW block driver */
456 typedef struct BDRVRawState {
457 int fd;
458 } BDRVRawState;
460 static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
461 {
462 return 1; /* maybe */
463 }
465 static int raw_open(BlockDriverState *bs, const char *filename)
466 {
467 BDRVRawState *s = bs->opaque;
468 int fd;
469 int64_t size;
471 fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
472 if (fd < 0) {
473 fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
474 if (fd < 0)
475 return -1;
476 bs->read_only = 1;
477 }
478 size = lseek(fd, 0, SEEK_END);
479 bs->total_sectors = size / 512;
480 s->fd = fd;
481 return 0;
482 }
484 static int raw_read(BlockDriverState *bs, int64_t sector_num,
485 uint8_t *buf, int nb_sectors)
486 {
487 BDRVRawState *s = bs->opaque;
488 int ret;
490 lseek(s->fd, sector_num * 512, SEEK_SET);
491 ret = read(s->fd, buf, nb_sectors * 512);
492 if (ret != nb_sectors * 512)
493 return -1;
494 return 0;
495 }
497 static int raw_write(BlockDriverState *bs, int64_t sector_num,
498 const uint8_t *buf, int nb_sectors)
499 {
500 BDRVRawState *s = bs->opaque;
501 int ret;
503 lseek(s->fd, sector_num * 512, SEEK_SET);
504 ret = write(s->fd, buf, nb_sectors * 512);
505 if (ret != nb_sectors * 512)
506 return -1;
507 return 0;
508 }
510 static void raw_close(BlockDriverState *bs)
511 {
512 BDRVRawState *s = bs->opaque;
513 close(s->fd);
514 }
516 static int raw_create(const char *filename, int64_t total_size,
517 const char *backing_file, int flags)
518 {
519 int fd;
521 if (flags || backing_file)
522 return -ENOTSUP;
524 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
525 0644);
526 if (fd < 0)
527 return -EIO;
528 ftruncate(fd, total_size * 512);
529 close(fd);
530 return 0;
531 }
533 BlockDriver bdrv_raw = {
534 "raw",
535 sizeof(BDRVRawState),
536 raw_probe,
537 raw_open,
538 raw_read,
539 raw_write,
540 raw_close,
541 raw_create,
542 };
544 void bdrv_init(void)
545 {
546 bdrv_register(&bdrv_raw);
547 bdrv_register(&bdrv_qcow);
548 bdrv_register(&bdrv_cloop);
549 }