ia64/xen-unstable

view tools/ioemu/block.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

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