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 version 0.8.2: 6 version 0.8.2:
2 7
3 - ACPI support 8 - ACPI support
Makefile
@@ -25,14 +25,22 @@ else @@ -25,14 +25,22 @@ else
25 DOCS= 25 DOCS=
26 endif 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 all: $(TOOLS) $(DOCS) recurse-all 36 all: $(TOOLS) $(DOCS) recurse-all
29 37
30 subdir-%: dyngen$(EXESUF) 38 subdir-%: dyngen$(EXESUF)
31 $(MAKE) -C $(subst subdir-,,$@) all 39 $(MAKE) -C $(subst subdir-,,$@) all
32 40
33 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS)) 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 $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS) 44 $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
37 45
38 dyngen$(EXESUF): dyngen.c 46 dyngen$(EXESUF): dyngen.c
Makefile.target
@@ -289,7 +289,8 @@ ifeq ($(ARCH),alpha) @@ -289,7 +289,8 @@ ifeq ($(ARCH),alpha)
289 endif 289 endif
290 290
291 # must use static linking to avoid leaving stuff in virtual address space 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 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 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 ifdef CONFIG_WIN32 295 ifdef CONFIG_WIN32
295 VL_OBJS+=tap-win32.o 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,15 +85,15 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
85 return 0; 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 BDRVBochsState *s = bs->opaque; 90 BDRVBochsState *s = bs->opaque;
91 int fd, i; 91 int fd, i;
92 struct bochs_header bochs; 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 if (fd < 0) { 95 if (fd < 0) {
96 - fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); 96 + fd = open(filename, O_RDONLY | O_BINARY);
97 if (fd < 0) 97 if (fd < 0)
98 return -1; 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,14 +50,14 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
50 return 0; 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 BDRVCloopState *s = bs->opaque; 55 BDRVCloopState *s = bs->opaque;
56 uint32_t offsets_size,max_compressed_block_size=1,i; 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 if (s->fd < 0) 59 if (s->fd < 0)
60 - return -1; 60 + return -errno;
61 bs->read_only = 1; 61 bs->read_only = 1;
62 62
63 /* read header */ 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,7 +62,7 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
62 return 0; 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 BDRVCowState *s = bs->opaque; 67 BDRVCowState *s = bs->opaque;
68 int fd; 68 int fd;
@@ -93,22 +93,6 @@ static int cow_open(BlockDriverState *bs, const char *filename) @@ -93,22 +93,6 @@ static int cow_open(BlockDriverState *bs, const char *filename)
93 pstrcpy(bs->backing_file, sizeof(bs->backing_file), 93 pstrcpy(bs->backing_file, sizeof(bs->backing_file),
94 cow_header.backing_file); 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 /* mmap the bitmap */ 96 /* mmap the bitmap */
113 s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header); 97 s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
114 s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), 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,8 +163,15 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
179 if (ret != n * 512) 163 if (ret != n * 512)
180 return -1; 164 return -1;
181 } else { 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 memset(buf, 0, n * 512); 172 memset(buf, 0, n * 512);
183 } 173 }
  174 + }
184 nb_sectors -= n; 175 nb_sectors -= n;
185 sector_num += n; 176 sector_num += n;
186 buf += n * 512; 177 buf += n * 512;
@@ -220,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors, @@ -220,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors,
220 if (flags) 211 if (flags)
221 return -ENOTSUP; 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 0644); 215 0644);
225 if (cow_fd < 0) 216 if (cow_fd < 0)
226 return -1; 217 return -1;
@@ -228,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors, @@ -228,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors,
228 cow_header.magic = cpu_to_be32(COW_MAGIC); 219 cow_header.magic = cpu_to_be32(COW_MAGIC);
229 cow_header.version = cpu_to_be32(COW_VERSION); 220 cow_header.version = cpu_to_be32(COW_VERSION);
230 if (image_filename) { 221 if (image_filename) {
  222 + /* Note: if no file, we put a dummy mtime */
  223 + cow_header.mtime = cpu_to_be32(0);
  224 +
231 fd = open(image_filename, O_RDONLY | O_BINARY); 225 fd = open(image_filename, O_RDONLY | O_BINARY);
232 if (fd < 0) { 226 if (fd < 0) {
233 close(cow_fd); 227 close(cow_fd);
234 - return -1; 228 + goto mtime_fail;
235 } 229 }
236 if (fstat(fd, &st) != 0) { 230 if (fstat(fd, &st) != 0) {
237 close(fd); 231 close(fd);
238 - return -1; 232 + goto mtime_fail;
239 } 233 }
240 close(fd); 234 close(fd);
241 cow_header.mtime = cpu_to_be32(st.st_mtime); 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 cow_header.sectorsize = cpu_to_be32(512); 240 cow_header.sectorsize = cpu_to_be32(512);
245 cow_header.size = cpu_to_be64(image_sectors * 512); 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,16 +73,16 @@ static off_t read_uint32(int fd)
73 return be32_to_cpu(buffer); 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 BDRVDMGState *s = bs->opaque; 78 BDRVDMGState *s = bs->opaque;
79 off_t info_begin,info_end,last_in_offset,last_out_offset; 79 off_t info_begin,info_end,last_in_offset,last_out_offset;
80 uint32_t count; 80 uint32_t count;
81 uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i; 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 if (s->fd < 0) 84 if (s->fd < 0)
85 - return -1; 85 + return -errno;
86 bs->read_only = 1; 86 bs->read_only = 1;
87 s->n_chunks = 0; 87 s->n_chunks = 0;
88 s->offsets = s->lengths = s->sectors = s->sectorcounts = 0; 88 s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
@@ -93,7 +93,7 @@ dmg_close: @@ -93,7 +93,7 @@ dmg_close:
93 close(s->fd); 93 close(s->fd);
94 /* open raw instead */ 94 /* open raw instead */
95 bs->drv=&bdrv_raw; 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 info_begin=read_off(s->fd); 98 info_begin=read_off(s->fd);
99 if(info_begin==0) 99 if(info_begin==0)
block-qcow.c
1 /* 1 /*
2 * Block driver for the QCOW format 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 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 7 * of this software and associated documentation files (the "Software"), to deal
@@ -53,7 +53,7 @@ typedef struct QCowHeader { @@ -53,7 +53,7 @@ typedef struct QCowHeader {
53 #define L2_CACHE_SIZE 16 53 #define L2_CACHE_SIZE 16
54 54
55 typedef struct BDRVQcowState { 55 typedef struct BDRVQcowState {
56 - int fd; 56 + BlockDriverState *hd;
57 int cluster_bits; 57 int cluster_bits;
58 int cluster_size; 58 int cluster_size;
59 int cluster_sectors; 59 int cluster_sectors;
@@ -89,20 +89,16 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) @@ -89,20 +89,16 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
89 return 0; 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 BDRVQcowState *s = bs->opaque; 94 BDRVQcowState *s = bs->opaque;
95 - int fd, len, i, shift; 95 + int len, i, shift, ret;
96 QCowHeader header; 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 goto fail; 102 goto fail;
107 be32_to_cpus(&header.magic); 103 be32_to_cpus(&header.magic);
108 be32_to_cpus(&header.version); 104 be32_to_cpus(&header.version);
@@ -138,8 +134,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename) @@ -138,8 +134,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
138 s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t)); 134 s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
139 if (!s->l1_table) 135 if (!s->l1_table)
140 goto fail; 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 s->l1_size * sizeof(uint64_t)) 138 s->l1_size * sizeof(uint64_t))
144 goto fail; 139 goto fail;
145 for(i = 0;i < s->l1_size; i++) { 140 for(i = 0;i < s->l1_size; i++) {
@@ -162,8 +157,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename) @@ -162,8 +157,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
162 len = header.backing_file_size; 157 len = header.backing_file_size;
163 if (len > 1023) 158 if (len > 1023)
164 len = 1023; 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 goto fail; 161 goto fail;
168 bs->backing_file[len] = '\0'; 162 bs->backing_file[len] = '\0';
169 } 163 }
@@ -174,7 +168,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename) @@ -174,7 +168,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
174 qemu_free(s->l2_cache); 168 qemu_free(s->l2_cache);
175 qemu_free(s->cluster_cache); 169 qemu_free(s->cluster_cache);
176 qemu_free(s->cluster_data); 170 qemu_free(s->cluster_data);
177 - close(fd); 171 + bdrv_delete(s->hd);
178 return -1; 172 return -1;
179 } 173 }
180 174
@@ -276,14 +270,14 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, @@ -276,14 +270,14 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
276 if (!allocate) 270 if (!allocate)
277 return 0; 271 return 0;
278 /* allocate a new l2 entry */ 272 /* allocate a new l2 entry */
279 - l2_offset = lseek(s->fd, 0, SEEK_END); 273 + l2_offset = bdrv_getlength(s->hd);
280 /* round to cluster size */ 274 /* round to cluster size */
281 l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1); 275 l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
282 /* update the L1 entry */ 276 /* update the L1 entry */
283 s->l1_table[l1_index] = l2_offset; 277 s->l1_table[l1_index] = l2_offset;
284 tmp = cpu_to_be64(l2_offset); 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 return 0; 281 return 0;
288 new_l2_table = 1; 282 new_l2_table = 1;
289 } 283 }
@@ -309,14 +303,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, @@ -309,14 +303,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
309 } 303 }
310 } 304 }
311 l2_table = s->l2_cache + (min_index << s->l2_bits); 305 l2_table = s->l2_cache + (min_index << s->l2_bits);
312 - lseek(s->fd, l2_offset, SEEK_SET);  
313 if (new_l2_table) { 306 if (new_l2_table) {
314 memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); 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 s->l2_size * sizeof(uint64_t)) 309 s->l2_size * sizeof(uint64_t))
317 return 0; 310 return 0;
318 } else { 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 s->l2_size * sizeof(uint64_t)) 313 s->l2_size * sizeof(uint64_t))
321 return 0; 314 return 0;
322 } 315 }
@@ -337,21 +330,20 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, @@ -337,21 +330,20 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
337 overwritten */ 330 overwritten */
338 if (decompress_cluster(s, cluster_offset) < 0) 331 if (decompress_cluster(s, cluster_offset) < 0)
339 return 0; 332 return 0;
340 - cluster_offset = lseek(s->fd, 0, SEEK_END); 333 + cluster_offset = bdrv_getlength(s->hd);
341 cluster_offset = (cluster_offset + s->cluster_size - 1) & 334 cluster_offset = (cluster_offset + s->cluster_size - 1) &
342 ~(s->cluster_size - 1); 335 ~(s->cluster_size - 1);
343 /* write the cluster content */ 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 s->cluster_size) 338 s->cluster_size)
347 return -1; 339 return -1;
348 } else { 340 } else {
349 - cluster_offset = lseek(s->fd, 0, SEEK_END); 341 + cluster_offset = bdrv_getlength(s->hd);
350 if (allocate == 1) { 342 if (allocate == 1) {
351 /* round to cluster size */ 343 /* round to cluster size */
352 cluster_offset = (cluster_offset + s->cluster_size - 1) & 344 cluster_offset = (cluster_offset + s->cluster_size - 1) &
353 ~(s->cluster_size - 1); 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 /* if encrypted, we must initialize the cluster 347 /* if encrypted, we must initialize the cluster
356 content which won't be written */ 348 content which won't be written */
357 if (s->crypt_method && 349 if (s->crypt_method &&
@@ -365,8 +357,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, @@ -365,8 +357,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
365 s->cluster_data, 357 s->cluster_data,
366 s->cluster_data + 512, 1, 1, 358 s->cluster_data + 512, 1, 1,
367 &s->aes_encrypt_key); 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 return -1; 362 return -1;
371 } 363 }
372 } 364 }
@@ -379,8 +371,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, @@ -379,8 +371,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
379 /* update L2 table */ 371 /* update L2 table */
380 tmp = cpu_to_be64(cluster_offset); 372 tmp = cpu_to_be64(cluster_offset);
381 l2_table[l2_index] = tmp; 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 return 0; 376 return 0;
385 } 377 }
386 return cluster_offset; 378 return cluster_offset;
@@ -438,8 +430,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) @@ -438,8 +430,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
438 if (s->cluster_cache_offset != coffset) { 430 if (s->cluster_cache_offset != coffset) {
439 csize = cluster_offset >> (63 - s->cluster_bits); 431 csize = cluster_offset >> (63 - s->cluster_bits);
440 csize &= (s->cluster_size - 1); 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 if (ret != csize) 434 if (ret != csize)
444 return -1; 435 return -1;
445 if (decompress_buffer(s->cluster_cache, s->cluster_size, 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,6 +442,8 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
451 return 0; 442 return 0;
452 } 443 }
453 444
  445 +#if 0
  446 +
454 static int qcow_read(BlockDriverState *bs, int64_t sector_num, 447 static int qcow_read(BlockDriverState *bs, int64_t sector_num,
455 uint8_t *buf, int nb_sectors) 448 uint8_t *buf, int nb_sectors)
456 { 449 {
@@ -465,14 +458,20 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, @@ -465,14 +458,20 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
465 if (n > nb_sectors) 458 if (n > nb_sectors)
466 n = nb_sectors; 459 n = nb_sectors;
467 if (!cluster_offset) { 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 } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { 469 } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
470 if (decompress_cluster(s, cluster_offset) < 0) 470 if (decompress_cluster(s, cluster_offset) < 0)
471 return -1; 471 return -1;
472 memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n); 472 memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
473 } else { 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 if (ret != n * 512) 475 if (ret != n * 512)
477 return -1; 476 return -1;
478 if (s->crypt_method) { 477 if (s->crypt_method) {
@@ -486,6 +485,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, @@ -486,6 +485,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
486 } 485 }
487 return 0; 486 return 0;
488 } 487 }
  488 +#endif
489 489
490 static int qcow_write(BlockDriverState *bs, int64_t sector_num, 490 static int qcow_write(BlockDriverState *bs, int64_t sector_num,
491 const uint8_t *buf, int nb_sectors) 491 const uint8_t *buf, int nb_sectors)
@@ -504,13 +504,13 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, @@ -504,13 +504,13 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
504 index_in_cluster + n); 504 index_in_cluster + n);
505 if (!cluster_offset) 505 if (!cluster_offset)
506 return -1; 506 return -1;
507 - lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);  
508 if (s->crypt_method) { 507 if (s->crypt_method) {
509 encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1, 508 encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
510 &s->aes_encrypt_key); 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 } else { 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 if (ret != n * 512) 515 if (ret != n * 512)
516 return -1; 516 return -1;
@@ -522,6 +522,231 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, @@ -522,6 +522,231 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
522 return 0; 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 static void qcow_close(BlockDriverState *bs) 750 static void qcow_close(BlockDriverState *bs)
526 { 751 {
527 BDRVQcowState *s = bs->opaque; 752 BDRVQcowState *s = bs->opaque;
@@ -529,7 +754,7 @@ static void qcow_close(BlockDriverState *bs) @@ -529,7 +754,7 @@ static void qcow_close(BlockDriverState *bs)
529 qemu_free(s->l2_cache); 754 qemu_free(s->l2_cache);
530 qemu_free(s->cluster_cache); 755 qemu_free(s->cluster_cache);
531 qemu_free(s->cluster_data); 756 qemu_free(s->cluster_data);
532 - close(s->fd); 757 + bdrv_delete(s->hd);
533 } 758 }
534 759
535 static int qcow_create(const char *filename, int64_t total_size, 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,12 +762,9 @@ static int qcow_create(const char *filename, int64_t total_size,
537 { 762 {
538 int fd, header_size, backing_filename_len, l1_size, i, shift; 763 int fd, header_size, backing_filename_len, l1_size, i, shift;
539 QCowHeader header; 764 QCowHeader header;
540 - char backing_filename[1024];  
541 uint64_t tmp; 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 if (fd < 0) 768 if (fd < 0)
547 return -1; 769 return -1;
548 memset(&header, 0, sizeof(header)); 770 memset(&header, 0, sizeof(header));
@@ -552,28 +774,11 @@ static int qcow_create(const char *filename, int64_t total_size, @@ -552,28 +774,11 @@ static int qcow_create(const char *filename, int64_t total_size,
552 header_size = sizeof(header); 774 header_size = sizeof(header);
553 backing_filename_len = 0; 775 backing_filename_len = 0;
554 if (backing_file) { 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 header.cluster_bits = 9; /* 512 byte cluster to avoid copying 782 header.cluster_bits = 9; /* 512 byte cluster to avoid copying
578 unmodifyed sectors */ 783 unmodifyed sectors */
579 header.l2_bits = 12; /* 32 KB L2 tables */ 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,7 +800,7 @@ static int qcow_create(const char *filename, int64_t total_size,
595 /* write all the data */ 800 /* write all the data */
596 write(fd, &header, sizeof(header)); 801 write(fd, &header, sizeof(header));
597 if (backing_file) { 802 if (backing_file) {
598 - write(fd, backing_filename, backing_filename_len); 803 + write(fd, backing_file, backing_filename_len);
599 } 804 }
600 lseek(fd, header_size, SEEK_SET); 805 lseek(fd, header_size, SEEK_SET);
601 tmp = 0; 806 tmp = 0;
@@ -610,12 +815,14 @@ int qcow_make_empty(BlockDriverState *bs) @@ -610,12 +815,14 @@ int qcow_make_empty(BlockDriverState *bs)
610 { 815 {
611 BDRVQcowState *s = bs->opaque; 816 BDRVQcowState *s = bs->opaque;
612 uint32_t l1_length = s->l1_size * sizeof(uint64_t); 817 uint32_t l1_length = s->l1_size * sizeof(uint64_t);
  818 + int ret;
613 819
614 memset(s->l1_table, 0, l1_length); 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 return -1; 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 memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); 827 memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
621 memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t)); 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,8 +889,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
682 cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, 889 cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
683 out_len, 0, 0); 890 out_len, 0, 0);
684 cluster_offset &= s->cluster_offset_mask; 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 qemu_free(out_buf); 893 qemu_free(out_buf);
688 return -1; 894 return -1;
689 } 895 }
@@ -696,7 +902,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num, @@ -696,7 +902,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
696 static void qcow_flush(BlockDriverState *bs) 902 static void qcow_flush(BlockDriverState *bs)
697 { 903 {
698 BDRVQcowState *s = bs->opaque; 904 BDRVQcowState *s = bs->opaque;
699 - fsync(s->fd); 905 + bdrv_flush(s->hd);
700 } 906 }
701 907
702 BlockDriver bdrv_qcow = { 908 BlockDriver bdrv_qcow = {
@@ -704,14 +910,20 @@ BlockDriver bdrv_qcow = { @@ -704,14 +910,20 @@ BlockDriver bdrv_qcow = {
704 sizeof(BDRVQcowState), 910 sizeof(BDRVQcowState),
705 qcow_probe, 911 qcow_probe,
706 qcow_open, 912 qcow_open,
707 - qcow_read,  
708 - qcow_write, 913 + NULL,
  914 + NULL,
709 qcow_close, 915 qcow_close,
710 qcow_create, 916 qcow_create,
711 qcow_flush, 917 qcow_flush,
712 qcow_is_allocated, 918 qcow_is_allocated,
713 qcow_set_key, 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,7 +89,7 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
89 return 0; 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 BDRVVmdkState *s = bs->opaque; 94 BDRVVmdkState *s = bs->opaque;
95 int fd, i; 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,19 +86,16 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
86 return 0; 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 BDRVVPCState *s = bs->opaque; 91 BDRVVPCState *s = bs->opaque;
92 int fd, i; 92 int fd, i;
93 struct vpc_subheader header; 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 bs->read_only = 1; // no write support yet 99 bs->read_only = 1; // no write support yet
103 100
104 s->fd = fd; 101 s->fd = fd;
block-vvfat.c
@@ -351,13 +351,6 @@ typedef struct BDRVVVFATState { @@ -351,13 +351,6 @@ typedef struct BDRVVVFATState {
351 } BDRVVVFATState; 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 static void init_mbr(BDRVVVFATState* s) 354 static void init_mbr(BDRVVVFATState* s)
362 { 355 {
363 /* TODO: if the files mbr.img and bootsect.img exist, use them */ 356 /* TODO: if the files mbr.img and bootsect.img exist, use them */
@@ -954,18 +947,22 @@ static int init_directories(BDRVVVFATState* s, @@ -954,18 +947,22 @@ static int init_directories(BDRVVVFATState* s,
954 return 0; 947 return 0;
955 } 948 }
956 949
  950 +#ifdef DEBUG
957 static BDRVVVFATState *vvv = NULL; 951 static BDRVVVFATState *vvv = NULL;
  952 +#endif
958 953
959 static int enable_write_target(BDRVVVFATState *s); 954 static int enable_write_target(BDRVVVFATState *s);
960 static int is_consistent(BDRVVVFATState *s); 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 BDRVVVFATState *s = bs->opaque; 959 BDRVVVFATState *s = bs->opaque;
965 int floppy = 0; 960 int floppy = 0;
966 int i; 961 int i;
967 962
  963 +#ifdef DEBUG
968 vvv = s; 964 vvv = s;
  965 +#endif
969 966
970 DLOG(if (stderr == NULL) { 967 DLOG(if (stderr == NULL) {
971 stderr = fopen("vvfat.log", "a"); 968 stderr = fopen("vvfat.log", "a");
@@ -1040,7 +1037,6 @@ DLOG(if (stderr == NULL) { @@ -1040,7 +1037,6 @@ DLOG(if (stderr == NULL) {
1040 bs->heads = bs->cyls = bs->secs = 0; 1037 bs->heads = bs->cyls = bs->secs = 0;
1041 1038
1042 // assert(is_consistent(s)); 1039 // assert(is_consistent(s));
1043 -  
1044 return 0; 1040 return 0;
1045 } 1041 }
1046 1042
@@ -2732,8 +2728,7 @@ static int enable_write_target(BDRVVVFATState *s) @@ -2732,8 +2728,7 @@ static int enable_write_target(BDRVVVFATState *s)
2732 array_init(&(s->commits), sizeof(commit_t)); 2728 array_init(&(s->commits), sizeof(commit_t));
2733 2729
2734 s->qcow_filename = malloc(1024); 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 if (bdrv_create(&bdrv_qcow, 2732 if (bdrv_create(&bdrv_qcow,
2738 s->qcow_filename, s->sector_count, "fat:", 0) < 0) 2733 s->qcow_filename, s->sector_count, "fat:", 0) < 0)
2739 return -1; 2734 return -1;
@@ -2767,14 +2762,15 @@ static void vvfat_close(BlockDriverState *bs) @@ -2767,14 +2762,15 @@ static void vvfat_close(BlockDriverState *bs)
2767 BlockDriver bdrv_vvfat = { 2762 BlockDriver bdrv_vvfat = {
2768 "vvfat", 2763 "vvfat",
2769 sizeof(BDRVVVFATState), 2764 sizeof(BDRVVVFATState),
2770 - vvfat_probe, 2765 + NULL, /* no probe for protocols */
2771 vvfat_open, 2766 vvfat_open,
2772 vvfat_read, 2767 vvfat_read,
2773 vvfat_write, 2768 vvfat_write,
2774 vvfat_close, 2769 vvfat_close,
2775 NULL, /* ??? Not sure if we can do any meaningful flushing. */ 2770 NULL, /* ??? Not sure if we can do any meaningful flushing. */
2776 NULL, 2771 NULL,
2777 - vvfat_is_allocated 2772 + vvfat_is_allocated,
  2773 + .protocol_name = "fat",
2778 }; 2774 };
2779 2775
2780 #ifdef DEBUG 2776 #ifdef DEBUG
@@ -32,85 +32,92 @@ @@ -32,85 +32,92 @@
32 #include <sys/disk.h> 32 #include <sys/disk.h>
33 #endif 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 static BlockDriverState *bdrv_first; 50 static BlockDriverState *bdrv_first;
52 static BlockDriver *first_drv; 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 void bdrv_register(BlockDriver *bdrv) 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 bdrv->next = first_drv; 121 bdrv->next = first_drv;
115 first_drv = bdrv; 122 first_drv = bdrv;
116 } 123 }
@@ -156,14 +163,7 @@ int bdrv_create(BlockDriver *drv, @@ -156,14 +163,7 @@ int bdrv_create(BlockDriver *drv,
156 #ifdef _WIN32 163 #ifdef _WIN32
157 void get_tmp_filename(char *filename, int size) 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 #else 168 #else
169 void get_tmp_filename(char *filename, int size) 169 void get_tmp_filename(char *filename, int size)
@@ -176,101 +176,107 @@ void get_tmp_filename(char *filename, int size) @@ -176,101 +176,107 @@ void get_tmp_filename(char *filename, int size)
176 } 176 }
177 #endif 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 /* XXX: force raw format if block or character device ? It would 207 /* XXX: force raw format if block or character device ? It would
180 simplify the BSD case */ 208 simplify the BSD case */
181 static BlockDriver *find_image_format(const char *filename) 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 BlockDriver *drv1, *drv; 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 score_max = 0; 233 score_max = 0;
221 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { 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 return drv; 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 BlockDriver *drv) 269 BlockDriver *drv)
265 { 270 {
266 - int ret; 271 + int ret, open_flags;
267 char tmp_filename[1024]; 272 char tmp_filename[1024];
  273 + char backing_filename[1024];
268 274
269 bs->read_only = 0; 275 bs->read_only = 0;
270 bs->is_temporary = 0; 276 bs->is_temporary = 0;
271 bs->encrypted = 0; 277 bs->encrypted = 0;
272 278
273 - if (snapshot) { 279 + if (flags & BDRV_O_SNAPSHOT) {
274 BlockDriverState *bs1; 280 BlockDriverState *bs1;
275 int64_t total_size; 281 int64_t total_size;
276 282
@@ -280,17 +286,16 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, @@ -280,17 +286,16 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
280 /* if there is a backing file, use it */ 286 /* if there is a backing file, use it */
281 bs1 = bdrv_new(""); 287 bs1 = bdrv_new("");
282 if (!bs1) { 288 if (!bs1) {
283 - return -1; 289 + return -ENOMEM;
284 } 290 }
285 if (bdrv_open(bs1, filename, 0) < 0) { 291 if (bdrv_open(bs1, filename, 0) < 0) {
286 bdrv_delete(bs1); 292 bdrv_delete(bs1);
287 return -1; 293 return -1;
288 } 294 }
289 - total_size = bs1->total_sectors; 295 + total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
290 bdrv_delete(bs1); 296 bdrv_delete(bs1);
291 297
292 get_tmp_filename(tmp_filename, sizeof(tmp_filename)); 298 get_tmp_filename(tmp_filename, sizeof(tmp_filename));
293 - /* XXX: use cow for linux as it is more efficient ? */  
294 if (bdrv_create(&bdrv_qcow, tmp_filename, 299 if (bdrv_create(&bdrv_qcow, tmp_filename,
295 total_size, filename, 0) < 0) { 300 total_size, filename, 0) < 0) {
296 return -1; 301 return -1;
@@ -300,27 +305,43 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, @@ -300,27 +305,43 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
300 } 305 }
301 306
302 pstrcpy(bs->filename, sizeof(bs->filename), filename); 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 if (!drv) 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 bs->drv = drv; 319 bs->drv = drv;
309 bs->opaque = qemu_mallocz(drv->instance_size); 320 bs->opaque = qemu_mallocz(drv->instance_size);
310 if (bs->opaque == NULL && drv->instance_size > 0) 321 if (bs->opaque == NULL && drv->instance_size > 0)
311 return -1; 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 if (ret < 0) { 334 if (ret < 0) {
315 qemu_free(bs->opaque); 335 qemu_free(bs->opaque);
316 - return -1; 336 + return ret;
317 } 337 }
  338 +
318 #ifndef _WIN32 339 #ifndef _WIN32
319 if (bs->is_temporary) { 340 if (bs->is_temporary) {
320 unlink(filename); 341 unlink(filename);
321 } 342 }
322 #endif 343 #endif
323 - if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) { 344 + if (bs->backing_file[0] != '\0') {
324 /* if there is a backing file, use it */ 345 /* if there is a backing file, use it */
325 bs->backing_hd = bdrv_new(""); 346 bs->backing_hd = bdrv_new("");
326 if (!bs->backing_hd) { 347 if (!bs->backing_hd) {
@@ -328,7 +349,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, @@ -328,7 +349,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
328 bdrv_close(bs); 349 bdrv_close(bs);
329 return -1; 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 goto fail; 355 goto fail;
333 } 356 }
334 357
@@ -373,7 +396,7 @@ void bdrv_delete(BlockDriverState *bs) @@ -373,7 +396,7 @@ void bdrv_delete(BlockDriverState *bs)
373 /* commit COW file into the raw image */ 396 /* commit COW file into the raw image */
374 int bdrv_commit(BlockDriverState *bs) 397 int bdrv_commit(BlockDriverState *bs)
375 { 398 {
376 - int64_t i; 399 + int64_t i, total_sectors;
377 int n, j; 400 int n, j;
378 unsigned char sector[512]; 401 unsigned char sector[512];
379 402
@@ -388,7 +411,8 @@ int bdrv_commit(BlockDriverState *bs) @@ -388,7 +411,8 @@ int bdrv_commit(BlockDriverState *bs)
388 return -ENOTSUP; 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 if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) { 416 if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
393 for(j = 0; j < n; j++) { 417 for(j = 0; j < n; j++) {
394 if (bdrv_read(bs, i, sector, 1) != 0) { 418 if (bdrv_read(bs, i, sector, 1) != 0) {
@@ -411,49 +435,43 @@ int bdrv_commit(BlockDriverState *bs) @@ -411,49 +435,43 @@ int bdrv_commit(BlockDriverState *bs)
411 return 0; 435 return 0;
412 } 436 }
413 437
414 -/* return -1 if error */ 438 +/* return < 0 if error */
415 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 439 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
416 uint8_t *buf, int nb_sectors) 440 uint8_t *buf, int nb_sectors)
417 { 441 {
418 - int ret, n;  
419 BlockDriver *drv = bs->drv; 442 BlockDriver *drv = bs->drv;
420 443
421 if (!bs->inserted) 444 if (!bs->inserted)
422 return -1; 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 memcpy(buf, bs->boot_sector_data, 512); 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 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 471 int bdrv_write(BlockDriverState *bs, int64_t sector_num,
455 const uint8_t *buf, int nb_sectors) 472 const uint8_t *buf, int nb_sectors)
456 { 473 {
  474 + BlockDriver *drv = bs->drv;
457 if (!bs->inserted) 475 if (!bs->inserted)
458 return -1; 476 return -1;
459 if (bs->read_only) 477 if (bs->read_only)
@@ -461,12 +479,183 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, @@ -461,12 +479,183 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
461 if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { 479 if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
462 memcpy(bs->boot_sector_data, buf, 512); 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 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr) 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 /* force a given boot sector. */ 661 /* force a given boot sector. */
@@ -660,187 +849,251 @@ void bdrv_info(void) @@ -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 return -1; 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 return 0; 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 uint8_t *buf, int nb_sectors) 952 uint8_t *buf, int nb_sectors)
734 { 953 {
735 - BDRVRawState *s = bs->opaque;  
736 int ret; 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 return 0; 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 const uint8_t *buf, int nb_sectors) 961 const uint8_t *buf, int nb_sectors)
747 { 962 {
748 - BDRVRawState *s = bs->opaque;  
749 int ret; 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 return 0; 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 void bdrv_init(void) 1098 void bdrv_init(void)
846 { 1099 {
block_int.h
@@ -28,7 +28,7 @@ struct BlockDriver { @@ -28,7 +28,7 @@ struct BlockDriver {
28 const char *format_name; 28 const char *format_name;
29 int instance_size; 29 int instance_size;
30 int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename); 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 int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, 32 int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
33 uint8_t *buf, int nb_sectors); 33 uint8_t *buf, int nb_sectors);
34 int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, 34 int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
@@ -41,11 +41,28 @@ struct BlockDriver { @@ -41,11 +41,28 @@ struct BlockDriver {
41 int nb_sectors, int *pnum); 41 int nb_sectors, int *pnum);
42 int (*bdrv_set_key)(BlockDriverState *bs, const char *key); 42 int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
43 int (*bdrv_make_empty)(BlockDriverState *bs); 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 struct BlockDriver *next; 61 struct BlockDriver *next;
45 }; 62 };
46 63
47 struct BlockDriverState { 64 struct BlockDriverState {
48 - int64_t total_sectors; 65 + int64_t total_sectors; /* XXX: will be suppressed */
49 int read_only; /* if true, the media is read only */ 66 int read_only; /* if true, the media is read only */
50 int inserted; /* if true, the media is present */ 67 int inserted; /* if true, the media is present */
51 int removable; /* if true, the media can be removed */ 68 int removable; /* if true, the media can be removed */
@@ -67,6 +84,9 @@ struct BlockDriverState { @@ -67,6 +84,9 @@ struct BlockDriverState {
67 int is_temporary; 84 int is_temporary;
68 85
69 BlockDriverState *backing_hd; 86 BlockDriverState *backing_hd;
  87 + /* sync read/write emulation */
  88 +
  89 + BlockDriverAIOCB *sync_aiocb;
70 90
71 /* NOTE: the following infos are only hints for real hardware 91 /* NOTE: the following infos are only hints for real hardware
72 drivers. They are not used by the block driver */ 92 drivers. They are not used by the block driver */
@@ -76,6 +96,14 @@ struct BlockDriverState { @@ -76,6 +96,14 @@ struct BlockDriverState {
76 BlockDriverState *next; 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 void get_tmp_filename(char *filename, int size); 107 void get_tmp_filename(char *filename, int size);
80 108
81 #endif /* BLOCK_INT_H */ 109 #endif /* BLOCK_INT_H */
@@ -4772,6 +4772,77 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) @@ -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 /* machine registration */ 4846 /* machine registration */
4776 4847
4777 QEMUMachine *first_machine = NULL; 4848 QEMUMachine *first_machine = NULL;
@@ -5030,6 +5101,8 @@ void main_loop_wait(int timeout) @@ -5030,6 +5101,8 @@ void main_loop_wait(int timeout)
5030 #ifdef _WIN32 5101 #ifdef _WIN32
5031 tap_win32_poll(); 5102 tap_win32_poll();
5032 #endif 5103 #endif
  5104 + qemu_aio_poll();
  5105 + qemu_bh_poll();
5033 5106
5034 if (vm_running) { 5107 if (vm_running) {
5035 qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 5108 qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
@@ -6049,6 +6122,7 @@ int main(int argc, char **argv) @@ -6049,6 +6122,7 @@ int main(int argc, char **argv)
6049 6122
6050 init_timers(); 6123 init_timers();
6051 init_timer_alarm(); 6124 init_timer_alarm();
  6125 + qemu_aio_init();
6052 6126
6053 #ifdef _WIN32 6127 #ifdef _WIN32
6054 socket_init(); 6128 socket_init();
@@ -6093,7 +6167,7 @@ int main(int argc, char **argv) @@ -6093,7 +6167,7 @@ int main(int argc, char **argv)
6093 snprintf(buf, sizeof(buf), "hd%c", i + 'a'); 6167 snprintf(buf, sizeof(buf), "hd%c", i + 'a');
6094 bs_table[i] = bdrv_new(buf); 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 fprintf(stderr, "qemu: could not open hard disk image '%s'\n", 6171 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
6098 hd_filename[i]); 6172 hd_filename[i]);
6099 exit(1); 6173 exit(1);
@@ -6118,7 +6192,8 @@ int main(int argc, char **argv) @@ -6118,7 +6192,8 @@ int main(int argc, char **argv)
6118 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY); 6192 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
6119 } 6193 }
6120 if (fd_filename[i] != '\0') { 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 fprintf(stderr, "qemu: could not open floppy disk image '%s'\n", 6197 fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
6123 fd_filename[i]); 6198 fd_filename[i]);
6124 exit(1); 6199 exit(1);
@@ -481,6 +481,16 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); @@ -481,6 +481,16 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
481 void cpu_save(QEMUFile *f, void *opaque); 481 void cpu_save(QEMUFile *f, void *opaque);
482 int cpu_load(QEMUFile *f, void *opaque, int version_id); 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 /* block.c */ 494 /* block.c */
485 typedef struct BlockDriverState BlockDriverState; 495 typedef struct BlockDriverState BlockDriverState;
486 typedef struct BlockDriver BlockDriver; 496 typedef struct BlockDriver BlockDriver;
@@ -495,6 +505,16 @@ extern BlockDriver bdrv_bochs; @@ -495,6 +505,16 @@ extern BlockDriver bdrv_bochs;
495 extern BlockDriver bdrv_vpc; 505 extern BlockDriver bdrv_vpc;
496 extern BlockDriver bdrv_vvfat; 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 void bdrv_init(void); 518 void bdrv_init(void);
499 BlockDriver *bdrv_find_format(const char *format_name); 519 BlockDriver *bdrv_find_format(const char *format_name);
500 int bdrv_create(BlockDriver *drv, 520 int bdrv_create(BlockDriver *drv,
@@ -502,17 +522,44 @@ int bdrv_create(BlockDriver *drv, @@ -502,17 +522,44 @@ int bdrv_create(BlockDriver *drv,
502 const char *backing_file, int flags); 522 const char *backing_file, int flags);
503 BlockDriverState *bdrv_new(const char *device_name); 523 BlockDriverState *bdrv_new(const char *device_name);
504 void bdrv_delete(BlockDriverState *bs); 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 BlockDriver *drv); 528 BlockDriver *drv);
508 void bdrv_close(BlockDriverState *bs); 529 void bdrv_close(BlockDriverState *bs);
509 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 530 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
510 uint8_t *buf, int nb_sectors); 531 uint8_t *buf, int nb_sectors);
511 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 532 int bdrv_write(BlockDriverState *bs, int64_t sector_num,
512 const uint8_t *buf, int nb_sectors); 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 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr); 540 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
514 int bdrv_commit(BlockDriverState *bs); 541 int bdrv_commit(BlockDriverState *bs);
515 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); 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 /* Ensure contents are flushed to disk. */ 563 /* Ensure contents are flushed to disk. */
517 void bdrv_flush(BlockDriverState *bs); 564 void bdrv_flush(BlockDriverState *bs);
518 565
@@ -551,6 +598,13 @@ const char *bdrv_get_device_name(BlockDriverState *bs); @@ -551,6 +598,13 @@ const char *bdrv_get_device_name(BlockDriverState *bs);
551 int qcow_get_cluster_size(BlockDriverState *bs); 598 int qcow_get_cluster_size(BlockDriverState *bs);
552 int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num, 599 int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
553 const uint8_t *buf); 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 #ifndef QEMU_TOOL 609 #ifndef QEMU_TOOL
556 610