diff options
34 files changed, 958 insertions, 162 deletions
@@ -4396,55 +4396,65 @@ void bdrv_img_create(const char *filename, const char *fmt, backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT); - // The size for the image must always be specified, with one exception: - // If we are using a backing file, we can obtain the size from there + /* The size for the image must always be specified, unless we have a backing + * file and we have not been forbidden from opening it. */ size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0); - if (size == -1) { - if (backing_file) { - BlockDriverState *bs; - char *full_backing = g_new0(char, PATH_MAX); - int64_t size; - int back_flags; - QDict *backing_options = NULL; - - bdrv_get_full_backing_filename_from_filename(filename, backing_file, - full_backing, PATH_MAX, - &local_err); - if (local_err) { - g_free(full_backing); - goto out; - } + if (backing_file && !(flags & BDRV_O_NO_BACKING)) { + BlockDriverState *bs; + char *full_backing = g_new0(char, PATH_MAX); + int back_flags; + QDict *backing_options = NULL; + + bdrv_get_full_backing_filename_from_filename(filename, backing_file, + full_backing, PATH_MAX, + &local_err); + if (local_err) { + g_free(full_backing); + goto out; + } - /* backing files always opened read-only */ - back_flags = flags; - back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); + /* backing files always opened read-only */ + back_flags = flags; + back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); - if (backing_fmt) { - backing_options = qdict_new(); - qdict_put_str(backing_options, "driver", backing_fmt); - } + if (backing_fmt) { + backing_options = qdict_new(); + qdict_put_str(backing_options, "driver", backing_fmt); + } - bs = bdrv_open(full_backing, NULL, backing_options, back_flags, - &local_err); - g_free(full_backing); - if (!bs) { - goto out; - } - size = bdrv_getlength(bs); - if (size < 0) { - error_setg_errno(errp, -size, "Could not get size of '%s'", - backing_file); - bdrv_unref(bs); - goto out; + bs = bdrv_open(full_backing, NULL, backing_options, back_flags, + &local_err); + g_free(full_backing); + if (!bs && size != -1) { + /* Couldn't open BS, but we have a size, so it's nonfatal */ + warn_reportf_err(local_err, + "Could not verify backing image. " + "This may become an error in future versions.\n"); + local_err = NULL; + } else if (!bs) { + /* Couldn't open bs, do not have size */ + error_append_hint(&local_err, + "Could not open backing image to determine size.\n"); + goto out; + } else { + if (size == -1) { + /* Opened BS, have no size */ + size = bdrv_getlength(bs); + if (size < 0) { + error_setg_errno(errp, -size, "Could not get size of '%s'", + backing_file); + bdrv_unref(bs); + goto out; + } + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort); } - - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort); - bdrv_unref(bs); - } else { - error_setg(errp, "Image creation needs a size parameter"); - goto out; } + } /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */ + + if (size == -1) { + error_setg(errp, "Image creation needs a size parameter"); + goto out; } if (!quiet) { diff --git a/block/block-backend.c b/block/block-backend.c index fe3542b3f8..968438c149 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -83,7 +83,6 @@ static const AIOCBInfo block_backend_aiocb_info = { static void drive_info_del(DriveInfo *dinfo); static BlockBackend *bdrv_first_blk(BlockDriverState *bs); -static char *blk_get_attached_dev_id(BlockBackend *blk); /* All BlockBackends */ static QTAILQ_HEAD(, BlockBackend) block_backends = @@ -343,7 +342,7 @@ void blk_unref(BlockBackend *blk) * Behaves similarly to blk_next() but iterates over all BlockBackends, even the * ones which are hidden (i.e. are not referenced by the monitor). */ -static BlockBackend *blk_all_next(BlockBackend *blk) +BlockBackend *blk_all_next(BlockBackend *blk) { return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&block_backends); @@ -726,7 +725,7 @@ void *blk_get_attached_dev(BlockBackend *blk) /* Return the qdev ID, or if no ID is assigned the QOM path, of the block * device attached to the BlockBackend. */ -static char *blk_get_attached_dev_id(BlockBackend *blk) +char *blk_get_attached_dev_id(BlockBackend *blk) { DeviceState *dev; diff --git a/block/commit.c b/block/commit.c index 13143608f8..5cc910f567 100644 --- a/block/commit.c +++ b/block/commit.c @@ -90,7 +90,9 @@ static void commit_complete(BlockJob *job, void *opaque) /* Make sure overlay_bs and top stay around until bdrv_set_backing_hd() */ bdrv_ref(top); - bdrv_ref(overlay_bs); + if (overlay_bs) { + bdrv_ref(overlay_bs); + } /* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before * the normal backing chain can be restored. */ diff --git a/block/qapi.c b/block/qapi.c index 080eb8f115..95b2e2daa5 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -322,11 +322,21 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, { BlockInfo *info = g_malloc0(sizeof(*info)); BlockDriverState *bs = blk_bs(blk); + char *qdev; + info->device = g_strdup(blk_name(blk)); info->type = g_strdup("unknown"); info->locked = blk_dev_is_medium_locked(blk); info->removable = blk_dev_has_removable_media(blk); + qdev = blk_get_attached_dev_id(blk); + if (qdev && *qdev) { + info->has_qdev = true; + info->qdev = qdev; + } else { + g_free(qdev); + } + if (blk_dev_has_tray(blk)) { info->has_tray_open = true; info->tray_open = blk_dev_is_tray_open(blk); @@ -462,8 +472,14 @@ BlockInfoList *qmp_query_block(Error **errp) BlockBackend *blk; Error *local_err = NULL; - for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { - BlockInfoList *info = g_malloc0(sizeof(*info)); + for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) { + BlockInfoList *info; + + if (!*blk_name(blk) && !blk_get_attached_dev(blk)) { + continue; + } + + info = g_malloc0(sizeof(*info)); bdrv_query_info(blk, &info->value, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/block/throttle-groups.c b/block/throttle-groups.c index da2b490c38..890bfded3f 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -61,6 +61,7 @@ typedef struct ThrottleGroup { QLIST_HEAD(, BlockBackendPublic) head; BlockBackend *tokens[2]; bool any_timer_armed[2]; + QEMUClockType clock_type; /* These two are protected by the global throttle_groups_lock */ unsigned refcount; @@ -98,6 +99,12 @@ ThrottleState *throttle_group_incref(const char *name) if (!tg) { tg = g_new0(ThrottleGroup, 1); tg->name = g_strdup(name); + tg->clock_type = QEMU_CLOCK_REALTIME; + + if (qtest_enabled()) { + /* For testing block IO throttling only */ + tg->clock_type = QEMU_CLOCK_VIRTUAL; + } qemu_mutex_init(&tg->lock); throttle_init(&tg->ts); QLIST_INIT(&tg->head); @@ -310,7 +317,7 @@ static void schedule_next_request(BlockBackend *blk, bool is_write) token = blk; } else { ThrottleTimers *tt = &blk_get_public(token)->throttle_timers; - int64_t now = qemu_clock_get_ns(tt->clock_type); + int64_t now = qemu_clock_get_ns(tg->clock_type); timer_mod(tt->timers[is_write], now); tg->any_timer_armed[is_write] = true; } @@ -419,18 +426,10 @@ void throttle_group_restart_blk(BlockBackend *blk) void throttle_group_config(BlockBackend *blk, ThrottleConfig *cfg) { BlockBackendPublic *blkp = blk_get_public(blk); - ThrottleTimers *tt = &blkp->throttle_timers; ThrottleState *ts = blkp->throttle_state; ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts); qemu_mutex_lock(&tg->lock); - /* throttle_config() cancels the timers */ - if (timer_pending(tt->timers[0])) { - tg->any_timer_armed[0] = false; - } - if (timer_pending(tt->timers[1])) { - tg->any_timer_armed[1] = false; - } - throttle_config(ts, tt, cfg); + throttle_config(ts, tg->clock_type, cfg); qemu_mutex_unlock(&tg->lock); throttle_group_restart_blk(blk); @@ -497,13 +496,6 @@ void throttle_group_register_blk(BlockBackend *blk, const char *groupname) BlockBackendPublic *blkp = blk_get_public(blk); ThrottleState *ts = throttle_group_incref(groupname); ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts); - int clock_type = QEMU_CLOCK_REALTIME; - - if (qtest_enabled()) { - /* For testing block IO throttling only */ - clock_type = QEMU_CLOCK_VIRTUAL; - } - blkp->throttle_state = ts; qemu_mutex_lock(&tg->lock); @@ -518,7 +510,7 @@ void throttle_group_register_blk(BlockBackend *blk, const char *groupname) throttle_timers_init(&blkp->throttle_timers, blk_get_aio_context(blk), - clock_type, + tg->clock_type, read_timer_cb, write_timer_cb, blk); diff --git a/block/vmdk.c b/block/vmdk.c index 24d71b5982..0fc97391a6 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -242,10 +242,11 @@ static void vmdk_free_last_extent(BlockDriverState *bs) s->extents = g_renew(VmdkExtent, s->extents, s->num_extents); } -static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) +/* Return -ve errno, or 0 on success and write CID into *pcid. */ +static int vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid) { char *desc; - uint32_t cid = 0xffffffff; + uint32_t cid; const char *p_name, *cid_str; size_t cid_str_size; BDRVVmdkState *s = bs->opaque; @@ -254,8 +255,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) desc = g_malloc0(DESC_SIZE); ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE); if (ret < 0) { - g_free(desc); - return 0; + goto out; } if (parent) { @@ -268,13 +268,21 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) desc[DESC_SIZE - 1] = '\0'; p_name = strstr(desc, cid_str); - if (p_name != NULL) { - p_name += cid_str_size; - sscanf(p_name, "%" SCNx32, &cid); + if (p_name == NULL) { + ret = -EINVAL; + goto out; } + p_name += cid_str_size; + if (sscanf(p_name, "%" SCNx32, &cid) != 1) { + ret = -EINVAL; + goto out; + } + *pcid = cid; + ret = 0; +out: g_free(desc); - return cid; + return ret; } static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) @@ -322,7 +330,10 @@ static int vmdk_is_cid_valid(BlockDriverState *bs) if (!s->cid_checked && bs->backing) { BlockDriverState *p_bs = bs->backing->bs; - cur_pcid = vmdk_read_cid(p_bs, 0); + if (vmdk_read_cid(p_bs, 0, &cur_pcid) != 0) { + /* read failure: report as not valid */ + return 0; + } if (s->parent_cid != cur_pcid) { /* CID not valid */ return 0; @@ -975,8 +986,14 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, if (ret) { goto fail; } - s->cid = vmdk_read_cid(bs, 0); - s->parent_cid = vmdk_read_cid(bs, 1); + ret = vmdk_read_cid(bs, 0, &s->cid); + if (ret) { + goto fail; + } + ret = vmdk_read_cid(bs, 1, &s->parent_cid); + if (ret) { + goto fail; + } qemu_co_mutex_init(&s->lock); /* Disable migration when VMDK images are used */ @@ -2008,8 +2025,11 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) ret = -EINVAL; goto exit; } - parent_cid = vmdk_read_cid(blk_bs(blk), 0); + ret = vmdk_read_cid(blk_bs(blk), 0, &parent_cid); blk_unref(blk); + if (ret) { + goto exit; + } snprintf(parent_desc_line, BUF_SIZE, "parentFileNameHint=\"%s\"", backing_file); } diff --git a/block/vpc.c b/block/vpc.c index 8057d42a23..10e6519d78 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -460,17 +460,23 @@ static int vpc_reopen_prepare(BDRVReopenState *state, /* * Returns the absolute byte offset of the given sector in the image file. * If the sector is not allocated, -1 is returned instead. + * If an error occurred trying to write an updated block bitmap back to + * the file, -2 is returned, and the error value is written to *err. + * This can only happen for a write operation. * * The parameter write must be 1 if the offset will be used for a write * operation (the block bitmaps is updated then), 0 otherwise. + * If write is true then err must not be NULL. */ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, - bool write) + bool write, int *err) { BDRVVPCState *s = bs->opaque; uint64_t bitmap_offset, block_offset; uint32_t pagetable_index, offset_in_block; + assert(!(write && err == NULL)); + pagetable_index = offset / s->block_size; offset_in_block = offset % s->block_size; @@ -487,10 +493,15 @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, correctness. */ if (write && (s->last_bitmap_offset != bitmap_offset)) { uint8_t bitmap[s->bitmap_size]; + int r; s->last_bitmap_offset = bitmap_offset; memset(bitmap, 0xff, s->bitmap_size); - bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size); + r = bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size); + if (r < 0) { + *err = r; + return -2; + } } return block_offset; @@ -561,7 +572,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t offset) if (ret < 0) goto fail; - return get_image_offset(bs, offset, false); + return get_image_offset(bs, offset, false, NULL); fail: s->free_data_block_offset -= (s->block_size + s->bitmap_size); @@ -601,7 +612,7 @@ vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, qemu_iovec_init(&local_qiov, qiov->niov); while (bytes > 0) { - image_offset = get_image_offset(bs, offset, false); + image_offset = get_image_offset(bs, offset, false, NULL); n_bytes = MIN(bytes, s->block_size - (offset % s->block_size)); if (image_offset == -1) { @@ -650,7 +661,11 @@ vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, qemu_iovec_init(&local_qiov, qiov->niov); while (bytes > 0) { - image_offset = get_image_offset(bs, offset, true); + image_offset = get_image_offset(bs, offset, true, &ret); + if (image_offset == -2) { + /* Failed to write block bitmap: can't proceed with write */ + goto fail; + } n_bytes = MIN(bytes, s->block_size - (offset % s->block_size)); if (image_offset == -1) { @@ -702,7 +717,7 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs, qemu_co_mutex_lock(&s->lock); - offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false); + offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false, NULL); start = offset; allocated = (offset != -1); *pnum = 0; @@ -727,7 +742,8 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs, if (nb_sectors == 0) { break; } - offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false); + offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false, + NULL); } while (offset == -1); qemu_co_mutex_unlock(&s->lock); diff --git a/block/vvfat.c b/block/vvfat.c index 4dae790203..a9e207f7f0 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -71,6 +71,17 @@ void nonono(const char* file, int line, const char* msg) { #endif +/* bootsector OEM name. see related compatibility problems at: + * https://jdebp.eu/FGA/volume-boot-block-oem-name-field.html + * http://seasip.info/Misc/oemid.html + */ +#define BOOTSECTOR_OEM_NAME "MSWIN4.1" + +#define DIR_DELETED 0xe5 +#define DIR_KANJI DIR_DELETED +#define DIR_KANJI_FAKE 0x05 +#define DIR_FREE 0x00 + /* dynamic array functions */ typedef struct array_t { char* pointer; @@ -104,6 +115,7 @@ static inline int array_ensure_allocated(array_t* array, int index) array->pointer = g_realloc(array->pointer, new_size); if (!array->pointer) return -1; + memset(array->pointer + array->size, 0, new_size - array->size); array->size = new_size; array->next = index + 1; } @@ -466,7 +478,7 @@ static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename) static char is_free(const direntry_t* direntry) { - return direntry->name[0]==0xe5 || direntry->name[0]==0x00; + return direntry->name[0] == DIR_DELETED || direntry->name[0] == DIR_FREE; } static char is_volume_label(const direntry_t* direntry) @@ -487,7 +499,7 @@ static char is_short_name(const direntry_t* direntry) static char is_directory(const direntry_t* direntry) { - return direntry->attributes & 0x10 && direntry->name[0] != 0xe5; + return direntry->attributes & 0x10 && direntry->name[0] != DIR_DELETED; } static inline char is_dot(const direntry_t* direntry) @@ -537,7 +549,7 @@ static direntry_t *create_short_filename(BDRVVVFATState *s, const gchar *p, *last_dot = NULL; gunichar c; bool lossy_conversion = false; - char tail[11]; + char tail[8]; if (!entry) { return NULL; @@ -589,8 +601,8 @@ static direntry_t *create_short_filename(BDRVVVFATState *s, } } - if (entry->name[0] == 0xe5) { - entry->name[0] = 0x05; + if (entry->name[0] == DIR_KANJI) { + entry->name[0] = DIR_KANJI_FAKE; } /* numeric-tail generation */ @@ -602,7 +614,8 @@ static direntry_t *create_short_filename(BDRVVVFATState *s, for (i = lossy_conversion ? 1 : 0; i < 999999; i++) { direntry_t *entry1; if (i > 0) { - int len = sprintf(tail, "~%d", i); + int len = snprintf(tail, sizeof(tail), "~%u", (unsigned)i); + assert(len <= 7); memcpy(entry->name + MIN(j, 8 - len), tail, len); } for (entry1 = array_get(&(s->directory), directory_start); @@ -1023,7 +1036,7 @@ static int init_directories(BDRVVVFATState* s, bootsector->jump[0]=0xeb; bootsector->jump[1]=0x3e; bootsector->jump[2]=0x90; - memcpy(bootsector->name, "MSWIN4.1", 8); + memcpy(bootsector->name, BOOTSECTOR_OEM_NAME, 8); bootsector->sector_size=cpu_to_le16(0x200); bootsector->sectors_per_cluster=s->sectors_per_cluster; bootsector->reserved_sectors=cpu_to_le16(1); @@ -1658,6 +1671,7 @@ typedef struct { * filename length is 0x3f * 13 bytes. */ unsigned char name[0x3f * 13 + 1]; + gunichar2 name2[0x3f * 13 + 1]; int checksum, len; int sequence_number; } long_file_name; @@ -1679,16 +1693,21 @@ static int parse_long_name(long_file_name* lfn, return 1; if (pointer[0] & 0x40) { + /* first entry; do some initialization */ lfn->sequence_number = pointer[0] & 0x3f; lfn->checksum = pointer[13]; lfn->name[0] = 0; lfn->name[lfn->sequence_number * 13] = 0; - } else if ((pointer[0] & 0x3f) != --lfn->sequence_number) + } else if ((pointer[0] & 0x3f) != --lfn->sequence_number) { + /* not the expected sequence number */ return -1; - else if (pointer[13] != lfn->checksum) + } else if (pointer[13] != lfn->checksum) { + /* not the expected checksum */ return -2; - else if (pointer[12] || pointer[26] || pointer[27]) + } else if (pointer[12] || pointer[26] || pointer[27]) { + /* invalid zero fields */ return -3; + } offset = 13 * (lfn->sequence_number - 1); for (i = 0, j = 1; i < 13; i++, j+=2) { @@ -1697,16 +1716,29 @@ static int parse_long_name(long_file_name* lfn, else if (j == 26) j = 28; - if (pointer[j+1] == 0) - lfn->name[offset + i] = pointer[j]; - else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0) - return -4; - else - lfn->name[offset + i] = 0; + if (pointer[j] == 0 && pointer[j + 1] == 0) { + /* end of long file name */ + break; + } + gunichar2 c = (pointer[j + 1] << 8) + pointer[j]; + lfn->name2[offset + i] = c; } - if (pointer[0] & 0x40) - lfn->len = offset + strlen((char*)lfn->name + offset); + if (pointer[0] & 0x40) { + /* first entry; set len */ + lfn->len = offset + i; + } + if ((pointer[0] & 0x3f) == 0x01) { + /* last entry; finalize entry */ + glong olen; + gchar *utf8 = g_utf16_to_utf8(lfn->name2, lfn->len, NULL, &olen, NULL); + if (!utf8) { + return -4; + } + lfn->len = olen; + memcpy(lfn->name, utf8, olen + 1); + g_free(utf8); + } return 0; } @@ -1722,12 +1754,14 @@ static int parse_short_name(BDRVVVFATState* s, for (j = 7; j >= 0 && direntry->name[j] == ' '; j--); for (i = 0; i <= j; i++) { - if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f) + uint8_t c = direntry->name[i]; + if (c != to_valid_short_char(c)) { return -1; - else if (s->downcase_short_names) + } else if (s->downcase_short_names) { lfn->name[i] = qemu_tolower(direntry->name[i]); - else + } else { lfn->name[i] = direntry->name[i]; + } } for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) { @@ -1737,7 +1771,7 @@ static int parse_short_name(BDRVVVFATState* s, lfn->name[i + j + 1] = '\0'; for (;j >= 0; j--) { uint8_t c = direntry->name[8 + j]; - if (c <= ' ' || c > 0x7f) { + if (c != to_valid_short_char(c)) { return -2; } else if (s->downcase_short_names) { lfn->name[i + j] = qemu_tolower(c); @@ -1748,8 +1782,8 @@ static int parse_short_name(BDRVVVFATState* s, } else lfn->name[i + j + 1] = '\0'; - if (lfn->name[0] == 0x05) { - lfn->name[0] = 0xe5; + if (lfn->name[0] == DIR_KANJI_FAKE) { + lfn->name[0] = DIR_KANJI; } lfn->len = strlen((char*)lfn->name); @@ -2955,7 +2989,6 @@ DLOG(checkpoint()); /* * Some sanity checks: * - do not allow writing to the boot sector - * - do not allow to write non-ASCII filenames */ if (sector_num < s->offset_to_fat) @@ -2989,13 +3022,8 @@ DLOG(checkpoint()); direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num)); for (k = 0; k < (end - begin) * 0x10; k++) { - /* do not allow non-ASCII filenames */ - if (parse_long_name(&lfn, direntries + k) < 0) { - fprintf(stderr, "Warning: non-ASCII filename\n"); - return -1; - } /* no access to the direntry of a read-only file */ - else if (is_short_name(direntries+k) && + if (is_short_name(direntries + k) && (direntries[k].attributes & 1)) { if (memcmp(direntries + k, array_get(&(s->directory), dir_index + k), diff --git a/blockdev.c b/blockdev.c index 7f53cc8bb3..6469f161df 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1710,7 +1710,8 @@ static void external_snapshot_prepare(BlkActionState *common, } flags = state->old_bs->open_flags; - flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ); + flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_COPY_ON_READ); + flags |= BDRV_O_NO_BACKING; /* create new image w/backing file */ mode = s->has_mode ? s->mode : NEW_IMAGE_MODE_ABSOLUTE_PATHS; @@ -1735,8 +1736,6 @@ static void external_snapshot_prepare(BlkActionState *common, qdict_put_str(options, "node-name", snapshot_node_name); } qdict_put_str(options, "driver", format); - - flags |= BDRV_O_NO_BACKING; } state->new_bs = bdrv_open(new_image_file, snapshot_ref, options, flags, @@ -3548,6 +3547,9 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) backing_mode = MIRROR_OPEN_BACKING_CHAIN; } + /* Don't open backing image in create() */ + flags |= BDRV_O_NO_BACKING; + if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source) && arg->mode != NEW_IMAGE_MODE_EXISTING) { @@ -3587,8 +3589,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) /* Mirroring takes care of copy-on-write using the source's backing * file. */ - target_bs = bdrv_open(arg->target, NULL, options, - flags | BDRV_O_NO_BACKING, errp); + target_bs = bdrv_open(arg->target, NULL, options, flags, errp); if (!target_bs) { goto out; } diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c index 7ae4e86646..49eebb5412 100644 --- a/fsdev/qemu-fsdev-throttle.c +++ b/fsdev/qemu-fsdev-throttle.c @@ -86,7 +86,7 @@ void fsdev_throttle_init(FsThrottle *fst) fsdev_throttle_read_timer_cb, fsdev_throttle_write_timer_cb, fst); - throttle_config(&fst->ts, &fst->tt, &fst->cfg); + throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg); qemu_co_queue_init(&fst->throttled_reqs[0]); qemu_co_queue_init(&fst->throttled_reqs[1]); } @@ -401,16 +401,16 @@ static void print_block_info(Monitor *mon, BlockInfo *info, assert(!info || !info->has_inserted || info->inserted == inserted); - if (info) { + if (info && *info->device) { monitor_printf(mon, "%s", info->device); if (inserted && inserted->has_node_name) { monitor_printf(mon, " (%s)", inserted->node_name); } } else { - assert(inserted); + assert(info || inserted); monitor_printf(mon, "%s", - inserted->has_node_name - ? inserted->node_name + inserted && inserted->has_node_name ? inserted->node_name + : info && info->has_qdev ? info->qdev : "<anonymous>"); } @@ -425,6 +425,9 @@ static void print_block_info(Monitor *mon, BlockInfo *info, } if (info) { + if (info->has_qdev) { + monitor_printf(mon, " Attached to: %s\n", info->qdev); + } if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) { monitor_printf(mon, " I/O status: %s\n", BlockDeviceIoStatus_lookup[info->io_status]); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 299e592fa2..cc2f5bd280 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -164,6 +164,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); IDEState *s = bus->ifs + dev->unit; Error *err = NULL; + int ret; if (!dev->conf.blk) { if (kind != IDE_CD) { @@ -172,6 +173,8 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) } else { /* Anonymous BlockBackend for an empty drive */ dev->conf.blk = blk_new(0, BLK_PERM_ALL); + ret = blk_attach_dev(dev->conf.blk, &dev->qdev); + assert(ret == 0); } } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index a53f058621..5f1e5e8070 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2384,9 +2384,14 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp) static void scsi_cd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + int ret; if (!dev->conf.blk) { + /* Anonymous BlockBackend for an empty drive. As we put it into + * dev->conf, qdev takes care of detaching on unplug. */ dev->conf.blk = blk_new(0, BLK_PERM_ALL); + ret = blk_attach_dev(dev->conf.blk, &dev->qdev); + assert(ret == 0); } s->qdev.blocksize = 2048; diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h index 9109657609..d056008c18 100644 --- a/include/qemu/throttle.h +++ b/include/qemu/throttle.h @@ -139,7 +139,7 @@ bool throttle_enabled(ThrottleConfig *cfg); bool throttle_is_valid(ThrottleConfig *cfg, Error **errp); void throttle_config(ThrottleState *ts, - ThrottleTimers *tt, + QEMUClockType clock_type, ThrottleConfig *cfg); void throttle_get_config(ThrottleState *ts, ThrottleConfig *cfg); diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index d9ea0cdb0f..4a3730596b 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -100,6 +100,7 @@ void blk_remove_all_bs(void); const char *blk_name(const BlockBackend *blk); BlockBackend *blk_by_name(const char *name); BlockBackend *blk_next(BlockBackend *blk); +BlockBackend *blk_all_next(BlockBackend *blk); bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp); void monitor_remove_blk(BlockBackend *blk); @@ -126,6 +127,7 @@ int blk_attach_dev(BlockBackend *blk, DeviceState *dev); void blk_attach_dev_legacy(BlockBackend *blk, void *dev); void blk_detach_dev(BlockBackend *blk, void *dev); void *blk_get_attached_dev(BlockBackend *blk); +char *blk_get_attached_dev_id(BlockBackend *blk); BlockBackend *blk_by_dev(void *dev); BlockBackend *blk_by_qdev_id(const char *id, Error **errp); void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque); diff --git a/qapi/block-core.json b/qapi/block-core.json index c437aa50ef..ff8e2ba0cb 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -457,6 +457,9 @@ # # @device: The device name associated with the virtual device. # +# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block +# device. (since 2.10) +# # @type: This field is returned only for compatibility reasons, it should # not be used (always returns 'unknown') # @@ -482,7 +485,7 @@ # Since: 0.14.0 ## { 'struct': 'BlockInfo', - 'data': {'device': 'str', 'type': 'str', 'removable': 'bool', + 'data': {'device': 'str', '*qdev': 'str', 'type': 'str', 'removable': 'bool', 'locked': 'bool', '*inserted': 'BlockDeviceInfo', '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus', '*dirty-bitmaps': ['BlockDirtyInfo'] } } @@ -577,6 +580,7 @@ # } # } # }, +# "qdev": "ide_disk", # "type":"unknown" # }, # { @@ -584,12 +588,15 @@ # "device":"ide1-cd0", # "locked":false, # "removable":true, +# "qdev": "/machine/unattached/device[23]", +# "tray_open": false, # "type":"unknown" # }, # { # "device":"floppy0", # "locked":false, # "removable":true, +# "qdev": "/machine/unattached/device[20]", # "type":"unknown" # }, # { diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index ac5946bc4f..3763f13625 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -22,9 +22,9 @@ STEXI ETEXI DEF("create", img_create, - "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-o options] filename [size]") + "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-u] [-o options] filename [size]") STEXI -@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}] +@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-u] [-o @var{options}] @var{filename} [@var{size}] ETEXI DEF("commit", img_commit, diff --git a/qemu-img.c b/qemu-img.c index 182e697f81..eb32b93e90 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -150,9 +150,11 @@ static void QEMU_NORETURN help(void) " 'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n" " instead\n" " '-c' indicates that target image must be compressed (qcow format only)\n" - " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n" - " match exactly. The image doesn't need a working backing file before\n" - " rebasing in this case (useful for renaming the backing file)\n" + " '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n" + " new backing file match exactly. The image doesn't need a working\n" + " backing file before rebasing in this case (useful for renaming the\n" + " backing file). For image creation, allow creating without attempting\n" + " to open the backing file.\n" " '-h' with or without a command shows this help and lists the supported formats\n" " '-p' show progress of command (only certain commands)\n" " '-q' use Quiet mode - do not print any output (except errors)\n" @@ -429,6 +431,7 @@ static int img_create(int argc, char **argv) char *options = NULL; Error *local_err = NULL; bool quiet = false; + int flags = 0; for(;;) { static const struct option long_options[] = { @@ -436,7 +439,7 @@ static int img_create(int argc, char **argv) {"object", required_argument, 0, OPTION_OBJECT}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, ":F:b:f:ho:q", + c = getopt_long(argc, argv, ":F:b:f:ho:qu", long_options, NULL); if (c == -1) { break; @@ -476,6 +479,9 @@ static int img_create(int argc, char **argv) case 'q': quiet = true; break; + case 'u': + flags |= BDRV_O_NO_BACKING; + break; case OPTION_OBJECT: { QemuOpts *opts; opts = qemu_opts_parse_noisily(&qemu_object_opts, @@ -528,7 +534,7 @@ static int img_create(int argc, char **argv) } bdrv_img_create(filename, fmt, base_filename, base_fmt, - options, img_size, 0, quiet, &local_err); + options, img_size, flags, quiet, &local_err); if (local_err) { error_reportf_err(local_err, "%s: ", filename); goto fail; diff --git a/qemu-img.texi b/qemu-img.texi index f11f6036ad..72dabd6b3e 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -233,7 +233,7 @@ If @code{-r} is specified, exit codes representing the image state refer to the state after (the attempt at) repairing it. That is, a successful @code{-r all} will yield the exit code 0, independently of the image state before. -@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}] +@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-u] [-o @var{options}] @var{filename} [@var{size}] Create the new disk image @var{filename} of size @var{size} and format @var{fmt}. Depending on the file format, you can add one or more @var{options} @@ -244,6 +244,13 @@ only the differences from @var{backing_file}. No size needs to be specified in this case. @var{backing_file} will never be modified unless you use the @code{commit} monitor command (or qemu-img commit). +Note that a given backing file will be opened to check that it is valid. Use +the @code{-u} option to enable unsafe backing file mode, which means that the +image will be created even if the associated backing file cannot be opened. A +matching backing file must be created or additional options be used to make the +backing file specification valid when you want to use an image created this +way. + The size can also be specified using the @var{size} option with @code{-o}, it doesn't need to be specified separately in this case. diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 index 38d23fce6b..5d4ca4bc61 100755 --- a/tests/qemu-iotests/067 +++ b/tests/qemu-iotests/067 @@ -137,6 +137,19 @@ run_qemu <<EOF { "execute": "quit" } EOF +echo +echo === Empty drive with -device and device_del === +echo + +run_qemu -device virtio-scsi-pci -device scsi-cd,id=cd0 <<EOF +{ "execute": "qmp_capabilities" } +{ "execute": "query-block" } +{ "execute": "device_del", "arguments": { "id": "cd0" } } +{ "execute": "system_reset" } +{ "execute": "query-block" } +{ "execute": "quit" } +EOF + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 782eae27a0..bd70557ddc 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -57,6 +57,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false }, + "qdev": "/machine/peripheral/virtio0/virtio-backend", "type": "unknown" } ] @@ -415,4 +416,43 @@ Testing: "return": { } } + +=== Empty drive with -device and device_del === + +Testing: -device virtio-scsi-pci -device scsi-cd,id=cd0 +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": [ + { + "device": "", + "locked": false, + "removable": true, + "qdev": "cd0", + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": [ + ] +} +{ + "return": { + } +} *** done diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082 index ad1d9fadc1..d5c83d45ed 100755 --- a/tests/qemu-iotests/082 +++ b/tests/qemu-iotests/082 @@ -85,8 +85,8 @@ run_qemu_img create -f $IMGFMT -o cluster_size=4k -o help "$TEST_IMG" $size run_qemu_img create -f $IMGFMT -o cluster_size=4k -o \? "$TEST_IMG" $size # Looks like a help option, but is part of the backing file name -run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG",,help "$TEST_IMG" $size -run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG",,\? "$TEST_IMG" $size +run_qemu_img create -f $IMGFMT -u -o backing_file="$TEST_IMG",,help "$TEST_IMG" $size +run_qemu_img create -f $IMGFMT -u -o backing_file="$TEST_IMG",,\? "$TEST_IMG" $size # Try to trick qemu-img into creating escaped commas run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG", -o help "$TEST_IMG" $size diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out index dbed67f2ba..1527fbe1b7 100644 --- a/tests/qemu-iotests/082.out +++ b/tests/qemu-iotests/082.out @@ -210,10 +210,10 @@ lazy_refcounts Postpone refcount updates refcount_bits Width of a reference count entry in bits nocow Turn off copy-on-write (valid only on btrfs) -Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M +Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16 -Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M +Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085 index b97adcd8db..71efe50d34 100755 --- a/tests/qemu-iotests/085 +++ b/tests/qemu-iotests/085 @@ -104,7 +104,7 @@ function add_snapshot_image() { base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}" snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}" - _make_test_img -b "${base_image}" "$size" + _make_test_img -u -b "${base_image}" "$size" mv "${TEST_IMG}" "${snapshot_file}" do_blockdev_add "$1" "'backing': '', " "${snapshot_file}" } diff --git a/tests/qemu-iotests/111.out b/tests/qemu-iotests/111.out index 683c01a679..5279c462fc 100644 --- a/tests/qemu-iotests/111.out +++ b/tests/qemu-iotests/111.out @@ -1,3 +1,4 @@ QA output created by 111 qemu-img: TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT.inexistent': No such file or directory +Could not open backing image to determine size. *** done diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139 index 175d8f0008..9ff51d9647 100644 --- a/tests/qemu-iotests/139 +++ b/tests/qemu-iotests/139 @@ -65,7 +65,7 @@ class TestBlockdevDel(iotests.QMPTestCase): # Add a BlockDriverState that will be used as overlay for the base_img BDS def addBlockDriverStateOverlay(self, node): self.checkBlockDriverState(node, False) - iotests.qemu_img('create', '-f', iotests.imgfmt, + iotests.qemu_img('create', '-u', '-f', iotests.imgfmt, '-b', base_img, new_img, '1M') opts = {'driver': iotests.imgfmt, 'node-name': node, diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156 index d799b73e1e..2c4a06e2d8 100755 --- a/tests/qemu-iotests/156 +++ b/tests/qemu-iotests/156 @@ -66,7 +66,7 @@ _send_qemu_cmd $QEMU_HANDLE \ 'return' # Create snapshot -TEST_IMG="$TEST_IMG.overlay" _make_test_img -b "$TEST_IMG" 1M +TEST_IMG="$TEST_IMG.overlay" _make_test_img -u -b "$TEST_IMG" 1M _send_qemu_cmd $QEMU_HANDLE \ "{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'source', diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158 index 823c12002e..24ac600a4a 100755 --- a/tests/qemu-iotests/158 +++ b/tests/qemu-iotests/158 @@ -66,7 +66,7 @@ echo "== verify pattern ==" $QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir echo "== create overlay ==" -_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size +_make_test_img -u --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size echo echo "== writing part of a cluster ==" diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186 new file mode 100755 index 0000000000..ab83ee402a --- /dev/null +++ b/tests/qemu-iotests/186 @@ -0,0 +1,147 @@ +#!/bin/bash +# +# Test 'info block' with all kinds of configurations +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +if [ "$QEMU_DEFAULT_MACHINE" != "pc" ]; then + _notrun "Requires a PC machine" +fi + +function do_run_qemu() +{ + echo Testing: "$@" + + ( + if ! test -t 0; then + while read cmd; do + echo $cmd + done + fi + echo quit + ) | $QEMU -S -nodefaults -display none -device virtio-scsi-pci -monitor stdio "$@" + echo +} + +function check_info_block() +{ + echo "info block" | + QEMU_OPTIONS="" do_run_qemu "$@" | _filter_win32 | _filter_hmp | + _filter_qemu | _filter_generated_node_ids +} + + +size=64M +_make_test_img $size + +removable="floppy ide-cd scsi-cd" +fixed="ide-hd scsi-hd virtio-blk-pci" + +echo +echo "=== Empty drives ===" +echo + +for dev in $removable; do + check_info_block -device $dev + check_info_block -device $dev,id=qdev_id +done + +echo +echo "=== -blockdev/-device=<node-name> ===" +echo + +for dev in $fixed $removable; do + check_info_block -blockdev driver=null-co,node-name=null -device $dev,drive=null + check_info_block -blockdev driver=null-co,node-name=null -device $dev,drive=null,id=qdev_id +done + +echo +echo "=== -drive if=none/-device=<node-name> ===" +echo + +# This creates two BlockBackends that will show up in 'info block'! +# A monitor-owned one from -drive, and anonymous one from -device +for dev in $fixed $removable; do + check_info_block -drive if=none,driver=null-co,node-name=null -device $dev,drive=null,id=qdev_id +done + +echo +echo "=== -drive if=none/-device=<bb-name> (with medium) ===" +echo + +for dev in $fixed $removable; do + check_info_block -drive if=none,driver=null-co,node-name=null -device $dev,drive=none0 + check_info_block -drive if=none,driver=null-co,node-name=null -device $dev,drive=none0,id=qdev_id +done + +echo +echo "=== -drive if=none/-device=<bb-name> (without medium) ===" +echo + +check_info_block -drive if=none + +for dev in $removable; do + check_info_block -drive if=none -device $dev,drive=none0 + check_info_block -drive if=none -device $dev,drive=none0,id=qdev_id +done + +echo +echo "=== -drive if=... ===" +echo + +check_info_block -drive if=floppy +check_info_block -drive if=floppy,driver=null-co + +check_info_block -drive if=ide,driver=null-co +check_info_block -drive if=ide,media=cdrom +check_info_block -drive if=ide,driver=null-co,media=cdrom + +check_info_block -drive if=scsi,driver=null-co +check_info_block -drive if=scsi,media=cdrom +check_info_block -drive if=scsi,driver=null-co,media=cdrom + +check_info_block -drive if=virtio,driver=null-co + +check_info_block -drive if=pflash,driver=null-co,size=1M + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/186.out b/tests/qemu-iotests/186.out new file mode 100644 index 0000000000..b963b12d64 --- /dev/null +++ b/tests/qemu-iotests/186.out @@ -0,0 +1,489 @@ +QA output created by 186 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + +=== Empty drives === + +Testing: -device floppy +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +/machine/peripheral-anon/device[1]: [not inserted] + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -device floppy,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +qdev_id: [not inserted] + Attached to: qdev_id + Removable device: not locked, tray closed +(qemu) quit + +Testing: -device ide-cd +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +/machine/peripheral-anon/device[1]: [not inserted] + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -device ide-cd,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +qdev_id: [not inserted] + Attached to: qdev_id + Removable device: not locked, tray closed +(qemu) quit + +Testing: -device scsi-cd +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +/machine/peripheral-anon/device[1]: [not inserted] + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -device scsi-cd,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +qdev_id: [not inserted] + Attached to: qdev_id + Removable device: not locked, tray closed +(qemu) quit + + +=== -blockdev/-device=<node-name> === + +Testing: -blockdev driver=null-co,node-name=null -device ide-hd,drive=null +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device ide-hd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: qdev_id + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device scsi-hd,drive=null +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device scsi-hd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: qdev_id + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device virtio-blk-pci,drive=null +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1]/virtio-backend + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device virtio-blk-pci,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral/qdev_id/virtio-backend + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device floppy,drive=null +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device floppy,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device ide-cd,drive=null +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device ide-cd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device scsi-cd,drive=null +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -blockdev driver=null-co,node-name=null -device scsi-cd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +null: null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + + +=== -drive if=none/-device=<node-name> === + +Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Removable device: not locked, tray closed + Cache mode: writeback + +null: null-co:// (null-co) + Attached to: qdev_id + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Removable device: not locked, tray closed + Cache mode: writeback + +null: null-co:// (null-co) + Attached to: qdev_id + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Removable device: not locked, tray closed + Cache mode: writeback + +null: null-co:// (null-co) + Attached to: /machine/peripheral/qdev_id/virtio-backend + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Removable device: not locked, tray closed + Cache mode: writeback + +null: null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Removable device: not locked, tray closed + Cache mode: writeback + +null: null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=null,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Removable device: not locked, tray closed + Cache mode: writeback + +null: null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + + +=== -drive if=none/-device=<bb-name> (with medium) === + +Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: qdev_id + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: qdev_id + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1]/virtio-backend + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral/qdev_id/virtio-backend + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0 (null): null-co:// (null-co) + Attached to: qdev_id + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + + +=== -drive if=none/-device=<bb-name> (without medium) === + +Testing: -drive if=none +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=none -device floppy,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=none -device floppy,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Attached to: qdev_id + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=none -device ide-cd,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=none -device ide-cd,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Attached to: qdev_id + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=none -device scsi-cd,drive=none0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Attached to: /machine/peripheral-anon/device[1] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=none -device scsi-cd,drive=none0,id=qdev_id +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +none0: [not inserted] + Attached to: qdev_id + Removable device: not locked, tray closed +(qemu) quit + + +=== -drive if=... === + +Testing: -drive if=floppy +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +floppy0: [not inserted] + Attached to: /machine/unattached/device[17] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=floppy,driver=null-co +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +floppy0 (NODE_NAME): null-co:// (null-co) + Attached to: /machine/unattached/device[17] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=ide,driver=null-co +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +ide0-hd0 (NODE_NAME): null-co:// (null-co) + Attached to: /machine/unattached/device[18] + Cache mode: writeback +(qemu) quit + +Testing: -drive if=ide,media=cdrom +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +ide0-cd0: [not inserted] + Attached to: /machine/unattached/device[18] + Removable device: not locked, tray closed +(qemu) quit + +Testing: -drive if=ide,driver=null-co,media=cdrom +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +ide0-cd0 (NODE_NAME): null-co:// (null-co, read-only) + Attached to: /machine/unattached/device[18] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +warning: qemu-system-x86_64: -drive if=scsi,driver=null-co: bus=0,unit=0 is deprecated with this machine type +Testing: -drive if=scsi,driver=null-co +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +scsi0-hd0 (NODE_NAME): null-co:// (null-co) + Attached to: /machine/unattached/device[27]/scsi.0/legacy[0] + Cache mode: writeback +(qemu) quit + +warning: qemu-system-x86_64: -drive if=scsi,media=cdrom: bus=0,unit=0 is deprecated with this machine type +Testing: -drive if=scsi,media=cdrom +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +scsi0-cd0: [not inserted] + Attached to: /machine/unattached/device[27]/scsi.0/legacy[0] + Removable device: not locked, tray closed +(qemu) quit + +warning: qemu-system-x86_64: -drive if=scsi,driver=null-co,media=cdrom: bus=0,unit=0 is deprecated with this machine type +Testing: -drive if=scsi,driver=null-co,media=cdrom +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +scsi0-cd0 (NODE_NAME): null-co:// (null-co, read-only) + Attached to: /machine/unattached/device[27]/scsi.0/legacy[0] + Removable device: not locked, tray closed + Cache mode: writeback +(qemu) quit + +Testing: -drive if=virtio,driver=null-co +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +virtio0 (NODE_NAME): null-co:// (null-co) + Attached to: /machine/peripheral-anon/device[1]/virtio-backend + Cache mode: writeback +(qemu) quit + +Testing: -drive if=pflash,driver=null-co,size=1M +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) info block +pflash0 (NODE_NAME): json:{"driver": "null-co", "size": "1M"} (null-co) + Attached to: /machine/unattached/device[2] + Cache mode: writeback +(qemu) quit + +*** done diff --git a/tests/qemu-iotests/189 b/tests/qemu-iotests/189 index 54ad980a4e..e695475722 100755 --- a/tests/qemu-iotests/189 +++ b/tests/qemu-iotests/189 @@ -66,7 +66,7 @@ echo "== verify pattern ==" $QEMU_IO --object $SECRET0 -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir echo "== create overlay ==" -_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -b "$TEST_IMG_BASE" $size +_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -u -b "$TEST_IMG_BASE" $size echo echo "== writing part of a cluster ==" diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 2aba585287..0961f8cc4e 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -181,5 +181,6 @@ 182 rw auto quick 183 rw auto migration 185 rw auto +186 rw auto 188 rw auto quick 189 rw auto quick diff --git a/tests/test-throttle.c b/tests/test-throttle.c index a9201b1fea..768f11dfed 100644 --- a/tests/test-throttle.c +++ b/tests/test-throttle.c @@ -228,7 +228,7 @@ static void test_config_functions(void) read_timer_cb, write_timer_cb, &ts); /* structure reset by throttle_init previous_leak should be null */ g_assert(!ts.previous_leak); - throttle_config(&ts, &tt, &orig_cfg); + throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg); /* has previous leak been initialized by throttle_config ? */ g_assert(ts.previous_leak); @@ -486,7 +486,7 @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */ throttle_init(&ts); throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts); - throttle_config(&ts, &tt, &cfg); + throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg); /* account a read */ throttle_account(&ts, false, size); diff --git a/util/throttle.c b/util/throttle.c index 3570ed25fc..b2a52b8b34 100644 --- a/util/throttle.c +++ b/util/throttle.c @@ -388,22 +388,14 @@ static void throttle_unfix_bucket(LeakyBucket *bkt) } } -/* take care of canceling a timer */ -static void throttle_cancel_timer(QEMUTimer *timer) -{ - assert(timer != NULL); - - timer_del(timer); -} - /* Used to configure the throttle * * @ts: the throttle state we are working on - * @tt: the throttle timers we use in this aio context + * @clock_type: the group's clock_type * @cfg: the config to set */ void throttle_config(ThrottleState *ts, - ThrottleTimers *tt, + QEMUClockType clock_type, ThrottleConfig *cfg) { int i; @@ -414,11 +406,7 @@ void throttle_config(ThrottleState *ts, throttle_fix_bucket(&ts->cfg.buckets[i]); } - ts->previous_leak = qemu_clock_get_ns(tt->clock_type); - - for (i = 0; i < 2; i++) { - throttle_cancel_timer(tt->timers[i]); - } + ts->previous_leak = qemu_clock_get_ns(clock_type); } /* used to get config |