Commit 83f6409109acd7cd13ff8a603f29c46033c4fb00

Authored by bellard
1 parent 7954c734

async file I/O API


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2075 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
  1 +version 0.8.3:
  2 +
  3 + - Support for relative paths in backing files for disk images
  4 + - Async file I/O API
  5 +
1 6 version 0.8.2:
2 7  
3 8 - ACPI support
... ...
Makefile
... ... @@ -25,14 +25,22 @@ else
25 25 DOCS=
26 26 endif
27 27  
  28 +ifndef CONFIG_DARWIN
  29 +ifndef CONFIG_WIN32
  30 +ifndef CONFIG_SOLARIS
  31 +LIBS+=-lrt
  32 +endif
  33 +endif
  34 +endif
  35 +
28 36 all: $(TOOLS) $(DOCS) recurse-all
29 37  
30 38 subdir-%: dyngen$(EXESUF)
31 39 $(MAKE) -C $(subst subdir-,,$@) all
32 40  
33 41 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
34   -
35   -qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
  42 +
  43 +qemu-img$(EXESUF): qemu-img.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
36 44 $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
37 45  
38 46 dyngen$(EXESUF): dyngen.c
... ...
Makefile.target
... ... @@ -289,7 +289,8 @@ ifeq ($(ARCH),alpha)
289 289 endif
290 290  
291 291 # must use static linking to avoid leaving stuff in virtual address space
292   -VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o
  292 +VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o
  293 +VL_OBJS+=block.o block-raw.o
293 294 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
294 295 ifdef CONFIG_WIN32
295 296 VL_OBJS+=tap-win32.o
... ...
block-bochs.c
... ... @@ -85,15 +85,15 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
85 85 return 0;
86 86 }
87 87  
88   -static int bochs_open(BlockDriverState *bs, const char *filename)
  88 +static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
89 89 {
90 90 BDRVBochsState *s = bs->opaque;
91 91 int fd, i;
92 92 struct bochs_header bochs;
93 93  
94   - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  94 + fd = open(filename, O_RDWR | O_BINARY);
95 95 if (fd < 0) {
96   - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  96 + fd = open(filename, O_RDONLY | O_BINARY);
97 97 if (fd < 0)
98 98 return -1;
99 99 }
... ...
block-cloop.c
... ... @@ -50,14 +50,14 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
50 50 return 0;
51 51 }
52 52  
53   -static int cloop_open(BlockDriverState *bs, const char *filename)
  53 +static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
54 54 {
55 55 BDRVCloopState *s = bs->opaque;
56 56 uint32_t offsets_size,max_compressed_block_size=1,i;
57 57  
58   - s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  58 + s->fd = open(filename, O_RDONLY | O_BINARY);
59 59 if (s->fd < 0)
60   - return -1;
  60 + return -errno;
61 61 bs->read_only = 1;
62 62  
63 63 /* read header */
... ...
block-cow.c
... ... @@ -62,7 +62,7 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
62 62 return 0;
63 63 }
64 64  
65   -static int cow_open(BlockDriverState *bs, const char *filename)
  65 +static int cow_open(BlockDriverState *bs, const char *filename, int flags)
66 66 {
67 67 BDRVCowState *s = bs->opaque;
68 68 int fd;
... ... @@ -93,22 +93,6 @@ static int cow_open(BlockDriverState *bs, const char *filename)
93 93 pstrcpy(bs->backing_file, sizeof(bs->backing_file),
94 94 cow_header.backing_file);
95 95  
96   -#if 0
97   - if (cow_header.backing_file[0] != '\0') {
98   - if (stat(cow_header.backing_file, &st) != 0) {
99   - fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
100   - goto fail;
101   - }
102   - if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
103   - fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
104   - goto fail;
105   - }
106   - fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
107   - if (fd < 0)
108   - goto fail;
109   - bs->fd = fd;
110   - }
111   -#endif
112 96 /* mmap the bitmap */
113 97 s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
114 98 s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
... ... @@ -179,8 +163,15 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
179 163 if (ret != n * 512)
180 164 return -1;
181 165 } else {
  166 + if (bs->backing_hd) {
  167 + /* read from the base image */
  168 + ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  169 + if (ret < 0)
  170 + return -1;
  171 + } else {
182 172 memset(buf, 0, n * 512);
183 173 }
  174 + }
184 175 nb_sectors -= n;
185 176 sector_num += n;
186 177 buf += n * 512;
... ... @@ -220,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors,
220 211 if (flags)
221 212 return -ENOTSUP;
222 213  
223   - cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
  214 + cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
224 215 0644);
225 216 if (cow_fd < 0)
226 217 return -1;
... ... @@ -228,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors,
228 219 cow_header.magic = cpu_to_be32(COW_MAGIC);
229 220 cow_header.version = cpu_to_be32(COW_VERSION);
230 221 if (image_filename) {
  222 + /* Note: if no file, we put a dummy mtime */
  223 + cow_header.mtime = cpu_to_be32(0);
  224 +
231 225 fd = open(image_filename, O_RDONLY | O_BINARY);
232 226 if (fd < 0) {
233 227 close(cow_fd);
234   - return -1;
  228 + goto mtime_fail;
235 229 }
236 230 if (fstat(fd, &st) != 0) {
237 231 close(fd);
238   - return -1;
  232 + goto mtime_fail;
239 233 }
240 234 close(fd);
241 235 cow_header.mtime = cpu_to_be32(st.st_mtime);
242   - realpath(image_filename, cow_header.backing_file);
  236 + mtime_fail:
  237 + pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
  238 + image_filename);
243 239 }
244 240 cow_header.sectorsize = cpu_to_be32(512);
245 241 cow_header.size = cpu_to_be64(image_sectors * 512);
... ...
block-dmg.c
... ... @@ -73,16 +73,16 @@ static off_t read_uint32(int fd)
73 73 return be32_to_cpu(buffer);
74 74 }
75 75  
76   -static int dmg_open(BlockDriverState *bs, const char *filename)
  76 +static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
77 77 {
78 78 BDRVDMGState *s = bs->opaque;
79 79 off_t info_begin,info_end,last_in_offset,last_out_offset;
80 80 uint32_t count;
81 81 uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
82 82  
83   - s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  83 + s->fd = open(filename, O_RDONLY | O_BINARY);
84 84 if (s->fd < 0)
85   - return -1;
  85 + return -errno;
86 86 bs->read_only = 1;
87 87 s->n_chunks = 0;
88 88 s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
... ... @@ -93,7 +93,7 @@ dmg_close:
93 93 close(s->fd);
94 94 /* open raw instead */
95 95 bs->drv=&bdrv_raw;
96   - return bs->drv->bdrv_open(bs,filename);
  96 + return bs->drv->bdrv_open(bs, filename, flags);
97 97 }
98 98 info_begin=read_off(s->fd);
99 99 if(info_begin==0)
... ...
block-qcow.c
1 1 /*
2 2 * Block driver for the QCOW format
3 3 *
4   - * Copyright (c) 2004 Fabrice Bellard
  4 + * Copyright (c) 2004-2006 Fabrice Bellard
5 5 *
6 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
... ... @@ -53,7 +53,7 @@ typedef struct QCowHeader {
53 53 #define L2_CACHE_SIZE 16
54 54  
55 55 typedef struct BDRVQcowState {
56   - int fd;
  56 + BlockDriverState *hd;
57 57 int cluster_bits;
58 58 int cluster_size;
59 59 int cluster_sectors;
... ... @@ -89,20 +89,16 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
89 89 return 0;
90 90 }
91 91  
92   -static int qcow_open(BlockDriverState *bs, const char *filename)
  92 +static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
93 93 {
94 94 BDRVQcowState *s = bs->opaque;
95   - int fd, len, i, shift;
  95 + int len, i, shift, ret;
96 96 QCowHeader header;
97   -
98   - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
99   - if (fd < 0) {
100   - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
101   - if (fd < 0)
102   - return -1;
103   - }
104   - s->fd = fd;
105   - if (read(fd, &header, sizeof(header)) != sizeof(header))
  97 +
  98 + ret = bdrv_file_open(&s->hd, filename, flags);
  99 + if (ret < 0)
  100 + return ret;
  101 + if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
106 102 goto fail;
107 103 be32_to_cpus(&header.magic);
108 104 be32_to_cpus(&header.version);
... ... @@ -138,8 +134,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
138 134 s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
139 135 if (!s->l1_table)
140 136 goto fail;
141   - lseek(fd, s->l1_table_offset, SEEK_SET);
142   - if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
  137 + if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
143 138 s->l1_size * sizeof(uint64_t))
144 139 goto fail;
145 140 for(i = 0;i < s->l1_size; i++) {
... ... @@ -162,8 +157,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
162 157 len = header.backing_file_size;
163 158 if (len > 1023)
164 159 len = 1023;
165   - lseek(fd, header.backing_file_offset, SEEK_SET);
166   - if (read(fd, bs->backing_file, len) != len)
  160 + if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
167 161 goto fail;
168 162 bs->backing_file[len] = '\0';
169 163 }
... ... @@ -174,7 +168,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
174 168 qemu_free(s->l2_cache);
175 169 qemu_free(s->cluster_cache);
176 170 qemu_free(s->cluster_data);
177   - close(fd);
  171 + bdrv_delete(s->hd);
178 172 return -1;
179 173 }
180 174  
... ... @@ -276,14 +270,14 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
276 270 if (!allocate)
277 271 return 0;
278 272 /* allocate a new l2 entry */
279   - l2_offset = lseek(s->fd, 0, SEEK_END);
  273 + l2_offset = bdrv_getlength(s->hd);
280 274 /* round to cluster size */
281 275 l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
282 276 /* update the L1 entry */
283 277 s->l1_table[l1_index] = l2_offset;
284 278 tmp = cpu_to_be64(l2_offset);
285   - lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
286   - if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
  279 + if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
  280 + &tmp, sizeof(tmp)) != sizeof(tmp))
287 281 return 0;
288 282 new_l2_table = 1;
289 283 }
... ... @@ -309,14 +303,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
309 303 }
310 304 }
311 305 l2_table = s->l2_cache + (min_index << s->l2_bits);
312   - lseek(s->fd, l2_offset, SEEK_SET);
313 306 if (new_l2_table) {
314 307 memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
315   - if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
  308 + if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
316 309 s->l2_size * sizeof(uint64_t))
317 310 return 0;
318 311 } else {
319   - if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
  312 + if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
320 313 s->l2_size * sizeof(uint64_t))
321 314 return 0;
322 315 }
... ... @@ -337,21 +330,20 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
337 330 overwritten */
338 331 if (decompress_cluster(s, cluster_offset) < 0)
339 332 return 0;
340   - cluster_offset = lseek(s->fd, 0, SEEK_END);
  333 + cluster_offset = bdrv_getlength(s->hd);
341 334 cluster_offset = (cluster_offset + s->cluster_size - 1) &
342 335 ~(s->cluster_size - 1);
343 336 /* write the cluster content */
344   - lseek(s->fd, cluster_offset, SEEK_SET);
345   - if (write(s->fd, s->cluster_cache, s->cluster_size) !=
  337 + if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
346 338 s->cluster_size)
347 339 return -1;
348 340 } else {
349   - cluster_offset = lseek(s->fd, 0, SEEK_END);
  341 + cluster_offset = bdrv_getlength(s->hd);
350 342 if (allocate == 1) {
351 343 /* round to cluster size */
352 344 cluster_offset = (cluster_offset + s->cluster_size - 1) &
353 345 ~(s->cluster_size - 1);
354   - ftruncate(s->fd, cluster_offset + s->cluster_size);
  346 + bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
355 347 /* if encrypted, we must initialize the cluster
356 348 content which won't be written */
357 349 if (s->crypt_method &&
... ... @@ -365,8 +357,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
365 357 s->cluster_data,
366 358 s->cluster_data + 512, 1, 1,
367 359 &s->aes_encrypt_key);
368   - lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
369   - if (write(s->fd, s->cluster_data, 512) != 512)
  360 + if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
  361 + s->cluster_data, 512) != 512)
370 362 return -1;
371 363 }
372 364 }
... ... @@ -379,8 +371,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
379 371 /* update L2 table */
380 372 tmp = cpu_to_be64(cluster_offset);
381 373 l2_table[l2_index] = tmp;
382   - lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
383   - if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
  374 + if (bdrv_pwrite(s->hd,
  375 + l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
384 376 return 0;
385 377 }
386 378 return cluster_offset;
... ... @@ -438,8 +430,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
438 430 if (s->cluster_cache_offset != coffset) {
439 431 csize = cluster_offset >> (63 - s->cluster_bits);
440 432 csize &= (s->cluster_size - 1);
441   - lseek(s->fd, coffset, SEEK_SET);
442   - ret = read(s->fd, s->cluster_data, csize);
  433 + ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
443 434 if (ret != csize)
444 435 return -1;
445 436 if (decompress_buffer(s->cluster_cache, s->cluster_size,
... ... @@ -451,6 +442,8 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
451 442 return 0;
452 443 }
453 444  
  445 +#if 0
  446 +
454 447 static int qcow_read(BlockDriverState *bs, int64_t sector_num,
455 448 uint8_t *buf, int nb_sectors)
456 449 {
... ... @@ -465,14 +458,20 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
465 458 if (n > nb_sectors)
466 459 n = nb_sectors;
467 460 if (!cluster_offset) {
468   - memset(buf, 0, 512 * n);
  461 + if (bs->backing_hd) {
  462 + /* read from the base image */
  463 + ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  464 + if (ret < 0)
  465 + return -1;
  466 + } else {
  467 + memset(buf, 0, 512 * n);
  468 + }
469 469 } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
470 470 if (decompress_cluster(s, cluster_offset) < 0)
471 471 return -1;
472 472 memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
473 473 } else {
474   - lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
475   - ret = read(s->fd, buf, n * 512);
  474 + ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
476 475 if (ret != n * 512)
477 476 return -1;
478 477 if (s->crypt_method) {
... ... @@ -486,6 +485,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
486 485 }
487 486 return 0;
488 487 }
  488 +#endif
489 489  
490 490 static int qcow_write(BlockDriverState *bs, int64_t sector_num,
491 491 const uint8_t *buf, int nb_sectors)
... ... @@ -504,13 +504,13 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
504 504 index_in_cluster + n);
505 505 if (!cluster_offset)
506 506 return -1;
507   - lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
508 507 if (s->crypt_method) {
509 508 encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
510 509 &s->aes_encrypt_key);
511   - ret = write(s->fd, s->cluster_data, n * 512);
  510 + ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
  511 + s->cluster_data, n * 512);
512 512 } else {
513   - ret = write(s->fd, buf, n * 512);
  513 + ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
514 514 }
515 515 if (ret != n * 512)
516 516 return -1;
... ... @@ -522,6 +522,231 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
522 522 return 0;
523 523 }
524 524  
  525 +typedef struct {
  526 + int64_t sector_num;
  527 + uint8_t *buf;
  528 + int nb_sectors;
  529 + int n;
  530 + uint64_t cluster_offset;
  531 + uint8_t *cluster_data;
  532 + BlockDriverAIOCB *hd_aiocb;
  533 + BlockDriverAIOCB *backing_hd_aiocb;
  534 +} QCowAIOCB;
  535 +
  536 +static void qcow_aio_delete(BlockDriverAIOCB *acb);
  537 +
  538 +static int qcow_aio_new(BlockDriverAIOCB *acb)
  539 +{
  540 + BlockDriverState *bs = acb->bs;
  541 + BDRVQcowState *s = bs->opaque;
  542 + QCowAIOCB *acb1;
  543 + acb1 = qemu_mallocz(sizeof(QCowAIOCB));
  544 + if (!acb1)
  545 + return -1;
  546 + acb->opaque = acb1;
  547 + acb1->hd_aiocb = bdrv_aio_new(s->hd);
  548 + if (!acb1->hd_aiocb)
  549 + goto fail;
  550 + if (bs->backing_hd) {
  551 + acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd);
  552 + if (!acb1->backing_hd_aiocb)
  553 + goto fail;
  554 + }
  555 + return 0;
  556 + fail:
  557 + qcow_aio_delete(acb);
  558 + return -1;
  559 +}
  560 +
  561 +static void qcow_aio_read_cb(void *opaque, int ret)
  562 +{
  563 + BlockDriverAIOCB *acb = opaque;
  564 + BlockDriverState *bs = acb->bs;
  565 + BDRVQcowState *s = bs->opaque;
  566 + QCowAIOCB *acb1 = acb->opaque;
  567 + int index_in_cluster;
  568 +
  569 + if (ret < 0) {
  570 + fail:
  571 + acb->cb(acb->cb_opaque, ret);
  572 + return;
  573 + }
  574 +
  575 + redo:
  576 + /* post process the read buffer */
  577 + if (!acb1->cluster_offset) {
  578 + /* nothing to do */
  579 + } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  580 + /* nothing to do */
  581 + } else {
  582 + if (s->crypt_method) {
  583 + encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf,
  584 + acb1->n, 0,
  585 + &s->aes_decrypt_key);
  586 + }
  587 + }
  588 +
  589 + acb1->nb_sectors -= acb1->n;
  590 + acb1->sector_num += acb1->n;
  591 + acb1->buf += acb1->n * 512;
  592 +
  593 + if (acb1->nb_sectors == 0) {
  594 + /* request completed */
  595 + acb->cb(acb->cb_opaque, 0);
  596 + return;
  597 + }
  598 +
  599 + /* prepare next AIO request */
  600 + acb1->cluster_offset = get_cluster_offset(bs,
  601 + acb1->sector_num << 9,
  602 + 0, 0, 0, 0);
  603 + index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
  604 + acb1->n = s->cluster_sectors - index_in_cluster;
  605 + if (acb1->n > acb1->nb_sectors)
  606 + acb1->n = acb1->nb_sectors;
  607 +
  608 + if (!acb1->cluster_offset) {
  609 + if (bs->backing_hd) {
  610 + /* read from the base image */
  611 + ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num,
  612 + acb1->buf, acb1->n, qcow_aio_read_cb, acb);
  613 + if (ret < 0)
  614 + goto fail;
  615 + } else {
  616 + /* Note: in this case, no need to wait */
  617 + memset(acb1->buf, 0, 512 * acb1->n);
  618 + goto redo;
  619 + }
  620 + } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  621 + /* add AIO support for compressed blocks ? */
  622 + if (decompress_cluster(s, acb1->cluster_offset) < 0)
  623 + goto fail;
  624 + memcpy(acb1->buf,
  625 + s->cluster_cache + index_in_cluster * 512, 512 * acb1->n);
  626 + goto redo;
  627 + } else {
  628 + if ((acb1->cluster_offset & 511) != 0) {
  629 + ret = -EIO;
  630 + goto fail;
  631 + }
  632 + ret = bdrv_aio_read(acb1->hd_aiocb,
  633 + (acb1->cluster_offset >> 9) + index_in_cluster,
  634 + acb1->buf, acb1->n, qcow_aio_read_cb, acb);
  635 + if (ret < 0)
  636 + goto fail;
  637 + }
  638 +}
  639 +
  640 +static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
  641 + uint8_t *buf, int nb_sectors)
  642 +{
  643 + QCowAIOCB *acb1 = acb->opaque;
  644 +
  645 + acb1->sector_num = sector_num;
  646 + acb1->buf = buf;
  647 + acb1->nb_sectors = nb_sectors;
  648 + acb1->n = 0;
  649 + acb1->cluster_offset = 0;
  650 +
  651 + qcow_aio_read_cb(acb, 0);
  652 +}
  653 +
  654 +static void qcow_aio_write_cb(void *opaque, int ret)
  655 +{
  656 + BlockDriverAIOCB *acb = opaque;
  657 + BlockDriverState *bs = acb->bs;
  658 + BDRVQcowState *s = bs->opaque;
  659 + QCowAIOCB *acb1 = acb->opaque;
  660 + int index_in_cluster;
  661 + uint64_t cluster_offset;
  662 + const uint8_t *src_buf;
  663 +
  664 + if (ret < 0) {
  665 + fail:
  666 + acb->cb(acb->cb_opaque, ret);
  667 + return;
  668 + }
  669 +
  670 + acb1->nb_sectors -= acb1->n;
  671 + acb1->sector_num += acb1->n;
  672 + acb1->buf += acb1->n * 512;
  673 +
  674 + if (acb1->nb_sectors == 0) {
  675 + /* request completed */
  676 + acb->cb(acb->cb_opaque, 0);
  677 + return;
  678 + }
  679 +
  680 + index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
  681 + acb1->n = s->cluster_sectors - index_in_cluster;
  682 + if (acb1->n > acb1->nb_sectors)
  683 + acb1->n = acb1->nb_sectors;
  684 + cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0,
  685 + index_in_cluster,
  686 + index_in_cluster + acb1->n);
  687 + if (!cluster_offset || (cluster_offset & 511) != 0) {
  688 + ret = -EIO;
  689 + goto fail;
  690 + }
  691 + if (s->crypt_method) {
  692 + if (!acb1->cluster_data) {
  693 + acb1->cluster_data = qemu_mallocz(s->cluster_size);
  694 + if (!acb1->cluster_data) {
  695 + ret = -ENOMEM;
  696 + goto fail;
  697 + }
  698 + }
  699 + encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf,
  700 + acb1->n, 1, &s->aes_encrypt_key);
  701 + src_buf = acb1->cluster_data;
  702 + } else {
  703 + src_buf = acb1->buf;
  704 + }
  705 + ret = bdrv_aio_write(acb1->hd_aiocb,
  706 + (cluster_offset >> 9) + index_in_cluster,
  707 + src_buf, acb1->n,
  708 + qcow_aio_write_cb, acb);
  709 + if (ret < 0)
  710 + goto fail;
  711 +}
  712 +
  713 +static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
  714 + const uint8_t *buf, int nb_sectors)
  715 +{
  716 + QCowAIOCB *acb1 = acb->opaque;
  717 + BlockDriverState *bs = acb->bs;
  718 + BDRVQcowState *s = bs->opaque;
  719 +
  720 + s->cluster_cache_offset = -1; /* disable compressed cache */
  721 +
  722 + acb1->sector_num = sector_num;
  723 + acb1->buf = (uint8_t *)buf;
  724 + acb1->nb_sectors = nb_sectors;
  725 + acb1->n = 0;
  726 +
  727 + qcow_aio_write_cb(acb, 0);
  728 +}
  729 +
  730 +static void qcow_aio_cancel(BlockDriverAIOCB *acb)
  731 +{
  732 + QCowAIOCB *acb1 = acb->opaque;
  733 + if (acb1->hd_aiocb)
  734 + bdrv_aio_cancel(acb1->hd_aiocb);
  735 + if (acb1->backing_hd_aiocb)
  736 + bdrv_aio_cancel(acb1->backing_hd_aiocb);
  737 +}
  738 +
  739 +static void qcow_aio_delete(BlockDriverAIOCB *acb)
  740 +{
  741 + QCowAIOCB *acb1 = acb->opaque;
  742 + if (acb1->hd_aiocb)
  743 + bdrv_aio_delete(acb1->hd_aiocb);
  744 + if (acb1->backing_hd_aiocb)
  745 + bdrv_aio_delete(acb1->backing_hd_aiocb);
  746 + qemu_free(acb1->cluster_data);
  747 + qemu_free(acb1);
  748 +}
  749 +
525 750 static void qcow_close(BlockDriverState *bs)
526 751 {
527 752 BDRVQcowState *s = bs->opaque;
... ... @@ -529,7 +754,7 @@ static void qcow_close(BlockDriverState *bs)
529 754 qemu_free(s->l2_cache);
530 755 qemu_free(s->cluster_cache);
531 756 qemu_free(s->cluster_data);
532   - close(s->fd);
  757 + bdrv_delete(s->hd);
533 758 }
534 759  
535 760 static int qcow_create(const char *filename, int64_t total_size,
... ... @@ -537,12 +762,9 @@ static int qcow_create(const char *filename, int64_t total_size,
537 762 {
538 763 int fd, header_size, backing_filename_len, l1_size, i, shift;
539 764 QCowHeader header;
540   - char backing_filename[1024];
541 765 uint64_t tmp;
542   - struct stat st;
543 766  
544   - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
545   - 0644);
  767 + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
546 768 if (fd < 0)
547 769 return -1;
548 770 memset(&header, 0, sizeof(header));
... ... @@ -552,28 +774,11 @@ static int qcow_create(const char *filename, int64_t total_size,
552 774 header_size = sizeof(header);
553 775 backing_filename_len = 0;
554 776 if (backing_file) {
555   - if (strcmp(backing_file, "fat:")) {
556   - const char *p;
557   - /* XXX: this is a hack: we do not attempt to check for URL
558   - like syntax */
559   - p = strchr(backing_file, ':');
560   - if (p && (p - backing_file) >= 2) {
561   - /* URL like but exclude "c:" like filenames */
562   - pstrcpy(backing_filename, sizeof(backing_filename),
563   - backing_file);
564   - } else {
565   - realpath(backing_file, backing_filename);
566   - if (stat(backing_filename, &st) != 0) {
567   - return -1;
568   - }
569   - }
570   - header.backing_file_offset = cpu_to_be64(header_size);
571   - backing_filename_len = strlen(backing_filename);
572   - header.backing_file_size = cpu_to_be32(backing_filename_len);
573   - header_size += backing_filename_len;
574   - } else
575   - backing_file = NULL;
576   - header.mtime = cpu_to_be32(st.st_mtime);
  777 + header.backing_file_offset = cpu_to_be64(header_size);
  778 + backing_filename_len = strlen(backing_file);
  779 + header.backing_file_size = cpu_to_be32(backing_filename_len);
  780 + header_size += backing_filename_len;
  781 + header.mtime = cpu_to_be32(0);
577 782 header.cluster_bits = 9; /* 512 byte cluster to avoid copying
578 783 unmodifyed sectors */
579 784 header.l2_bits = 12; /* 32 KB L2 tables */
... ... @@ -595,7 +800,7 @@ static int qcow_create(const char *filename, int64_t total_size,
595 800 /* write all the data */
596 801 write(fd, &header, sizeof(header));
597 802 if (backing_file) {
598   - write(fd, backing_filename, backing_filename_len);
  803 + write(fd, backing_file, backing_filename_len);
599 804 }
600 805 lseek(fd, header_size, SEEK_SET);
601 806 tmp = 0;
... ... @@ -610,12 +815,14 @@ int qcow_make_empty(BlockDriverState *bs)
610 815 {
611 816 BDRVQcowState *s = bs->opaque;
612 817 uint32_t l1_length = s->l1_size * sizeof(uint64_t);
  818 + int ret;
613 819  
614 820 memset(s->l1_table, 0, l1_length);
615   - lseek(s->fd, s->l1_table_offset, SEEK_SET);
616   - if (write(s->fd, s->l1_table, l1_length) < 0)
  821 + if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
617 822 return -1;
618   - ftruncate(s->fd, s->l1_table_offset + l1_length);
  823 + ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
  824 + if (ret < 0)
  825 + return ret;
619 826  
620 827 memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
621 828 memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
... ... @@ -682,8 +889,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
682 889 cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
683 890 out_len, 0, 0);
684 891 cluster_offset &= s->cluster_offset_mask;
685   - lseek(s->fd, cluster_offset, SEEK_SET);
686   - if (write(s->fd, out_buf, out_len) != out_len) {
  892 + if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
687 893 qemu_free(out_buf);
688 894 return -1;
689 895 }
... ... @@ -696,7 +902,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
696 902 static void qcow_flush(BlockDriverState *bs)
697 903 {
698 904 BDRVQcowState *s = bs->opaque;
699   - fsync(s->fd);
  905 + bdrv_flush(s->hd);
700 906 }
701 907  
702 908 BlockDriver bdrv_qcow = {
... ... @@ -704,14 +910,20 @@ BlockDriver bdrv_qcow = {
704 910 sizeof(BDRVQcowState),
705 911 qcow_probe,
706 912 qcow_open,
707   - qcow_read,
708   - qcow_write,
  913 + NULL,
  914 + NULL,
709 915 qcow_close,
710 916 qcow_create,
711 917 qcow_flush,
712 918 qcow_is_allocated,
713 919 qcow_set_key,
714   - qcow_make_empty
  920 + qcow_make_empty,
  921 +
  922 + .bdrv_aio_new = qcow_aio_new,
  923 + .bdrv_aio_read = qcow_aio_read,
  924 + .bdrv_aio_write = qcow_aio_write,
  925 + .bdrv_aio_cancel = qcow_aio_cancel,
  926 + .bdrv_aio_delete = qcow_aio_delete,
715 927 };
716 928  
717 929  
... ...
block-raw.c 0 โ†’ 100644
  1 +/*
  2 + * Block driver for RAW files
  3 + *
  4 + * Copyright (c) 2006 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"
  26 +#include <assert.h>
  27 +#ifndef _WIN32
  28 +#include <aio.h>
  29 +
  30 +#ifndef QEMU_TOOL
  31 +#include "exec-all.h"
  32 +#endif
  33 +
  34 +#ifdef CONFIG_COCOA
  35 +#include <paths.h>
  36 +#include <sys/param.h>
  37 +#include <IOKit/IOKitLib.h>
  38 +#include <IOKit/IOBSD.h>
  39 +#include <IOKit/storage/IOMediaBSDClient.h>
  40 +#include <IOKit/storage/IOMedia.h>
  41 +#include <IOKit/storage/IOCDMedia.h>
  42 +//#include <IOKit/storage/IOCDTypes.h>
  43 +#include <CoreFoundation/CoreFoundation.h>
  44 +#endif
  45 +
  46 +#ifdef __sun__
  47 +#include <sys/dkio.h>
  48 +#endif
  49 +
  50 +typedef struct BDRVRawState {
  51 + int fd;
  52 +} BDRVRawState;
  53 +
  54 +#ifdef CONFIG_COCOA
  55 +static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
  56 +static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
  57 +
  58 +kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
  59 +{
  60 + kern_return_t kernResult;
  61 + mach_port_t masterPort;
  62 + CFMutableDictionaryRef classesToMatch;
  63 +
  64 + kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
  65 + if ( KERN_SUCCESS != kernResult ) {
  66 + printf( "IOMasterPort returned %d\n", kernResult );
  67 + }
  68 +
  69 + classesToMatch = IOServiceMatching( kIOCDMediaClass );
  70 + if ( classesToMatch == NULL ) {
  71 + printf( "IOServiceMatching returned a NULL dictionary.\n" );
  72 + } else {
  73 + CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
  74 + }
  75 + kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
  76 + if ( KERN_SUCCESS != kernResult )
  77 + {
  78 + printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
  79 + }
  80 +
  81 + return kernResult;
  82 +}
  83 +
  84 +kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
  85 +{
  86 + io_object_t nextMedia;
  87 + kern_return_t kernResult = KERN_FAILURE;
  88 + *bsdPath = '\0';
  89 + nextMedia = IOIteratorNext( mediaIterator );
  90 + if ( nextMedia )
  91 + {
  92 + CFTypeRef bsdPathAsCFString;
  93 + bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
  94 + if ( bsdPathAsCFString ) {
  95 + size_t devPathLength;
  96 + strcpy( bsdPath, _PATH_DEV );
  97 + strcat( bsdPath, "r" );
  98 + devPathLength = strlen( bsdPath );
  99 + if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
  100 + kernResult = KERN_SUCCESS;
  101 + }
  102 + CFRelease( bsdPathAsCFString );
  103 + }
  104 + IOObjectRelease( nextMedia );
  105 + }
  106 +
  107 + return kernResult;
  108 +}
  109 +
  110 +#endif
  111 +
  112 +static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  113 +{
  114 + BDRVRawState *s = bs->opaque;
  115 + int fd, open_flags;
  116 +
  117 +#ifdef CONFIG_COCOA
  118 + if (strstart(filename, "/dev/cdrom", NULL)) {
  119 + kern_return_t kernResult;
  120 + io_iterator_t mediaIterator;
  121 + char bsdPath[ MAXPATHLEN ];
  122 + int fd;
  123 +
  124 + kernResult = FindEjectableCDMedia( &mediaIterator );
  125 + kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  126 +
  127 + if ( bsdPath[ 0 ] != '\0' ) {
  128 + strcat(bsdPath,"s0");
  129 + /* some CDs don't have a partition 0 */
  130 + fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  131 + if (fd < 0) {
  132 + bsdPath[strlen(bsdPath)-1] = '1';
  133 + } else {
  134 + close(fd);
  135 + }
  136 + filename = bsdPath;
  137 + }
  138 +
  139 + if ( mediaIterator )
  140 + IOObjectRelease( mediaIterator );
  141 + }
  142 +#endif
  143 + open_flags = O_BINARY;
  144 + if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  145 + open_flags |= O_RDWR;
  146 + } else {
  147 + open_flags |= O_RDONLY;
  148 + bs->read_only = 1;
  149 + }
  150 + if (flags & BDRV_O_CREAT)
  151 + open_flags |= O_CREAT | O_TRUNC;
  152 +
  153 + fd = open(filename, open_flags, 0644);
  154 + if (fd < 0)
  155 + return -errno;
  156 + s->fd = fd;
  157 + return 0;
  158 +}
  159 +
  160 +/* XXX: use host sector size if necessary with:
  161 +#ifdef DIOCGSECTORSIZE
  162 + {
  163 + unsigned int sectorsize = 512;
  164 + if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  165 + sectorsize > bufsize)
  166 + bufsize = sectorsize;
  167 + }
  168 +#endif
  169 +#ifdef CONFIG_COCOA
  170 + u_int32_t blockSize = 512;
  171 + if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  172 + bufsize = blockSize;
  173 + }
  174 +#endif
  175 +*/
  176 +
  177 +static int raw_pread(BlockDriverState *bs, int64_t offset,
  178 + uint8_t *buf, int count)
  179 +{
  180 + BDRVRawState *s = bs->opaque;
  181 + int ret;
  182 +
  183 + lseek(s->fd, offset, SEEK_SET);
  184 + ret = read(s->fd, buf, count);
  185 + return ret;
  186 +}
  187 +
  188 +static int raw_pwrite(BlockDriverState *bs, int64_t offset,
  189 + const uint8_t *buf, int count)
  190 +{
  191 + BDRVRawState *s = bs->opaque;
  192 + int ret;
  193 +
  194 + lseek(s->fd, offset, SEEK_SET);
  195 + ret = write(s->fd, buf, count);
  196 + return ret;
  197 +}
  198 +
  199 +/***********************************************************/
  200 +/* Unix AOP using POSIX AIO */
  201 +
  202 +typedef struct RawAIOCB {
  203 + struct aiocb aiocb;
  204 + int busy; /* only used for debugging */
  205 + BlockDriverAIOCB *next;
  206 +} RawAIOCB;
  207 +
  208 +static int aio_sig_num = SIGUSR2;
  209 +static BlockDriverAIOCB *first_aio; /* AIO issued */
  210 +
  211 +#ifndef QEMU_TOOL
  212 +static void aio_signal_handler(int signum)
  213 +{
  214 + CPUState *env = cpu_single_env;
  215 + if (env) {
  216 + /* stop the currently executing cpu because a timer occured */
  217 + cpu_interrupt(env, CPU_INTERRUPT_EXIT);
  218 +#ifdef USE_KQEMU
  219 + if (env->kqemu_enabled) {
  220 + kqemu_cpu_interrupt(env);
  221 + }
  222 +#endif
  223 + }
  224 +}
  225 +
  226 +void qemu_aio_init(void)
  227 +{
  228 + struct sigaction act;
  229 +
  230 + sigfillset(&act.sa_mask);
  231 + act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
  232 + act.sa_handler = aio_signal_handler;
  233 + sigaction(aio_sig_num, &act, NULL);
  234 +
  235 + {
  236 + /* XXX: aio thread exit seems to hang on RH 9 */
  237 + struct aioinit ai;
  238 + memset(&ai, 0, sizeof(ai));
  239 + ai.aio_threads = 2;
  240 + ai.aio_num = 1;
  241 + ai.aio_idle_time = 365 * 100000;
  242 + aio_init(&ai);
  243 + }
  244 +}
  245 +#endif /* !QEMU_TOOL */
  246 +
  247 +void qemu_aio_poll(void)
  248 +{
  249 + BlockDriverAIOCB *acb, **pacb;
  250 + RawAIOCB *acb1;
  251 + int ret;
  252 +
  253 + for(;;) {
  254 + pacb = &first_aio;
  255 + for(;;) {
  256 + acb = *pacb;
  257 + if (!acb)
  258 + goto the_end;
  259 + acb1 = acb->opaque;
  260 + ret = aio_error(&acb1->aiocb);
  261 + if (ret == ECANCELED) {
  262 + /* remove the request */
  263 + acb1->busy = 0;
  264 + *pacb = acb1->next;
  265 + } else if (ret != EINPROGRESS) {
  266 + /* end of aio */
  267 + if (ret == 0) {
  268 + ret = aio_return(&acb1->aiocb);
  269 + if (ret == acb1->aiocb.aio_nbytes)
  270 + ret = 0;
  271 + else
  272 + ret = -1;
  273 + } else {
  274 + ret = -ret;
  275 + }
  276 + /* remove the request */
  277 + acb1->busy = 0;
  278 + *pacb = acb1->next;
  279 + /* call the callback */
  280 + acb->cb(acb->cb_opaque, ret);
  281 + break;
  282 + } else {
  283 + pacb = &acb1->next;
  284 + }
  285 + }
  286 + }
  287 + the_end: ;
  288 +}
  289 +
  290 +/* wait until at least one AIO was handled */
  291 +static sigset_t wait_oset;
  292 +
  293 +void qemu_aio_wait_start(void)
  294 +{
  295 + sigset_t set;
  296 + sigemptyset(&set);
  297 + sigaddset(&set, aio_sig_num);
  298 + sigprocmask(SIG_BLOCK, &set, &wait_oset);
  299 +}
  300 +
  301 +void qemu_aio_wait(void)
  302 +{
  303 + sigset_t set;
  304 + int nb_sigs;
  305 + sigemptyset(&set);
  306 + sigaddset(&set, aio_sig_num);
  307 + sigwait(&set, &nb_sigs);
  308 + qemu_aio_poll();
  309 +}
  310 +
  311 +void qemu_aio_wait_end(void)
  312 +{
  313 + sigprocmask(SIG_SETMASK, &wait_oset, NULL);
  314 +}
  315 +
  316 +static int raw_aio_new(BlockDriverAIOCB *acb)
  317 +{
  318 + RawAIOCB *acb1;
  319 + BDRVRawState *s = acb->bs->opaque;
  320 +
  321 + acb1 = qemu_mallocz(sizeof(RawAIOCB));
  322 + if (!acb1)
  323 + return -1;
  324 + acb->opaque = acb1;
  325 + acb1->aiocb.aio_fildes = s->fd;
  326 + acb1->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
  327 + acb1->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  328 + return 0;
  329 +}
  330 +
  331 +static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
  332 + uint8_t *buf, int nb_sectors)
  333 +{
  334 + RawAIOCB *acb1 = acb->opaque;
  335 +
  336 + assert(acb1->busy == 0);
  337 + acb1->busy = 1;
  338 + acb1->aiocb.aio_buf = buf;
  339 + acb1->aiocb.aio_nbytes = nb_sectors * 512;
  340 + acb1->aiocb.aio_offset = sector_num * 512;
  341 + acb1->next = first_aio;
  342 + first_aio = acb;
  343 + if (aio_read(&acb1->aiocb) < 0) {
  344 + acb1->busy = 0;
  345 + return -errno;
  346 + }
  347 + return 0;
  348 +}
  349 +
  350 +static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
  351 + const uint8_t *buf, int nb_sectors)
  352 +{
  353 + RawAIOCB *acb1 = acb->opaque;
  354 +
  355 + assert(acb1->busy == 0);
  356 + acb1->busy = 1;
  357 + acb1->aiocb.aio_buf = (uint8_t *)buf;
  358 + acb1->aiocb.aio_nbytes = nb_sectors * 512;
  359 + acb1->aiocb.aio_offset = sector_num * 512;
  360 + acb1->next = first_aio;
  361 + first_aio = acb;
  362 + if (aio_write(&acb1->aiocb) < 0) {
  363 + acb1->busy = 0;
  364 + return -errno;
  365 + }
  366 + return 0;
  367 +}
  368 +
  369 +static void raw_aio_cancel(BlockDriverAIOCB *acb)
  370 +{
  371 + RawAIOCB *acb1 = acb->opaque;
  372 + int ret;
  373 + BlockDriverAIOCB **pacb;
  374 +
  375 + ret = aio_cancel(acb1->aiocb.aio_fildes, &acb1->aiocb);
  376 + if (ret == AIO_NOTCANCELED) {
  377 + /* fail safe: if the aio could not be canceled, we wait for
  378 + it */
  379 + while (aio_error(&acb1->aiocb) == EINPROGRESS);
  380 + }
  381 +
  382 + /* remove the callback from the queue */
  383 + pacb = &first_aio;
  384 + for(;;) {
  385 + if (*pacb == NULL) {
  386 + break;
  387 + } else if (*pacb == acb) {
  388 + acb1->busy = 0;
  389 + *pacb = acb1->next;
  390 + break;
  391 + }
  392 + acb1 = (*pacb)->opaque;
  393 + pacb = &acb1->next;
  394 + }
  395 +}
  396 +
  397 +static void raw_aio_delete(BlockDriverAIOCB *acb)
  398 +{
  399 + RawAIOCB *acb1 = acb->opaque;
  400 + raw_aio_cancel(acb);
  401 + qemu_free(acb1);
  402 +}
  403 +
  404 +static void raw_close(BlockDriverState *bs)
  405 +{
  406 + BDRVRawState *s = bs->opaque;
  407 + close(s->fd);
  408 +}
  409 +
  410 +static int raw_truncate(BlockDriverState *bs, int64_t offset)
  411 +{
  412 + BDRVRawState *s = bs->opaque;
  413 + if (ftruncate(s->fd, offset) < 0)
  414 + return -errno;
  415 + return 0;
  416 +}
  417 +
  418 +static int64_t raw_getlength(BlockDriverState *bs)
  419 +{
  420 + BDRVRawState *s = bs->opaque;
  421 + int fd = s->fd;
  422 + int64_t size;
  423 +#ifdef _BSD
  424 + struct stat sb;
  425 +#endif
  426 +#ifdef __sun__
  427 + struct dk_minfo minfo;
  428 + int rv;
  429 +#endif
  430 +
  431 +#ifdef _BSD
  432 + if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  433 +#ifdef DIOCGMEDIASIZE
  434 + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  435 +#endif
  436 +#ifdef CONFIG_COCOA
  437 + size = LONG_LONG_MAX;
  438 +#else
  439 + size = lseek(fd, 0LL, SEEK_END);
  440 +#endif
  441 + } else
  442 +#endif
  443 +#ifdef __sun__
  444 + /*
  445 + * use the DKIOCGMEDIAINFO ioctl to read the size.
  446 + */
  447 + rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
  448 + if ( rv != -1 ) {
  449 + size = minfo.dki_lbsize * minfo.dki_capacity;
  450 + } else /* there are reports that lseek on some devices
  451 + fails, but irc discussion said that contingency
  452 + on contingency was overkill */
  453 +#endif
  454 + {
  455 + size = lseek(fd, 0, SEEK_END);
  456 + }
  457 +#ifdef _WIN32
  458 + /* On Windows hosts it can happen that we're unable to get file size
  459 + for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
  460 + if (size == -1)
  461 + size = LONG_LONG_MAX;
  462 +#endif
  463 + return size;
  464 +}
  465 +
  466 +static int raw_create(const char *filename, int64_t total_size,
  467 + const char *backing_file, int flags)
  468 +{
  469 + int fd;
  470 +
  471 + if (flags || backing_file)
  472 + return -ENOTSUP;
  473 +
  474 + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
  475 + 0644);
  476 + if (fd < 0)
  477 + return -EIO;
  478 + ftruncate(fd, total_size * 512);
  479 + close(fd);
  480 + return 0;
  481 +}
  482 +
  483 +static void raw_flush(BlockDriverState *bs)
  484 +{
  485 + BDRVRawState *s = bs->opaque;
  486 + fsync(s->fd);
  487 +}
  488 +
  489 +BlockDriver bdrv_raw = {
  490 + "raw",
  491 + sizeof(BDRVRawState),
  492 + NULL, /* no probe for protocols */
  493 + raw_open,
  494 + NULL,
  495 + NULL,
  496 + raw_close,
  497 + raw_create,
  498 + raw_flush,
  499 +
  500 + .bdrv_aio_new = raw_aio_new,
  501 + .bdrv_aio_read = raw_aio_read,
  502 + .bdrv_aio_write = raw_aio_write,
  503 + .bdrv_aio_cancel = raw_aio_cancel,
  504 + .bdrv_aio_delete = raw_aio_delete,
  505 + .protocol_name = "file",
  506 + .bdrv_pread = raw_pread,
  507 + .bdrv_pwrite = raw_pwrite,
  508 + .bdrv_truncate = raw_truncate,
  509 + .bdrv_getlength = raw_getlength,
  510 +};
  511 +
  512 +#else /* _WIN32 */
  513 +
  514 +/* XXX: use another file ? */
  515 +#include <windows.h>
  516 +#include <winioctl.h>
  517 +
  518 +typedef struct BDRVRawState {
  519 + HANDLE hfile;
  520 +} BDRVRawState;
  521 +
  522 +typedef struct RawAIOCB {
  523 + HANDLE hEvent;
  524 + OVERLAPPED ov;
  525 + int count;
  526 +} RawAIOCB;
  527 +
  528 +int qemu_ftruncate64(int fd, int64_t length)
  529 +{
  530 + LARGE_INTEGER li;
  531 + LONG high;
  532 + HANDLE h;
  533 + BOOL res;
  534 +
  535 + if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
  536 + return -1;
  537 +
  538 + h = (HANDLE)_get_osfhandle(fd);
  539 +
  540 + /* get current position, ftruncate do not change position */
  541 + li.HighPart = 0;
  542 + li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
  543 + if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
  544 + return -1;
  545 +
  546 + high = length >> 32;
  547 + if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
  548 + return -1;
  549 + res = SetEndOfFile(h);
  550 +
  551 + /* back to old position */
  552 + SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
  553 + return res ? 0 : -1;
  554 +}
  555 +
  556 +static int set_sparse(int fd)
  557 +{
  558 + DWORD returned;
  559 + return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
  560 + NULL, 0, NULL, 0, &returned, NULL);
  561 +}
  562 +
  563 +static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  564 +{
  565 + BDRVRawState *s = bs->opaque;
  566 + int access_flags, create_flags;
  567 +
  568 + if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  569 + access_flags = GENERIC_READ | GENERIC_WRITE;
  570 + } else {
  571 + access_flags = GENERIC_READ;
  572 + }
  573 + if (flags & BDRV_O_CREATE) {
  574 + create_flags = CREATE_ALWAYS;
  575 + } else {
  576 + create_flags = OPEN_EXISTING;
  577 + }
  578 + s->hfile = CreateFile(filename, access_flags,
  579 + FILE_SHARE_READ, NULL,
  580 + create_flags, FILE_FLAG_OVERLAPPED, 0);
  581 + if (s->hfile == INVALID_HANDLE_VALUE)
  582 + return -1;
  583 + return 0;
  584 +}
  585 +
  586 +static int raw_pread(BlockDriverState *bs, int64_t offset,
  587 + uint8_t *buf, int count)
  588 +{
  589 + BDRVRawState *s = bs->opaque;
  590 + OVERLAPPED ov;
  591 + DWORD ret_count;
  592 + int ret;
  593 +
  594 + memset(&ov, 0, sizeof(ov));
  595 + ov.Offset = offset;
  596 + ov.OffsetHigh = offset >> 32;
  597 + ret = ReadFile(s->hfile, buf, count, NULL, &ov);
  598 + if (!ret)
  599 + return -EIO;
  600 + ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  601 + if (!ret)
  602 + return -EIO;
  603 + return ret_count;
  604 +}
  605 +
  606 +static int raw_pwrite(BlockDriverState *bs, int64_t offset,
  607 + const uint8_t *buf, int count)
  608 +{
  609 + BDRVRawState *s = bs->opaque;
  610 + OVERLAPPED ov;
  611 + DWORD ret_count;
  612 + int ret;
  613 +
  614 + memset(&ov, 0, sizeof(ov));
  615 + ov.Offset = offset;
  616 + ov.OffsetHigh = offset >> 32;
  617 + ret = WriteFile(s->hfile, buf, count, NULL, &ov);
  618 + if (!ret)
  619 + return -EIO;
  620 + ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  621 + if (!ret)
  622 + return -EIO;
  623 + return ret_count;
  624 +}
  625 +
  626 +static int raw_aio_new(BlockDriverAIOCB *acb)
  627 +{
  628 + RawAIOCB *acb1;
  629 + BDRVRawState *s = acb->bs->opaque;
  630 +
  631 + acb1 = qemu_mallocz(sizeof(RawAIOCB));
  632 + if (!acb1)
  633 + return -ENOMEM;
  634 + acb->opaque = acb1;
  635 + s->hevent = CreateEvent(NULL, TRUE, FALSE, NULL);
  636 + if (!s->hevent)
  637 + return -ENOMEM;
  638 + return 0;
  639 +}
  640 +
  641 +static void raw_aio_cb(void *opaque)
  642 +{
  643 + BlockDriverAIOCB *acb = acb1;
  644 + RawAIOCB *acb1 = acb->opaque;
  645 + DWORD ret_count;
  646 + int ret;
  647 +
  648 + ret = GetOverlappedResult(s->hfile, &acb1->ov, &ret_count, TRUE);
  649 + if (!ret || ret_count != acb1->count) {
  650 + acb->cb(acb->cb_opaque, -EIO);
  651 + } else {
  652 + acb->cb(acb->cb_opaque, 0);
  653 + }
  654 +}
  655 +
  656 +static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
  657 + uint8_t *buf, int nb_sectors)
  658 +{
  659 + BlockDriverState *bs = acb->bs;
  660 + BDRVRawState *s = bs->opaque;
  661 + RawAIOCB *acb1 = acb->opaque;
  662 + DWORD ret_count;
  663 + int ret;
  664 + int64_t offset;
  665 +
  666 + memset(&acb1->ov, 0, sizeof(acb1->ov));
  667 + offset = sector_num * 512;
  668 + acb1->ov.Offset = offset;
  669 + acb1->ov.OffsetHigh = offset >> 32;
  670 + acb1->ov.hEvent = acb1->hEvent;
  671 + acb1->count = nb_sectors * 512;
  672 + qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
  673 + ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
  674 + if (!ret)
  675 + return -EIO;
  676 + return 0;
  677 +}
  678 +
  679 +static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
  680 + uint8_t *buf, int nb_sectors)
  681 +{
  682 + BlockDriverState *bs = acb->bs;
  683 + BDRVRawState *s = bs->opaque;
  684 + RawAIOCB *acb1 = acb->opaque;
  685 + DWORD ret_count;
  686 + int ret;
  687 + int64_t offset;
  688 +
  689 + memset(&acb1->ov, 0, sizeof(acb1->ov));
  690 + offset = sector_num * 512;
  691 + acb1->ov.Offset = offset;
  692 + acb1->ov.OffsetHigh = offset >> 32;
  693 + acb1->ov.hEvent = acb1->hEvent;
  694 + acb1->count = nb_sectors * 512;
  695 + qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
  696 + ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
  697 + if (!ret)
  698 + return -EIO;
  699 + return 0;
  700 +}
  701 +
  702 +static void raw_aio_cancel(BlockDriverAIOCB *acb)
  703 +{
  704 + BlockDriverState *bs = acb->bs;
  705 + BDRVRawState *s = bs->opaque;
  706 + RawAIOCB *acb1 = acb->opaque;
  707 +
  708 + qemu_del_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
  709 + /* XXX: if more than one async I/O it is not correct */
  710 + CancelIo(s->hfile);
  711 +}
  712 +
  713 +static void raw_aio_delete(BlockDriverAIOCB *acb)
  714 +{
  715 + RawAIOCB *acb1 = acb->opaque;
  716 + raw_aio_cancel(acb);
  717 + CloseHandle(acb1->hEvent);
  718 + qemu_free(acb1);
  719 +}
  720 +
  721 +static void raw_flush(BlockDriverState *bs)
  722 +{
  723 + /* XXX: add it */
  724 +}
  725 +
  726 +static void raw_close(BlockDriverState *bs)
  727 +{
  728 + BDRVRawState *s = bs->opaque;
  729 + CloseHandle(s->hfile);
  730 +}
  731 +
  732 +static int raw_truncate(BlockDriverState *bs, int64_t offset)
  733 +{
  734 + BDRVRawState *s = bs->opaque;
  735 + DWORD low, high;
  736 +
  737 + low = length;
  738 + high = length >> 32;
  739 + if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
  740 + return -EIO;
  741 + if (!SetEndOfFile(s->hfile))
  742 + return -EIO;
  743 + return 0;
  744 +}
  745 +
  746 +static int64_t raw_getlength(BlockDriverState *bs)
  747 +{
  748 + BDRVRawState *s = bs->opaque;
  749 + LARGE_INTEGER l;
  750 + if (!GetFileSizeEx(s->hfile, &l))
  751 + return -EIO;
  752 + return l.QuadPart;
  753 +}
  754 +
  755 +static int raw_create(const char *filename, int64_t total_size,
  756 + const char *backing_file, int flags)
  757 +{
  758 + int fd;
  759 +
  760 + if (flags || backing_file)
  761 + return -ENOTSUP;
  762 +
  763 + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
  764 + 0644);
  765 + if (fd < 0)
  766 + return -EIO;
  767 + set_sparse(fd);
  768 + ftruncate(fd, total_size * 512);
  769 + close(fd);
  770 + return 0;
  771 +}
  772 +
  773 +void qemu_aio_init(void)
  774 +{
  775 +}
  776 +
  777 +void qemu_aio_poll(void)
  778 +{
  779 +}
  780 +
  781 +void qemu_aio_wait_start(void)
  782 +{
  783 +}
  784 +
  785 +void qemu_aio_wait(void)
  786 +{
  787 +}
  788 +
  789 +void qemu_aio_wait_end(void)
  790 +{
  791 +}
  792 +
  793 +BlockDriver bdrv_raw = {
  794 + "raw",
  795 + sizeof(BDRVRawState),
  796 + NULL, /* no probe for protocols */
  797 + raw_open,
  798 + NULL,
  799 + NULL,
  800 + raw_close,
  801 + raw_create,
  802 + raw_flush,
  803 +
  804 +#if 0
  805 + .bdrv_aio_new = raw_aio_new,
  806 + .bdrv_aio_read = raw_aio_read,
  807 + .bdrv_aio_write = raw_aio_write,
  808 + .bdrv_aio_cancel = raw_aio_cancel,
  809 + .bdrv_aio_delete = raw_aio_delete,
  810 +#endif
  811 + .protocol_name = "file",
  812 + .bdrv_pread = raw_pread,
  813 + .bdrv_pwrite = raw_pwrite,
  814 + .bdrv_truncate = raw_truncate,
  815 + .bdrv_getlength = raw_getlength,
  816 +};
  817 +#endif /* _WIN32 */
... ...
block-vmdk.c
... ... @@ -89,7 +89,7 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
89 89 return 0;
90 90 }
91 91  
92   -static int vmdk_open(BlockDriverState *bs, const char *filename)
  92 +static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
93 93 {
94 94 BDRVVmdkState *s = bs->opaque;
95 95 int fd, i;
... ...
block-vpc.c
... ... @@ -86,19 +86,16 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
86 86 return 0;
87 87 }
88 88  
89   -static int vpc_open(BlockDriverState *bs, const char *filename)
  89 +static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
90 90 {
91 91 BDRVVPCState *s = bs->opaque;
92 92 int fd, i;
93 93 struct vpc_subheader header;
94 94  
95   - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
96   - if (fd < 0) {
97   - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
98   - if (fd < 0)
99   - return -1;
100   - }
101   -
  95 + fd = open(filename, O_RDONLY | O_BINARY);
  96 + if (fd < 0)
  97 + return -1;
  98 +
102 99 bs->read_only = 1; // no write support yet
103 100  
104 101 s->fd = fd;
... ...
block-vvfat.c
... ... @@ -351,13 +351,6 @@ typedef struct BDRVVVFATState {
351 351 } BDRVVVFATState;
352 352  
353 353  
354   -static int vvfat_probe(const uint8_t *buf, int buf_size, const char *filename)
355   -{
356   - if (strstart(filename, "fat:", NULL))
357   - return 100;
358   - return 0;
359   -}
360   -
361 354 static void init_mbr(BDRVVVFATState* s)
362 355 {
363 356 /* TODO: if the files mbr.img and bootsect.img exist, use them */
... ... @@ -954,18 +947,22 @@ static int init_directories(BDRVVVFATState* s,
954 947 return 0;
955 948 }
956 949  
  950 +#ifdef DEBUG
957 951 static BDRVVVFATState *vvv = NULL;
  952 +#endif
958 953  
959 954 static int enable_write_target(BDRVVVFATState *s);
960 955 static int is_consistent(BDRVVVFATState *s);
961 956  
962   -static int vvfat_open(BlockDriverState *bs, const char* dirname)
  957 +static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
963 958 {
964 959 BDRVVVFATState *s = bs->opaque;
965 960 int floppy = 0;
966 961 int i;
967 962  
  963 +#ifdef DEBUG
968 964 vvv = s;
  965 +#endif
969 966  
970 967 DLOG(if (stderr == NULL) {
971 968 stderr = fopen("vvfat.log", "a");
... ... @@ -1040,7 +1037,6 @@ DLOG(if (stderr == NULL) {
1040 1037 bs->heads = bs->cyls = bs->secs = 0;
1041 1038  
1042 1039 // assert(is_consistent(s));
1043   -
1044 1040 return 0;
1045 1041 }
1046 1042  
... ... @@ -2732,8 +2728,7 @@ static int enable_write_target(BDRVVVFATState *s)
2732 2728 array_init(&(s->commits), sizeof(commit_t));
2733 2729  
2734 2730 s->qcow_filename = malloc(1024);
2735   - strcpy(s->qcow_filename, "/tmp/vl.XXXXXX");
2736   - get_tmp_filename(s->qcow_filename, strlen(s->qcow_filename) + 1);
  2731 + get_tmp_filename(s->qcow_filename, 1024);
2737 2732 if (bdrv_create(&bdrv_qcow,
2738 2733 s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2739 2734 return -1;
... ... @@ -2767,14 +2762,15 @@ static void vvfat_close(BlockDriverState *bs)
2767 2762 BlockDriver bdrv_vvfat = {
2768 2763 "vvfat",
2769 2764 sizeof(BDRVVVFATState),
2770   - vvfat_probe,
  2765 + NULL, /* no probe for protocols */
2771 2766 vvfat_open,
2772 2767 vvfat_read,
2773 2768 vvfat_write,
2774 2769 vvfat_close,
2775 2770 NULL, /* ??? Not sure if we can do any meaningful flushing. */
2776 2771 NULL,
2777   - vvfat_is_allocated
  2772 + vvfat_is_allocated,
  2773 + .protocol_name = "fat",
2778 2774 };
2779 2775  
2780 2776 #ifdef DEBUG
... ...
... ... @@ -32,85 +32,92 @@
32 32 #include <sys/disk.h>
33 33 #endif
34 34  
35   -#ifdef CONFIG_COCOA
36   -#include <paths.h>
37   -#include <sys/param.h>
38   -#include <IOKit/IOKitLib.h>
39   -#include <IOKit/IOBSD.h>
40   -#include <IOKit/storage/IOMediaBSDClient.h>
41   -#include <IOKit/storage/IOMedia.h>
42   -#include <IOKit/storage/IOCDMedia.h>
43   -//#include <IOKit/storage/IOCDTypes.h>
44   -#include <CoreFoundation/CoreFoundation.h>
45   -#endif
46   -
47   -#ifdef __sun__
48   -#include <sys/dkio.h>
49   -#endif
  35 +#define SECTOR_BITS 9
  36 +#define SECTOR_SIZE (1 << SECTOR_BITS)
  37 +
  38 +static int bdrv_aio_new_em(BlockDriverAIOCB *acb);
  39 +static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
  40 + uint8_t *buf, int nb_sectors);
  41 +static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
  42 + const uint8_t *buf, int nb_sectors);
  43 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
  44 +static void bdrv_aio_delete_em(BlockDriverAIOCB *acb);
  45 +static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
  46 + uint8_t *buf, int nb_sectors);
  47 +static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
  48 + const uint8_t *buf, int nb_sectors);
50 49  
51 50 static BlockDriverState *bdrv_first;
52 51 static BlockDriver *first_drv;
53 52  
54   -#ifdef CONFIG_COCOA
55   -static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
56   -static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
  53 +#ifdef _WIN32
  54 +#define PATH_SEP '\\'
  55 +#else
  56 +#define PATH_SEP '/'
  57 +#endif
57 58  
58   -kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
  59 +int path_is_absolute(const char *path)
59 60 {
60   - kern_return_t kernResult;
61   - mach_port_t masterPort;
62   - CFMutableDictionaryRef classesToMatch;
63   -
64   - kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
65   - if ( KERN_SUCCESS != kernResult ) {
66   - printf( "IOMasterPort returned %d\n", kernResult );
67   - }
68   -
69   - classesToMatch = IOServiceMatching( kIOCDMediaClass );
70   - if ( classesToMatch == NULL ) {
71   - printf( "IOServiceMatching returned a NULL dictionary.\n" );
72   - } else {
73   - CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
74   - }
75   - kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
76   - if ( KERN_SUCCESS != kernResult )
77   - {
78   - printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
79   - }
80   -
81   - return kernResult;
  61 + const char *p;
  62 + p = strchr(path, ':');
  63 + if (p)
  64 + p++;
  65 + else
  66 + p = path;
  67 + return (*p == PATH_SEP);
82 68 }
83 69  
84   -kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
  70 +/* if filename is absolute, just copy it to dest. Otherwise, build a
  71 + path to it by considering it is relative to base_path. URL are
  72 + supported. */
  73 +void path_combine(char *dest, int dest_size,
  74 + const char *base_path,
  75 + const char *filename)
85 76 {
86   - io_object_t nextMedia;
87   - kern_return_t kernResult = KERN_FAILURE;
88   - *bsdPath = '\0';
89   - nextMedia = IOIteratorNext( mediaIterator );
90   - if ( nextMedia )
91   - {
92   - CFTypeRef bsdPathAsCFString;
93   - bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
94   - if ( bsdPathAsCFString ) {
95   - size_t devPathLength;
96   - strcpy( bsdPath, _PATH_DEV );
97   - strcat( bsdPath, "r" );
98   - devPathLength = strlen( bsdPath );
99   - if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
100   - kernResult = KERN_SUCCESS;
101   - }
102   - CFRelease( bsdPathAsCFString );
103   - }
104   - IOObjectRelease( nextMedia );
  77 + const char *p, *p1;
  78 + int len;
  79 +
  80 + if (dest_size <= 0)
  81 + return;
  82 + if (path_is_absolute(filename)) {
  83 + pstrcpy(dest, dest_size, filename);
  84 + } else {
  85 + p = strchr(base_path, ':');
  86 + if (p)
  87 + p++;
  88 + else
  89 + p = base_path;
  90 + p1 = strrchr(base_path, PATH_SEP);
  91 + if (p1)
  92 + p1++;
  93 + else
  94 + p1 = base_path;
  95 + if (p1 > p)
  96 + p = p1;
  97 + len = p - base_path;
  98 + if (len > dest_size - 1)
  99 + len = dest_size - 1;
  100 + memcpy(dest, base_path, len);
  101 + dest[len] = '\0';
  102 + pstrcat(dest, dest_size, filename);
105 103 }
106   -
107   - return kernResult;
108 104 }
109 105  
110   -#endif
111 106  
112 107 void bdrv_register(BlockDriver *bdrv)
113 108 {
  109 + if (!bdrv->bdrv_aio_new) {
  110 + /* add AIO emulation layer */
  111 + bdrv->bdrv_aio_new = bdrv_aio_new_em;
  112 + bdrv->bdrv_aio_read = bdrv_aio_read_em;
  113 + bdrv->bdrv_aio_write = bdrv_aio_write_em;
  114 + bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
  115 + bdrv->bdrv_aio_delete = bdrv_aio_delete_em;
  116 + } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
  117 + /* add synchronous IO emulation layer */
  118 + bdrv->bdrv_read = bdrv_read_em;
  119 + bdrv->bdrv_write = bdrv_write_em;
  120 + }
114 121 bdrv->next = first_drv;
115 122 first_drv = bdrv;
116 123 }
... ... @@ -156,14 +163,7 @@ int bdrv_create(BlockDriver *drv,
156 163 #ifdef _WIN32
157 164 void get_tmp_filename(char *filename, int size)
158 165 {
159   - char* p = strrchr(filename, '/');
160   -
161   - if (p == NULL)
162   - return;
163   -
164   - /* XXX: find a better function */
165   - tmpnam(p);
166   - *p = '/';
  166 + tmpnam(filename);
167 167 }
168 168 #else
169 169 void get_tmp_filename(char *filename, int size)
... ... @@ -176,101 +176,107 @@ void get_tmp_filename(char *filename, int size)
176 176 }
177 177 #endif
178 178  
  179 +static BlockDriver *find_protocol(const char *filename)
  180 +{
  181 + BlockDriver *drv1;
  182 + char protocol[128];
  183 + int len;
  184 + const char *p;
  185 + p = strchr(filename, ':');
  186 + if (!p)
  187 + return &bdrv_raw;
  188 + len = p - filename;
  189 + if (len > sizeof(protocol) - 1)
  190 + len = sizeof(protocol) - 1;
  191 +#ifdef _WIN32
  192 + if (len == 1) {
  193 + /* specific win32 case for driver letters */
  194 + return &bdrv_raw;
  195 + }
  196 +#endif
  197 + memcpy(protocol, filename, len);
  198 + protocol[len] = '\0';
  199 + for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  200 + if (drv1->protocol_name &&
  201 + !strcmp(drv1->protocol_name, protocol))
  202 + return drv1;
  203 + }
  204 + return NULL;
  205 +}
  206 +
179 207 /* XXX: force raw format if block or character device ? It would
180 208 simplify the BSD case */
181 209 static BlockDriver *find_image_format(const char *filename)
182 210 {
183   - int fd, ret, score, score_max;
  211 + int ret, score, score_max;
184 212 BlockDriver *drv1, *drv;
185   - uint8_t *buf;
186   - size_t bufsize = 1024;
187   -
188   - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
189   - if (fd < 0) {
190   - buf = NULL;
191   - ret = 0;
192   - } else {
193   -#ifdef DIOCGSECTORSIZE
194   - {
195   - unsigned int sectorsize = 512;
196   - if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
197   - sectorsize > bufsize)
198   - bufsize = sectorsize;
199   - }
200   -#endif
201   -#ifdef CONFIG_COCOA
202   - u_int32_t blockSize = 512;
203   - if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
204   - bufsize = blockSize;
205   - }
206   -#endif
207   - buf = qemu_malloc(bufsize);
208   - if (!buf)
209   - return NULL;
210   - ret = read(fd, buf, bufsize);
211   - if (ret < 0) {
212   - close(fd);
213   - qemu_free(buf);
214   - return NULL;
215   - }
216   - close(fd);
217   - }
  213 + uint8_t buf[2048];
  214 + BlockDriverState *bs;
218 215  
219   - drv = NULL;
  216 + drv = find_protocol(filename);
  217 + /* no need to test disk image formats for vvfat or host specific
  218 + devices */
  219 + if (drv == &bdrv_vvfat)
  220 + return drv;
  221 + if (strstart(filename, "/dev/", NULL))
  222 + return &bdrv_raw;
  223 +
  224 + ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
  225 + if (ret < 0)
  226 + return NULL;
  227 + ret = bdrv_pread(bs, 0, buf, sizeof(buf));
  228 + bdrv_delete(bs);
  229 + if (ret < 0) {
  230 + return NULL;
  231 + }
  232 +
220 233 score_max = 0;
221 234 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
222   - score = drv1->bdrv_probe(buf, ret, filename);
223   - if (score > score_max) {
224   - score_max = score;
225   - drv = drv1;
  235 + if (drv1->bdrv_probe) {
  236 + score = drv1->bdrv_probe(buf, ret, filename);
  237 + if (score > score_max) {
  238 + score_max = score;
  239 + drv = drv1;
  240 + }
226 241 }
227 242 }
228   - qemu_free(buf);
229 243 return drv;
230 244 }
231 245  
232   -int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
  246 +int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
233 247 {
234   -#ifdef CONFIG_COCOA
235   - if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
236   - kern_return_t kernResult;
237   - io_iterator_t mediaIterator;
238   - char bsdPath[ MAXPATHLEN ];
239   - int fd;
240   -
241   - kernResult = FindEjectableCDMedia( &mediaIterator );
242   - kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
243   -
244   - if ( bsdPath[ 0 ] != '\0' ) {
245   - strcat(bsdPath,"s0");
246   - /* some CDs don't have a partition 0 */
247   - fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
248   - if (fd < 0) {
249   - bsdPath[strlen(bsdPath)-1] = '1';
250   - } else {
251   - close(fd);
252   - }
253   - filename = bsdPath;
254   - }
255   -
256   - if ( mediaIterator )
257   - IOObjectRelease( mediaIterator );
  248 + BlockDriverState *bs;
  249 + int ret;
  250 +
  251 + bs = bdrv_new("");
  252 + if (!bs)
  253 + return -ENOMEM;
  254 + ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
  255 + if (ret < 0) {
  256 + bdrv_delete(bs);
  257 + return ret;
258 258 }
259   -#endif
260   - return bdrv_open2(bs, filename, snapshot, NULL);
  259 + *pbs = bs;
  260 + return 0;
  261 +}
  262 +
  263 +int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
  264 +{
  265 + return bdrv_open2(bs, filename, flags, NULL);
261 266 }
262 267  
263   -int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
  268 +int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
264 269 BlockDriver *drv)
265 270 {
266   - int ret;
  271 + int ret, open_flags;
267 272 char tmp_filename[1024];
  273 + char backing_filename[1024];
268 274  
269 275 bs->read_only = 0;
270 276 bs->is_temporary = 0;
271 277 bs->encrypted = 0;
272 278  
273   - if (snapshot) {
  279 + if (flags & BDRV_O_SNAPSHOT) {
274 280 BlockDriverState *bs1;
275 281 int64_t total_size;
276 282  
... ... @@ -280,17 +286,16 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
280 286 /* if there is a backing file, use it */
281 287 bs1 = bdrv_new("");
282 288 if (!bs1) {
283   - return -1;
  289 + return -ENOMEM;
284 290 }
285 291 if (bdrv_open(bs1, filename, 0) < 0) {
286 292 bdrv_delete(bs1);
287 293 return -1;
288 294 }
289   - total_size = bs1->total_sectors;
  295 + total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
290 296 bdrv_delete(bs1);
291 297  
292 298 get_tmp_filename(tmp_filename, sizeof(tmp_filename));
293   - /* XXX: use cow for linux as it is more efficient ? */
294 299 if (bdrv_create(&bdrv_qcow, tmp_filename,
295 300 total_size, filename, 0) < 0) {
296 301 return -1;
... ... @@ -300,27 +305,43 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
300 305 }
301 306  
302 307 pstrcpy(bs->filename, sizeof(bs->filename), filename);
303   - if (!drv) {
304   - drv = find_image_format(filename);
  308 + if (flags & BDRV_O_FILE) {
  309 + drv = find_protocol(filename);
305 310 if (!drv)
306   - return -1;
  311 + return -ENOENT;
  312 + } else {
  313 + if (!drv) {
  314 + drv = find_image_format(filename);
  315 + if (!drv)
  316 + return -1;
  317 + }
307 318 }
308 319 bs->drv = drv;
309 320 bs->opaque = qemu_mallocz(drv->instance_size);
310 321 if (bs->opaque == NULL && drv->instance_size > 0)
311 322 return -1;
312   -
313   - ret = drv->bdrv_open(bs, filename);
  323 + /* Note: for compatibility, we open disk image files as RDWR, and
  324 + RDONLY as fallback */
  325 + if (!(flags & BDRV_O_FILE))
  326 + open_flags = BDRV_O_RDWR;
  327 + else
  328 + open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
  329 + ret = drv->bdrv_open(bs, filename, open_flags);
  330 + if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
  331 + ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
  332 + bs->read_only = 1;
  333 + }
314 334 if (ret < 0) {
315 335 qemu_free(bs->opaque);
316   - return -1;
  336 + return ret;
317 337 }
  338 +
318 339 #ifndef _WIN32
319 340 if (bs->is_temporary) {
320 341 unlink(filename);
321 342 }
322 343 #endif
323   - if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
  344 + if (bs->backing_file[0] != '\0') {
324 345 /* if there is a backing file, use it */
325 346 bs->backing_hd = bdrv_new("");
326 347 if (!bs->backing_hd) {
... ... @@ -328,7 +349,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
328 349 bdrv_close(bs);
329 350 return -1;
330 351 }
331   - if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
  352 + path_combine(backing_filename, sizeof(backing_filename),
  353 + filename, bs->backing_file);
  354 + if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
332 355 goto fail;
333 356 }
334 357  
... ... @@ -373,7 +396,7 @@ void bdrv_delete(BlockDriverState *bs)
373 396 /* commit COW file into the raw image */
374 397 int bdrv_commit(BlockDriverState *bs)
375 398 {
376   - int64_t i;
  399 + int64_t i, total_sectors;
377 400 int n, j;
378 401 unsigned char sector[512];
379 402  
... ... @@ -388,7 +411,8 @@ int bdrv_commit(BlockDriverState *bs)
388 411 return -ENOTSUP;
389 412 }
390 413  
391   - for (i = 0; i < bs->total_sectors;) {
  414 + total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  415 + for (i = 0; i < total_sectors;) {
392 416 if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
393 417 for(j = 0; j < n; j++) {
394 418 if (bdrv_read(bs, i, sector, 1) != 0) {
... ... @@ -411,49 +435,43 @@ int bdrv_commit(BlockDriverState *bs)
411 435 return 0;
412 436 }
413 437  
414   -/* return -1 if error */
  438 +/* return < 0 if error */
415 439 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
416 440 uint8_t *buf, int nb_sectors)
417 441 {
418   - int ret, n;
419 442 BlockDriver *drv = bs->drv;
420 443  
421 444 if (!bs->inserted)
422 445 return -1;
423 446  
424   - while (nb_sectors > 0) {
425   - if (sector_num == 0 && bs->boot_sector_enabled) {
  447 + if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
426 448 memcpy(buf, bs->boot_sector_data, 512);
427   - n = 1;
428   - } else if (bs->backing_hd) {
429   - if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
430   - ret = drv->bdrv_read(bs, sector_num, buf, n);
431   - if (ret < 0)
432   - return -1;
433   - } else {
434   - /* read from the base image */
435   - ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
436   - if (ret < 0)
437   - return -1;
438   - }
439   - } else {
440   - ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
441   - if (ret < 0)
442   - return -1;
443   - /* no need to loop */
444   - break;
445   - }
446   - nb_sectors -= n;
447   - sector_num += n;
448   - buf += n * 512;
  449 + sector_num++;
  450 + nb_sectors--;
  451 + buf += 512;
  452 + if (nb_sectors == 0)
  453 + return 0;
  454 + }
  455 + if (drv->bdrv_pread) {
  456 + int ret, len;
  457 + len = nb_sectors * 512;
  458 + ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
  459 + if (ret < 0)
  460 + return ret;
  461 + else if (ret != len)
  462 + return -EIO;
  463 + else
  464 + return 0;
  465 + } else {
  466 + return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
449 467 }
450   - return 0;
451 468 }
452 469  
453   -/* return -1 if error */
  470 +/* return < 0 if error */
454 471 int bdrv_write(BlockDriverState *bs, int64_t sector_num,
455 472 const uint8_t *buf, int nb_sectors)
456 473 {
  474 + BlockDriver *drv = bs->drv;
457 475 if (!bs->inserted)
458 476 return -1;
459 477 if (bs->read_only)
... ... @@ -461,12 +479,183 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
461 479 if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
462 480 memcpy(bs->boot_sector_data, buf, 512);
463 481 }
464   - return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  482 + if (drv->bdrv_pwrite) {
  483 + int ret, len;
  484 + len = nb_sectors * 512;
  485 + ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
  486 + if (ret < 0)
  487 + return ret;
  488 + else if (ret != len)
  489 + return -EIO;
  490 + else
  491 + return 0;
  492 + } else {
  493 + return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  494 + }
  495 +}
  496 +
  497 +#if 0
  498 +/* not necessary now */
  499 +static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
  500 + void *buf1, int count1)
  501 +{
  502 + uint8_t *buf = buf1;
  503 + uint8_t tmp_buf[SECTOR_SIZE];
  504 + int len, nb_sectors, count;
  505 + int64_t sector_num;
  506 +
  507 + count = count1;
  508 + /* first read to align to sector start */
  509 + len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  510 + if (len > count)
  511 + len = count;
  512 + sector_num = offset >> SECTOR_BITS;
  513 + if (len > 0) {
  514 + if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  515 + return -EIO;
  516 + memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
  517 + count -= len;
  518 + if (count == 0)
  519 + return count1;
  520 + sector_num++;
  521 + buf += len;
  522 + }
  523 +
  524 + /* read the sectors "in place" */
  525 + nb_sectors = count >> SECTOR_BITS;
  526 + if (nb_sectors > 0) {
  527 + if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
  528 + return -EIO;
  529 + sector_num += nb_sectors;
  530 + len = nb_sectors << SECTOR_BITS;
  531 + buf += len;
  532 + count -= len;
  533 + }
  534 +
  535 + /* add data from the last sector */
  536 + if (count > 0) {
  537 + if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  538 + return -EIO;
  539 + memcpy(buf, tmp_buf, count);
  540 + }
  541 + return count1;
  542 +}
  543 +
  544 +static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
  545 + const void *buf1, int count1)
  546 +{
  547 + const uint8_t *buf = buf1;
  548 + uint8_t tmp_buf[SECTOR_SIZE];
  549 + int len, nb_sectors, count;
  550 + int64_t sector_num;
  551 +
  552 + count = count1;
  553 + /* first write to align to sector start */
  554 + len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  555 + if (len > count)
  556 + len = count;
  557 + sector_num = offset >> SECTOR_BITS;
  558 + if (len > 0) {
  559 + if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  560 + return -EIO;
  561 + memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
  562 + if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  563 + return -EIO;
  564 + count -= len;
  565 + if (count == 0)
  566 + return count1;
  567 + sector_num++;
  568 + buf += len;
  569 + }
  570 +
  571 + /* write the sectors "in place" */
  572 + nb_sectors = count >> SECTOR_BITS;
  573 + if (nb_sectors > 0) {
  574 + if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
  575 + return -EIO;
  576 + sector_num += nb_sectors;
  577 + len = nb_sectors << SECTOR_BITS;
  578 + buf += len;
  579 + count -= len;
  580 + }
  581 +
  582 + /* add data from the last sector */
  583 + if (count > 0) {
  584 + if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  585 + return -EIO;
  586 + memcpy(tmp_buf, buf, count);
  587 + if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  588 + return -EIO;
  589 + }
  590 + return count1;
  591 +}
  592 +#endif
  593 +
  594 +/**
  595 + * Read with byte offsets (needed only for file protocols)
  596 + */
  597 +int bdrv_pread(BlockDriverState *bs, int64_t offset,
  598 + void *buf1, int count1)
  599 +{
  600 + BlockDriver *drv = bs->drv;
  601 +
  602 + if (!drv)
  603 + return -ENOENT;
  604 + if (!drv->bdrv_pread)
  605 + return -ENOTSUP;
  606 + return drv->bdrv_pread(bs, offset, buf1, count1);
  607 +}
  608 +
  609 +/**
  610 + * Write with byte offsets (needed only for file protocols)
  611 + */
  612 +int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
  613 + const void *buf1, int count1)
  614 +{
  615 + BlockDriver *drv = bs->drv;
  616 +
  617 + if (!drv)
  618 + return -ENOENT;
  619 + if (!drv->bdrv_pwrite)
  620 + return -ENOTSUP;
  621 + return drv->bdrv_pwrite(bs, offset, buf1, count1);
  622 +}
  623 +
  624 +/**
  625 + * Truncate file to 'offset' bytes (needed only for file protocols)
  626 + */
  627 +int bdrv_truncate(BlockDriverState *bs, int64_t offset)
  628 +{
  629 + BlockDriver *drv = bs->drv;
  630 + if (!drv)
  631 + return -ENOENT;
  632 + if (!drv->bdrv_truncate)
  633 + return -ENOTSUP;
  634 + return drv->bdrv_truncate(bs, offset);
  635 +}
  636 +
  637 +/**
  638 + * Length of a file in bytes. Return < 0 if error or unknown.
  639 + */
  640 +int64_t bdrv_getlength(BlockDriverState *bs)
  641 +{
  642 + BlockDriver *drv = bs->drv;
  643 + if (!drv)
  644 + return -ENOENT;
  645 + if (!drv->bdrv_getlength) {
  646 + /* legacy mode */
  647 + return bs->total_sectors * SECTOR_SIZE;
  648 + }
  649 + return drv->bdrv_getlength(bs);
465 650 }
466 651  
467 652 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
468 653 {
469   - *nb_sectors_ptr = bs->total_sectors;
  654 + int64_t size;
  655 + size = bdrv_getlength(bs);
  656 + if (size < 0)
  657 + size = 0;
  658 + *nb_sectors_ptr = size >> SECTOR_BITS;
470 659 }
471 660  
472 661 /* force a given boot sector. */
... ... @@ -660,187 +849,251 @@ void bdrv_info(void)
660 849 }
661 850 }
662 851  
  852 +void bdrv_get_backing_filename(BlockDriverState *bs,
  853 + char *filename, int filename_size)
  854 +{
  855 + if (!bs->backing_hd) {
  856 + pstrcpy(filename, filename_size, "");
  857 + } else {
  858 + pstrcpy(filename, filename_size, bs->backing_file);
  859 + }
  860 +}
  861 +
  862 +
663 863 /**************************************************************/
664   -/* RAW block driver */
  864 +/* async I/Os */
665 865  
666   -typedef struct BDRVRawState {
667   - int fd;
668   -} BDRVRawState;
  866 +BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs)
  867 +{
  868 + BlockDriver *drv = bs->drv;
  869 + BlockDriverAIOCB *acb;
  870 + acb = qemu_mallocz(sizeof(BlockDriverAIOCB));
  871 + if (!acb)
  872 + return NULL;
  873 +
  874 + acb->bs = bs;
  875 + if (drv->bdrv_aio_new(acb) < 0) {
  876 + qemu_free(acb);
  877 + return NULL;
  878 + }
  879 + return acb;
  880 +}
669 881  
670   -static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
  882 +int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
  883 + uint8_t *buf, int nb_sectors,
  884 + BlockDriverCompletionFunc *cb, void *opaque)
671 885 {
672   - return 1; /* maybe */
  886 + BlockDriverState *bs = acb->bs;
  887 + BlockDriver *drv = bs->drv;
  888 +
  889 + if (!bs->inserted)
  890 + return -1;
  891 +
  892 + /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
  893 + if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  894 + memcpy(buf, bs->boot_sector_data, 512);
  895 + sector_num++;
  896 + nb_sectors--;
  897 + buf += 512;
  898 + }
  899 +
  900 + acb->cb = cb;
  901 + acb->cb_opaque = opaque;
  902 + return drv->bdrv_aio_read(acb, sector_num, buf, nb_sectors);
673 903 }
674 904  
675   -static int raw_open(BlockDriverState *bs, const char *filename)
  905 +int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
  906 + const uint8_t *buf, int nb_sectors,
  907 + BlockDriverCompletionFunc *cb, void *opaque)
676 908 {
677   - BDRVRawState *s = bs->opaque;
678   - int fd;
679   - int64_t size;
680   -#ifdef _BSD
681   - struct stat sb;
682   -#endif
683   -#ifdef __sun__
684   - struct dk_minfo minfo;
685   - int rv;
686   -#endif
  909 + BlockDriverState *bs = acb->bs;
  910 + BlockDriver *drv = bs->drv;
687 911  
688   - fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
689   - if (fd < 0) {
690   - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
691   - if (fd < 0)
  912 + if (!bs->inserted)
692 913 return -1;
693   - bs->read_only = 1;
  914 + if (bs->read_only)
  915 + return -1;
  916 + if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  917 + memcpy(bs->boot_sector_data, buf, 512);
694 918 }
695   -#ifdef _BSD
696   - if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
697   -#ifdef DIOCGMEDIASIZE
698   - if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
699   -#endif
700   -#ifdef CONFIG_COCOA
701   - size = LONG_LONG_MAX;
702   -#else
703   - size = lseek(fd, 0LL, SEEK_END);
704   -#endif
705   - } else
706   -#endif
707   -#ifdef __sun__
708   - /*
709   - * use the DKIOCGMEDIAINFO ioctl to read the size.
710   - */
711   - rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
712   - if ( rv != -1 ) {
713   - size = minfo.dki_lbsize * minfo.dki_capacity;
714   - } else /* there are reports that lseek on some devices
715   - fails, but irc discussion said that contingency
716   - on contingency was overkill */
717   -#endif
  919 +
  920 + acb->cb = cb;
  921 + acb->cb_opaque = opaque;
  922 + return drv->bdrv_aio_write(acb, sector_num, buf, nb_sectors);
  923 +}
  924 +
  925 +void bdrv_aio_cancel(BlockDriverAIOCB *acb)
718 926 {
719   - size = lseek(fd, 0, SEEK_END);
  927 + BlockDriverState *bs = acb->bs;
  928 + BlockDriver *drv = bs->drv;
  929 +
  930 + drv->bdrv_aio_cancel(acb);
720 931 }
721   -#ifdef _WIN32
722   - /* On Windows hosts it can happen that we're unable to get file size
723   - for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
724   - if (size == -1)
725   - size = LONG_LONG_MAX;
726   -#endif
727   - bs->total_sectors = size / 512;
728   - s->fd = fd;
  932 +
  933 +void bdrv_aio_delete(BlockDriverAIOCB *acb)
  934 +{
  935 + BlockDriverState *bs = acb->bs;
  936 + BlockDriver *drv = bs->drv;
  937 +
  938 + drv->bdrv_aio_delete(acb);
  939 + qemu_free(acb);
  940 +}
  941 +
  942 +/**************************************************************/
  943 +/* async block device emulation */
  944 +
  945 +#ifdef QEMU_TOOL
  946 +static int bdrv_aio_new_em(BlockDriverAIOCB *acb)
  947 +{
729 948 return 0;
730 949 }
731 950  
732   -static int raw_read(BlockDriverState *bs, int64_t sector_num,
  951 +static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
733 952 uint8_t *buf, int nb_sectors)
734 953 {
735   - BDRVRawState *s = bs->opaque;
736 954 int ret;
737   -
738   - lseek(s->fd, sector_num * 512, SEEK_SET);
739   - ret = read(s->fd, buf, nb_sectors * 512);
740   - if (ret != nb_sectors * 512)
741   - return -1;
  955 + ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors);
  956 + acb->cb(acb->cb_opaque, ret);
742 957 return 0;
743 958 }
744 959  
745   -static int raw_write(BlockDriverState *bs, int64_t sector_num,
  960 +static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
746 961 const uint8_t *buf, int nb_sectors)
747 962 {
748   - BDRVRawState *s = bs->opaque;
749 963 int ret;
750   -
751   - lseek(s->fd, sector_num * 512, SEEK_SET);
752   - ret = write(s->fd, buf, nb_sectors * 512);
753   - if (ret != nb_sectors * 512)
754   - return -1;
  964 + ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors);
  965 + acb->cb(acb->cb_opaque, ret);
755 966 return 0;
756 967 }
757 968  
758   -static void raw_close(BlockDriverState *bs)
  969 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
759 970 {
760   - BDRVRawState *s = bs->opaque;
761   - close(s->fd);
762 971 }
763 972  
764   -#ifdef _WIN32
765   -#include <windows.h>
766   -#include <winioctl.h>
767   -
768   -int qemu_ftruncate64(int fd, int64_t length)
  973 +static void bdrv_aio_delete_em(BlockDriverAIOCB *acb)
769 974 {
770   - LARGE_INTEGER li;
771   - LONG high;
772   - HANDLE h;
773   - BOOL res;
774   -
775   - if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
776   - return -1;
  975 +}
  976 +#else
  977 +typedef struct BlockDriverAIOCBSync {
  978 + QEMUBH *bh;
  979 + int ret;
  980 +} BlockDriverAIOCBSync;
777 981  
778   - h = (HANDLE)_get_osfhandle(fd);
  982 +static void bdrv_aio_bh_cb(void *opaque)
  983 +{
  984 + BlockDriverAIOCB *acb = opaque;
  985 + BlockDriverAIOCBSync *acb1 = acb->opaque;
  986 + acb->cb(acb->cb_opaque, acb1->ret);
  987 +}
779 988  
780   - /* get current position, ftruncate do not change position */
781   - li.HighPart = 0;
782   - li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
783   - if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
784   - return -1;
  989 +static int bdrv_aio_new_em(BlockDriverAIOCB *acb)
  990 +{
  991 + BlockDriverAIOCBSync *acb1;
785 992  
786   - high = length >> 32;
787   - if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
788   - return -1;
789   - res = SetEndOfFile(h);
  993 + acb1 = qemu_mallocz(sizeof(BlockDriverAIOCBSync));
  994 + if (!acb1)
  995 + return -1;
  996 + acb->opaque = acb1;
  997 + acb1->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
  998 + return 0;
  999 +}
790 1000  
791   - /* back to old position */
792   - SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
793   - return res ? 0 : -1;
  1001 +static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
  1002 + uint8_t *buf, int nb_sectors)
  1003 +{
  1004 + BlockDriverAIOCBSync *acb1 = acb->opaque;
  1005 + int ret;
  1006 +
  1007 + ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors);
  1008 + acb1->ret = ret;
  1009 + qemu_bh_schedule(acb1->bh);
  1010 + return 0;
794 1011 }
795 1012  
796   -static int set_sparse(int fd)
  1013 +static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
  1014 + const uint8_t *buf, int nb_sectors)
797 1015 {
798   - DWORD returned;
799   - return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
800   - NULL, 0, NULL, 0, &returned, NULL);
  1016 + BlockDriverAIOCBSync *acb1 = acb->opaque;
  1017 + int ret;
  1018 +
  1019 + ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors);
  1020 + acb1->ret = ret;
  1021 + qemu_bh_schedule(acb1->bh);
  1022 + return 0;
801 1023 }
802   -#else
803   -static inline int set_sparse(int fd)
  1024 +
  1025 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
804 1026 {
805   - return 1;
  1027 + BlockDriverAIOCBSync *acb1 = acb->opaque;
  1028 + qemu_bh_cancel(acb1->bh);
806 1029 }
807   -#endif
808 1030  
809   -static int raw_create(const char *filename, int64_t total_size,
810   - const char *backing_file, int flags)
  1031 +static void bdrv_aio_delete_em(BlockDriverAIOCB *acb)
811 1032 {
812   - int fd;
  1033 + BlockDriverAIOCBSync *acb1 = acb->opaque;
  1034 + qemu_bh_delete(acb1->bh);
  1035 +}
  1036 +#endif /* !QEMU_TOOL */
813 1037  
814   - if (flags || backing_file)
815   - return -ENOTSUP;
  1038 +/**************************************************************/
  1039 +/* sync block device emulation */
816 1040  
817   - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
818   - 0644);
819   - if (fd < 0)
820   - return -EIO;
821   - set_sparse(fd);
822   - ftruncate(fd, total_size * 512);
823   - close(fd);
824   - return 0;
  1041 +static void bdrv_rw_em_cb(void *opaque, int ret)
  1042 +{
  1043 + *(int *)opaque = ret;
825 1044 }
826 1045  
827   -static void raw_flush(BlockDriverState *bs)
  1046 +#define NOT_DONE 0x7fffffff
  1047 +
  1048 +static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
  1049 + uint8_t *buf, int nb_sectors)
828 1050 {
829   - BDRVRawState *s = bs->opaque;
830   - fsync(s->fd);
  1051 + int async_ret, ret;
  1052 +
  1053 + if (!bs->sync_aiocb) {
  1054 + bs->sync_aiocb = bdrv_aio_new(bs);
  1055 + if (!bs->sync_aiocb)
  1056 + return -1;
  1057 + }
  1058 + async_ret = NOT_DONE;
  1059 + qemu_aio_wait_start();
  1060 + ret = bdrv_aio_read(bs->sync_aiocb, sector_num, buf, nb_sectors,
  1061 + bdrv_rw_em_cb, &async_ret);
  1062 + if (ret < 0) {
  1063 + qemu_aio_wait_end();
  1064 + return ret;
  1065 + }
  1066 + while (async_ret == NOT_DONE) {
  1067 + qemu_aio_wait();
  1068 + }
  1069 + qemu_aio_wait_end();
  1070 + return async_ret;
831 1071 }
832 1072  
833   -BlockDriver bdrv_raw = {
834   - "raw",
835   - sizeof(BDRVRawState),
836   - raw_probe,
837   - raw_open,
838   - raw_read,
839   - raw_write,
840   - raw_close,
841   - raw_create,
842   - raw_flush,
843   -};
  1073 +static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
  1074 + const uint8_t *buf, int nb_sectors)
  1075 +{
  1076 + int async_ret, ret;
  1077 +
  1078 + if (!bs->sync_aiocb) {
  1079 + bs->sync_aiocb = bdrv_aio_new(bs);
  1080 + if (!bs->sync_aiocb)
  1081 + return -1;
  1082 + }
  1083 + async_ret = NOT_DONE;
  1084 + qemu_aio_wait_start();
  1085 + ret = bdrv_aio_write(bs->sync_aiocb, sector_num, buf, nb_sectors,
  1086 + bdrv_rw_em_cb, &async_ret);
  1087 + if (ret < 0) {
  1088 + qemu_aio_wait_end();
  1089 + return ret;
  1090 + }
  1091 + while (async_ret == NOT_DONE) {
  1092 + qemu_aio_wait();
  1093 + }
  1094 + qemu_aio_wait_end();
  1095 + return async_ret;
  1096 +}
844 1097  
845 1098 void bdrv_init(void)
846 1099 {
... ...
block_int.h
... ... @@ -28,7 +28,7 @@ struct BlockDriver {
28 28 const char *format_name;
29 29 int instance_size;
30 30 int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
31   - int (*bdrv_open)(BlockDriverState *bs, const char *filename);
  31 + int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
32 32 int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
33 33 uint8_t *buf, int nb_sectors);
34 34 int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
... ... @@ -41,11 +41,28 @@ struct BlockDriver {
41 41 int nb_sectors, int *pnum);
42 42 int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
43 43 int (*bdrv_make_empty)(BlockDriverState *bs);
  44 + /* aio */
  45 + int (*bdrv_aio_new)(BlockDriverAIOCB *acb);
  46 + int (*bdrv_aio_read)(BlockDriverAIOCB *acb, int64_t sector_num,
  47 + uint8_t *buf, int nb_sectors);
  48 + int (*bdrv_aio_write)(BlockDriverAIOCB *acb, int64_t sector_num,
  49 + const uint8_t *buf, int nb_sectors);
  50 + void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
  51 + void (*bdrv_aio_delete)(BlockDriverAIOCB *acb);
  52 +
  53 + const char *protocol_name;
  54 + int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
  55 + uint8_t *buf, int count);
  56 + int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset,
  57 + const uint8_t *buf, int count);
  58 + int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
  59 + int64_t (*bdrv_getlength)(BlockDriverState *bs);
  60 +
44 61 struct BlockDriver *next;
45 62 };
46 63  
47 64 struct BlockDriverState {
48   - int64_t total_sectors;
  65 + int64_t total_sectors; /* XXX: will be suppressed */
49 66 int read_only; /* if true, the media is read only */
50 67 int inserted; /* if true, the media is present */
51 68 int removable; /* if true, the media can be removed */
... ... @@ -67,6 +84,9 @@ struct BlockDriverState {
67 84 int is_temporary;
68 85  
69 86 BlockDriverState *backing_hd;
  87 + /* sync read/write emulation */
  88 +
  89 + BlockDriverAIOCB *sync_aiocb;
70 90  
71 91 /* NOTE: the following infos are only hints for real hardware
72 92 drivers. They are not used by the block driver */
... ... @@ -76,6 +96,14 @@ struct BlockDriverState {
76 96 BlockDriverState *next;
77 97 };
78 98  
  99 +struct BlockDriverAIOCB {
  100 + BlockDriverState *bs;
  101 + BlockDriverCompletionFunc *cb;
  102 + void *cb_opaque;
  103 +
  104 + void *opaque; /* driver opaque */
  105 +};
  106 +
79 107 void get_tmp_filename(char *filename, int size);
80 108  
81 109 #endif /* BLOCK_INT_H */
... ...
... ... @@ -4772,6 +4772,77 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
4772 4772 }
4773 4773  
4774 4774 /***********************************************************/
  4775 +/* bottom halves (can be seen as timers which expire ASAP) */
  4776 +
  4777 +struct QEMUBH {
  4778 + QEMUBHFunc *cb;
  4779 + void *opaque;
  4780 + int scheduled;
  4781 + QEMUBH *next;
  4782 +};
  4783 +
  4784 +static QEMUBH *first_bh = NULL;
  4785 +
  4786 +QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
  4787 +{
  4788 + QEMUBH *bh;
  4789 + bh = qemu_mallocz(sizeof(QEMUBH));
  4790 + if (!bh)
  4791 + return NULL;
  4792 + bh->cb = cb;
  4793 + bh->opaque = opaque;
  4794 + return bh;
  4795 +}
  4796 +
  4797 +void qemu_bh_poll(void)
  4798 +{
  4799 + QEMUBH *bh, **pbh;
  4800 +
  4801 + for(;;) {
  4802 + pbh = &first_bh;
  4803 + bh = *pbh;
  4804 + if (!bh)
  4805 + break;
  4806 + *pbh = bh->next;
  4807 + bh->scheduled = 0;
  4808 + bh->cb(bh->opaque);
  4809 + }
  4810 +}
  4811 +
  4812 +void qemu_bh_schedule(QEMUBH *bh)
  4813 +{
  4814 + CPUState *env = cpu_single_env;
  4815 + if (bh->scheduled)
  4816 + return;
  4817 + bh->scheduled = 1;
  4818 + bh->next = first_bh;
  4819 + first_bh = bh;
  4820 +
  4821 + /* stop the currently executing CPU to execute the BH ASAP */
  4822 + if (env) {
  4823 + cpu_interrupt(env, CPU_INTERRUPT_EXIT);
  4824 + }
  4825 +}
  4826 +
  4827 +void qemu_bh_cancel(QEMUBH *bh)
  4828 +{
  4829 + QEMUBH **pbh;
  4830 + if (bh->scheduled) {
  4831 + pbh = &first_bh;
  4832 + while (*pbh != bh)
  4833 + pbh = &(*pbh)->next;
  4834 + *pbh = bh->next;
  4835 + bh->scheduled = 0;
  4836 + }
  4837 +}
  4838 +
  4839 +void qemu_bh_delete(QEMUBH *bh)
  4840 +{
  4841 + qemu_bh_cancel(bh);
  4842 + qemu_free(bh);
  4843 +}
  4844 +
  4845 +/***********************************************************/
4775 4846 /* machine registration */
4776 4847  
4777 4848 QEMUMachine *first_machine = NULL;
... ... @@ -5030,6 +5101,8 @@ void main_loop_wait(int timeout)
5030 5101 #ifdef _WIN32
5031 5102 tap_win32_poll();
5032 5103 #endif
  5104 + qemu_aio_poll();
  5105 + qemu_bh_poll();
5033 5106  
5034 5107 if (vm_running) {
5035 5108 qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
... ... @@ -6049,6 +6122,7 @@ int main(int argc, char **argv)
6049 6122  
6050 6123 init_timers();
6051 6124 init_timer_alarm();
  6125 + qemu_aio_init();
6052 6126  
6053 6127 #ifdef _WIN32
6054 6128 socket_init();
... ... @@ -6093,7 +6167,7 @@ int main(int argc, char **argv)
6093 6167 snprintf(buf, sizeof(buf), "hd%c", i + 'a');
6094 6168 bs_table[i] = bdrv_new(buf);
6095 6169 }
6096   - if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
  6170 + if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
6097 6171 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
6098 6172 hd_filename[i]);
6099 6173 exit(1);
... ... @@ -6118,7 +6192,8 @@ int main(int argc, char **argv)
6118 6192 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
6119 6193 }
6120 6194 if (fd_filename[i] != '\0') {
6121   - if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
  6195 + if (bdrv_open(fd_table[i], fd_filename[i],
  6196 + snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
6122 6197 fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
6123 6198 fd_filename[i]);
6124 6199 exit(1);
... ...
... ... @@ -481,6 +481,16 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
481 481 void cpu_save(QEMUFile *f, void *opaque);
482 482 int cpu_load(QEMUFile *f, void *opaque, int version_id);
483 483  
  484 +/* bottom halves */
  485 +typedef struct QEMUBH QEMUBH;
  486 +typedef void QEMUBHFunc(void *opaque);
  487 +
  488 +QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
  489 +void qemu_bh_schedule(QEMUBH *bh);
  490 +void qemu_bh_cancel(QEMUBH *bh);
  491 +void qemu_bh_delete(QEMUBH *bh);
  492 +void qemu_bh_poll(void);
  493 +
484 494 /* block.c */
485 495 typedef struct BlockDriverState BlockDriverState;
486 496 typedef struct BlockDriver BlockDriver;
... ... @@ -495,6 +505,16 @@ extern BlockDriver bdrv_bochs;
495 505 extern BlockDriver bdrv_vpc;
496 506 extern BlockDriver bdrv_vvfat;
497 507  
  508 +#define BDRV_O_RDONLY 0x0000
  509 +#define BDRV_O_RDWR 0x0002
  510 +#define BDRV_O_ACCESS 0x0003
  511 +#define BDRV_O_CREAT 0x0004 /* create an empty file */
  512 +#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
  513 +#define BDRV_O_FILE 0x0010 /* open as a raw file (do not try to
  514 + use a disk image format on top of
  515 + it (default for
  516 + bdrv_file_open()) */
  517 +
498 518 void bdrv_init(void);
499 519 BlockDriver *bdrv_find_format(const char *format_name);
500 520 int bdrv_create(BlockDriver *drv,
... ... @@ -502,17 +522,44 @@ int bdrv_create(BlockDriver *drv,
502 522 const char *backing_file, int flags);
503 523 BlockDriverState *bdrv_new(const char *device_name);
504 524 void bdrv_delete(BlockDriverState *bs);
505   -int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot);
506   -int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
  525 +int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
  526 +int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
  527 +int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
507 528 BlockDriver *drv);
508 529 void bdrv_close(BlockDriverState *bs);
509 530 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
510 531 uint8_t *buf, int nb_sectors);
511 532 int bdrv_write(BlockDriverState *bs, int64_t sector_num,
512 533 const uint8_t *buf, int nb_sectors);
  534 +int bdrv_pread(BlockDriverState *bs, int64_t offset,
  535 + void *buf, int count);
  536 +int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
  537 + const void *buf, int count);
  538 +int bdrv_truncate(BlockDriverState *bs, int64_t offset);
  539 +int64_t bdrv_getlength(BlockDriverState *bs);
513 540 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
514 541 int bdrv_commit(BlockDriverState *bs);
515 542 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
  543 +/* async block I/O */
  544 +typedef struct BlockDriverAIOCB BlockDriverAIOCB;
  545 +typedef void BlockDriverCompletionFunc(void *opaque, int ret);
  546 +
  547 +BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs);
  548 +int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
  549 + uint8_t *buf, int nb_sectors,
  550 + BlockDriverCompletionFunc *cb, void *opaque);
  551 +int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
  552 + const uint8_t *buf, int nb_sectors,
  553 + BlockDriverCompletionFunc *cb, void *opaque);
  554 +void bdrv_aio_cancel(BlockDriverAIOCB *acb);
  555 +void bdrv_aio_delete(BlockDriverAIOCB *acb);
  556 +
  557 +void qemu_aio_init(void);
  558 +void qemu_aio_poll(void);
  559 +void qemu_aio_wait_start(void);
  560 +void qemu_aio_wait(void);
  561 +void qemu_aio_wait_end(void);
  562 +
516 563 /* Ensure contents are flushed to disk. */
517 564 void bdrv_flush(BlockDriverState *bs);
518 565  
... ... @@ -551,6 +598,13 @@ const char *bdrv_get_device_name(BlockDriverState *bs);
551 598 int qcow_get_cluster_size(BlockDriverState *bs);
552 599 int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
553 600 const uint8_t *buf);
  601 +void bdrv_get_backing_filename(BlockDriverState *bs,
  602 + char *filename, int filename_size);
  603 +
  604 +int path_is_absolute(const char *path);
  605 +void path_combine(char *dest, int dest_size,
  606 + const char *base_path,
  607 + const char *filename);
554 608  
555 609 #ifndef QEMU_TOOL
556 610  
... ...