Loading block.c +103 −22 Original line number Diff line number Diff line Loading @@ -63,6 +63,9 @@ static QTAILQ_HEAD(, BlockDriverState) bdrv_states = static QLIST_HEAD(, BlockDriver) bdrv_drivers = QLIST_HEAD_INITIALIZER(bdrv_drivers); /* The device to use for VM snapshots */ static BlockDriverState *bs_snapshots; /* If non-zero, use only whitelisted block drivers */ static int use_bdrv_whitelist; Loading Loading @@ -288,23 +291,30 @@ BlockDriver *bdrv_find_protocol(const char *filename) char protocol[128]; int len; const char *p; int is_drive; /* TODO Drivers without bdrv_file_open must be specified explicitly */ /* * XXX(hch): we really should not let host device detection * override an explicit protocol specification, but moving this * later breaks access to device names with colons in them. * Thanks to the brain-dead persistent naming schemes on udev- * based Linux systems those actually are quite common. */ drv1 = find_hdev_driver(filename); if (drv1) { return drv1; } #ifdef _WIN32 is_drive = is_windows_drive(filename) || is_windows_drive_prefix(filename); #else is_drive = 0; if (is_windows_drive(filename) || is_windows_drive_prefix(filename)) return bdrv_find_format("file"); #endif p = strchr(filename, ':'); if (!p || is_drive) { drv1 = find_hdev_driver(filename); if (!drv1) { drv1 = bdrv_find_format("file"); } return drv1; if (!p) { return bdrv_find_format("file"); } len = p - filename; if (len > sizeof(protocol) - 1) Loading Loading @@ -393,7 +403,6 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, bs->file = NULL; bs->total_sectors = 0; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; Loading Loading @@ -623,6 +632,9 @@ unlink_and_fail: void bdrv_close(BlockDriverState *bs) { if (bs->drv) { if (bs == bs_snapshots) { bs_snapshots = NULL; } if (bs->backing_hd) { bdrv_delete(bs->backing_hd); bs->backing_hd = NULL; Loading Loading @@ -659,6 +671,8 @@ void bdrv_close_all(void) void bdrv_delete(BlockDriverState *bs) { assert(!bs->peer); /* remove from list, if necessary */ if (bs->device_name[0] != '\0') { QTAILQ_REMOVE(&bdrv_states, bs, list); Loading @@ -669,9 +683,30 @@ void bdrv_delete(BlockDriverState *bs) bdrv_delete(bs->file); } assert(bs != bs_snapshots); qemu_free(bs); } int bdrv_attach(BlockDriverState *bs, DeviceState *qdev) { if (bs->peer) { return -EBUSY; } bs->peer = qdev; return 0; } void bdrv_detach(BlockDriverState *bs, DeviceState *qdev) { assert(bs->peer == qdev); bs->peer = NULL; } DeviceState *bdrv_get_attached(BlockDriverState *bs) { return bs->peer; } /* * Run consistency checks on an image * Loading Loading @@ -1264,6 +1299,14 @@ BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read) return is_read ? bs->on_read_error : bs->on_write_error; } void bdrv_set_removable(BlockDriverState *bs, int removable) { bs->removable = removable; if (removable && bs == bs_snapshots) { bs_snapshots = NULL; } } int bdrv_is_removable(BlockDriverState *bs) { return bs->removable; Loading Loading @@ -1750,6 +1793,24 @@ int bdrv_can_snapshot(BlockDriverState *bs) return 1; } BlockDriverState *bdrv_snapshots(void) { BlockDriverState *bs; if (bs_snapshots) { return bs_snapshots; } bs = NULL; while ((bs = bdrv_next(bs))) { if (bdrv_can_snapshot(bs)) { bs_snapshots = bs; return bs; } } return NULL; } int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) { Loading Loading @@ -1981,14 +2042,11 @@ static void multiwrite_cb(void *opaque, int ret) if (ret < 0 && !mcb->error) { mcb->error = ret; multiwrite_user_cb(mcb); } mcb->num_requests--; if (mcb->num_requests == 0) { if (mcb->error == 0) { multiwrite_user_cb(mcb); } qemu_free(mcb); } } Loading Loading @@ -2122,8 +2180,29 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // Check for mergable requests num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb); // Run the aio requests /* * Run the aio requests. As soon as one request can't be submitted * successfully, fail all requests that are not yet submitted (we must * return failure for all requests anyway) * * num_requests cannot be set to the right value immediately: If * bdrv_aio_writev fails for some request, num_requests would be too high * and therefore multiwrite_cb() would never recognize the multiwrite * request as completed. We also cannot use the loop variable i to set it * when the first request fails because the callback may already have been * called for previously submitted requests. Thus, num_requests must be * incremented for each request that is submitted. * * The problem that callbacks may be called early also means that we need * to take care that num_requests doesn't become 0 before all requests are * submitted - multiwrite_cb() would consider the multiwrite request * completed. A dummy request that is "completed" by a manual call to * multiwrite_cb() takes care of this. */ mcb->num_requests = 1; for (i = 0; i < num_reqs; i++) { mcb->num_requests++; acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov, reqs[i].nb_sectors, multiwrite_cb, mcb); Loading @@ -2131,22 +2210,24 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // We can only fail the whole thing if no request has been // submitted yet. Otherwise we'll wait for the submitted AIOs to // complete and report the error in the callback. if (mcb->num_requests == 0) { reqs[i].error = -EIO; if (i == 0) { goto fail; } else { mcb->num_requests++; multiwrite_cb(mcb, -EIO); break; } } else { mcb->num_requests++; } } /* Complete the dummy request */ multiwrite_cb(mcb, 0); return 0; fail: for (i = 0; i < mcb->num_callbacks; i++) { reqs[i].error = -EIO; } qemu_free(mcb); return -1; } Loading block.h +5 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,9 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv); void bdrv_close(BlockDriverState *bs); int bdrv_attach(BlockDriverState *bs, DeviceState *qdev); void bdrv_detach(BlockDriverState *bs, DeviceState *qdev); DeviceState *bdrv_get_attached(BlockDriverState *bs); int bdrv_check(BlockDriverState *bs); int bdrv_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); Loading Loading @@ -159,6 +162,7 @@ int bdrv_get_translation_hint(BlockDriverState *bs); void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, BlockErrorAction on_write_error); BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read); void bdrv_set_removable(BlockDriverState *bs, int removable); int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); Loading Loading @@ -190,6 +194,7 @@ const char *bdrv_get_encrypted_filename(BlockDriverState *bs); void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size); int bdrv_can_snapshot(BlockDriverState *bs); BlockDriverState *bdrv_snapshots(void); int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); int bdrv_snapshot_goto(BlockDriverState *bs, Loading block/blkdebug.c +6 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ static QemuOptsList inject_error_opts = { static QemuOptsList set_state_opts = { .name = "set-state", .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head), .head = QTAILQ_HEAD_INITIALIZER(set_state_opts.head), .desc = { { .name = "event", Loading Loading @@ -267,6 +267,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename) ret = 0; fail: qemu_opts_reset(&inject_error_opts); qemu_opts_reset(&set_state_opts); fclose(f); return ret; } Loading Loading @@ -299,6 +301,9 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags) } filename = c + 1; /* Set initial state */ s->vars.state = 1; /* Open the backing file */ ret = bdrv_file_open(&bs->file, filename, flags); if (ret < 0) { Loading block/qcow2.c +9 −6 Original line number Diff line number Diff line Loading @@ -805,14 +805,14 @@ static int preallocate(BlockDriverState *bs) while (nb_sectors) { num = MIN(nb_sectors, INT_MAX >> 9); ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, &meta); if (ret < 0) { return -1; return ret; } if (qcow2_alloc_cluster_link_l2(bs, &meta) < 0) { ret = qcow2_alloc_cluster_link_l2(bs, &meta); if (ret < 0) { qcow2_free_any_clusters(bs, meta.cluster_offset, meta.nb_clusters); return -1; return ret; } /* There are no dependent requests, but we need to remove our request Loading @@ -833,7 +833,10 @@ static int preallocate(BlockDriverState *bs) if (meta.cluster_offset != 0) { uint8_t buf[512]; memset(buf, 0, 512); bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1); ret = bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1); if (ret < 0) { return ret; } } return 0; Loading Loading @@ -1030,7 +1033,7 @@ exit: BlockDriver *drv = bdrv_find_format("qcow2"); bs = bdrv_new(""); bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, drv); preallocate(bs); ret = preallocate(bs); bdrv_close(bs); } Loading block_int.h +4 −4 Original line number Diff line number Diff line Loading @@ -148,6 +148,8 @@ struct BlockDriverState { BlockDriver *drv; /* NULL means no media */ void *opaque; DeviceState *peer; char filename[1024]; char backing_file[1024]; /* if non zero, the image is a diff of this file image */ Loading Loading @@ -210,10 +212,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size); int is_windows_drive(const char *filename); #endif struct DriveInfo; typedef struct BlockConf { struct DriveInfo *dinfo; BlockDriverState *bs; uint16_t physical_block_size; uint16_t logical_block_size; uint16_t min_io_size; Loading @@ -234,7 +234,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) } #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ DEFINE_PROP_DRIVE("drive", _state, _conf.dinfo), \ DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \ DEFINE_PROP_UINT16("logical_block_size", _state, \ _conf.logical_block_size, 512), \ DEFINE_PROP_UINT16("physical_block_size", _state, \ Loading Loading
block.c +103 −22 Original line number Diff line number Diff line Loading @@ -63,6 +63,9 @@ static QTAILQ_HEAD(, BlockDriverState) bdrv_states = static QLIST_HEAD(, BlockDriver) bdrv_drivers = QLIST_HEAD_INITIALIZER(bdrv_drivers); /* The device to use for VM snapshots */ static BlockDriverState *bs_snapshots; /* If non-zero, use only whitelisted block drivers */ static int use_bdrv_whitelist; Loading Loading @@ -288,23 +291,30 @@ BlockDriver *bdrv_find_protocol(const char *filename) char protocol[128]; int len; const char *p; int is_drive; /* TODO Drivers without bdrv_file_open must be specified explicitly */ /* * XXX(hch): we really should not let host device detection * override an explicit protocol specification, but moving this * later breaks access to device names with colons in them. * Thanks to the brain-dead persistent naming schemes on udev- * based Linux systems those actually are quite common. */ drv1 = find_hdev_driver(filename); if (drv1) { return drv1; } #ifdef _WIN32 is_drive = is_windows_drive(filename) || is_windows_drive_prefix(filename); #else is_drive = 0; if (is_windows_drive(filename) || is_windows_drive_prefix(filename)) return bdrv_find_format("file"); #endif p = strchr(filename, ':'); if (!p || is_drive) { drv1 = find_hdev_driver(filename); if (!drv1) { drv1 = bdrv_find_format("file"); } return drv1; if (!p) { return bdrv_find_format("file"); } len = p - filename; if (len > sizeof(protocol) - 1) Loading Loading @@ -393,7 +403,6 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, bs->file = NULL; bs->total_sectors = 0; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; bs->open_flags = flags; Loading Loading @@ -623,6 +632,9 @@ unlink_and_fail: void bdrv_close(BlockDriverState *bs) { if (bs->drv) { if (bs == bs_snapshots) { bs_snapshots = NULL; } if (bs->backing_hd) { bdrv_delete(bs->backing_hd); bs->backing_hd = NULL; Loading Loading @@ -659,6 +671,8 @@ void bdrv_close_all(void) void bdrv_delete(BlockDriverState *bs) { assert(!bs->peer); /* remove from list, if necessary */ if (bs->device_name[0] != '\0') { QTAILQ_REMOVE(&bdrv_states, bs, list); Loading @@ -669,9 +683,30 @@ void bdrv_delete(BlockDriverState *bs) bdrv_delete(bs->file); } assert(bs != bs_snapshots); qemu_free(bs); } int bdrv_attach(BlockDriverState *bs, DeviceState *qdev) { if (bs->peer) { return -EBUSY; } bs->peer = qdev; return 0; } void bdrv_detach(BlockDriverState *bs, DeviceState *qdev) { assert(bs->peer == qdev); bs->peer = NULL; } DeviceState *bdrv_get_attached(BlockDriverState *bs) { return bs->peer; } /* * Run consistency checks on an image * Loading Loading @@ -1264,6 +1299,14 @@ BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read) return is_read ? bs->on_read_error : bs->on_write_error; } void bdrv_set_removable(BlockDriverState *bs, int removable) { bs->removable = removable; if (removable && bs == bs_snapshots) { bs_snapshots = NULL; } } int bdrv_is_removable(BlockDriverState *bs) { return bs->removable; Loading Loading @@ -1750,6 +1793,24 @@ int bdrv_can_snapshot(BlockDriverState *bs) return 1; } BlockDriverState *bdrv_snapshots(void) { BlockDriverState *bs; if (bs_snapshots) { return bs_snapshots; } bs = NULL; while ((bs = bdrv_next(bs))) { if (bdrv_can_snapshot(bs)) { bs_snapshots = bs; return bs; } } return NULL; } int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) { Loading Loading @@ -1981,14 +2042,11 @@ static void multiwrite_cb(void *opaque, int ret) if (ret < 0 && !mcb->error) { mcb->error = ret; multiwrite_user_cb(mcb); } mcb->num_requests--; if (mcb->num_requests == 0) { if (mcb->error == 0) { multiwrite_user_cb(mcb); } qemu_free(mcb); } } Loading Loading @@ -2122,8 +2180,29 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // Check for mergable requests num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb); // Run the aio requests /* * Run the aio requests. As soon as one request can't be submitted * successfully, fail all requests that are not yet submitted (we must * return failure for all requests anyway) * * num_requests cannot be set to the right value immediately: If * bdrv_aio_writev fails for some request, num_requests would be too high * and therefore multiwrite_cb() would never recognize the multiwrite * request as completed. We also cannot use the loop variable i to set it * when the first request fails because the callback may already have been * called for previously submitted requests. Thus, num_requests must be * incremented for each request that is submitted. * * The problem that callbacks may be called early also means that we need * to take care that num_requests doesn't become 0 before all requests are * submitted - multiwrite_cb() would consider the multiwrite request * completed. A dummy request that is "completed" by a manual call to * multiwrite_cb() takes care of this. */ mcb->num_requests = 1; for (i = 0; i < num_reqs; i++) { mcb->num_requests++; acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov, reqs[i].nb_sectors, multiwrite_cb, mcb); Loading @@ -2131,22 +2210,24 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) // We can only fail the whole thing if no request has been // submitted yet. Otherwise we'll wait for the submitted AIOs to // complete and report the error in the callback. if (mcb->num_requests == 0) { reqs[i].error = -EIO; if (i == 0) { goto fail; } else { mcb->num_requests++; multiwrite_cb(mcb, -EIO); break; } } else { mcb->num_requests++; } } /* Complete the dummy request */ multiwrite_cb(mcb, 0); return 0; fail: for (i = 0; i < mcb->num_callbacks; i++) { reqs[i].error = -EIO; } qemu_free(mcb); return -1; } Loading
block.h +5 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,9 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); int bdrv_open(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv); void bdrv_close(BlockDriverState *bs); int bdrv_attach(BlockDriverState *bs, DeviceState *qdev); void bdrv_detach(BlockDriverState *bs, DeviceState *qdev); DeviceState *bdrv_get_attached(BlockDriverState *bs); int bdrv_check(BlockDriverState *bs); int bdrv_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); Loading Loading @@ -159,6 +162,7 @@ int bdrv_get_translation_hint(BlockDriverState *bs); void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, BlockErrorAction on_write_error); BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read); void bdrv_set_removable(BlockDriverState *bs, int removable); int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); Loading Loading @@ -190,6 +194,7 @@ const char *bdrv_get_encrypted_filename(BlockDriverState *bs); void bdrv_get_backing_filename(BlockDriverState *bs, char *filename, int filename_size); int bdrv_can_snapshot(BlockDriverState *bs); BlockDriverState *bdrv_snapshots(void); int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); int bdrv_snapshot_goto(BlockDriverState *bs, Loading
block/blkdebug.c +6 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ static QemuOptsList inject_error_opts = { static QemuOptsList set_state_opts = { .name = "set-state", .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head), .head = QTAILQ_HEAD_INITIALIZER(set_state_opts.head), .desc = { { .name = "event", Loading Loading @@ -267,6 +267,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename) ret = 0; fail: qemu_opts_reset(&inject_error_opts); qemu_opts_reset(&set_state_opts); fclose(f); return ret; } Loading Loading @@ -299,6 +301,9 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags) } filename = c + 1; /* Set initial state */ s->vars.state = 1; /* Open the backing file */ ret = bdrv_file_open(&bs->file, filename, flags); if (ret < 0) { Loading
block/qcow2.c +9 −6 Original line number Diff line number Diff line Loading @@ -805,14 +805,14 @@ static int preallocate(BlockDriverState *bs) while (nb_sectors) { num = MIN(nb_sectors, INT_MAX >> 9); ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, &meta); if (ret < 0) { return -1; return ret; } if (qcow2_alloc_cluster_link_l2(bs, &meta) < 0) { ret = qcow2_alloc_cluster_link_l2(bs, &meta); if (ret < 0) { qcow2_free_any_clusters(bs, meta.cluster_offset, meta.nb_clusters); return -1; return ret; } /* There are no dependent requests, but we need to remove our request Loading @@ -833,7 +833,10 @@ static int preallocate(BlockDriverState *bs) if (meta.cluster_offset != 0) { uint8_t buf[512]; memset(buf, 0, 512); bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1); ret = bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1); if (ret < 0) { return ret; } } return 0; Loading Loading @@ -1030,7 +1033,7 @@ exit: BlockDriver *drv = bdrv_find_format("qcow2"); bs = bdrv_new(""); bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, drv); preallocate(bs); ret = preallocate(bs); bdrv_close(bs); } Loading
block_int.h +4 −4 Original line number Diff line number Diff line Loading @@ -148,6 +148,8 @@ struct BlockDriverState { BlockDriver *drv; /* NULL means no media */ void *opaque; DeviceState *peer; char filename[1024]; char backing_file[1024]; /* if non zero, the image is a diff of this file image */ Loading Loading @@ -210,10 +212,8 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size); int is_windows_drive(const char *filename); #endif struct DriveInfo; typedef struct BlockConf { struct DriveInfo *dinfo; BlockDriverState *bs; uint16_t physical_block_size; uint16_t logical_block_size; uint16_t min_io_size; Loading @@ -234,7 +234,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) } #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ DEFINE_PROP_DRIVE("drive", _state, _conf.dinfo), \ DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \ DEFINE_PROP_UINT16("logical_block_size", _state, \ _conf.logical_block_size, 512), \ DEFINE_PROP_UINT16("physical_block_size", _state, \ Loading