Revision 73c632ed block/qcow2.c
b/block/qcow2.c | ||
---|---|---|
62 | 62 |
|
63 | 63 |
#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */ |
64 | 64 |
|
65 |
#define MIN_CLUSTER_BITS 9 |
|
66 |
#define MAX_CLUSTER_BITS 16 |
|
67 |
|
|
65 | 68 |
typedef struct QCowHeader { |
66 | 69 |
uint32_t magic; |
67 | 70 |
uint32_t version; |
... | ... | |
300 | 303 |
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) |
301 | 304 |
goto fail; |
302 | 305 |
if (header.size <= 1 || |
303 |
header.cluster_bits < 9 ||
|
|
304 |
header.cluster_bits > 16)
|
|
306 |
header.cluster_bits < MIN_CLUSTER_BITS ||
|
|
307 |
header.cluster_bits > MAX_CLUSTER_BITS)
|
|
305 | 308 |
goto fail; |
306 | 309 |
if (header.crypt_method > QCOW_CRYPT_AES) |
307 | 310 |
goto fail; |
... | ... | |
1583 | 1586 |
} |
1584 | 1587 |
} |
1585 | 1588 |
|
1589 |
static int get_bits_from_size(size_t size) |
|
1590 |
{ |
|
1591 |
int res = 0; |
|
1592 |
|
|
1593 |
if (size == 0) { |
|
1594 |
return -1; |
|
1595 |
} |
|
1596 |
|
|
1597 |
while (size != 1) { |
|
1598 |
/* Not a power of two */ |
|
1599 |
if (size & 1) { |
|
1600 |
return -1; |
|
1601 |
} |
|
1602 |
|
|
1603 |
size >>= 1; |
|
1604 |
res++; |
|
1605 |
} |
|
1606 |
|
|
1607 |
return res; |
|
1608 |
} |
|
1609 |
|
|
1586 | 1610 |
static int qcow_create2(const char *filename, int64_t total_size, |
1587 | 1611 |
const char *backing_file, const char *backing_format, |
1588 |
int flags) |
|
1612 |
int flags, size_t cluster_size)
|
|
1589 | 1613 |
{ |
1590 | 1614 |
|
1591 | 1615 |
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; |
... | ... | |
1619 | 1643 |
header.backing_file_size = cpu_to_be32(backing_filename_len); |
1620 | 1644 |
header_size += backing_filename_len; |
1621 | 1645 |
} |
1622 |
s->cluster_bits = 12; /* 4 KB clusters */ |
|
1646 |
|
|
1647 |
/* Cluster size */ |
|
1648 |
s->cluster_bits = get_bits_from_size(cluster_size); |
|
1649 |
if (s->cluster_bits < MIN_CLUSTER_BITS || |
|
1650 |
s->cluster_bits > MAX_CLUSTER_BITS) |
|
1651 |
{ |
|
1652 |
fprintf(stderr, "Cluster size must be a power of two between " |
|
1653 |
"%d and %dk\n", |
|
1654 |
1 << MIN_CLUSTER_BITS, |
|
1655 |
1 << (MAX_CLUSTER_BITS - 10)); |
|
1656 |
return -EINVAL; |
|
1657 |
} |
|
1623 | 1658 |
s->cluster_size = 1 << s->cluster_bits; |
1659 |
|
|
1624 | 1660 |
header.cluster_bits = cpu_to_be32(s->cluster_bits); |
1625 | 1661 |
header_size = (header_size + 7) & ~7; |
1626 | 1662 |
if (flags & BLOCK_FLAG_ENCRYPT) { |
... | ... | |
1702 | 1738 |
const char *backing_fmt = NULL; |
1703 | 1739 |
uint64_t sectors = 0; |
1704 | 1740 |
int flags = 0; |
1741 |
size_t cluster_size = 4096; |
|
1705 | 1742 |
|
1706 | 1743 |
/* Read out options */ |
1707 | 1744 |
while (options && options->name) { |
... | ... | |
1713 | 1750 |
backing_fmt = options->value.s; |
1714 | 1751 |
} else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { |
1715 | 1752 |
flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; |
1753 |
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { |
|
1754 |
if (options->value.n) { |
|
1755 |
cluster_size = options->value.n; |
|
1756 |
} |
|
1716 | 1757 |
} |
1717 | 1758 |
options++; |
1718 | 1759 |
} |
1719 | 1760 |
|
1720 |
return qcow_create2(filename, sectors, backing_file, backing_fmt, flags); |
|
1761 |
return qcow_create2(filename, sectors, backing_file, backing_fmt, flags, |
|
1762 |
cluster_size); |
|
1721 | 1763 |
} |
1722 | 1764 |
|
1723 | 1765 |
static int qcow_make_empty(BlockDriverState *bs) |
... | ... | |
2920 | 2962 |
{ BLOCK_OPT_BACKING_FILE, OPT_STRING }, |
2921 | 2963 |
{ BLOCK_OPT_BACKING_FMT, OPT_STRING }, |
2922 | 2964 |
{ BLOCK_OPT_ENCRYPT, OPT_FLAG }, |
2965 |
{ BLOCK_OPT_CLUSTER_SIZE, OPT_SIZE }, |
|
2923 | 2966 |
{ NULL } |
2924 | 2967 |
}; |
2925 | 2968 |
|
Also available in: Unified diff