Loading Makefile.objs +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o block-nested-y += cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o block-nested-y += parallels.o nbd.o blkdebug.o block-nested-$(CONFIG_WIN32) += raw-win32.o Loading block.c +275 −109 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); static BlockDriver *find_protocol(const char *filename); static QTAILQ_HEAD(, BlockDriverState) bdrv_states = QTAILQ_HEAD_INITIALIZER(bdrv_states); Loading Loading @@ -203,6 +204,18 @@ int bdrv_create(BlockDriver *drv, const char* filename, return drv->bdrv_create(filename, options); } int bdrv_create_file(const char* filename, QEMUOptionParameter *options) { BlockDriver *drv; drv = find_protocol(filename); if (drv == NULL) { drv = bdrv_find_format("file"); } return bdrv_create(drv, filename, options); } #ifdef _WIN32 void get_tmp_filename(char *filename, int size) { Loading Loading @@ -246,6 +259,28 @@ int is_windows_drive(const char *filename) } #endif /* * Detect host devices. By convention, /dev/cdrom[N] is always * recognized as a host CDROM. */ static BlockDriver *find_hdev_driver(const char *filename) { int score_max = 0, score; BlockDriver *drv = NULL, *d; QLIST_FOREACH(d, &bdrv_drivers, list) { if (d->bdrv_probe_device) { score = d->bdrv_probe_device(filename); if (score > score_max) { score_max = score; drv = d; } } } return drv; } static BlockDriver *find_protocol(const char *filename) { BlockDriver *drv1; Loading @@ -253,14 +288,21 @@ static BlockDriver *find_protocol(const char *filename) int len; const char *p; /* TODO Drivers without bdrv_file_open must be specified explicitly */ #ifdef _WIN32 if (is_windows_drive(filename) || is_windows_drive_prefix(filename)) return bdrv_find_format("raw"); return bdrv_find_format("file"); #endif p = strchr(filename, ':'); if (!p) return bdrv_find_format("raw"); if (!p) { drv1 = find_hdev_driver(filename); if (!drv1) { drv1 = bdrv_find_format("file"); } return drv1; } len = p - filename; if (len > sizeof(protocol) - 1) len = sizeof(protocol) - 1; Loading @@ -275,28 +317,6 @@ static BlockDriver *find_protocol(const char *filename) return NULL; } /* * Detect host devices. By convention, /dev/cdrom[N] is always * recognized as a host CDROM. */ static BlockDriver *find_hdev_driver(const char *filename) { int score_max = 0, score; BlockDriver *drv = NULL, *d; QLIST_FOREACH(d, &bdrv_drivers, list) { if (d->bdrv_probe_device) { score = d->bdrv_probe_device(filename); if (score > score_max) { score_max = score; drv = d; } } } return drv; } static BlockDriver *find_image_format(const char *filename) { int ret, score, score_max; Loading @@ -319,6 +339,7 @@ static BlockDriver *find_image_format(const char *filename) } score_max = 0; drv = NULL; QLIST_FOREACH(drv1, &bdrv_drivers, list) { if (drv1->bdrv_probe) { score = drv1->bdrv_probe(buf, ret, filename); Loading @@ -331,6 +352,118 @@ static BlockDriver *find_image_format(const char *filename) return drv; } /** * Set the current 'total_sectors' value */ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) { BlockDriver *drv = bs->drv; /* query actual device if possible, otherwise just trust the hint */ if (drv->bdrv_getlength) { int64_t length = drv->bdrv_getlength(bs); if (length < 0) { return length; } hint = length >> BDRV_SECTOR_BITS; } bs->total_sectors = hint; return 0; } /* * Common part for opening disk images and files */ static int bdrv_open_common(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv) { int ret, open_flags; assert(drv != NULL); bs->file = NULL; bs->total_sectors = 0; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; /* buffer_alignment defaulted to 512, drivers can change this value */ bs->buffer_alignment = 512; pstrcpy(bs->filename, sizeof(bs->filename), filename); if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { return -ENOTSUP; } bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); /* * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a * write cache to the guest. We do need the fdatasync to flush * out transactions for block allocations, and we maybe have a * volatile write cache in our backing device to deal with. */ if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) bs->enable_write_cache = 1; /* * Clear flags that are internal to the block layer before opening the * image. */ open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); /* * Snapshots should be writeable. */ if (bs->is_temporary) { open_flags |= BDRV_O_RDWR; } /* Open the image, either directly or using a protocol */ if (drv->bdrv_file_open) { ret = drv->bdrv_file_open(bs, filename, open_flags); } else { ret = bdrv_file_open(&bs->file, filename, open_flags); if (ret >= 0) { ret = drv->bdrv_open(bs, open_flags); } } if (ret < 0) { goto free_and_fail; } bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR); ret = refresh_total_sectors(bs, bs->total_sectors); if (ret < 0) { goto free_and_fail; } #ifndef _WIN32 if (bs->is_temporary) { unlink(filename); } #endif return 0; free_and_fail: if (bs->file) { bdrv_delete(bs->file); bs->file = NULL; } qemu_free(bs->opaque); bs->opaque = NULL; bs->drv = NULL; return ret; } /* * Opens a file using a protocol (file, host_device, nbd, ...) */ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) { BlockDriverState *bs; Loading @@ -343,7 +476,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) } bs = bdrv_new(""); ret = bdrv_open(bs, filename, flags, drv); ret = bdrv_open_common(bs, filename, flags, drv); if (ret < 0) { bdrv_delete(bs); return ret; Loading @@ -353,19 +486,13 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) return 0; } /* * Opens a disk image (raw, qcow2, vmdk, ...) */ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv) { int ret, open_flags; char tmp_filename[PATH_MAX]; char backing_filename[PATH_MAX]; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; /* buffer_alignment defaulted to 512, drivers can change this value */ bs->buffer_alignment = 512; int ret; if (flags & BDRV_O_SNAPSHOT) { BlockDriverState *bs1; Loading @@ -373,6 +500,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, int is_protocol = 0; BlockDriver *bdrv_qcow2; QEMUOptionParameter *options; char tmp_filename[PATH_MAX]; char backing_filename[PATH_MAX]; /* if snapshot, we create a temporary backing file and open it instead of opening 'filename' directly */ Loading Loading @@ -411,6 +540,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, } ret = bdrv_create(bdrv_qcow2, tmp_filename, options); free_option_parameters(options); if (ret < 0) { return ret; } Loading @@ -420,66 +550,28 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bs->is_temporary = 1; } pstrcpy(bs->filename, sizeof(bs->filename), filename); if (!drv) { drv = find_hdev_driver(filename); /* Find the right image format driver */ if (!drv) { drv = find_image_format(filename); } } if (!drv) { ret = -ENOENT; goto unlink_and_fail; } if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { ret = -ENOTSUP; goto unlink_and_fail; } bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); /* * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a * write cache to the guest. We do need the fdatasync to flush * out transactions for block allocations, and we maybe have a * volatile write cache in our backing device to deal with. */ if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) bs->enable_write_cache = 1; /* * Clear flags that are internal to the block layer before opening the * image. */ open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); /* * Snapshots should be writeable. */ if (bs->is_temporary) { open_flags |= BDRV_O_RDWR; } ret = drv->bdrv_open(bs, filename, open_flags); /* Open the image */ ret = bdrv_open_common(bs, filename, flags, drv); if (ret < 0) { goto free_and_fail; goto unlink_and_fail; } bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR); if (drv->bdrv_getlength) { bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; } #ifndef _WIN32 if (bs->is_temporary) { unlink(filename); } #endif /* If there is a backing file, use it */ if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') { /* if there is a backing file, use it */ char backing_filename[PATH_MAX]; int back_flags; BlockDriver *back_drv = NULL; bs->backing_hd = bdrv_new(""); path_combine(backing_filename, sizeof(backing_filename), filename, bs->backing_file); Loading @@ -487,9 +579,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, back_drv = bdrv_find_format(bs->backing_format); /* backing files always opened read-only */ open_flags &= ~BDRV_O_RDWR; back_flags = flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv); ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv); if (ret < 0) { bdrv_close(bs); return ret; Loading @@ -508,23 +601,23 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, if (bs->change_cb) bs->change_cb(bs->change_opaque); } return 0; free_and_fail: qemu_free(bs->opaque); bs->opaque = NULL; bs->drv = NULL; unlink_and_fail: if (bs->is_temporary) if (bs->is_temporary) { unlink(filename); } return ret; } void bdrv_close(BlockDriverState *bs) { if (bs->drv) { if (bs->backing_hd) if (bs->backing_hd) { bdrv_delete(bs->backing_hd); bs->backing_hd = NULL; } bs->drv->bdrv_close(bs); qemu_free(bs->opaque); #ifdef _WIN32 Loading @@ -535,6 +628,10 @@ void bdrv_close(BlockDriverState *bs) bs->opaque = NULL; bs->drv = NULL; if (bs->file != NULL) { bdrv_close(bs->file); } /* call the change callback */ bs->media_changed = 1; if (bs->change_cb) Loading @@ -550,6 +647,10 @@ void bdrv_delete(BlockDriverState *bs) } bdrv_close(bs); if (bs->file != NULL) { bdrv_delete(bs->file); } qemu_free(bs); } Loading Loading @@ -780,6 +881,10 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, set_dirty_bitmap(bs, sector_num, nb_sectors, 1); } if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { bs->wr_highest_sector = sector_num + nb_sectors - 1; } return drv->bdrv_write(bs, sector_num, buf, nb_sectors); } Loading Loading @@ -883,13 +988,18 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset, int bdrv_truncate(BlockDriverState *bs, int64_t offset) { BlockDriver *drv = bs->drv; int ret; if (!drv) return -ENOMEDIUM; if (!drv->bdrv_truncate) return -ENOTSUP; if (bs->read_only) return -EACCES; return drv->bdrv_truncate(bs, offset); ret = drv->bdrv_truncate(bs, offset); if (ret == 0) { ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); } return ret; } /** Loading @@ -900,8 +1010,12 @@ int64_t bdrv_getlength(BlockDriverState *bs) BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; if (!drv->bdrv_getlength) { /* legacy mode */ /* Fixed size devices use the total_sectors value for speed instead of issuing a length query (like lseek) on each call. Also, legacy block drivers don't provide a bdrv_getlength function and must use total_sectors. */ if (!bs->growable || !drv->bdrv_getlength) { return bs->total_sectors * BDRV_SECTOR_SIZE; } return drv->bdrv_getlength(bs); Loading Loading @@ -1208,6 +1322,19 @@ void bdrv_flush_all(void) } } int bdrv_has_zero_init(BlockDriverState *bs) { assert(bs->drv); if (bs->drv->no_zero_init) { return 0; } else if (bs->file) { return bdrv_has_zero_init(bs->file); } return 1; } /* * Returns true iff the specified sector is present in the disk image. Drivers * not implementing the functionality are assumed to not support backing files, Loading Loading @@ -1408,6 +1535,35 @@ void bdrv_stats_print(Monitor *mon, const QObject *data) qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon); } static QObject* bdrv_info_stats_bs(BlockDriverState *bs) { QObject *res; QDict *dict; res = qobject_from_jsonf("{ 'stats': {" "'rd_bytes': %" PRId64 "," "'wr_bytes': %" PRId64 "," "'rd_operations': %" PRId64 "," "'wr_operations': %" PRId64 "," "'wr_highest_offset': %" PRId64 "} }", bs->rd_bytes, bs->wr_bytes, bs->rd_ops, bs->wr_ops, bs->wr_highest_sector * 512); dict = qobject_to_qdict(res); if (*bs->device_name) { qdict_put(dict, "device", qstring_from_str(bs->device_name)); } if (bs->file) { QObject *parent = bdrv_info_stats_bs(bs->file); qdict_put_obj(dict, "parent", parent); } return res; } /** * bdrv_info_stats(): show block device statistics * Loading @@ -1422,6 +1578,11 @@ void bdrv_stats_print(Monitor *mon, const QObject *data) * - "wr_bytes": bytes written * - "rd_operations": read operations * - "wr_operations": write operations * - "wr_highest_offset": Highest offset of a sector written since the * BlockDriverState has been opened * - "parent": Contains recursively the statistics of the underlying * protocol (e.g. the host file for a qcow2 image). If there is no * underlying protocol, this field is omitted. * * Example: * Loading @@ -1429,12 +1590,22 @@ void bdrv_stats_print(Monitor *mon, const QObject *data) * "stats": { "rd_bytes": 512, * "wr_bytes": 0, * "rd_operations": 1, * "wr_operations": 0 } }, * "wr_operations": 0, * "wr_highest_offset": 0, * "parent": { * "stats": { "rd_bytes": 1024, * "wr_bytes": 0, * "rd_operations": 2, * "wr_operations": 0, * "wr_highest_offset": 0, * } * } } }, * { "device": "ide1-cd0", * "stats": { "rd_bytes": 0, * "wr_bytes": 0, * "rd_operations": 0, * "wr_operations": 0 } } ] * "wr_operations": 0, * "wr_highest_offset": 0 } }, */ void bdrv_info_stats(Monitor *mon, QObject **ret_data) { Loading @@ -1445,15 +1616,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data) devices = qlist_new(); QTAILQ_FOREACH(bs, &bdrv_states, list) { obj = qobject_from_jsonf("{ 'device': %s, 'stats': {" "'rd_bytes': %" PRId64 "," "'wr_bytes': %" PRId64 "," "'rd_operations': %" PRId64 "," "'wr_operations': %" PRId64 "} }", bs->device_name, bs->rd_bytes, bs->wr_bytes, bs->rd_ops, bs->wr_ops); obj = bdrv_info_stats_bs(bs); qlist_append_obj(devices, obj); } Loading Loading @@ -1715,6 +1878,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, /* Update stats even though technically transfer has not happened. */ bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE; bs->wr_ops ++; if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { bs->wr_highest_sector = sector_num + nb_sectors - 1; } } return ret; Loading block.h +2 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ BlockDriver *bdrv_find_format(const char *format_name); BlockDriver *bdrv_find_whitelisted_format(const char *format_name); int bdrv_create(BlockDriver *drv, const char* filename, QEMUOptionParameter *options); int bdrv_create_file(const char* filename, QEMUOptionParameter *options); BlockDriverState *bdrv_new(const char *device_name); void bdrv_delete(BlockDriverState *bs); int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); Loading Loading @@ -121,6 +122,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, void bdrv_flush(BlockDriverState *bs); void bdrv_flush_all(void); int bdrv_has_zero_init(BlockDriverState *bs); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); Loading block/blkdebug.c +6 −11 Original line number Diff line number Diff line Loading @@ -44,7 +44,6 @@ typedef struct BlkdebugVars { } BlkdebugVars; typedef struct BDRVBlkdebugState { BlockDriverState *hd; BlkdebugVars vars; QLIST_HEAD(list, BlkdebugRule) rules[BLKDBG_EVENT_MAX]; } BDRVBlkdebugState; Loading Loading @@ -303,7 +302,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags) filename = c + 1; /* Open the backing file */ ret = bdrv_file_open(&s->hd, filename, flags); ret = bdrv_file_open(&bs->file, filename, flags); if (ret < 0) { return ret; } Loading Loading @@ -362,7 +361,7 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs, } BlockDriverAIOCB *acb = bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque); bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque); return acb; } Loading @@ -377,7 +376,7 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs, } BlockDriverAIOCB *acb = bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque); bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque); return acb; } Loading @@ -393,21 +392,17 @@ static void blkdebug_close(BlockDriverState *bs) qemu_free(rule); } } bdrv_delete(s->hd); } static void blkdebug_flush(BlockDriverState *bs) { BDRVBlkdebugState *s = bs->opaque; bdrv_flush(s->hd); bdrv_flush(bs->file); } static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BDRVBlkdebugState *s = bs->opaque; return bdrv_aio_flush(s->hd, cb, opaque); return bdrv_aio_flush(bs->file, cb, opaque); } static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, Loading Loading @@ -456,7 +451,7 @@ static BlockDriver bdrv_blkdebug = { .instance_size = sizeof(BDRVBlkdebugState), .bdrv_open = blkdebug_open, .bdrv_file_open = blkdebug_open, .bdrv_close = blkdebug_close, .bdrv_flush = blkdebug_flush, Loading block/bochs.c +1 −1 Original line number Diff line number Diff line Loading @@ -252,7 +252,7 @@ static BlockDriver bdrv_bochs = { .format_name = "bochs", .instance_size = sizeof(BDRVBochsState), .bdrv_probe = bochs_probe, .bdrv_open = bochs_open, .bdrv_file_open = bochs_open, .bdrv_read = bochs_read, .bdrv_close = bochs_close, }; Loading Loading
Makefile.objs +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o block-nested-y += cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o block-nested-y += parallels.o nbd.o blkdebug.o block-nested-$(CONFIG_WIN32) += raw-win32.o Loading
block.c +275 −109 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); static BlockDriver *find_protocol(const char *filename); static QTAILQ_HEAD(, BlockDriverState) bdrv_states = QTAILQ_HEAD_INITIALIZER(bdrv_states); Loading Loading @@ -203,6 +204,18 @@ int bdrv_create(BlockDriver *drv, const char* filename, return drv->bdrv_create(filename, options); } int bdrv_create_file(const char* filename, QEMUOptionParameter *options) { BlockDriver *drv; drv = find_protocol(filename); if (drv == NULL) { drv = bdrv_find_format("file"); } return bdrv_create(drv, filename, options); } #ifdef _WIN32 void get_tmp_filename(char *filename, int size) { Loading Loading @@ -246,6 +259,28 @@ int is_windows_drive(const char *filename) } #endif /* * Detect host devices. By convention, /dev/cdrom[N] is always * recognized as a host CDROM. */ static BlockDriver *find_hdev_driver(const char *filename) { int score_max = 0, score; BlockDriver *drv = NULL, *d; QLIST_FOREACH(d, &bdrv_drivers, list) { if (d->bdrv_probe_device) { score = d->bdrv_probe_device(filename); if (score > score_max) { score_max = score; drv = d; } } } return drv; } static BlockDriver *find_protocol(const char *filename) { BlockDriver *drv1; Loading @@ -253,14 +288,21 @@ static BlockDriver *find_protocol(const char *filename) int len; const char *p; /* TODO Drivers without bdrv_file_open must be specified explicitly */ #ifdef _WIN32 if (is_windows_drive(filename) || is_windows_drive_prefix(filename)) return bdrv_find_format("raw"); return bdrv_find_format("file"); #endif p = strchr(filename, ':'); if (!p) return bdrv_find_format("raw"); if (!p) { drv1 = find_hdev_driver(filename); if (!drv1) { drv1 = bdrv_find_format("file"); } return drv1; } len = p - filename; if (len > sizeof(protocol) - 1) len = sizeof(protocol) - 1; Loading @@ -275,28 +317,6 @@ static BlockDriver *find_protocol(const char *filename) return NULL; } /* * Detect host devices. By convention, /dev/cdrom[N] is always * recognized as a host CDROM. */ static BlockDriver *find_hdev_driver(const char *filename) { int score_max = 0, score; BlockDriver *drv = NULL, *d; QLIST_FOREACH(d, &bdrv_drivers, list) { if (d->bdrv_probe_device) { score = d->bdrv_probe_device(filename); if (score > score_max) { score_max = score; drv = d; } } } return drv; } static BlockDriver *find_image_format(const char *filename) { int ret, score, score_max; Loading @@ -319,6 +339,7 @@ static BlockDriver *find_image_format(const char *filename) } score_max = 0; drv = NULL; QLIST_FOREACH(drv1, &bdrv_drivers, list) { if (drv1->bdrv_probe) { score = drv1->bdrv_probe(buf, ret, filename); Loading @@ -331,6 +352,118 @@ static BlockDriver *find_image_format(const char *filename) return drv; } /** * Set the current 'total_sectors' value */ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) { BlockDriver *drv = bs->drv; /* query actual device if possible, otherwise just trust the hint */ if (drv->bdrv_getlength) { int64_t length = drv->bdrv_getlength(bs); if (length < 0) { return length; } hint = length >> BDRV_SECTOR_BITS; } bs->total_sectors = hint; return 0; } /* * Common part for opening disk images and files */ static int bdrv_open_common(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv) { int ret, open_flags; assert(drv != NULL); bs->file = NULL; bs->total_sectors = 0; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; /* buffer_alignment defaulted to 512, drivers can change this value */ bs->buffer_alignment = 512; pstrcpy(bs->filename, sizeof(bs->filename), filename); if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { return -ENOTSUP; } bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); /* * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a * write cache to the guest. We do need the fdatasync to flush * out transactions for block allocations, and we maybe have a * volatile write cache in our backing device to deal with. */ if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) bs->enable_write_cache = 1; /* * Clear flags that are internal to the block layer before opening the * image. */ open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); /* * Snapshots should be writeable. */ if (bs->is_temporary) { open_flags |= BDRV_O_RDWR; } /* Open the image, either directly or using a protocol */ if (drv->bdrv_file_open) { ret = drv->bdrv_file_open(bs, filename, open_flags); } else { ret = bdrv_file_open(&bs->file, filename, open_flags); if (ret >= 0) { ret = drv->bdrv_open(bs, open_flags); } } if (ret < 0) { goto free_and_fail; } bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR); ret = refresh_total_sectors(bs, bs->total_sectors); if (ret < 0) { goto free_and_fail; } #ifndef _WIN32 if (bs->is_temporary) { unlink(filename); } #endif return 0; free_and_fail: if (bs->file) { bdrv_delete(bs->file); bs->file = NULL; } qemu_free(bs->opaque); bs->opaque = NULL; bs->drv = NULL; return ret; } /* * Opens a file using a protocol (file, host_device, nbd, ...) */ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) { BlockDriverState *bs; Loading @@ -343,7 +476,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) } bs = bdrv_new(""); ret = bdrv_open(bs, filename, flags, drv); ret = bdrv_open_common(bs, filename, flags, drv); if (ret < 0) { bdrv_delete(bs); return ret; Loading @@ -353,19 +486,13 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) return 0; } /* * Opens a disk image (raw, qcow2, vmdk, ...) */ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv) { int ret, open_flags; char tmp_filename[PATH_MAX]; char backing_filename[PATH_MAX]; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; /* buffer_alignment defaulted to 512, drivers can change this value */ bs->buffer_alignment = 512; int ret; if (flags & BDRV_O_SNAPSHOT) { BlockDriverState *bs1; Loading @@ -373,6 +500,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, int is_protocol = 0; BlockDriver *bdrv_qcow2; QEMUOptionParameter *options; char tmp_filename[PATH_MAX]; char backing_filename[PATH_MAX]; /* if snapshot, we create a temporary backing file and open it instead of opening 'filename' directly */ Loading Loading @@ -411,6 +540,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, } ret = bdrv_create(bdrv_qcow2, tmp_filename, options); free_option_parameters(options); if (ret < 0) { return ret; } Loading @@ -420,66 +550,28 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bs->is_temporary = 1; } pstrcpy(bs->filename, sizeof(bs->filename), filename); if (!drv) { drv = find_hdev_driver(filename); /* Find the right image format driver */ if (!drv) { drv = find_image_format(filename); } } if (!drv) { ret = -ENOENT; goto unlink_and_fail; } if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { ret = -ENOTSUP; goto unlink_and_fail; } bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); /* * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a * write cache to the guest. We do need the fdatasync to flush * out transactions for block allocations, and we maybe have a * volatile write cache in our backing device to deal with. */ if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) bs->enable_write_cache = 1; /* * Clear flags that are internal to the block layer before opening the * image. */ open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); /* * Snapshots should be writeable. */ if (bs->is_temporary) { open_flags |= BDRV_O_RDWR; } ret = drv->bdrv_open(bs, filename, open_flags); /* Open the image */ ret = bdrv_open_common(bs, filename, flags, drv); if (ret < 0) { goto free_and_fail; goto unlink_and_fail; } bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR); if (drv->bdrv_getlength) { bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; } #ifndef _WIN32 if (bs->is_temporary) { unlink(filename); } #endif /* If there is a backing file, use it */ if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') { /* if there is a backing file, use it */ char backing_filename[PATH_MAX]; int back_flags; BlockDriver *back_drv = NULL; bs->backing_hd = bdrv_new(""); path_combine(backing_filename, sizeof(backing_filename), filename, bs->backing_file); Loading @@ -487,9 +579,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, back_drv = bdrv_find_format(bs->backing_format); /* backing files always opened read-only */ open_flags &= ~BDRV_O_RDWR; back_flags = flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv); ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv); if (ret < 0) { bdrv_close(bs); return ret; Loading @@ -508,23 +601,23 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, if (bs->change_cb) bs->change_cb(bs->change_opaque); } return 0; free_and_fail: qemu_free(bs->opaque); bs->opaque = NULL; bs->drv = NULL; unlink_and_fail: if (bs->is_temporary) if (bs->is_temporary) { unlink(filename); } return ret; } void bdrv_close(BlockDriverState *bs) { if (bs->drv) { if (bs->backing_hd) if (bs->backing_hd) { bdrv_delete(bs->backing_hd); bs->backing_hd = NULL; } bs->drv->bdrv_close(bs); qemu_free(bs->opaque); #ifdef _WIN32 Loading @@ -535,6 +628,10 @@ void bdrv_close(BlockDriverState *bs) bs->opaque = NULL; bs->drv = NULL; if (bs->file != NULL) { bdrv_close(bs->file); } /* call the change callback */ bs->media_changed = 1; if (bs->change_cb) Loading @@ -550,6 +647,10 @@ void bdrv_delete(BlockDriverState *bs) } bdrv_close(bs); if (bs->file != NULL) { bdrv_delete(bs->file); } qemu_free(bs); } Loading Loading @@ -780,6 +881,10 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, set_dirty_bitmap(bs, sector_num, nb_sectors, 1); } if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { bs->wr_highest_sector = sector_num + nb_sectors - 1; } return drv->bdrv_write(bs, sector_num, buf, nb_sectors); } Loading Loading @@ -883,13 +988,18 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset, int bdrv_truncate(BlockDriverState *bs, int64_t offset) { BlockDriver *drv = bs->drv; int ret; if (!drv) return -ENOMEDIUM; if (!drv->bdrv_truncate) return -ENOTSUP; if (bs->read_only) return -EACCES; return drv->bdrv_truncate(bs, offset); ret = drv->bdrv_truncate(bs, offset); if (ret == 0) { ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); } return ret; } /** Loading @@ -900,8 +1010,12 @@ int64_t bdrv_getlength(BlockDriverState *bs) BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; if (!drv->bdrv_getlength) { /* legacy mode */ /* Fixed size devices use the total_sectors value for speed instead of issuing a length query (like lseek) on each call. Also, legacy block drivers don't provide a bdrv_getlength function and must use total_sectors. */ if (!bs->growable || !drv->bdrv_getlength) { return bs->total_sectors * BDRV_SECTOR_SIZE; } return drv->bdrv_getlength(bs); Loading Loading @@ -1208,6 +1322,19 @@ void bdrv_flush_all(void) } } int bdrv_has_zero_init(BlockDriverState *bs) { assert(bs->drv); if (bs->drv->no_zero_init) { return 0; } else if (bs->file) { return bdrv_has_zero_init(bs->file); } return 1; } /* * Returns true iff the specified sector is present in the disk image. Drivers * not implementing the functionality are assumed to not support backing files, Loading Loading @@ -1408,6 +1535,35 @@ void bdrv_stats_print(Monitor *mon, const QObject *data) qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon); } static QObject* bdrv_info_stats_bs(BlockDriverState *bs) { QObject *res; QDict *dict; res = qobject_from_jsonf("{ 'stats': {" "'rd_bytes': %" PRId64 "," "'wr_bytes': %" PRId64 "," "'rd_operations': %" PRId64 "," "'wr_operations': %" PRId64 "," "'wr_highest_offset': %" PRId64 "} }", bs->rd_bytes, bs->wr_bytes, bs->rd_ops, bs->wr_ops, bs->wr_highest_sector * 512); dict = qobject_to_qdict(res); if (*bs->device_name) { qdict_put(dict, "device", qstring_from_str(bs->device_name)); } if (bs->file) { QObject *parent = bdrv_info_stats_bs(bs->file); qdict_put_obj(dict, "parent", parent); } return res; } /** * bdrv_info_stats(): show block device statistics * Loading @@ -1422,6 +1578,11 @@ void bdrv_stats_print(Monitor *mon, const QObject *data) * - "wr_bytes": bytes written * - "rd_operations": read operations * - "wr_operations": write operations * - "wr_highest_offset": Highest offset of a sector written since the * BlockDriverState has been opened * - "parent": Contains recursively the statistics of the underlying * protocol (e.g. the host file for a qcow2 image). If there is no * underlying protocol, this field is omitted. * * Example: * Loading @@ -1429,12 +1590,22 @@ void bdrv_stats_print(Monitor *mon, const QObject *data) * "stats": { "rd_bytes": 512, * "wr_bytes": 0, * "rd_operations": 1, * "wr_operations": 0 } }, * "wr_operations": 0, * "wr_highest_offset": 0, * "parent": { * "stats": { "rd_bytes": 1024, * "wr_bytes": 0, * "rd_operations": 2, * "wr_operations": 0, * "wr_highest_offset": 0, * } * } } }, * { "device": "ide1-cd0", * "stats": { "rd_bytes": 0, * "wr_bytes": 0, * "rd_operations": 0, * "wr_operations": 0 } } ] * "wr_operations": 0, * "wr_highest_offset": 0 } }, */ void bdrv_info_stats(Monitor *mon, QObject **ret_data) { Loading @@ -1445,15 +1616,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data) devices = qlist_new(); QTAILQ_FOREACH(bs, &bdrv_states, list) { obj = qobject_from_jsonf("{ 'device': %s, 'stats': {" "'rd_bytes': %" PRId64 "," "'wr_bytes': %" PRId64 "," "'rd_operations': %" PRId64 "," "'wr_operations': %" PRId64 "} }", bs->device_name, bs->rd_bytes, bs->wr_bytes, bs->rd_ops, bs->wr_ops); obj = bdrv_info_stats_bs(bs); qlist_append_obj(devices, obj); } Loading Loading @@ -1715,6 +1878,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, /* Update stats even though technically transfer has not happened. */ bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE; bs->wr_ops ++; if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { bs->wr_highest_sector = sector_num + nb_sectors - 1; } } return ret; Loading
block.h +2 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ BlockDriver *bdrv_find_format(const char *format_name); BlockDriver *bdrv_find_whitelisted_format(const char *format_name); int bdrv_create(BlockDriver *drv, const char* filename, QEMUOptionParameter *options); int bdrv_create_file(const char* filename, QEMUOptionParameter *options); BlockDriverState *bdrv_new(const char *device_name); void bdrv_delete(BlockDriverState *bs); int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); Loading Loading @@ -121,6 +122,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, void bdrv_flush(BlockDriverState *bs); void bdrv_flush_all(void); int bdrv_has_zero_init(BlockDriverState *bs); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); Loading
block/blkdebug.c +6 −11 Original line number Diff line number Diff line Loading @@ -44,7 +44,6 @@ typedef struct BlkdebugVars { } BlkdebugVars; typedef struct BDRVBlkdebugState { BlockDriverState *hd; BlkdebugVars vars; QLIST_HEAD(list, BlkdebugRule) rules[BLKDBG_EVENT_MAX]; } BDRVBlkdebugState; Loading Loading @@ -303,7 +302,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags) filename = c + 1; /* Open the backing file */ ret = bdrv_file_open(&s->hd, filename, flags); ret = bdrv_file_open(&bs->file, filename, flags); if (ret < 0) { return ret; } Loading Loading @@ -362,7 +361,7 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs, } BlockDriverAIOCB *acb = bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque); bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque); return acb; } Loading @@ -377,7 +376,7 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs, } BlockDriverAIOCB *acb = bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque); bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque); return acb; } Loading @@ -393,21 +392,17 @@ static void blkdebug_close(BlockDriverState *bs) qemu_free(rule); } } bdrv_delete(s->hd); } static void blkdebug_flush(BlockDriverState *bs) { BDRVBlkdebugState *s = bs->opaque; bdrv_flush(s->hd); bdrv_flush(bs->file); } static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BDRVBlkdebugState *s = bs->opaque; return bdrv_aio_flush(s->hd, cb, opaque); return bdrv_aio_flush(bs->file, cb, opaque); } static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, Loading Loading @@ -456,7 +451,7 @@ static BlockDriver bdrv_blkdebug = { .instance_size = sizeof(BDRVBlkdebugState), .bdrv_open = blkdebug_open, .bdrv_file_open = blkdebug_open, .bdrv_close = blkdebug_close, .bdrv_flush = blkdebug_flush, Loading
block/bochs.c +1 −1 Original line number Diff line number Diff line Loading @@ -252,7 +252,7 @@ static BlockDriver bdrv_bochs = { .format_name = "bochs", .instance_size = sizeof(BDRVBochsState), .bdrv_probe = bochs_probe, .bdrv_open = bochs_open, .bdrv_file_open = bochs_open, .bdrv_read = bochs_read, .bdrv_close = bochs_close, }; Loading