diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-12-10 15:42:55 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-12-10 15:42:55 +0900 |
commit | 0d6a2f7e595218b5632ba7005128470e65138951 (patch) | |
tree | 596b09930ef1538e6606450e2d8b88ec2e296a9b /block/vpc.c | |
parent | 16b1353a36171ae06d63fd309f4772dbfb1da113 (diff) | |
download | qemu-0d6a2f7e595218b5632ba7005128470e65138951.tar.gz qemu-0d6a2f7e595218b5632ba7005128470e65138951.tar.bz2 qemu-0d6a2f7e595218b5632ba7005128470e65138951.zip |
Imported Upstream version 2.2.0upstream/2.2.1upstream/2.2.0
Diffstat (limited to 'block/vpc.c')
-rw-r--r-- | block/vpc.c | 169 |
1 files changed, 77 insertions, 92 deletions
diff --git a/block/vpc.c b/block/vpc.c index 8b376a40b..38c4f02ff 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -29,13 +29,6 @@ #if defined(CONFIG_UUID) #include <uuid/uuid.h> #endif -#ifdef __linux__ -#include <linux/fs.h> -#include <sys/ioctl.h> -#ifndef FS_NOCOW_FL -#define FS_NOCOW_FL 0x00800000 /* Do not cow file */ -#endif -#endif /**************************************************************/ @@ -214,7 +207,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, "incorrect.\n", bs->filename); /* Write 'checksum' back to footer, or else will leave it with zero. */ - footer->checksum = be32_to_cpu(checksum); + footer->checksum = cpu_to_be32(checksum); // The visible size of a image in Virtual PC depends on the geometry // rather than on the size stored in the footer (the size in the footer @@ -276,7 +269,11 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } - s->pagetable = qemu_blockalign(bs, s->max_table_entries * 4); + s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4); + if (s->pagetable == NULL) { + ret = -ENOMEM; + goto fail; + } s->bat_offset = be64_to_cpu(dyndisk_header->table_offset); @@ -323,7 +320,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, /* Disable migration when VHD images are used */ error_set(&s->migration_blocker, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, - "vpc", bs->device_name, "live migration"); + "vpc", bdrv_get_device_name(bs), "live migration"); migrate_add_blocker(s->migration_blocker); return 0; @@ -475,7 +472,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) // Write BAT entry to disk bat_offset = s->bat_offset + (4 * index); - bat_value = be32_to_cpu(s->pagetable[index]); + bat_value = cpu_to_be32(s->pagetable[index]); ret = bdrv_pwrite_sync(bs->file, bat_offset, &bat_value, 4); if (ret < 0) goto fail; @@ -492,7 +489,7 @@ static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) BDRVVPCState *s = (BDRVVPCState *)bs->opaque; VHDFooter *footer = (VHDFooter *) s->footer_buf; - if (cpu_to_be32(footer->type) != VHD_FIXED) { + if (be32_to_cpu(footer->type) != VHD_FIXED) { bdi->cluster_size = s->block_size; } @@ -509,7 +506,7 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num, int64_t sectors, sectors_per_block; VHDFooter *footer = (VHDFooter *) s->footer_buf; - if (cpu_to_be32(footer->type) == VHD_FIXED) { + if (be32_to_cpu(footer->type) == VHD_FIXED) { return bdrv_read(bs->file, sector_num, buf, nb_sectors); } while (nb_sectors > 0) { @@ -558,7 +555,7 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num, int ret; VHDFooter *footer = (VHDFooter *) s->footer_buf; - if (cpu_to_be32(footer->type) == VHD_FIXED) { + if (be32_to_cpu(footer->type) == VHD_FIXED) { return bdrv_write(bs->file, sector_num, buf, nb_sectors); } while (nb_sectors > 0) { @@ -656,39 +653,41 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, return 0; } -static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors) +static int create_dynamic_disk(BlockDriverState *bs, uint8_t *buf, + int64_t total_sectors) { VHDDynDiskHeader *dyndisk_header = (VHDDynDiskHeader *) buf; size_t block_size, num_bat_entries; int i; - int ret = -EIO; + int ret; + int64_t offset = 0; // Write the footer (twice: at the beginning and at the end) block_size = 0x200000; num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512); - if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) { + ret = bdrv_pwrite_sync(bs, offset, buf, HEADER_SIZE); + if (ret) { goto fail; } - if (lseek(fd, 1536 + ((num_bat_entries * 4 + 511) & ~511), SEEK_SET) < 0) { - goto fail; - } - if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) { + offset = 1536 + ((num_bat_entries * 4 + 511) & ~511); + ret = bdrv_pwrite_sync(bs, offset, buf, HEADER_SIZE); + if (ret < 0) { goto fail; } // Write the initial BAT - if (lseek(fd, 3 * 512, SEEK_SET) < 0) { - goto fail; - } + offset = 3 * 512; memset(buf, 0xFF, 512); for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++) { - if (write(fd, buf, 512) != 512) { + ret = bdrv_pwrite_sync(bs, offset, buf, 512); + if (ret < 0) { goto fail; } + offset += 512; } // Prepare the Dynamic Disk Header @@ -700,48 +699,44 @@ static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors) * Note: The spec is actually wrong here for data_offset, it says * 0xFFFFFFFF, but MS tools expect all 64 bits to be set. */ - dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL); - dyndisk_header->table_offset = be64_to_cpu(3 * 512); - dyndisk_header->version = be32_to_cpu(0x00010000); - dyndisk_header->block_size = be32_to_cpu(block_size); - dyndisk_header->max_table_entries = be32_to_cpu(num_bat_entries); + dyndisk_header->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL); + dyndisk_header->table_offset = cpu_to_be64(3 * 512); + dyndisk_header->version = cpu_to_be32(0x00010000); + dyndisk_header->block_size = cpu_to_be32(block_size); + dyndisk_header->max_table_entries = cpu_to_be32(num_bat_entries); - dyndisk_header->checksum = be32_to_cpu(vpc_checksum(buf, 1024)); + dyndisk_header->checksum = cpu_to_be32(vpc_checksum(buf, 1024)); // Write the header - if (lseek(fd, 512, SEEK_SET) < 0) { - goto fail; - } + offset = 512; - if (write(fd, buf, 1024) != 1024) { + ret = bdrv_pwrite_sync(bs, offset, buf, 1024); + if (ret < 0) { goto fail; } - ret = 0; fail: return ret; } -static int create_fixed_disk(int fd, uint8_t *buf, int64_t total_size) +static int create_fixed_disk(BlockDriverState *bs, uint8_t *buf, + int64_t total_size) { - int ret = -EIO; + int ret; /* Add footer to total size */ - total_size += 512; - if (ftruncate(fd, total_size) != 0) { - ret = -errno; - goto fail; - } - if (lseek(fd, -512, SEEK_END) < 0) { - goto fail; - } - if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) { - goto fail; + total_size += HEADER_SIZE; + + ret = bdrv_truncate(bs, total_size); + if (ret < 0) { + return ret; } - ret = 0; + ret = bdrv_pwrite_sync(bs, total_size - HEADER_SIZE, buf, HEADER_SIZE); + if (ret < 0) { + return ret; + } - fail: return ret; } @@ -750,7 +745,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) uint8_t buf[1024]; VHDFooter *footer = (VHDFooter *) buf; char *disk_type_param; - int fd, i; + int i; uint16_t cyls = 0; uint8_t heads = 0; uint8_t secs_per_cyl = 0; @@ -758,10 +753,12 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) int64_t total_size; int disk_type; int ret = -EIO; - bool nocow = false; + Error *local_err = NULL; + BlockDriverState *bs = NULL; /* Read out options */ - total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); + total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); disk_type_param = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); if (disk_type_param) { if (!strcmp(disk_type_param, "dynamic")) { @@ -775,28 +772,17 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) } else { disk_type = VHD_DYNAMIC; } - nocow = qemu_opt_get_bool_del(opts, BLOCK_OPT_NOCOW, false); - /* Create the file */ - fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - if (fd < 0) { - ret = -EIO; + ret = bdrv_create_file(filename, opts, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); goto out; } - - if (nocow) { -#ifdef __linux__ - /* Set NOCOW flag to solve performance issue on fs like btrfs. - * This is an optimisation. The FS_IOC_SETFLAGS ioctl return value will - * be ignored since any failure of this operation should not block the - * left work. - */ - int attr; - if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0) { - attr |= FS_NOCOW_FL; - ioctl(fd, FS_IOC_SETFLAGS, &attr); - } -#endif + ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, + NULL, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); + goto out; } /* @@ -810,7 +796,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) &secs_per_cyl)) { ret = -EFBIG; - goto fail; + goto out; } } @@ -824,46 +810,45 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) memcpy(footer->creator_app, "qemu", 4); memcpy(footer->creator_os, "Wi2k", 4); - footer->features = be32_to_cpu(0x02); - footer->version = be32_to_cpu(0x00010000); + footer->features = cpu_to_be32(0x02); + footer->version = cpu_to_be32(0x00010000); if (disk_type == VHD_DYNAMIC) { - footer->data_offset = be64_to_cpu(HEADER_SIZE); + footer->data_offset = cpu_to_be64(HEADER_SIZE); } else { - footer->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL); + footer->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL); } - footer->timestamp = be32_to_cpu(time(NULL) - VHD_TIMESTAMP_BASE); + footer->timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE); /* Version of Virtual PC 2007 */ - footer->major = be16_to_cpu(0x0005); - footer->minor = be16_to_cpu(0x0003); + footer->major = cpu_to_be16(0x0005); + footer->minor = cpu_to_be16(0x0003); if (disk_type == VHD_DYNAMIC) { - footer->orig_size = be64_to_cpu(total_sectors * 512); - footer->size = be64_to_cpu(total_sectors * 512); + footer->orig_size = cpu_to_be64(total_sectors * 512); + footer->size = cpu_to_be64(total_sectors * 512); } else { - footer->orig_size = be64_to_cpu(total_size); - footer->size = be64_to_cpu(total_size); + footer->orig_size = cpu_to_be64(total_size); + footer->size = cpu_to_be64(total_size); } - footer->cyls = be16_to_cpu(cyls); + footer->cyls = cpu_to_be16(cyls); footer->heads = heads; footer->secs_per_cyl = secs_per_cyl; - footer->type = be32_to_cpu(disk_type); + footer->type = cpu_to_be32(disk_type); #if defined(CONFIG_UUID) uuid_generate(footer->uuid); #endif - footer->checksum = be32_to_cpu(vpc_checksum(buf, HEADER_SIZE)); + footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE)); if (disk_type == VHD_DYNAMIC) { - ret = create_dynamic_disk(fd, buf, total_sectors); + ret = create_dynamic_disk(bs, buf, total_sectors); } else { - ret = create_fixed_disk(fd, buf, total_size); + ret = create_fixed_disk(bs, buf, total_size); } -fail: - qemu_close(fd); out: + bdrv_unref(bs); g_free(disk_type_param); return ret; } @@ -873,7 +858,7 @@ static int vpc_has_zero_init(BlockDriverState *bs) BDRVVPCState *s = bs->opaque; VHDFooter *footer = (VHDFooter *) s->footer_buf; - if (cpu_to_be32(footer->type) == VHD_FIXED) { + if (be32_to_cpu(footer->type) == VHD_FIXED) { return bdrv_has_zero_init(bs->file); } else { return 1; |