Merge remote-tracking branch 'kwolf/for-anthony' into staging
* kwolf/for-anthony: block: Don't forget to delete temporary file Don't require encryption password for 'qemu-img info' command qemu-img: Add json output option to the info command. qapi: Add SnapshotInfo and ImageInfo. ahci: properly reset PxCMD on HBA reset block: fix block tray status vdi: Fix warning from clang block/curl: Fix wrong free statement ide: Fix error messages from static code analysis (no real error) ATAPI: STARTSTOPUNIT only eject/load media if powercondition is 0 sheepdog: fix savevm and loadvm
This commit is contained in:
commit
109820df4a
3
Makefile
3
Makefile
@ -157,7 +157,8 @@ tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
|
||||
iohandler.o cutils.o iov.o async.o
|
||||
tools-obj-$(CONFIG_POSIX) += compatfd.o
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
|
||||
qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) $(qapi-obj-y) \
|
||||
qapi-visit.o qapi-types.o
|
||||
qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
|
||||
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
|
||||
|
||||
|
10
block.c
10
block.c
@ -433,7 +433,11 @@ int get_tmp_filename(char *filename, int size)
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
fd = mkstemp(filename);
|
||||
if (fd < 0 || close(fd)) {
|
||||
if (fd < 0) {
|
||||
return -errno;
|
||||
}
|
||||
if (close(fd) != 0) {
|
||||
unlink(filename);
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
@ -897,10 +901,10 @@ void bdrv_close(BlockDriverState *bs)
|
||||
bdrv_delete(bs->file);
|
||||
bs->file = NULL;
|
||||
}
|
||||
|
||||
bdrv_dev_change_media_cb(bs, false);
|
||||
}
|
||||
|
||||
bdrv_dev_change_media_cb(bs, false);
|
||||
|
||||
/*throttling disk I/O limits*/
|
||||
if (bs->io_limits_enabled) {
|
||||
bdrv_io_limits_disable(bs);
|
||||
|
@ -542,8 +542,7 @@ static void curl_close(BlockDriverState *bs)
|
||||
}
|
||||
if (s->multi)
|
||||
curl_multi_cleanup(s->multi);
|
||||
if (s->url)
|
||||
free(s->url);
|
||||
g_free(s->url);
|
||||
}
|
||||
|
||||
static int64_t curl_getlength(BlockDriverState *bs)
|
||||
|
@ -1986,7 +1986,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
vdi_index = pos / SD_DATA_OBJ_SIZE;
|
||||
offset = pos % SD_DATA_OBJ_SIZE;
|
||||
|
||||
data_len = MIN(remaining, SD_DATA_OBJ_SIZE);
|
||||
data_len = MIN(remaining, SD_DATA_OBJ_SIZE - offset);
|
||||
|
||||
vmstate_oid = vid_to_vmstate_oid(s->inode.vdi_id, vdi_index);
|
||||
|
||||
@ -2007,6 +2007,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
}
|
||||
|
||||
pos += data_len;
|
||||
data += data_len;
|
||||
remaining -= data_len;
|
||||
}
|
||||
ret = size;
|
||||
|
25
block/vdi.c
25
block/vdi.c
@ -628,7 +628,6 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
|
||||
VdiHeader header;
|
||||
size_t i;
|
||||
size_t bmap_size;
|
||||
uint32_t *bmap;
|
||||
|
||||
logout("\n");
|
||||
|
||||
@ -693,21 +692,21 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
|
||||
result = -errno;
|
||||
}
|
||||
|
||||
bmap = NULL;
|
||||
if (bmap_size > 0) {
|
||||
bmap = (uint32_t *)g_malloc0(bmap_size);
|
||||
}
|
||||
for (i = 0; i < blocks; i++) {
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
bmap[i] = i;
|
||||
} else {
|
||||
bmap[i] = VDI_UNALLOCATED;
|
||||
uint32_t *bmap = g_malloc0(bmap_size);
|
||||
for (i = 0; i < blocks; i++) {
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
bmap[i] = i;
|
||||
} else {
|
||||
bmap[i] = VDI_UNALLOCATED;
|
||||
}
|
||||
}
|
||||
if (write(fd, bmap, bmap_size) < 0) {
|
||||
result = -errno;
|
||||
}
|
||||
g_free(bmap);
|
||||
}
|
||||
if (write(fd, bmap, bmap_size) < 0) {
|
||||
result = -errno;
|
||||
}
|
||||
g_free(bmap);
|
||||
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
|
||||
result = -errno;
|
||||
|
@ -1175,7 +1175,6 @@ void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports)
|
||||
ad->port_no = i;
|
||||
ad->port.dma = &ad->dma;
|
||||
ad->port.dma->ops = &ahci_dma_ops;
|
||||
ad->port_regs.cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1199,6 +1198,7 @@ void ahci_reset(AHCIState *s)
|
||||
pr->irq_stat = 0;
|
||||
pr->irq_mask = 0;
|
||||
pr->scr_ctl = 0;
|
||||
pr->cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON;
|
||||
ahci_reset_port(s, i);
|
||||
}
|
||||
}
|
||||
|
@ -875,6 +875,12 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
|
||||
int sense;
|
||||
bool start = buf[4] & 1;
|
||||
bool loej = buf[4] & 2; /* load on start, eject on !start */
|
||||
int pwrcnd = buf[4] & 0xf0;
|
||||
|
||||
if (pwrcnd) {
|
||||
/* eject/load only happens for power condition == 0 */
|
||||
return;
|
||||
}
|
||||
|
||||
if (loej) {
|
||||
if (!start && !s->tray_open && s->tray_locked) {
|
||||
|
@ -53,8 +53,6 @@ static const int smart_attributes[][12] = {
|
||||
{ 0x0c, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* airflow-temperature-celsius */
|
||||
{ 190, 0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
|
||||
/* end of list */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
};
|
||||
|
||||
static int ide_handle_rw_error(IDEState *s, int error, int op);
|
||||
@ -1468,9 +1466,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
||||
case SMART_READ_THRESH:
|
||||
memset(s->io_buffer, 0, 0x200);
|
||||
s->io_buffer[0] = 0x01; /* smart struct version */
|
||||
for (n=0; n<30; n++) {
|
||||
if (smart_attributes[n][0] == 0)
|
||||
break;
|
||||
for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {
|
||||
s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
|
||||
s->io_buffer[2+1+(n*12)] = smart_attributes[n][11];
|
||||
}
|
||||
@ -1484,10 +1480,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
||||
case SMART_READ_DATA:
|
||||
memset(s->io_buffer, 0, 0x200);
|
||||
s->io_buffer[0] = 0x01; /* smart struct version */
|
||||
for (n=0; n<30; n++) {
|
||||
if (smart_attributes[n][0] == 0) {
|
||||
break;
|
||||
}
|
||||
for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {
|
||||
int i;
|
||||
for(i = 0; i < 11; i++) {
|
||||
s->io_buffer[2+i+(n*12)] = smart_attributes[n][i];
|
||||
|
@ -155,6 +155,70 @@
|
||||
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
|
||||
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog' ] }
|
||||
|
||||
##
|
||||
# @SnapshotInfo
|
||||
#
|
||||
# @id: unique snapshot id
|
||||
#
|
||||
# @name: user chosen name
|
||||
#
|
||||
# @vm-state-size: size of the VM state
|
||||
#
|
||||
# @date-sec: UTC date of the snapshot in seconds
|
||||
#
|
||||
# @date-nsec: fractional part in nano seconds to be used with date-sec
|
||||
#
|
||||
# @vm-clock-sec: VM clock relative to boot in seconds
|
||||
#
|
||||
# @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec
|
||||
#
|
||||
# Since: 1.3
|
||||
#
|
||||
##
|
||||
|
||||
{ 'type': 'SnapshotInfo',
|
||||
'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int',
|
||||
'date-sec': 'int', 'date-nsec': 'int',
|
||||
'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
|
||||
|
||||
##
|
||||
# @ImageInfo:
|
||||
#
|
||||
# Information about a QEMU image file
|
||||
#
|
||||
# @filename: name of the image file
|
||||
#
|
||||
# @format: format of the image file
|
||||
#
|
||||
# @virtual-size: maximum capacity in bytes of the image
|
||||
#
|
||||
# @actual-size: #optional actual size on disk in bytes of the image
|
||||
#
|
||||
# @dirty-flag: #optional true if image is not cleanly closed
|
||||
#
|
||||
# @cluster-size: #optional size of a cluster in bytes
|
||||
#
|
||||
# @encrypted: #optional true if the image is encrypted
|
||||
#
|
||||
# @backing-filename: #optional name of the backing file
|
||||
#
|
||||
# @full-backing-filename: #optional full path of the backing file
|
||||
#
|
||||
# @backing-filename-format: #optional the format of the backing file
|
||||
#
|
||||
# @snapshots: #optional list of VM snapshots
|
||||
#
|
||||
# Since: 1.3
|
||||
#
|
||||
##
|
||||
|
||||
{ 'type': 'ImageInfo',
|
||||
'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
|
||||
'*actual-size': 'int', 'virtual-size': 'int',
|
||||
'*cluster-size': 'int', '*encrypted': 'bool',
|
||||
'*backing-filename': 'str', '*full-backing-filename': 'str',
|
||||
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } }
|
||||
|
||||
##
|
||||
# @StatusInfo:
|
||||
#
|
||||
|
@ -34,9 +34,9 @@ STEXI
|
||||
ETEXI
|
||||
|
||||
DEF("info", img_info,
|
||||
"info [-f fmt] filename")
|
||||
"info [-f fmt] [--output=ofmt] filename")
|
||||
STEXI
|
||||
@item info [-f @var{fmt}] @var{filename}
|
||||
@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
|
||||
ETEXI
|
||||
|
||||
DEF("snapshot", img_snapshot,
|
||||
|
257
qemu-img.c
257
qemu-img.c
@ -21,12 +21,16 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qjson.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-option.h"
|
||||
#include "qemu-error.h"
|
||||
#include "osdep.h"
|
||||
#include "sysemu.h"
|
||||
#include "block_int.h"
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -84,6 +88,7 @@ static void help(void)
|
||||
" '-p' show progress of command (only certain commands)\n"
|
||||
" '-S' indicates the consecutive number of bytes that must contain only zeros\n"
|
||||
" for qemu-img to create a sparse image during conversion\n"
|
||||
" '--output' takes the format in which the output must be done (human or json)\n"
|
||||
"\n"
|
||||
"Parameters to check subcommand:\n"
|
||||
" '-r' tries to repair any inconsistencies that are found during the check.\n"
|
||||
@ -221,7 +226,8 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
||||
|
||||
static BlockDriverState *bdrv_new_open(const char *filename,
|
||||
const char *fmt,
|
||||
int flags)
|
||||
int flags,
|
||||
bool require_io)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *drv;
|
||||
@ -246,7 +252,7 @@ static BlockDriverState *bdrv_new_open(const char *filename,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (bdrv_is_encrypted(bs)) {
|
||||
if (bdrv_is_encrypted(bs) && require_io) {
|
||||
printf("Disk image '%s' is encrypted.\n", filename);
|
||||
if (read_password(password, sizeof(password)) < 0) {
|
||||
error_report("No password given");
|
||||
@ -413,7 +419,7 @@ static int img_check(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, flags);
|
||||
bs = bdrv_new_open(filename, fmt, flags, true);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@ -520,7 +526,7 @@ static int img_commit(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, flags);
|
||||
bs = bdrv_new_open(filename, fmt, flags, true);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@ -762,7 +768,7 @@ static int img_convert(int argc, char **argv)
|
||||
|
||||
total_sectors = 0;
|
||||
for (bs_i = 0; bs_i < bs_n; bs_i++) {
|
||||
bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
|
||||
bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true);
|
||||
if (!bs[bs_i]) {
|
||||
error_report("Could not open '%s'", argv[optind + bs_i]);
|
||||
ret = -1;
|
||||
@ -881,7 +887,7 @@ static int img_convert(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_bs = bdrv_new_open(out_filename, out_fmt, flags);
|
||||
out_bs = bdrv_new_open(out_filename, out_fmt, flags, true);
|
||||
if (!out_bs) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
@ -1102,21 +1108,174 @@ static void dump_snapshots(BlockDriverState *bs)
|
||||
g_free(sn_tab);
|
||||
}
|
||||
|
||||
static int img_info(int argc, char **argv)
|
||||
static void collect_snapshots(BlockDriverState *bs , ImageInfo *info)
|
||||
{
|
||||
int i, sn_count;
|
||||
QEMUSnapshotInfo *sn_tab = NULL;
|
||||
SnapshotInfoList *info_list, *cur_item = NULL;
|
||||
sn_count = bdrv_snapshot_list(bs, &sn_tab);
|
||||
|
||||
for (i = 0; i < sn_count; i++) {
|
||||
info->has_snapshots = true;
|
||||
info_list = g_new0(SnapshotInfoList, 1);
|
||||
|
||||
info_list->value = g_new0(SnapshotInfo, 1);
|
||||
info_list->value->id = g_strdup(sn_tab[i].id_str);
|
||||
info_list->value->name = g_strdup(sn_tab[i].name);
|
||||
info_list->value->vm_state_size = sn_tab[i].vm_state_size;
|
||||
info_list->value->date_sec = sn_tab[i].date_sec;
|
||||
info_list->value->date_nsec = sn_tab[i].date_nsec;
|
||||
info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000;
|
||||
info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
|
||||
|
||||
/* XXX: waiting for the qapi to support qemu-queue.h types */
|
||||
if (!cur_item) {
|
||||
info->snapshots = cur_item = info_list;
|
||||
} else {
|
||||
cur_item->next = info_list;
|
||||
cur_item = info_list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_free(sn_tab);
|
||||
}
|
||||
|
||||
static void dump_json_image_info(ImageInfo *info)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
QString *str;
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj;
|
||||
visit_type_ImageInfo(qmp_output_get_visitor(ov),
|
||||
&info, NULL, &errp);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
assert(str != NULL);
|
||||
printf("%s\n", qstring_get_str(str));
|
||||
qobject_decref(obj);
|
||||
qmp_output_visitor_cleanup(ov);
|
||||
QDECREF(str);
|
||||
}
|
||||
|
||||
static void collect_image_info(BlockDriverState *bs,
|
||||
ImageInfo *info,
|
||||
const char *filename,
|
||||
const char *fmt)
|
||||
{
|
||||
int c;
|
||||
const char *filename, *fmt;
|
||||
BlockDriverState *bs;
|
||||
char size_buf[128], dsize_buf[128];
|
||||
uint64_t total_sectors;
|
||||
int64_t allocated_size;
|
||||
char backing_filename[1024];
|
||||
char backing_filename2[1024];
|
||||
BlockDriverInfo bdi;
|
||||
|
||||
bdrv_get_geometry(bs, &total_sectors);
|
||||
|
||||
info->filename = g_strdup(filename);
|
||||
info->format = g_strdup(bdrv_get_format_name(bs));
|
||||
info->virtual_size = total_sectors * 512;
|
||||
info->actual_size = bdrv_get_allocated_file_size(bs);
|
||||
info->has_actual_size = info->actual_size >= 0;
|
||||
if (bdrv_is_encrypted(bs)) {
|
||||
info->encrypted = true;
|
||||
info->has_encrypted = true;
|
||||
}
|
||||
if (bdrv_get_info(bs, &bdi) >= 0) {
|
||||
if (bdi.cluster_size != 0) {
|
||||
info->cluster_size = bdi.cluster_size;
|
||||
info->has_cluster_size = true;
|
||||
}
|
||||
info->dirty_flag = bdi.is_dirty;
|
||||
info->has_dirty_flag = true;
|
||||
}
|
||||
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
|
||||
if (backing_filename[0] != '\0') {
|
||||
info->backing_filename = g_strdup(backing_filename);
|
||||
info->has_backing_filename = true;
|
||||
bdrv_get_full_backing_filename(bs, backing_filename2,
|
||||
sizeof(backing_filename2));
|
||||
|
||||
if (strcmp(backing_filename, backing_filename2) != 0) {
|
||||
info->full_backing_filename =
|
||||
g_strdup(backing_filename2);
|
||||
info->has_full_backing_filename = true;
|
||||
}
|
||||
|
||||
if (bs->backing_format[0]) {
|
||||
info->backing_filename_format = g_strdup(bs->backing_format);
|
||||
info->has_backing_filename_format = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_human_image_info(ImageInfo *info)
|
||||
{
|
||||
char size_buf[128], dsize_buf[128];
|
||||
if (!info->has_actual_size) {
|
||||
snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
|
||||
} else {
|
||||
get_human_readable_size(dsize_buf, sizeof(dsize_buf),
|
||||
info->actual_size);
|
||||
}
|
||||
get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
|
||||
printf("image: %s\n"
|
||||
"file format: %s\n"
|
||||
"virtual size: %s (%" PRId64 " bytes)\n"
|
||||
"disk size: %s\n",
|
||||
info->filename, info->format, size_buf,
|
||||
info->virtual_size,
|
||||
dsize_buf);
|
||||
|
||||
if (info->has_encrypted && info->encrypted) {
|
||||
printf("encrypted: yes\n");
|
||||
}
|
||||
|
||||
if (info->has_cluster_size) {
|
||||
printf("cluster_size: %" PRId64 "\n", info->cluster_size);
|
||||
}
|
||||
|
||||
if (info->has_dirty_flag && info->dirty_flag) {
|
||||
printf("cleanly shut down: no\n");
|
||||
}
|
||||
|
||||
if (info->has_backing_filename) {
|
||||
printf("backing file: %s", info->backing_filename);
|
||||
if (info->has_full_backing_filename) {
|
||||
printf(" (actual path: %s)", info->full_backing_filename);
|
||||
}
|
||||
putchar('\n');
|
||||
if (info->has_backing_filename_format) {
|
||||
printf("backing file format: %s\n", info->backing_filename_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum {OPTION_OUTPUT = 256};
|
||||
|
||||
typedef enum OutputFormat {
|
||||
OFORMAT_JSON,
|
||||
OFORMAT_HUMAN,
|
||||
} OutputFormat;
|
||||
|
||||
static int img_info(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
OutputFormat output_format = OFORMAT_HUMAN;
|
||||
const char *filename, *fmt, *output;
|
||||
BlockDriverState *bs;
|
||||
ImageInfo *info;
|
||||
|
||||
fmt = NULL;
|
||||
output = NULL;
|
||||
for(;;) {
|
||||
c = getopt(argc, argv, "f:h");
|
||||
int option_index = 0;
|
||||
static const struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"format", required_argument, 0, 'f'},
|
||||
{"output", required_argument, 0, OPTION_OUTPUT},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, "f:h",
|
||||
long_options, &option_index);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -1128,6 +1287,9 @@ static int img_info(int argc, char **argv)
|
||||
case 'f':
|
||||
fmt = optarg;
|
||||
break;
|
||||
case OPTION_OUTPUT:
|
||||
output = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind >= argc) {
|
||||
@ -1135,48 +1297,35 @@ static int img_info(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
|
||||
if (output && !strcmp(output, "json")) {
|
||||
output_format = OFORMAT_JSON;
|
||||
} else if (output && !strcmp(output, "human")) {
|
||||
output_format = OFORMAT_HUMAN;
|
||||
} else if (output) {
|
||||
error_report("--output must be used with human or json as argument.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
bdrv_get_geometry(bs, &total_sectors);
|
||||
get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
|
||||
allocated_size = bdrv_get_allocated_file_size(bs);
|
||||
if (allocated_size < 0) {
|
||||
snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
|
||||
} else {
|
||||
get_human_readable_size(dsize_buf, sizeof(dsize_buf),
|
||||
allocated_size);
|
||||
|
||||
info = g_new0(ImageInfo, 1);
|
||||
collect_image_info(bs, info, filename, fmt);
|
||||
|
||||
switch (output_format) {
|
||||
case OFORMAT_HUMAN:
|
||||
dump_human_image_info(info);
|
||||
dump_snapshots(bs);
|
||||
break;
|
||||
case OFORMAT_JSON:
|
||||
collect_snapshots(bs, info);
|
||||
dump_json_image_info(info);
|
||||
break;
|
||||
}
|
||||
printf("image: %s\n"
|
||||
"file format: %s\n"
|
||||
"virtual size: %s (%" PRId64 " bytes)\n"
|
||||
"disk size: %s\n",
|
||||
filename, bdrv_get_format_name(bs), size_buf,
|
||||
(total_sectors * 512),
|
||||
dsize_buf);
|
||||
if (bdrv_is_encrypted(bs)) {
|
||||
printf("encrypted: yes\n");
|
||||
}
|
||||
if (bdrv_get_info(bs, &bdi) >= 0) {
|
||||
if (bdi.cluster_size != 0) {
|
||||
printf("cluster_size: %d\n", bdi.cluster_size);
|
||||
}
|
||||
if (bdi.is_dirty) {
|
||||
printf("cleanly shut down: no\n");
|
||||
}
|
||||
}
|
||||
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
|
||||
if (backing_filename[0] != '\0') {
|
||||
bdrv_get_full_backing_filename(bs, backing_filename2,
|
||||
sizeof(backing_filename2));
|
||||
printf("backing file: %s", backing_filename);
|
||||
if (strcmp(backing_filename, backing_filename2) != 0) {
|
||||
printf(" (actual path: %s)", backing_filename2);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
dump_snapshots(bs);
|
||||
|
||||
qapi_free_ImageInfo(info);
|
||||
bdrv_delete(bs);
|
||||
return 0;
|
||||
}
|
||||
@ -1248,7 +1397,7 @@ static int img_snapshot(int argc, char **argv)
|
||||
filename = argv[optind++];
|
||||
|
||||
/* Open the image */
|
||||
bs = bdrv_new_open(filename, NULL, bdrv_oflags);
|
||||
bs = bdrv_new_open(filename, NULL, bdrv_oflags, true);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@ -1366,7 +1515,7 @@ static int img_rebase(int argc, char **argv)
|
||||
* Ignore the old backing file for unsafe rebase in case we want to correct
|
||||
* the reference to a renamed or moved backing file.
|
||||
*/
|
||||
bs = bdrv_new_open(filename, fmt, flags);
|
||||
bs = bdrv_new_open(filename, fmt, flags, true);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@ -1639,7 +1788,7 @@ static int img_resize(int argc, char **argv)
|
||||
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
|
||||
qemu_opts_del(param);
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true);
|
||||
if (!bs) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
|
@ -129,12 +129,13 @@ created as a copy on write image of the specified base image; the
|
||||
@var{backing_file} should have the same content as the input's base image,
|
||||
however the path, image format, etc may differ.
|
||||
|
||||
@item info [-f @var{fmt}] @var{filename}
|
||||
@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
|
||||
|
||||
Give information about the disk image @var{filename}. Use it in
|
||||
particular to know the size reserved on disk which can be different
|
||||
from the displayed size. If VM snapshots are stored in the disk image,
|
||||
they are displayed too.
|
||||
they are displayed too. The command can output in the format @var{ofmt}
|
||||
which is either @code{human} or @code{json}.
|
||||
|
||||
@item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user