Revert "Fix OpenBSD build"
This reverts commit 20d97356c9
.
The BlockDriver definition should stay at the end of source files.
Conflicts:
block/qcow2.c
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
3cab721d0e
commit
de5f3f40af
490
block/qcow2.c
490
block/qcow2.c
@ -52,7 +52,7 @@ typedef struct {
|
||||
#define QCOW_EXT_MAGIC_END 0
|
||||
#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
|
||||
|
||||
static int qcow_create(const char *filename, QEMUOptionParameter *options);
|
||||
static BlockDriver bdrv_qcow2;
|
||||
|
||||
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
@ -830,6 +830,250 @@ static int preallocate(BlockDriverState *bs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcow_create2(const char *filename, int64_t total_size,
|
||||
const char *backing_file, const char *backing_format,
|
||||
int flags, size_t cluster_size, int prealloc)
|
||||
{
|
||||
|
||||
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
|
||||
int ref_clusters, reftable_clusters, backing_format_len = 0;
|
||||
int rounded_ext_bf_len = 0;
|
||||
QCowHeader header;
|
||||
uint64_t tmp, offset;
|
||||
uint64_t old_ref_clusters;
|
||||
QCowCreateState s1, *s = &s1;
|
||||
QCowExtension ext_bf = {0, 0};
|
||||
int ret;
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
memset(&header, 0, sizeof(header));
|
||||
header.magic = cpu_to_be32(QCOW_MAGIC);
|
||||
header.version = cpu_to_be32(QCOW_VERSION);
|
||||
header.size = cpu_to_be64(total_size * 512);
|
||||
header_size = sizeof(header);
|
||||
backing_filename_len = 0;
|
||||
if (backing_file) {
|
||||
if (backing_format) {
|
||||
ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT;
|
||||
backing_format_len = strlen(backing_format);
|
||||
ext_bf.len = backing_format_len;
|
||||
rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7;
|
||||
header_size += rounded_ext_bf_len;
|
||||
}
|
||||
header.backing_file_offset = cpu_to_be64(header_size);
|
||||
backing_filename_len = strlen(backing_file);
|
||||
header.backing_file_size = cpu_to_be32(backing_filename_len);
|
||||
header_size += backing_filename_len;
|
||||
}
|
||||
|
||||
/* Cluster size */
|
||||
s->cluster_bits = get_bits_from_size(cluster_size);
|
||||
if (s->cluster_bits < MIN_CLUSTER_BITS ||
|
||||
s->cluster_bits > MAX_CLUSTER_BITS)
|
||||
{
|
||||
fprintf(stderr, "Cluster size must be a power of two between "
|
||||
"%d and %dk\n",
|
||||
1 << MIN_CLUSTER_BITS,
|
||||
1 << (MAX_CLUSTER_BITS - 10));
|
||||
return -EINVAL;
|
||||
}
|
||||
s->cluster_size = 1 << s->cluster_bits;
|
||||
|
||||
header.cluster_bits = cpu_to_be32(s->cluster_bits);
|
||||
header_size = (header_size + 7) & ~7;
|
||||
if (flags & BLOCK_FLAG_ENCRYPT) {
|
||||
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
|
||||
} else {
|
||||
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
|
||||
}
|
||||
l2_bits = s->cluster_bits - 3;
|
||||
shift = s->cluster_bits + l2_bits;
|
||||
l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
|
||||
offset = align_offset(header_size, s->cluster_size);
|
||||
s->l1_table_offset = offset;
|
||||
header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
|
||||
header.l1_size = cpu_to_be32(l1_size);
|
||||
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
|
||||
|
||||
/* count how many refcount blocks needed */
|
||||
|
||||
#define NUM_CLUSTERS(bytes) \
|
||||
(((bytes) + (s->cluster_size) - 1) / (s->cluster_size))
|
||||
|
||||
ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t));
|
||||
|
||||
do {
|
||||
uint64_t image_clusters;
|
||||
old_ref_clusters = ref_clusters;
|
||||
|
||||
/* Number of clusters used for the refcount table */
|
||||
reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t));
|
||||
|
||||
/* Number of clusters that the whole image will have */
|
||||
image_clusters = NUM_CLUSTERS(offset) + ref_clusters
|
||||
+ reftable_clusters;
|
||||
|
||||
/* Number of refcount blocks needed for the image */
|
||||
ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t));
|
||||
|
||||
} while (ref_clusters != old_ref_clusters);
|
||||
|
||||
s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size);
|
||||
|
||||
s->refcount_table_offset = offset;
|
||||
header.refcount_table_offset = cpu_to_be64(offset);
|
||||
header.refcount_table_clusters = cpu_to_be32(reftable_clusters);
|
||||
offset += (reftable_clusters * s->cluster_size);
|
||||
s->refcount_block_offset = offset;
|
||||
|
||||
for (i=0; i < ref_clusters; i++) {
|
||||
s->refcount_table[i] = cpu_to_be64(offset);
|
||||
offset += s->cluster_size;
|
||||
}
|
||||
|
||||
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
|
||||
|
||||
/* update refcounts */
|
||||
qcow2_create_refcount_update(s, 0, header_size);
|
||||
qcow2_create_refcount_update(s, s->l1_table_offset,
|
||||
l1_size * sizeof(uint64_t));
|
||||
qcow2_create_refcount_update(s, s->refcount_table_offset,
|
||||
reftable_clusters * s->cluster_size);
|
||||
qcow2_create_refcount_update(s, s->refcount_block_offset,
|
||||
ref_clusters * s->cluster_size);
|
||||
|
||||
/* write all the data */
|
||||
ret = qemu_write_full(fd, &header, sizeof(header));
|
||||
if (ret != sizeof(header)) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
if (backing_file) {
|
||||
if (backing_format_len) {
|
||||
char zero[16];
|
||||
int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf));
|
||||
|
||||
memset(zero, 0, sizeof(zero));
|
||||
cpu_to_be32s(&ext_bf.magic);
|
||||
cpu_to_be32s(&ext_bf.len);
|
||||
ret = qemu_write_full(fd, &ext_bf, sizeof(ext_bf));
|
||||
if (ret != sizeof(ext_bf)) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
ret = qemu_write_full(fd, backing_format, backing_format_len);
|
||||
if (ret != backing_format_len) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
if (padding > 0) {
|
||||
ret = qemu_write_full(fd, zero, padding);
|
||||
if (ret != padding) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = qemu_write_full(fd, backing_file, backing_filename_len);
|
||||
if (ret != backing_filename_len) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
lseek(fd, s->l1_table_offset, SEEK_SET);
|
||||
tmp = 0;
|
||||
for(i = 0;i < l1_size; i++) {
|
||||
ret = qemu_write_full(fd, &tmp, sizeof(tmp));
|
||||
if (ret != sizeof(tmp)) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
lseek(fd, s->refcount_table_offset, SEEK_SET);
|
||||
ret = qemu_write_full(fd, s->refcount_table,
|
||||
reftable_clusters * s->cluster_size);
|
||||
if (ret != reftable_clusters * s->cluster_size) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
lseek(fd, s->refcount_block_offset, SEEK_SET);
|
||||
ret = qemu_write_full(fd, s->refcount_block,
|
||||
ref_clusters * s->cluster_size);
|
||||
if (ret != ref_clusters * s->cluster_size) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
qemu_free(s->refcount_table);
|
||||
qemu_free(s->refcount_block);
|
||||
close(fd);
|
||||
|
||||
/* Preallocate metadata */
|
||||
if (ret == 0 && prealloc) {
|
||||
BlockDriverState *bs;
|
||||
bs = bdrv_new("");
|
||||
bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, &bdrv_qcow2);
|
||||
preallocate(bs);
|
||||
bdrv_close(bs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
const char *backing_file = NULL;
|
||||
const char *backing_fmt = NULL;
|
||||
uint64_t sectors = 0;
|
||||
int flags = 0;
|
||||
size_t cluster_size = 65536;
|
||||
int prealloc = 0;
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
sectors = options->value.n / 512;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
|
||||
backing_file = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
|
||||
backing_fmt = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
|
||||
flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
if (options->value.n) {
|
||||
cluster_size = options->value.n;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(options->value.s, "metadata")) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid preallocation mode: '%s'\n",
|
||||
options->value.s);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
options++;
|
||||
}
|
||||
|
||||
if (backing_file && prealloc) {
|
||||
fprintf(stderr, "Backing file and preallocation cannot be used at "
|
||||
"the same time\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return qcow_create2(filename, sectors, backing_file, backing_fmt, flags,
|
||||
cluster_size, prealloc);
|
||||
}
|
||||
|
||||
static int qcow_make_empty(BlockDriverState *bs)
|
||||
{
|
||||
#if 0
|
||||
@ -1105,250 +1349,6 @@ static BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_check = qcow_check,
|
||||
};
|
||||
|
||||
static int qcow_create2(const char *filename, int64_t total_size,
|
||||
const char *backing_file, const char *backing_format,
|
||||
int flags, size_t cluster_size, int prealloc)
|
||||
{
|
||||
|
||||
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
|
||||
int ref_clusters, reftable_clusters, backing_format_len = 0;
|
||||
int rounded_ext_bf_len = 0;
|
||||
QCowHeader header;
|
||||
uint64_t tmp, offset;
|
||||
uint64_t old_ref_clusters;
|
||||
QCowCreateState s1, *s = &s1;
|
||||
QCowExtension ext_bf = {0, 0};
|
||||
int ret;
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
memset(&header, 0, sizeof(header));
|
||||
header.magic = cpu_to_be32(QCOW_MAGIC);
|
||||
header.version = cpu_to_be32(QCOW_VERSION);
|
||||
header.size = cpu_to_be64(total_size * 512);
|
||||
header_size = sizeof(header);
|
||||
backing_filename_len = 0;
|
||||
if (backing_file) {
|
||||
if (backing_format) {
|
||||
ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT;
|
||||
backing_format_len = strlen(backing_format);
|
||||
ext_bf.len = backing_format_len;
|
||||
rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7;
|
||||
header_size += rounded_ext_bf_len;
|
||||
}
|
||||
header.backing_file_offset = cpu_to_be64(header_size);
|
||||
backing_filename_len = strlen(backing_file);
|
||||
header.backing_file_size = cpu_to_be32(backing_filename_len);
|
||||
header_size += backing_filename_len;
|
||||
}
|
||||
|
||||
/* Cluster size */
|
||||
s->cluster_bits = get_bits_from_size(cluster_size);
|
||||
if (s->cluster_bits < MIN_CLUSTER_BITS ||
|
||||
s->cluster_bits > MAX_CLUSTER_BITS)
|
||||
{
|
||||
fprintf(stderr, "Cluster size must be a power of two between "
|
||||
"%d and %dk\n",
|
||||
1 << MIN_CLUSTER_BITS,
|
||||
1 << (MAX_CLUSTER_BITS - 10));
|
||||
return -EINVAL;
|
||||
}
|
||||
s->cluster_size = 1 << s->cluster_bits;
|
||||
|
||||
header.cluster_bits = cpu_to_be32(s->cluster_bits);
|
||||
header_size = (header_size + 7) & ~7;
|
||||
if (flags & BLOCK_FLAG_ENCRYPT) {
|
||||
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
|
||||
} else {
|
||||
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
|
||||
}
|
||||
l2_bits = s->cluster_bits - 3;
|
||||
shift = s->cluster_bits + l2_bits;
|
||||
l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
|
||||
offset = align_offset(header_size, s->cluster_size);
|
||||
s->l1_table_offset = offset;
|
||||
header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
|
||||
header.l1_size = cpu_to_be32(l1_size);
|
||||
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
|
||||
|
||||
/* count how many refcount blocks needed */
|
||||
|
||||
#define NUM_CLUSTERS(bytes) \
|
||||
(((bytes) + (s->cluster_size) - 1) / (s->cluster_size))
|
||||
|
||||
ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t));
|
||||
|
||||
do {
|
||||
uint64_t image_clusters;
|
||||
old_ref_clusters = ref_clusters;
|
||||
|
||||
/* Number of clusters used for the refcount table */
|
||||
reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t));
|
||||
|
||||
/* Number of clusters that the whole image will have */
|
||||
image_clusters = NUM_CLUSTERS(offset) + ref_clusters
|
||||
+ reftable_clusters;
|
||||
|
||||
/* Number of refcount blocks needed for the image */
|
||||
ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t));
|
||||
|
||||
} while (ref_clusters != old_ref_clusters);
|
||||
|
||||
s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size);
|
||||
|
||||
s->refcount_table_offset = offset;
|
||||
header.refcount_table_offset = cpu_to_be64(offset);
|
||||
header.refcount_table_clusters = cpu_to_be32(reftable_clusters);
|
||||
offset += (reftable_clusters * s->cluster_size);
|
||||
s->refcount_block_offset = offset;
|
||||
|
||||
for (i=0; i < ref_clusters; i++) {
|
||||
s->refcount_table[i] = cpu_to_be64(offset);
|
||||
offset += s->cluster_size;
|
||||
}
|
||||
|
||||
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
|
||||
|
||||
/* update refcounts */
|
||||
qcow2_create_refcount_update(s, 0, header_size);
|
||||
qcow2_create_refcount_update(s, s->l1_table_offset,
|
||||
l1_size * sizeof(uint64_t));
|
||||
qcow2_create_refcount_update(s, s->refcount_table_offset,
|
||||
reftable_clusters * s->cluster_size);
|
||||
qcow2_create_refcount_update(s, s->refcount_block_offset,
|
||||
ref_clusters * s->cluster_size);
|
||||
|
||||
/* write all the data */
|
||||
ret = qemu_write_full(fd, &header, sizeof(header));
|
||||
if (ret != sizeof(header)) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
if (backing_file) {
|
||||
if (backing_format_len) {
|
||||
char zero[16];
|
||||
int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf));
|
||||
|
||||
memset(zero, 0, sizeof(zero));
|
||||
cpu_to_be32s(&ext_bf.magic);
|
||||
cpu_to_be32s(&ext_bf.len);
|
||||
ret = qemu_write_full(fd, &ext_bf, sizeof(ext_bf));
|
||||
if (ret != sizeof(ext_bf)) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
ret = qemu_write_full(fd, backing_format, backing_format_len);
|
||||
if (ret != backing_format_len) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
if (padding > 0) {
|
||||
ret = qemu_write_full(fd, zero, padding);
|
||||
if (ret != padding) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = qemu_write_full(fd, backing_file, backing_filename_len);
|
||||
if (ret != backing_filename_len) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
lseek(fd, s->l1_table_offset, SEEK_SET);
|
||||
tmp = 0;
|
||||
for(i = 0;i < l1_size; i++) {
|
||||
ret = qemu_write_full(fd, &tmp, sizeof(tmp));
|
||||
if (ret != sizeof(tmp)) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
lseek(fd, s->refcount_table_offset, SEEK_SET);
|
||||
ret = qemu_write_full(fd, s->refcount_table,
|
||||
reftable_clusters * s->cluster_size);
|
||||
if (ret != reftable_clusters * s->cluster_size) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
lseek(fd, s->refcount_block_offset, SEEK_SET);
|
||||
ret = qemu_write_full(fd, s->refcount_block,
|
||||
ref_clusters * s->cluster_size);
|
||||
if (ret != ref_clusters * s->cluster_size) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
qemu_free(s->refcount_table);
|
||||
qemu_free(s->refcount_block);
|
||||
close(fd);
|
||||
|
||||
/* Preallocate metadata */
|
||||
if (ret == 0 && prealloc) {
|
||||
BlockDriverState *bs;
|
||||
bs = bdrv_new("");
|
||||
bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, &bdrv_qcow2);
|
||||
preallocate(bs);
|
||||
bdrv_close(bs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
const char *backing_file = NULL;
|
||||
const char *backing_fmt = NULL;
|
||||
uint64_t sectors = 0;
|
||||
int flags = 0;
|
||||
size_t cluster_size = 65536;
|
||||
int prealloc = 0;
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
sectors = options->value.n / 512;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
|
||||
backing_file = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
|
||||
backing_fmt = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
|
||||
flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
if (options->value.n) {
|
||||
cluster_size = options->value.n;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(options->value.s, "metadata")) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid preallocation mode: '%s'\n",
|
||||
options->value.s);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
options++;
|
||||
}
|
||||
|
||||
if (backing_file && prealloc) {
|
||||
fprintf(stderr, "Backing file and preallocation cannot be used at "
|
||||
"the same time\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return qcow_create2(filename, sectors, backing_file, backing_fmt, flags,
|
||||
cluster_size, prealloc);
|
||||
}
|
||||
|
||||
static void bdrv_qcow2_init(void)
|
||||
{
|
||||
bdrv_register(&bdrv_qcow2);
|
||||
|
Loading…
Reference in New Issue
Block a user