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:
Anthony Liguori 2012-09-17 10:23:15 -05:00
commit 109820df4a
12 changed files with 305 additions and 88 deletions

View File

@ -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
View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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];

View File

@ -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:
#

View File

@ -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,

View File

@ -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;

View File

@ -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}