diff options
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 356 |
1 files changed, 27 insertions, 329 deletions
@@ -99,9 +99,6 @@ 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; @@ -328,28 +325,40 @@ BlockDriver *bdrv_find_format(const char *format_name) return NULL; } -static int bdrv_is_whitelisted(BlockDriver *drv) +static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only) { - static const char *whitelist[] = { - CONFIG_BDRV_WHITELIST + static const char *whitelist_rw[] = { + CONFIG_BDRV_RW_WHITELIST + }; + static const char *whitelist_ro[] = { + CONFIG_BDRV_RO_WHITELIST }; const char **p; - if (!whitelist[0]) + if (!whitelist_rw[0] && !whitelist_ro[0]) { return 1; /* no whitelist, anything goes */ + } - for (p = whitelist; *p; p++) { + for (p = whitelist_rw; *p; p++) { if (!strcmp(drv->format_name, *p)) { return 1; } } + if (read_only) { + for (p = whitelist_ro; *p; p++) { + if (!strcmp(drv->format_name, *p)) { + return 1; + } + } + } return 0; } -BlockDriver *bdrv_find_whitelisted_format(const char *format_name) +BlockDriver *bdrv_find_whitelisted_format(const char *format_name, + bool read_only) { BlockDriver *drv = bdrv_find_format(format_name); - return drv && bdrv_is_whitelisted(drv) ? drv : NULL; + return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL; } typedef struct CreateCo { @@ -684,10 +693,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name); - if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { - return -ENOTSUP; - } - /* bdrv_open() with directly using a protocol as drv. This layer is already * opened, so assign it to bs (while file becomes a closed BlockDriverState) * and return immediately. */ @@ -698,9 +703,15 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, bs->open_flags = flags; bs->buffer_alignment = 512; + open_flags = bdrv_open_flags(bs, flags); + bs->read_only = !(open_flags & BDRV_O_RDWR); + + if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) { + return -ENOTSUP; + } assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */ - if ((flags & BDRV_O_RDWR) && (flags & BDRV_O_COPY_ON_READ)) { + if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) { bdrv_enable_copy_on_read(bs); } @@ -714,9 +725,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, bs->opaque = g_malloc0(drv->instance_size); bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB); - open_flags = bdrv_open_flags(bs, flags); - - bs->read_only = !(open_flags & BDRV_O_RDWR); /* Open the image, either directly or using a protocol */ if (drv->bdrv_file_open) { @@ -801,7 +809,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, /* Find the right block driver */ drvname = qdict_get_try_str(options, "driver"); if (drvname) { - drv = bdrv_find_whitelisted_format(drvname); + drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); qdict_del(options, "driver"); } else if (filename) { drv = bdrv_find_protocol(filename); @@ -1357,9 +1365,6 @@ void bdrv_close(BlockDriverState *bs) notifier_list_notify(&bs->close_notifiers, bs); if (bs->drv) { - if (bs == bs_snapshots) { - bs_snapshots = NULL; - } if (bs->backing_hd) { bdrv_delete(bs->backing_hd); bs->backing_hd = NULL; @@ -1591,7 +1596,6 @@ void bdrv_delete(BlockDriverState *bs) bdrv_close(bs); - assert(bs != bs_snapshots); g_free(bs); } @@ -1635,9 +1639,6 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, { bs->dev_ops = ops; bs->dev_opaque = opaque; - if (bdrv_dev_has_removable_media(bs) && bs == bs_snapshots) { - bs_snapshots = NULL; - } } void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, @@ -3099,128 +3100,6 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, return data.ret; } -BlockInfo *bdrv_query_info(BlockDriverState *bs) -{ - BlockInfo *info = g_malloc0(sizeof(*info)); - info->device = g_strdup(bs->device_name); - info->type = g_strdup("unknown"); - info->locked = bdrv_dev_is_medium_locked(bs); - info->removable = bdrv_dev_has_removable_media(bs); - - if (bdrv_dev_has_removable_media(bs)) { - info->has_tray_open = true; - info->tray_open = bdrv_dev_is_tray_open(bs); - } - - if (bdrv_iostatus_is_enabled(bs)) { - info->has_io_status = true; - info->io_status = bs->iostatus; - } - - if (bs->dirty_bitmap) { - info->has_dirty = true; - info->dirty = g_malloc0(sizeof(*info->dirty)); - info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE; - info->dirty->granularity = - ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap)); - } - - if (bs->drv) { - info->has_inserted = true; - info->inserted = g_malloc0(sizeof(*info->inserted)); - info->inserted->file = g_strdup(bs->filename); - info->inserted->ro = bs->read_only; - info->inserted->drv = g_strdup(bs->drv->format_name); - info->inserted->encrypted = bs->encrypted; - info->inserted->encryption_key_missing = bdrv_key_required(bs); - - if (bs->backing_file[0]) { - info->inserted->has_backing_file = true; - info->inserted->backing_file = g_strdup(bs->backing_file); - } - - info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs); - - if (bs->io_limits_enabled) { - info->inserted->bps = - bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; - info->inserted->bps_rd = - bs->io_limits.bps[BLOCK_IO_LIMIT_READ]; - info->inserted->bps_wr = - bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE]; - info->inserted->iops = - bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; - info->inserted->iops_rd = - bs->io_limits.iops[BLOCK_IO_LIMIT_READ]; - info->inserted->iops_wr = - bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; - } - } - return info; -} - -BlockInfoList *qmp_query_block(Error **errp) -{ - BlockInfoList *head = NULL, **p_next = &head; - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - BlockInfoList *info = g_malloc0(sizeof(*info)); - info->value = bdrv_query_info(bs); - - *p_next = info; - p_next = &info->next; - } - - return head; -} - -BlockStats *bdrv_query_stats(const BlockDriverState *bs) -{ - BlockStats *s; - - s = g_malloc0(sizeof(*s)); - - if (bs->device_name[0]) { - s->has_device = true; - s->device = g_strdup(bs->device_name); - } - - s->stats = g_malloc0(sizeof(*s->stats)); - s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ]; - s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE]; - s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ]; - s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE]; - s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE; - s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH]; - s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE]; - s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ]; - s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH]; - - if (bs->file) { - s->has_parent = true; - s->parent = bdrv_query_stats(bs->file); - } - - return s; -} - -BlockStatsList *qmp_query_blockstats(Error **errp) -{ - BlockStatsList *head = NULL, **p_next = &head; - BlockDriverState *bs; - - QTAILQ_FOREACH(bs, &bdrv_states, list) { - BlockStatsList *info = g_malloc0(sizeof(*info)); - info->value = bdrv_query_stats(bs); - - *p_next = info; - p_next = &info->next; - } - - return head; -} - const char *bdrv_get_encrypted_filename(BlockDriverState *bs) { if (bs->backing_hd && bs->backing_hd->encrypted) @@ -3356,129 +3235,11 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag) return false; } -/**************************************************************/ -/* handling of snapshots */ - -int bdrv_can_snapshot(BlockDriverState *bs) -{ - BlockDriver *drv = bs->drv; - if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { - return 0; - } - - if (!drv->bdrv_snapshot_create) { - if (bs->file != NULL) { - return bdrv_can_snapshot(bs->file); - } - return 0; - } - - return 1; -} - int bdrv_is_snapshot(BlockDriverState *bs) { return !!(bs->open_flags & BDRV_O_SNAPSHOT); } -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) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - if (drv->bdrv_snapshot_create) - return drv->bdrv_snapshot_create(bs, sn_info); - if (bs->file) - return bdrv_snapshot_create(bs->file, sn_info); - return -ENOTSUP; -} - -int bdrv_snapshot_goto(BlockDriverState *bs, - const char *snapshot_id) -{ - BlockDriver *drv = bs->drv; - int ret, open_ret; - - if (!drv) - return -ENOMEDIUM; - if (drv->bdrv_snapshot_goto) - return drv->bdrv_snapshot_goto(bs, snapshot_id); - - if (bs->file) { - drv->bdrv_close(bs); - ret = bdrv_snapshot_goto(bs->file, snapshot_id); - open_ret = drv->bdrv_open(bs, NULL, bs->open_flags); - if (open_ret < 0) { - bdrv_delete(bs->file); - bs->drv = NULL; - return open_ret; - } - return ret; - } - - return -ENOTSUP; -} - -int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - if (drv->bdrv_snapshot_delete) - return drv->bdrv_snapshot_delete(bs, snapshot_id); - if (bs->file) - return bdrv_snapshot_delete(bs->file, snapshot_id); - return -ENOTSUP; -} - -int bdrv_snapshot_list(BlockDriverState *bs, - QEMUSnapshotInfo **psn_info) -{ - BlockDriver *drv = bs->drv; - if (!drv) - return -ENOMEDIUM; - if (drv->bdrv_snapshot_list) - return drv->bdrv_snapshot_list(bs, psn_info); - if (bs->file) - return bdrv_snapshot_list(bs->file, psn_info); - return -ENOTSUP; -} - -int bdrv_snapshot_load_tmp(BlockDriverState *bs, - const char *snapshot_name) -{ - BlockDriver *drv = bs->drv; - if (!drv) { - return -ENOMEDIUM; - } - if (!bs->read_only) { - return -EINVAL; - } - if (drv->bdrv_snapshot_load_tmp) { - return drv->bdrv_snapshot_load_tmp(bs, snapshot_name); - } - return -ENOTSUP; -} - /* backing_file can either be relative, or absolute, or a protocol. If it is * relative, it must be relative to the chain. So, passing in bs->filename * from a BDS as backing_file should not be done, as that may be relative to @@ -3574,69 +3335,6 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs) return curr_bs; } -#define NB_SUFFIXES 4 - -char *get_human_readable_size(char *buf, int buf_size, int64_t size) -{ - static const char suffixes[NB_SUFFIXES] = "KMGT"; - int64_t base; - int i; - - if (size <= 999) { - snprintf(buf, buf_size, "%" PRId64, size); - } else { - base = 1024; - for(i = 0; i < NB_SUFFIXES; i++) { - if (size < (10 * base)) { - snprintf(buf, buf_size, "%0.1f%c", - (double)size / base, - suffixes[i]); - break; - } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { - snprintf(buf, buf_size, "%" PRId64 "%c", - ((size + (base >> 1)) / base), - suffixes[i]); - break; - } - base = base * 1024; - } - } - return buf; -} - -char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) -{ - char buf1[128], date_buf[128], clock_buf[128]; - struct tm tm; - time_t ti; - int64_t secs; - - if (!sn) { - snprintf(buf, buf_size, - "%-10s%-20s%7s%20s%15s", - "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); - } else { - ti = sn->date_sec; - localtime_r(&ti, &tm); - strftime(date_buf, sizeof(date_buf), - "%Y-%m-%d %H:%M:%S", &tm); - secs = sn->vm_clock_nsec / 1000000000; - snprintf(clock_buf, sizeof(clock_buf), - "%02d:%02d:%02d.%03d", - (int)(secs / 3600), - (int)((secs / 60) % 60), - (int)(secs % 60), - (int)((sn->vm_clock_nsec / 1000000) % 1000)); - snprintf(buf, buf_size, - "%-10s%-20s%7s%20s%15s", - sn->id_str, sn->name, - get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size), - date_buf, - clock_buf); - } - return buf; -} - /**************************************************************/ /* async I/Os */ |