Revision 5fafdf24 block.c
b/block.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU System Emulator block driver |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2003 Fabrice Bellard |
5 |
*
|
|
5 |
* |
|
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
8 | 8 |
* in the Software without restriction, including without limitation the rights |
... | ... | |
48 | 48 |
int64_t sector_num, const uint8_t *buf, int nb_sectors, |
49 | 49 |
BlockDriverCompletionFunc *cb, void *opaque); |
50 | 50 |
static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb); |
51 |
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
|
|
51 |
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, |
|
52 | 52 |
uint8_t *buf, int nb_sectors); |
53 | 53 |
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, |
54 | 54 |
const uint8_t *buf, int nb_sectors); |
... | ... | |
167 | 167 |
return NULL; |
168 | 168 |
} |
169 | 169 |
|
170 |
int bdrv_create(BlockDriver *drv,
|
|
170 |
int bdrv_create(BlockDriver *drv, |
|
171 | 171 |
const char *filename, int64_t size_in_sectors, |
172 | 172 |
const char *backing_file, int flags) |
173 | 173 |
{ |
... | ... | |
180 | 180 |
void get_tmp_filename(char *filename, int size) |
181 | 181 |
{ |
182 | 182 |
char temp_dir[MAX_PATH]; |
183 |
|
|
183 |
|
|
184 | 184 |
GetTempPath(MAX_PATH, temp_dir); |
185 | 185 |
GetTempFileName(temp_dir, "qem", 0, filename); |
186 | 186 |
} |
... | ... | |
202 | 202 |
(filename[0] >= 'A' && filename[0] <= 'Z')) && |
203 | 203 |
filename[1] == ':'); |
204 | 204 |
} |
205 |
|
|
205 |
|
|
206 | 206 |
static int is_windows_drive(const char *filename) |
207 | 207 |
{ |
208 |
if (is_windows_drive_prefix(filename) &&
|
|
208 |
if (is_windows_drive_prefix(filename) && |
|
209 | 209 |
filename[2] == '\0') |
210 | 210 |
return 1; |
211 | 211 |
if (strstart(filename, "\\\\.\\", NULL) || |
... | ... | |
236 | 236 |
memcpy(protocol, filename, len); |
237 | 237 |
protocol[len] = '\0'; |
238 | 238 |
for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { |
239 |
if (drv1->protocol_name &&
|
|
239 |
if (drv1->protocol_name && |
|
240 | 240 |
!strcmp(drv1->protocol_name, protocol)) |
241 | 241 |
return drv1; |
242 | 242 |
} |
... | ... | |
251 | 251 |
BlockDriver *drv1, *drv; |
252 | 252 |
uint8_t buf[2048]; |
253 | 253 |
BlockDriverState *bs; |
254 |
|
|
254 |
|
|
255 | 255 |
/* detect host devices. By convention, /dev/cdrom[N] is always |
256 | 256 |
recognized as a host CDROM */ |
257 | 257 |
if (strstart(filename, "/dev/cdrom", NULL)) |
... | ... | |
262 | 262 |
#else |
263 | 263 |
{ |
264 | 264 |
struct stat st; |
265 |
if (stat(filename, &st) >= 0 &&
|
|
265 |
if (stat(filename, &st) >= 0 && |
|
266 | 266 |
(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { |
267 | 267 |
return &bdrv_host_device; |
268 | 268 |
} |
269 | 269 |
} |
270 | 270 |
#endif |
271 |
|
|
271 |
|
|
272 | 272 |
drv = find_protocol(filename); |
273 | 273 |
/* no need to test disk image formats for vvfat */ |
274 | 274 |
if (drv == &bdrv_vvfat) |
... | ... | |
324 | 324 |
int ret, open_flags; |
325 | 325 |
char tmp_filename[PATH_MAX]; |
326 | 326 |
char backing_filename[PATH_MAX]; |
327 |
|
|
327 |
|
|
328 | 328 |
bs->read_only = 0; |
329 | 329 |
bs->is_temporary = 0; |
330 | 330 |
bs->encrypted = 0; |
... | ... | |
332 | 332 |
if (flags & BDRV_O_SNAPSHOT) { |
333 | 333 |
BlockDriverState *bs1; |
334 | 334 |
int64_t total_size; |
335 |
|
|
335 |
|
|
336 | 336 |
/* if snapshot, we create a temporary backing file and open it |
337 | 337 |
instead of opening 'filename' directly */ |
338 | 338 |
|
... | ... | |
347 | 347 |
} |
348 | 348 |
total_size = bdrv_getlength(bs1) >> SECTOR_BITS; |
349 | 349 |
bdrv_delete(bs1); |
350 |
|
|
350 |
|
|
351 | 351 |
get_tmp_filename(tmp_filename, sizeof(tmp_filename)); |
352 | 352 |
realpath(filename, backing_filename); |
353 |
if (bdrv_create(&bdrv_qcow2, tmp_filename,
|
|
353 |
if (bdrv_create(&bdrv_qcow2, tmp_filename, |
|
354 | 354 |
total_size, backing_filename, 0) < 0) { |
355 | 355 |
return -1; |
356 | 356 |
} |
... | ... | |
494 | 494 |
} |
495 | 495 |
|
496 | 496 |
/* return < 0 if error. See bdrv_write() for the return codes */ |
497 |
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
|
497 |
int bdrv_read(BlockDriverState *bs, int64_t sector_num, |
|
498 | 498 |
uint8_t *buf, int nb_sectors) |
499 | 499 |
{ |
500 | 500 |
BlockDriver *drv = bs->drv; |
... | ... | |
525 | 525 |
} |
526 | 526 |
} |
527 | 527 |
|
528 |
/* Return < 0 if error. Important errors are:
|
|
528 |
/* Return < 0 if error. Important errors are: |
|
529 | 529 |
-EIO generic I/O error (may happen for all errors) |
530 | 530 |
-ENOMEDIUM No media inserted. |
531 | 531 |
-EINVAL Invalid sector number or nb_sectors |
532 | 532 |
-EACCES Trying to write a read-only device |
533 | 533 |
*/ |
534 |
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
|
|
534 |
int bdrv_write(BlockDriverState *bs, int64_t sector_num, |
|
535 | 535 |
const uint8_t *buf, int nb_sectors) |
536 | 536 |
{ |
537 | 537 |
BlockDriver *drv = bs->drv; |
... | ... | |
540 | 540 |
if (bs->read_only) |
541 | 541 |
return -EACCES; |
542 | 542 |
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { |
543 |
memcpy(bs->boot_sector_data, buf, 512);
|
|
543 |
memcpy(bs->boot_sector_data, buf, 512); |
|
544 | 544 |
} |
545 | 545 |
if (drv->bdrv_pwrite) { |
546 | 546 |
int ret, len; |
... | ... | |
557 | 557 |
} |
558 | 558 |
} |
559 | 559 |
|
560 |
static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
|
|
560 |
static int bdrv_pread_em(BlockDriverState *bs, int64_t offset, |
|
561 | 561 |
uint8_t *buf, int count1) |
562 | 562 |
{ |
563 | 563 |
uint8_t tmp_buf[SECTOR_SIZE]; |
... | ... | |
601 | 601 |
return count1; |
602 | 602 |
} |
603 | 603 |
|
604 |
static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
|
|
604 |
static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset, |
|
605 | 605 |
const uint8_t *buf, int count1) |
606 | 606 |
{ |
607 | 607 |
uint8_t tmp_buf[SECTOR_SIZE]; |
... | ... | |
650 | 650 |
} |
651 | 651 |
|
652 | 652 |
/** |
653 |
* Read with byte offsets (needed only for file protocols)
|
|
653 |
* Read with byte offsets (needed only for file protocols) |
|
654 | 654 |
*/ |
655 |
int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
|
655 |
int bdrv_pread(BlockDriverState *bs, int64_t offset, |
|
656 | 656 |
void *buf1, int count1) |
657 | 657 |
{ |
658 | 658 |
BlockDriver *drv = bs->drv; |
... | ... | |
664 | 664 |
return drv->bdrv_pread(bs, offset, buf1, count1); |
665 | 665 |
} |
666 | 666 |
|
667 |
/**
|
|
668 |
* Write with byte offsets (needed only for file protocols)
|
|
667 |
/** |
|
668 |
* Write with byte offsets (needed only for file protocols) |
|
669 | 669 |
*/ |
670 |
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
|
670 |
int bdrv_pwrite(BlockDriverState *bs, int64_t offset, |
|
671 | 671 |
const void *buf1, int count1) |
672 | 672 |
{ |
673 | 673 |
BlockDriver *drv = bs->drv; |
... | ... | |
729 | 729 |
memset(bs->boot_sector_data + size, 0, 512 - size); |
730 | 730 |
} |
731 | 731 |
|
732 |
void bdrv_set_geometry_hint(BlockDriverState *bs,
|
|
732 |
void bdrv_set_geometry_hint(BlockDriverState *bs, |
|
733 | 733 |
int cyls, int heads, int secs) |
734 | 734 |
{ |
735 | 735 |
bs->cyls = cyls; |
... | ... | |
749 | 749 |
bs->translation = translation; |
750 | 750 |
} |
751 | 751 |
|
752 |
void bdrv_get_geometry_hint(BlockDriverState *bs,
|
|
752 |
void bdrv_get_geometry_hint(BlockDriverState *bs, |
|
753 | 753 |
int *pcyls, int *pheads, int *psecs) |
754 | 754 |
{ |
755 | 755 |
*pcyls = bs->cyls; |
... | ... | |
778 | 778 |
} |
779 | 779 |
|
780 | 780 |
/* XXX: no longer used */ |
781 |
void bdrv_set_change_cb(BlockDriverState *bs,
|
|
781 |
void bdrv_set_change_cb(BlockDriverState *bs, |
|
782 | 782 |
void (*change_cb)(void *opaque), void *opaque) |
783 | 783 |
{ |
784 | 784 |
bs->change_cb = change_cb; |
... | ... | |
816 | 816 |
} |
817 | 817 |
} |
818 | 818 |
|
819 |
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
|
819 |
void bdrv_iterate_format(void (*it)(void *opaque, const char *name), |
|
820 | 820 |
void *opaque) |
821 | 821 |
{ |
822 | 822 |
BlockDriver *drv; |
... | ... | |
899 | 899 |
} |
900 | 900 |
} |
901 | 901 |
|
902 |
void bdrv_get_backing_filename(BlockDriverState *bs,
|
|
902 |
void bdrv_get_backing_filename(BlockDriverState *bs, |
|
903 | 903 |
char *filename, int filename_size) |
904 | 904 |
{ |
905 | 905 |
if (!bs->backing_hd) { |
... | ... | |
909 | 909 |
} |
910 | 910 |
} |
911 | 911 |
|
912 |
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
|
912 |
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, |
|
913 | 913 |
const uint8_t *buf, int nb_sectors) |
914 | 914 |
{ |
915 | 915 |
BlockDriver *drv = bs->drv; |
... | ... | |
919 | 919 |
return -ENOTSUP; |
920 | 920 |
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors); |
921 | 921 |
} |
922 |
|
|
922 |
|
|
923 | 923 |
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) |
924 | 924 |
{ |
925 | 925 |
BlockDriver *drv = bs->drv; |
... | ... | |
934 | 934 |
/**************************************************************/ |
935 | 935 |
/* handling of snapshots */ |
936 | 936 |
|
937 |
int bdrv_snapshot_create(BlockDriverState *bs,
|
|
937 |
int bdrv_snapshot_create(BlockDriverState *bs, |
|
938 | 938 |
QEMUSnapshotInfo *sn_info) |
939 | 939 |
{ |
940 | 940 |
BlockDriver *drv = bs->drv; |
... | ... | |
945 | 945 |
return drv->bdrv_snapshot_create(bs, sn_info); |
946 | 946 |
} |
947 | 947 |
|
948 |
int bdrv_snapshot_goto(BlockDriverState *bs,
|
|
948 |
int bdrv_snapshot_goto(BlockDriverState *bs, |
|
949 | 949 |
const char *snapshot_id) |
950 | 950 |
{ |
951 | 951 |
BlockDriver *drv = bs->drv; |
... | ... | |
966 | 966 |
return drv->bdrv_snapshot_delete(bs, snapshot_id); |
967 | 967 |
} |
968 | 968 |
|
969 |
int bdrv_snapshot_list(BlockDriverState *bs,
|
|
969 |
int bdrv_snapshot_list(BlockDriverState *bs, |
|
970 | 970 |
QEMUSnapshotInfo **psn_info) |
971 | 971 |
{ |
972 | 972 |
BlockDriver *drv = bs->drv; |
... | ... | |
991 | 991 |
base = 1024; |
992 | 992 |
for(i = 0; i < NB_SUFFIXES; i++) { |
993 | 993 |
if (size < (10 * base)) { |
994 |
snprintf(buf, buf_size, "%0.1f%c",
|
|
994 |
snprintf(buf, buf_size, "%0.1f%c", |
|
995 | 995 |
(double)size / base, |
996 | 996 |
suffixes[i]); |
997 | 997 |
break; |
998 | 998 |
} else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { |
999 |
snprintf(buf, buf_size, "%" PRId64 "%c",
|
|
999 |
snprintf(buf, buf_size, "%" PRId64 "%c", |
|
1000 | 1000 |
((size + (base >> 1)) / base), |
1001 | 1001 |
suffixes[i]); |
1002 | 1002 |
break; |
... | ... | |
1019 | 1019 |
int64_t secs; |
1020 | 1020 |
|
1021 | 1021 |
if (!sn) { |
1022 |
snprintf(buf, buf_size,
|
|
1023 |
"%-10s%-20s%7s%20s%15s",
|
|
1022 |
snprintf(buf, buf_size, |
|
1023 |
"%-10s%-20s%7s%20s%15s", |
|
1024 | 1024 |
"ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); |
1025 | 1025 |
} else { |
1026 | 1026 |
ti = sn->date_sec; |
... | ... | |
1038 | 1038 |
"%02d:%02d:%02d.%03d", |
1039 | 1039 |
(int)(secs / 3600), |
1040 | 1040 |
(int)((secs / 60) % 60), |
1041 |
(int)(secs % 60),
|
|
1041 |
(int)(secs % 60), |
|
1042 | 1042 |
(int)((sn->vm_clock_nsec / 1000000) % 1000)); |
1043 | 1043 |
snprintf(buf, buf_size, |
1044 |
"%-10s%-20s%7s%20s%15s",
|
|
1044 |
"%-10s%-20s%7s%20s%15s", |
|
1045 | 1045 |
sn->id_str, sn->name, |
1046 | 1046 |
get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size), |
1047 | 1047 |
date_buf, |
... | ... | |
1062 | 1062 |
|
1063 | 1063 |
if (!drv) |
1064 | 1064 |
return NULL; |
1065 |
|
|
1065 |
|
|
1066 | 1066 |
/* XXX: we assume that nb_sectors == 0 is suppored by the async read */ |
1067 | 1067 |
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { |
1068 | 1068 |
memcpy(buf, bs->boot_sector_data, 512); |
... | ... | |
1085 | 1085 |
if (bs->read_only) |
1086 | 1086 |
return NULL; |
1087 | 1087 |
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { |
1088 |
memcpy(bs->boot_sector_data, buf, 512);
|
|
1088 |
memcpy(bs->boot_sector_data, buf, 512); |
|
1089 | 1089 |
} |
1090 | 1090 |
|
1091 | 1091 |
return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque); |
... | ... | |
1184 | 1184 |
|
1185 | 1185 |
#define NOT_DONE 0x7fffffff |
1186 | 1186 |
|
1187 |
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
|
|
1187 |
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, |
|
1188 | 1188 |
uint8_t *buf, int nb_sectors) |
1189 | 1189 |
{ |
1190 | 1190 |
int async_ret; |
... | ... | |
1192 | 1192 |
|
1193 | 1193 |
async_ret = NOT_DONE; |
1194 | 1194 |
qemu_aio_wait_start(); |
1195 |
acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
|
|
1195 |
acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, |
|
1196 | 1196 |
bdrv_rw_em_cb, &async_ret); |
1197 | 1197 |
if (acb == NULL) { |
1198 | 1198 |
qemu_aio_wait_end(); |
... | ... | |
1213 | 1213 |
|
1214 | 1214 |
async_ret = NOT_DONE; |
1215 | 1215 |
qemu_aio_wait_start(); |
1216 |
acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
|
|
1216 |
acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, |
|
1217 | 1217 |
bdrv_rw_em_cb, &async_ret); |
1218 | 1218 |
if (acb == NULL) { |
1219 | 1219 |
qemu_aio_wait_end(); |
... | ... | |
1293 | 1293 |
|
1294 | 1294 |
/** |
1295 | 1295 |
* Return TRUE if the media changed since the last call to this |
1296 |
* function. It is currently only used for floppy disks
|
|
1296 |
* function. It is currently only used for floppy disks |
|
1297 | 1297 |
*/ |
1298 | 1298 |
int bdrv_media_changed(BlockDriverState *bs) |
1299 | 1299 |
{ |
Also available in: Unified diff