mirror of https://github.com/xemu-project/xemu.git
add support for protocol driver create_options
This patch enables protocol drivers to use their create options which are not supported by the format. For example, protcol drivers can use a backing_file option with raw format. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
776cbbbd78
commit
b50cbabc1b
7
block.c
7
block.c
|
@ -56,7 +56,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
|
||||||
uint8_t *buf, int nb_sectors);
|
uint8_t *buf, int nb_sectors);
|
||||||
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
||||||
const uint8_t *buf, int nb_sectors);
|
const uint8_t *buf, int nb_sectors);
|
||||||
static BlockDriver *find_protocol(const char *filename);
|
|
||||||
|
|
||||||
static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
|
static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
|
||||||
QTAILQ_HEAD_INITIALIZER(bdrv_states);
|
QTAILQ_HEAD_INITIALIZER(bdrv_states);
|
||||||
|
@ -210,7 +209,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
|
||||||
{
|
{
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
|
|
||||||
drv = find_protocol(filename);
|
drv = bdrv_find_protocol(filename);
|
||||||
if (drv == NULL) {
|
if (drv == NULL) {
|
||||||
drv = bdrv_find_format("file");
|
drv = bdrv_find_format("file");
|
||||||
}
|
}
|
||||||
|
@ -283,7 +282,7 @@ static BlockDriver *find_hdev_driver(const char *filename)
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockDriver *find_protocol(const char *filename)
|
BlockDriver *bdrv_find_protocol(const char *filename)
|
||||||
{
|
{
|
||||||
BlockDriver *drv1;
|
BlockDriver *drv1;
|
||||||
char protocol[128];
|
char protocol[128];
|
||||||
|
@ -478,7 +477,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
drv = find_protocol(filename);
|
drv = bdrv_find_protocol(filename);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
1
block.h
1
block.h
|
@ -54,6 +54,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data);
|
||||||
|
|
||||||
void bdrv_init(void);
|
void bdrv_init(void);
|
||||||
void bdrv_init_with_whitelist(void);
|
void bdrv_init_with_whitelist(void);
|
||||||
|
BlockDriver *bdrv_find_protocol(const char *filename);
|
||||||
BlockDriver *bdrv_find_format(const char *format_name);
|
BlockDriver *bdrv_find_format(const char *format_name);
|
||||||
BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
|
BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
|
||||||
int bdrv_create(BlockDriver *drv, const char* filename,
|
int bdrv_create(BlockDriver *drv, const char* filename,
|
||||||
|
|
49
qemu-img.c
49
qemu-img.c
|
@ -252,8 +252,8 @@ static int img_create(int argc, char **argv)
|
||||||
const char *base_fmt = NULL;
|
const char *base_fmt = NULL;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
const char *base_filename = NULL;
|
const char *base_filename = NULL;
|
||||||
BlockDriver *drv;
|
BlockDriver *drv, *proto_drv;
|
||||||
QEMUOptionParameter *param = NULL;
|
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||||
char *options = NULL;
|
char *options = NULL;
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
@ -286,33 +286,42 @@ static int img_create(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the filename */
|
||||||
|
if (optind >= argc)
|
||||||
|
help();
|
||||||
|
filename = argv[optind++];
|
||||||
|
|
||||||
/* Find driver and parse its options */
|
/* Find driver and parse its options */
|
||||||
drv = bdrv_find_format(fmt);
|
drv = bdrv_find_format(fmt);
|
||||||
if (!drv)
|
if (!drv)
|
||||||
error("Unknown file format '%s'", fmt);
|
error("Unknown file format '%s'", fmt);
|
||||||
|
|
||||||
|
proto_drv = bdrv_find_protocol(filename);
|
||||||
|
if (!proto_drv)
|
||||||
|
error("Unknown protocol '%s'", filename);
|
||||||
|
|
||||||
|
create_options = append_option_parameters(create_options,
|
||||||
|
drv->create_options);
|
||||||
|
create_options = append_option_parameters(create_options,
|
||||||
|
proto_drv->create_options);
|
||||||
|
|
||||||
if (options && !strcmp(options, "?")) {
|
if (options && !strcmp(options, "?")) {
|
||||||
print_option_help(drv->create_options);
|
print_option_help(create_options);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create parameter list with default values */
|
/* Create parameter list with default values */
|
||||||
param = parse_option_parameters("", drv->create_options, param);
|
param = parse_option_parameters("", create_options, param);
|
||||||
set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
|
set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
|
||||||
|
|
||||||
/* Parse -o options */
|
/* Parse -o options */
|
||||||
if (options) {
|
if (options) {
|
||||||
param = parse_option_parameters(options, drv->create_options, param);
|
param = parse_option_parameters(options, create_options, param);
|
||||||
if (param == NULL) {
|
if (param == NULL) {
|
||||||
error("Invalid options for file format '%s'.", fmt);
|
error("Invalid options for file format '%s'.", fmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the filename */
|
|
||||||
if (optind >= argc)
|
|
||||||
help();
|
|
||||||
filename = argv[optind++];
|
|
||||||
|
|
||||||
/* Add size to parameters */
|
/* Add size to parameters */
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
|
set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
|
||||||
|
@ -362,6 +371,7 @@ static int img_create(int argc, char **argv)
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
ret = bdrv_create(drv, filename, param);
|
ret = bdrv_create(drv, filename, param);
|
||||||
|
free_option_parameters(create_options);
|
||||||
free_option_parameters(param);
|
free_option_parameters(param);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -543,14 +553,14 @@ static int img_convert(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
|
int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
|
||||||
const char *fmt, *out_fmt, *out_baseimg, *out_filename;
|
const char *fmt, *out_fmt, *out_baseimg, *out_filename;
|
||||||
BlockDriver *drv;
|
BlockDriver *drv, *proto_drv;
|
||||||
BlockDriverState **bs, *out_bs;
|
BlockDriverState **bs, *out_bs;
|
||||||
int64_t total_sectors, nb_sectors, sector_num, bs_offset;
|
int64_t total_sectors, nb_sectors, sector_num, bs_offset;
|
||||||
uint64_t bs_sectors;
|
uint64_t bs_sectors;
|
||||||
uint8_t * buf;
|
uint8_t * buf;
|
||||||
const uint8_t *buf1;
|
const uint8_t *buf1;
|
||||||
BlockDriverInfo bdi;
|
BlockDriverInfo bdi;
|
||||||
QEMUOptionParameter *param = NULL;
|
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||||
char *options = NULL;
|
char *options = NULL;
|
||||||
|
|
||||||
fmt = NULL;
|
fmt = NULL;
|
||||||
|
@ -615,19 +625,27 @@ static int img_convert(int argc, char **argv)
|
||||||
if (!drv)
|
if (!drv)
|
||||||
error("Unknown file format '%s'", out_fmt);
|
error("Unknown file format '%s'", out_fmt);
|
||||||
|
|
||||||
|
proto_drv = bdrv_find_protocol(out_filename);
|
||||||
|
if (!proto_drv)
|
||||||
|
error("Unknown protocol '%s'", out_filename);
|
||||||
|
|
||||||
|
create_options = append_option_parameters(create_options,
|
||||||
|
drv->create_options);
|
||||||
|
create_options = append_option_parameters(create_options,
|
||||||
|
proto_drv->create_options);
|
||||||
if (options && !strcmp(options, "?")) {
|
if (options && !strcmp(options, "?")) {
|
||||||
print_option_help(drv->create_options);
|
print_option_help(create_options);
|
||||||
free(bs);
|
free(bs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
param = parse_option_parameters(options, drv->create_options, param);
|
param = parse_option_parameters(options, create_options, param);
|
||||||
if (param == NULL) {
|
if (param == NULL) {
|
||||||
error("Invalid options for file format '%s'.", out_fmt);
|
error("Invalid options for file format '%s'.", out_fmt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
param = parse_option_parameters("", drv->create_options, param);
|
param = parse_option_parameters("", create_options, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
|
set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
|
||||||
|
@ -649,6 +667,7 @@ static int img_convert(int argc, char **argv)
|
||||||
|
|
||||||
/* Create the new image */
|
/* Create the new image */
|
||||||
ret = bdrv_create(drv, out_filename, param);
|
ret = bdrv_create(drv, out_filename, param);
|
||||||
|
free_option_parameters(create_options);
|
||||||
free_option_parameters(param);
|
free_option_parameters(param);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
|
@ -345,6 +345,51 @@ void free_option_parameters(QEMUOptionParameter *list)
|
||||||
qemu_free(list);
|
qemu_free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count valid options in list
|
||||||
|
*/
|
||||||
|
static size_t count_option_parameters(QEMUOptionParameter *list)
|
||||||
|
{
|
||||||
|
size_t num_options = 0;
|
||||||
|
|
||||||
|
while (list && list->name) {
|
||||||
|
num_options++;
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append an option list (list) to an option list (dest).
|
||||||
|
*
|
||||||
|
* If dest is NULL, a new copy of list is created.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the first element of dest (or the newly allocated copy)
|
||||||
|
*/
|
||||||
|
QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
|
||||||
|
QEMUOptionParameter *list)
|
||||||
|
{
|
||||||
|
size_t num_options, num_dest_options;
|
||||||
|
|
||||||
|
num_options = count_option_parameters(dest);
|
||||||
|
num_dest_options = num_options;
|
||||||
|
|
||||||
|
num_options += count_option_parameters(list);
|
||||||
|
|
||||||
|
dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
|
||||||
|
|
||||||
|
while (list && list->name) {
|
||||||
|
if (get_option_parameter(dest, list->name) == NULL) {
|
||||||
|
dest[num_dest_options++] = *list;
|
||||||
|
dest[num_dest_options].name = NULL;
|
||||||
|
}
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parses a parameter string (param) into an option list (dest).
|
* Parses a parameter string (param) into an option list (dest).
|
||||||
*
|
*
|
||||||
|
@ -365,7 +410,6 @@ void free_option_parameters(QEMUOptionParameter *list)
|
||||||
QEMUOptionParameter *parse_option_parameters(const char *param,
|
QEMUOptionParameter *parse_option_parameters(const char *param,
|
||||||
QEMUOptionParameter *list, QEMUOptionParameter *dest)
|
QEMUOptionParameter *list, QEMUOptionParameter *dest)
|
||||||
{
|
{
|
||||||
QEMUOptionParameter *cur;
|
|
||||||
QEMUOptionParameter *allocated = NULL;
|
QEMUOptionParameter *allocated = NULL;
|
||||||
char name[256];
|
char name[256];
|
||||||
char value[256];
|
char value[256];
|
||||||
|
@ -379,12 +423,7 @@ QEMUOptionParameter *parse_option_parameters(const char *param,
|
||||||
|
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
// Count valid options
|
// Count valid options
|
||||||
num_options = 0;
|
num_options = count_option_parameters(list);
|
||||||
cur = list;
|
|
||||||
while (cur->name) {
|
|
||||||
num_options++;
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a copy of the option list to fill in values
|
// Create a copy of the option list to fill in values
|
||||||
dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
|
dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
|
||||||
|
|
|
@ -70,6 +70,8 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
|
||||||
const char *value);
|
const char *value);
|
||||||
int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
|
int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
|
||||||
uint64_t value);
|
uint64_t value);
|
||||||
|
QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
|
||||||
|
QEMUOptionParameter *list);
|
||||||
QEMUOptionParameter *parse_option_parameters(const char *param,
|
QEMUOptionParameter *parse_option_parameters(const char *param,
|
||||||
QEMUOptionParameter *list, QEMUOptionParameter *dest);
|
QEMUOptionParameter *list, QEMUOptionParameter *dest);
|
||||||
void free_option_parameters(QEMUOptionParameter *list);
|
void free_option_parameters(QEMUOptionParameter *list);
|
||||||
|
|
Loading…
Reference in New Issue