Revision 917703c1 block/vmdk.c

b/block/vmdk.c
1452 1452
}
1453 1453

  
1454 1454
static int vmdk_create_extent(const char *filename, int64_t filesize,
1455
                              bool flat, bool compress, bool zeroed_grain)
1455
                              bool flat, bool compress, bool zeroed_grain,
1456
                              Error **errp)
1456 1457
{
1457 1458
    int ret, i;
1458
    int fd = 0;
1459
    BlockDriverState *bs = NULL;
1459 1460
    VMDK4Header header;
1460
    uint32_t tmp, magic, grains, gd_size, gt_size, gt_count;
1461
    Error *local_err;
1462
    uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;
1463
    uint32_t *gd_buf = NULL;
1464
    int gd_buf_size;
1461 1465

  
1462
    fd = qemu_open(filename,
1463
                   O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
1464
                   0644);
1465
    if (fd < 0) {
1466
        return -errno;
1466
    ret = bdrv_create_file(filename, NULL, &local_err);
1467
    if (ret < 0) {
1468
        error_propagate(errp, local_err);
1469
        goto exit;
1467 1470
    }
1471

  
1472
    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
1473
    if (ret < 0) {
1474
        error_propagate(errp, local_err);
1475
        goto exit;
1476
    }
1477

  
1468 1478
    if (flat) {
1469
        ret = ftruncate(fd, filesize);
1479
        ret = bdrv_truncate(bs, filesize);
1470 1480
        if (ret < 0) {
1471
            ret = -errno;
1481
            error_setg(errp, "Could not truncate file");
1472 1482
        }
1473 1483
        goto exit;
1474 1484
    }
......
1479 1489
                   | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0)
1480 1490
                   | (zeroed_grain ? VMDK4_FLAG_ZERO_GRAIN : 0);
1481 1491
    header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
1482
    header.capacity = filesize / 512;
1492
    header.capacity = filesize / BDRV_SECTOR_SIZE;
1483 1493
    header.granularity = 128;
1484
    header.num_gtes_per_gt = 512;
1494
    header.num_gtes_per_gt = BDRV_SECTOR_SIZE;
1485 1495

  
1486
    grains = (filesize / 512 + header.granularity - 1) / header.granularity;
1487
    gt_size = ((header.num_gtes_per_gt * sizeof(uint32_t)) + 511) >> 9;
1488
    gt_count =
1489
        (grains + header.num_gtes_per_gt - 1) / header.num_gtes_per_gt;
1490
    gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
1496
    grains = DIV_ROUND_UP(filesize / BDRV_SECTOR_SIZE, header.granularity);
1497
    gt_size = DIV_ROUND_UP(header.num_gtes_per_gt * sizeof(uint32_t),
1498
                           BDRV_SECTOR_SIZE);
1499
    gt_count = DIV_ROUND_UP(grains, header.num_gtes_per_gt);
1500
    gd_sectors = DIV_ROUND_UP(gt_count * sizeof(uint32_t), BDRV_SECTOR_SIZE);
1491 1501

  
1492 1502
    header.desc_offset = 1;
1493 1503
    header.desc_size = 20;
1494 1504
    header.rgd_offset = header.desc_offset + header.desc_size;
1495
    header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
1505
    header.gd_offset = header.rgd_offset + gd_sectors + (gt_size * gt_count);
1496 1506
    header.grain_offset =
1497
       ((header.gd_offset + gd_size + (gt_size * gt_count) +
1498
         header.granularity - 1) / header.granularity) *
1499
        header.granularity;
1507
        ROUND_UP(header.gd_offset + gd_sectors + (gt_size * gt_count),
1508
                 header.granularity);
1500 1509
    /* swap endianness for all header fields */
1501 1510
    header.version = cpu_to_le32(header.version);
1502 1511
    header.flags = cpu_to_le32(header.flags);
......
1516 1525
    header.check_bytes[3] = 0xa;
1517 1526

  
1518 1527
    /* write all the data */
1519
    ret = qemu_write_full(fd, &magic, sizeof(magic));
1520
    if (ret != sizeof(magic)) {
1521
        ret = -errno;
1528
    ret = bdrv_pwrite(bs, 0, &magic, sizeof(magic));
1529
    if (ret < 0) {
1530
        error_set(errp, QERR_IO_ERROR);
1522 1531
        goto exit;
1523 1532
    }
1524
    ret = qemu_write_full(fd, &header, sizeof(header));
1525
    if (ret != sizeof(header)) {
1526
        ret = -errno;
1533
    ret = bdrv_pwrite(bs, sizeof(magic), &header, sizeof(header));
1534
    if (ret < 0) {
1535
        error_set(errp, QERR_IO_ERROR);
1527 1536
        goto exit;
1528 1537
    }
1529 1538

  
1530
    ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9);
1539
    ret = bdrv_truncate(bs, le64_to_cpu(header.grain_offset) << 9);
1531 1540
    if (ret < 0) {
1532
        ret = -errno;
1541
        error_setg(errp, "Could not truncate file");
1533 1542
        goto exit;
1534 1543
    }
1535 1544

  
1536 1545
    /* write grain directory */
1537
    lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
1538
    for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size;
1546
    gd_buf_size = gd_sectors * BDRV_SECTOR_SIZE;
1547
    gd_buf = g_malloc0(gd_buf_size);
1548
    for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_sectors;
1539 1549
         i < gt_count; i++, tmp += gt_size) {
1540
        ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1541
        if (ret != sizeof(tmp)) {
1542
            ret = -errno;
1543
            goto exit;
1544
        }
1550
        gd_buf[i] = cpu_to_le32(tmp);
1551
    }
1552
    ret = bdrv_pwrite(bs, le64_to_cpu(header.rgd_offset) * BDRV_SECTOR_SIZE,
1553
                      gd_buf, gd_buf_size);
1554
    if (ret < 0) {
1555
        error_set(errp, QERR_IO_ERROR);
1556
        goto exit;
1545 1557
    }
1546 1558

  
1547 1559
    /* write backup grain directory */
1548
    lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
1549
    for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size;
1560
    for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_sectors;
1550 1561
         i < gt_count; i++, tmp += gt_size) {
1551
        ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1552
        if (ret != sizeof(tmp)) {
1553
            ret = -errno;
1554
            goto exit;
1555
        }
1562
        gd_buf[i] = cpu_to_le32(tmp);
1563
    }
1564
    ret = bdrv_pwrite(bs, le64_to_cpu(header.gd_offset) * BDRV_SECTOR_SIZE,
1565
                      gd_buf, gd_buf_size);
1566
    if (ret < 0) {
1567
        error_set(errp, QERR_IO_ERROR);
1568
        goto exit;
1556 1569
    }
1557 1570

  
1558 1571
    ret = 0;
1559
 exit:
1560
    qemu_close(fd);
1572
exit:
1573
    if (bs) {
1574
        bdrv_unref(bs);
1575
    }
1576
    g_free(gd_buf);
1561 1577
    return ret;
1562 1578
}
1563 1579

  
......
1604 1620
static int vmdk_create(const char *filename, QEMUOptionParameter *options,
1605 1621
                       Error **errp)
1606 1622
{
1607
    int fd, idx = 0;
1623
    int idx = 0;
1624
    BlockDriverState *new_bs = NULL;
1625
    Error *local_err;
1608 1626
    char *desc = NULL;
1609 1627
    int64_t total_size = 0, filesize;
1610 1628
    const char *adapter_type = NULL;
......
1621 1639
    uint32_t parent_cid = 0xffffffff;
1622 1640
    uint32_t number_heads = 16;
1623 1641
    bool zeroed_grain = false;
1642
    uint32_t desc_offset = 0, desc_len;
1624 1643
    const char desc_template[] =
1625 1644
        "# Disk DescriptorFile\n"
1626 1645
        "version=1\n"
......
1754 1773
                path, desc_filename);
1755 1774

  
1756 1775
        if (vmdk_create_extent(ext_filename, size,
1757
                               flat, compress, zeroed_grain)) {
1776
                               flat, compress, zeroed_grain, errp)) {
1758 1777
            ret = -EINVAL;
1759 1778
            goto exit;
1760 1779
        }
......
1762 1781

  
1763 1782
        /* Format description line */
1764 1783
        snprintf(desc_line, sizeof(desc_line),
1765
                    desc_extent_line, size / 512, desc_filename);
1784
                    desc_extent_line, size / BDRV_SECTOR_SIZE, desc_filename);
1766 1785
        g_string_append(ext_desc_lines, desc_line);
1767 1786
    }
1768 1787
    /* generate descriptor file */
......
1773 1792
                           parent_desc_line,
1774 1793
                           ext_desc_lines->str,
1775 1794
                           (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
1776
                           total_size / (int64_t)(63 * number_heads * 512),
1795
                           total_size /
1796
                               (int64_t)(63 * number_heads * BDRV_SECTOR_SIZE),
1777 1797
                           number_heads,
1778 1798
                           adapter_type);
1779
    if (split || flat) {
1780
        fd = qemu_open(filename,
1781
                       O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
1782
                       0644);
1799
    desc_len = strlen(desc);
1800
    /* the descriptor offset = 0x200 */
1801
    if (!split && !flat) {
1802
        desc_offset = 0x200;
1783 1803
    } else {
1784
        fd = qemu_open(filename,
1785
                       O_WRONLY | O_BINARY | O_LARGEFILE,
1786
                       0644);
1804
        ret = bdrv_create_file(filename, options, &local_err);
1805
        if (ret < 0) {
1806
            error_setg_errno(errp, -ret, "Could not create image file");
1807
            goto exit;
1808
        }
1787 1809
    }
1788
    if (fd < 0) {
1789
        ret = -errno;
1810
    ret = bdrv_file_open(&new_bs, filename, NULL, BDRV_O_RDWR, &local_err);
1811
    if (ret < 0) {
1812
        error_setg_errno(errp, -ret, "Could not write description");
1790 1813
        goto exit;
1791 1814
    }
1792
    /* the descriptor offset = 0x200 */
1793
    if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
1794
        ret = -errno;
1795
        goto close_exit;
1815
    ret = bdrv_pwrite(new_bs, desc_offset, desc, desc_len);
1816
    if (ret < 0) {
1817
        error_setg_errno(errp, -ret, "Could not write description");
1818
        goto exit;
1796 1819
    }
1797
    ret = qemu_write_full(fd, desc, strlen(desc));
1798
    if (ret != strlen(desc)) {
1799
        ret = -errno;
1800
        goto close_exit;
1820
    /* bdrv_pwrite write padding zeros to align to sector, we don't need that
1821
     * for description file */
1822
    if (desc_offset == 0) {
1823
        ret = bdrv_truncate(new_bs, desc_len);
1824
        if (ret < 0) {
1825
            error_setg(errp, "Could not truncate file");
1826
        }
1801 1827
    }
1802
    ret = 0;
1803
close_exit:
1804
    qemu_close(fd);
1805 1828
exit:
1829
    if (new_bs) {
1830
        bdrv_unref(new_bs);
1831
    }
1806 1832
    g_free(desc);
1807 1833
    g_string_free(ext_desc_lines, true);
1808 1834
    return ret;

Also available in: Unified diff