1
The following changes since commit 33d609990621dea6c7d056c86f707b8811320ac1:
1
The following changes since commit 474f3938d79ab36b9231c9ad3b5a9314c2aeacde:
2
2
3
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2019-06-18 17:00:52 +0100)
3
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jun-21-2019' into staging (2019-06-21 15:40:50 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2019-06-21
7
https://github.com/XanClic/qemu.git tags/pull-block-2019-06-24
8
8
9
for you to fetch changes up to e2a76186f7948b8b75d1b2b52638de7c2f7f7472:
9
for you to fetch changes up to ab5d4a30f7f3803ca5106b370969c1b7b54136f8:
10
10
11
iotests: Fix 205 for concurrent runs (2019-06-21 14:40:28 +0200)
11
iotests: Fix 205 for concurrent runs (2019-06-24 16:01:40 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Block patches:
15
- The SSH block driver now uses libssh instead of libssh2
15
- The SSH block driver now uses libssh instead of libssh2
16
- The VMDK block driver gets read-only support for the seSparse
16
- The VMDK block driver gets read-only support for the seSparse
17
subformat
17
subformat
18
- Various fixes
18
- Various fixes
19
20
---
21
22
v2:
23
- Squashed Pino's fix for pre-0.8 libssh into the libssh patch
19
24
20
----------------------------------------------------------------
25
----------------------------------------------------------------
21
Anton Nefedov (1):
26
Anton Nefedov (1):
22
iotest 134: test cluster-misaligned encrypted write
27
iotest 134: test cluster-misaligned encrypted write
23
28
...
...
38
Vladimir Sementsov-Ogievskiy (1):
43
Vladimir Sementsov-Ogievskiy (1):
39
blockdev: enable non-root nodes for transaction drive-backup source
44
blockdev: enable non-root nodes for transaction drive-backup source
40
45
41
configure | 65 +-
46
configure | 65 +-
42
block/Makefile.objs | 6 +-
47
block/Makefile.objs | 6 +-
43
block/ssh.c | 673 ++++++++++--------
48
block/ssh.c | 652 ++++++++++--------
44
block/vmdk.c | 372 +++++++++-
49
block/vmdk.c | 372 +++++++++-
45
blockdev.c | 2 +-
50
blockdev.c | 2 +-
46
hw/block/nvme.c | 1 -
51
hw/block/nvme.c | 1 -
47
.travis.yml | 4 +-
52
.travis.yml | 4 +-
48
block/trace-events | 14 +-
53
block/trace-events | 14 +-
...
...
56
tests/qemu-iotests/134 | 9 +
61
tests/qemu-iotests/134 | 9 +
57
tests/qemu-iotests/134.out | 10 +
62
tests/qemu-iotests/134.out | 10 +
58
tests/qemu-iotests/205 | 2 +-
63
tests/qemu-iotests/205 | 2 +-
59
tests/qemu-iotests/207 | 54 +-
64
tests/qemu-iotests/207 | 54 +-
60
tests/qemu-iotests/207.out | 2 +-
65
tests/qemu-iotests/207.out | 2 +-
61
20 files changed, 844 insertions(+), 384 deletions(-)
66
20 files changed, 823 insertions(+), 384 deletions(-)
62
67
63
--
68
--
64
2.21.0
69
2.21.0
65
70
66
71
diff view generated by jsdifflib
1
From: Klaus Birkelund Jensen <klaus@birkelund.eu>
1
From: Klaus Birkelund Jensen <klaus@birkelund.eu>
2
2
3
The device mistakenly reports that the Weighted Round Robin with Urgent
3
The device mistakenly reports that the Weighted Round Robin with Urgent
4
Priority Class arbitration mechanism is supported.
4
Priority Class arbitration mechanism is supported.
5
5
6
It is not.
6
It is not.
7
7
8
Signed-off-by: Klaus Birkelund Jensen <klaus.jensen@cnexlabs.com>
8
Signed-off-by: Klaus Birkelund Jensen <klaus.jensen@cnexlabs.com>
9
Message-id: 20190606092530.14206-1-klaus@birkelund.eu
9
Message-id: 20190606092530.14206-1-klaus@birkelund.eu
10
Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
12
---
13
hw/block/nvme.c | 1 -
13
hw/block/nvme.c | 1 -
14
1 file changed, 1 deletion(-)
14
1 file changed, 1 deletion(-)
15
15
16
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
16
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/block/nvme.c
18
--- a/hw/block/nvme.c
19
+++ b/hw/block/nvme.c
19
+++ b/hw/block/nvme.c
20
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
20
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
21
n->bar.cap = 0;
21
n->bar.cap = 0;
22
NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
22
NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
23
NVME_CAP_SET_CQR(n->bar.cap, 1);
23
NVME_CAP_SET_CQR(n->bar.cap, 1);
24
- NVME_CAP_SET_AMS(n->bar.cap, 1);
24
- NVME_CAP_SET_AMS(n->bar.cap, 1);
25
NVME_CAP_SET_TO(n->bar.cap, 0xf);
25
NVME_CAP_SET_TO(n->bar.cap, 0xf);
26
NVME_CAP_SET_CSS(n->bar.cap, 1);
26
NVME_CAP_SET_CSS(n->bar.cap, 1);
27
NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
27
NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
28
--
28
--
29
2.21.0
29
2.21.0
30
30
31
31
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
We forget to enable it for transaction .prepare, while it is already
3
We forget to enable it for transaction .prepare, while it is already
4
enabled in do_drive_backup since commit a2d665c1bc362
4
enabled in do_drive_backup since commit a2d665c1bc362
5
"blockdev: loosen restrictions on drive-backup source node"
5
"blockdev: loosen restrictions on drive-backup source node"
6
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-id: 20190618140804.59214-1-vsementsov@virtuozzo.com
8
Message-id: 20190618140804.59214-1-vsementsov@virtuozzo.com
9
Reviewed-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
11
---
12
blockdev.c | 2 +-
12
blockdev.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
14
15
diff --git a/blockdev.c b/blockdev.c
15
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/blockdev.c
17
--- a/blockdev.c
18
+++ b/blockdev.c
18
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
20
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
20
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
21
backup = common->action->u.drive_backup.data;
21
backup = common->action->u.drive_backup.data;
22
22
23
- bs = qmp_get_root_bs(backup->device, errp);
23
- bs = qmp_get_root_bs(backup->device, errp);
24
+ bs = bdrv_lookup_bs(backup->device, backup->device, errp);
24
+ bs = bdrv_lookup_bs(backup->device, backup->device, errp);
25
if (!bs) {
25
if (!bs) {
26
return;
26
return;
27
}
27
}
28
--
28
--
29
2.21.0
29
2.21.0
30
30
31
31
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
2
2
3
COW (even empty/zero) areas require encryption too
3
COW (even empty/zero) areas require encryption too
4
4
5
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
5
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-id: 20190516143028.81155-1-anton.nefedov@virtuozzo.com
9
Message-id: 20190516143028.81155-1-anton.nefedov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
11
---
12
tests/qemu-iotests/134 | 9 +++++++++
12
tests/qemu-iotests/134 | 9 +++++++++
13
tests/qemu-iotests/134.out | 10 ++++++++++
13
tests/qemu-iotests/134.out | 10 ++++++++++
14
2 files changed, 19 insertions(+)
14
2 files changed, 19 insertions(+)
15
15
16
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
16
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
17
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/134
18
--- a/tests/qemu-iotests/134
19
+++ b/tests/qemu-iotests/134
19
+++ b/tests/qemu-iotests/134
20
@@ -XXX,XX +XXX,XX @@ echo
20
@@ -XXX,XX +XXX,XX @@ echo
21
echo "== reading whole image =="
21
echo "== reading whole image =="
22
$QEMU_IO --object $SECRET -c "read 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
22
$QEMU_IO --object $SECRET -c "read 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
23
23
24
+echo
24
+echo
25
+echo "== rewriting cluster part =="
25
+echo "== rewriting cluster part =="
26
+$QEMU_IO --object $SECRET -c "write -P 0xb 512 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
26
+$QEMU_IO --object $SECRET -c "write -P 0xb 512 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
27
+
27
+
28
+echo
28
+echo
29
+echo "== verify pattern =="
29
+echo "== verify pattern =="
30
+$QEMU_IO --object $SECRET -c "read -P 0 0 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
30
+$QEMU_IO --object $SECRET -c "read -P 0 0 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
31
+$QEMU_IO --object $SECRET -c "read -P 0xb 512 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
31
+$QEMU_IO --object $SECRET -c "read -P 0xb 512 512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
32
+
32
+
33
echo
33
echo
34
echo "== rewriting whole image =="
34
echo "== rewriting whole image =="
35
$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
35
$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
36
diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out
36
diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out
37
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/134.out
38
--- a/tests/qemu-iotests/134.out
39
+++ b/tests/qemu-iotests/134.out
39
+++ b/tests/qemu-iotests/134.out
40
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.
40
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.
41
read 134217728/134217728 bytes at offset 0
41
read 134217728/134217728 bytes at offset 0
42
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
42
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
43
43
44
+== rewriting cluster part ==
44
+== rewriting cluster part ==
45
+wrote 512/512 bytes at offset 512
45
+wrote 512/512 bytes at offset 512
46
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
46
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
47
+
47
+
48
+== verify pattern ==
48
+== verify pattern ==
49
+read 512/512 bytes at offset 0
49
+read 512/512 bytes at offset 0
50
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
50
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
51
+read 512/512 bytes at offset 512
51
+read 512/512 bytes at offset 512
52
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
52
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
+
53
+
54
== rewriting whole image ==
54
== rewriting whole image ==
55
wrote 134217728/134217728 bytes at offset 0
55
wrote 134217728/134217728 bytes at offset 0
56
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
56
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
57
--
57
--
58
2.21.0
58
2.21.0
59
59
60
60
diff view generated by jsdifflib
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
2
2
3
Commit b0651b8c246d ("vmdk: Move l1_size check into vmdk_add_extent")
3
Commit b0651b8c246d ("vmdk: Move l1_size check into vmdk_add_extent")
4
extended the l1_size check from VMDK4 to VMDK3 but did not update the
4
extended the l1_size check from VMDK4 to VMDK3 but did not update the
5
default coverage in the moved comment.
5
default coverage in the moved comment.
6
6
7
The previous vmdk4 calculation:
7
The previous vmdk4 calculation:
8
8
9
(512 * 1024 * 1024) * 512(l2 entries) * 65536(grain) = 16PB
9
(512 * 1024 * 1024) * 512(l2 entries) * 65536(grain) = 16PB
10
10
11
The added vmdk3 calculation:
11
The added vmdk3 calculation:
12
12
13
(512 * 1024 * 1024) * 4096(l2 entries) * 512(grain) = 1PB
13
(512 * 1024 * 1024) * 4096(l2 entries) * 512(grain) = 1PB
14
14
15
Adding the calculation of vmdk3 to the comment.
15
Adding the calculation of vmdk3 to the comment.
16
16
17
In any case, VMware does not offer virtual disks more than 2TB for
17
In any case, VMware does not offer virtual disks more than 2TB for
18
vmdk4/vmdk3 or 64TB for the new undocumented seSparse format which is
18
vmdk4/vmdk3 or 64TB for the new undocumented seSparse format which is
19
not implemented yet in qemu.
19
not implemented yet in qemu.
20
20
21
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
21
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
22
Reviewed-by: Eyal Moscovici <eyal.moscovici@oracle.com>
22
Reviewed-by: Eyal Moscovici <eyal.moscovici@oracle.com>
23
Reviewed-by: Liran Alon <liran.alon@oracle.com>
23
Reviewed-by: Liran Alon <liran.alon@oracle.com>
24
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
24
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
25
Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com>
25
Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com>
26
Message-id: 20190620091057.47441-2-shmuel.eiderman@oracle.com
26
Message-id: 20190620091057.47441-2-shmuel.eiderman@oracle.com
27
Reviewed-by: yuchenlin <yuchenlin@synology.com>
27
Reviewed-by: yuchenlin <yuchenlin@synology.com>
28
Reviewed-by: Max Reitz <mreitz@redhat.com>
28
Reviewed-by: Max Reitz <mreitz@redhat.com>
29
Signed-off-by: Max Reitz <mreitz@redhat.com>
29
Signed-off-by: Max Reitz <mreitz@redhat.com>
30
---
30
---
31
block/vmdk.c | 11 ++++++++---
31
block/vmdk.c | 11 ++++++++---
32
1 file changed, 8 insertions(+), 3 deletions(-)
32
1 file changed, 8 insertions(+), 3 deletions(-)
33
33
34
diff --git a/block/vmdk.c b/block/vmdk.c
34
diff --git a/block/vmdk.c b/block/vmdk.c
35
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/vmdk.c
36
--- a/block/vmdk.c
37
+++ b/block/vmdk.c
37
+++ b/block/vmdk.c
38
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
38
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
39
return -EFBIG;
39
return -EFBIG;
40
}
40
}
41
if (l1_size > 512 * 1024 * 1024) {
41
if (l1_size > 512 * 1024 * 1024) {
42
- /* Although with big capacity and small l1_entry_sectors, we can get a
42
- /* Although with big capacity and small l1_entry_sectors, we can get a
43
+ /*
43
+ /*
44
+ * Although with big capacity and small l1_entry_sectors, we can get a
44
+ * Although with big capacity and small l1_entry_sectors, we can get a
45
* big l1_size, we don't want unbounded value to allocate the table.
45
* big l1_size, we don't want unbounded value to allocate the table.
46
- * Limit it to 512M, which is 16PB for default cluster and L2 table
46
- * Limit it to 512M, which is 16PB for default cluster and L2 table
47
- * size */
47
- * size */
48
+ * Limit it to 512M, which is:
48
+ * Limit it to 512M, which is:
49
+ * 16PB - for default "Hosted Sparse Extent" (VMDK4)
49
+ * 16PB - for default "Hosted Sparse Extent" (VMDK4)
50
+ * cluster size: 64KB, L2 table size: 512 entries
50
+ * cluster size: 64KB, L2 table size: 512 entries
51
+ * 1PB - for default "ESXi Host Sparse Extent" (VMDK3/vmfsSparse)
51
+ * 1PB - for default "ESXi Host Sparse Extent" (VMDK3/vmfsSparse)
52
+ * cluster size: 512B, L2 table size: 4096 entries
52
+ * cluster size: 512B, L2 table size: 4096 entries
53
+ */
53
+ */
54
error_setg(errp, "L1 size too big");
54
error_setg(errp, "L1 size too big");
55
return -EFBIG;
55
return -EFBIG;
56
}
56
}
57
--
57
--
58
2.21.0
58
2.21.0
59
59
60
60
diff view generated by jsdifflib
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
2
2
3
512M of L1 entries is a very loose bound, only 32M are required to store
3
512M of L1 entries is a very loose bound, only 32M are required to store
4
the maximal supported VMDK file size of 2TB.
4
the maximal supported VMDK file size of 2TB.
5
5
6
Fixed qemu-iotest 59# - now failure occures before on impossible L1
6
Fixed qemu-iotest 59# - now failure occures before on impossible L1
7
table size.
7
table size.
8
8
9
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
9
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
10
Reviewed-by: Eyal Moscovici <eyal.moscovici@oracle.com>
10
Reviewed-by: Eyal Moscovici <eyal.moscovici@oracle.com>
11
Reviewed-by: Liran Alon <liran.alon@oracle.com>
11
Reviewed-by: Liran Alon <liran.alon@oracle.com>
12
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
12
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
13
Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com>
13
Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com>
14
Message-id: 20190620091057.47441-3-shmuel.eiderman@oracle.com
14
Message-id: 20190620091057.47441-3-shmuel.eiderman@oracle.com
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
17
---
18
block/vmdk.c | 13 +++++++------
18
block/vmdk.c | 13 +++++++------
19
tests/qemu-iotests/059.out | 2 +-
19
tests/qemu-iotests/059.out | 2 +-
20
2 files changed, 8 insertions(+), 7 deletions(-)
20
2 files changed, 8 insertions(+), 7 deletions(-)
21
21
22
diff --git a/block/vmdk.c b/block/vmdk.c
22
diff --git a/block/vmdk.c b/block/vmdk.c
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/vmdk.c
24
--- a/block/vmdk.c
25
+++ b/block/vmdk.c
25
+++ b/block/vmdk.c
26
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
26
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
27
error_setg(errp, "Invalid granularity, image may be corrupt");
27
error_setg(errp, "Invalid granularity, image may be corrupt");
28
return -EFBIG;
28
return -EFBIG;
29
}
29
}
30
- if (l1_size > 512 * 1024 * 1024) {
30
- if (l1_size > 512 * 1024 * 1024) {
31
+ if (l1_size > 32 * 1024 * 1024) {
31
+ if (l1_size > 32 * 1024 * 1024) {
32
/*
32
/*
33
* Although with big capacity and small l1_entry_sectors, we can get a
33
* Although with big capacity and small l1_entry_sectors, we can get a
34
* big l1_size, we don't want unbounded value to allocate the table.
34
* big l1_size, we don't want unbounded value to allocate the table.
35
- * Limit it to 512M, which is:
35
- * Limit it to 512M, which is:
36
- * 16PB - for default "Hosted Sparse Extent" (VMDK4)
36
- * 16PB - for default "Hosted Sparse Extent" (VMDK4)
37
- * cluster size: 64KB, L2 table size: 512 entries
37
- * cluster size: 64KB, L2 table size: 512 entries
38
- * 1PB - for default "ESXi Host Sparse Extent" (VMDK3/vmfsSparse)
38
- * 1PB - for default "ESXi Host Sparse Extent" (VMDK3/vmfsSparse)
39
- * cluster size: 512B, L2 table size: 4096 entries
39
- * cluster size: 512B, L2 table size: 4096 entries
40
+ * Limit it to 32M, which is enough to store:
40
+ * Limit it to 32M, which is enough to store:
41
+ * 8TB - for both VMDK3 & VMDK4 with
41
+ * 8TB - for both VMDK3 & VMDK4 with
42
+ * minimal cluster size: 512B
42
+ * minimal cluster size: 512B
43
+ * minimal L2 table size: 512 entries
43
+ * minimal L2 table size: 512 entries
44
+ * 8 TB is still more than the maximal value supported for
44
+ * 8 TB is still more than the maximal value supported for
45
+ * VMDK3 & VMDK4 which is 2TB.
45
+ * VMDK3 & VMDK4 which is 2TB.
46
*/
46
*/
47
error_setg(errp, "L1 size too big");
47
error_setg(errp, "L1 size too big");
48
return -EFBIG;
48
return -EFBIG;
49
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
49
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
50
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
51
--- a/tests/qemu-iotests/059.out
51
--- a/tests/qemu-iotests/059.out
52
+++ b/tests/qemu-iotests/059.out
52
+++ b/tests/qemu-iotests/059.out
53
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
53
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
54
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
54
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
55
55
56
=== Testing afl image with a very large capacity ===
56
=== Testing afl image with a very large capacity ===
57
-qemu-img: Can't get image size 'TEST_DIR/afl9.IMGFMT': File too large
57
-qemu-img: Can't get image size 'TEST_DIR/afl9.IMGFMT': File too large
58
+qemu-img: Could not open 'TEST_DIR/afl9.IMGFMT': L1 size too big
58
+qemu-img: Could not open 'TEST_DIR/afl9.IMGFMT': L1 size too big
59
*** done
59
*** done
60
--
60
--
61
2.21.0
61
2.21.0
62
62
63
63
diff view generated by jsdifflib
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
1
From: Sam Eiderman <shmuel.eiderman@oracle.com>
2
2
3
Until ESXi 6.5 VMware used the vmfsSparse format for snapshots (VMDK3 in
3
Until ESXi 6.5 VMware used the vmfsSparse format for snapshots (VMDK3 in
4
QEMU).
4
QEMU).
5
5
6
This format was lacking in the following:
6
This format was lacking in the following:
7
7
8
* Grain directory (L1) and grain table (L2) entries were 32-bit,
8
* Grain directory (L1) and grain table (L2) entries were 32-bit,
9
allowing access to only 2TB (slightly less) of data.
9
allowing access to only 2TB (slightly less) of data.
10
* The grain size (default) was 512 bytes - leading to data
10
* The grain size (default) was 512 bytes - leading to data
11
fragmentation and many grain tables.
11
fragmentation and many grain tables.
12
* For space reclamation purposes, it was necessary to find all the
12
* For space reclamation purposes, it was necessary to find all the
13
grains which are not pointed to by any grain table - so a reverse
13
grains which are not pointed to by any grain table - so a reverse
14
mapping of "offset of grain in vmdk" to "grain table" must be
14
mapping of "offset of grain in vmdk" to "grain table" must be
15
constructed - which takes large amounts of CPU/RAM.
15
constructed - which takes large amounts of CPU/RAM.
16
16
17
The format specification can be found in VMware's documentation:
17
The format specification can be found in VMware's documentation:
18
https://www.vmware.com/support/developer/vddk/vmdk_50_technote.pdf
18
https://www.vmware.com/support/developer/vddk/vmdk_50_technote.pdf
19
19
20
In ESXi 6.5, to support snapshot files larger than 2TB, a new format was
20
In ESXi 6.5, to support snapshot files larger than 2TB, a new format was
21
introduced: SESparse (Space Efficient).
21
introduced: SESparse (Space Efficient).
22
22
23
This format fixes the above issues:
23
This format fixes the above issues:
24
24
25
* All entries are now 64-bit.
25
* All entries are now 64-bit.
26
* The grain size (default) is 4KB.
26
* The grain size (default) is 4KB.
27
* Grain directory and grain tables are now located at the beginning
27
* Grain directory and grain tables are now located at the beginning
28
of the file.
28
of the file.
29
+ seSparse format reserves space for all grain tables.
29
+ seSparse format reserves space for all grain tables.
30
+ Grain tables can be addressed using an index.
30
+ Grain tables can be addressed using an index.
31
+ Grains are located in the end of the file and can also be
31
+ Grains are located in the end of the file and can also be
32
addressed with an index.
32
addressed with an index.
33
- seSparse vmdks of large disks (64TB) have huge preallocated
33
- seSparse vmdks of large disks (64TB) have huge preallocated
34
headers - mainly due to L2 tables, even for empty snapshots.
34
headers - mainly due to L2 tables, even for empty snapshots.
35
* The header contains a reverse mapping ("backmap") of "offset of
35
* The header contains a reverse mapping ("backmap") of "offset of
36
grain in vmdk" to "grain table" and a bitmap ("free bitmap") which
36
grain in vmdk" to "grain table" and a bitmap ("free bitmap") which
37
specifies for each grain - whether it is allocated or not.
37
specifies for each grain - whether it is allocated or not.
38
Using these data structures we can implement space reclamation
38
Using these data structures we can implement space reclamation
39
efficiently.
39
efficiently.
40
* Due to the fact that the header now maintains two mappings:
40
* Due to the fact that the header now maintains two mappings:
41
* The regular one (grain directory & grain tables)
41
* The regular one (grain directory & grain tables)
42
* A reverse one (backmap and free bitmap)
42
* A reverse one (backmap and free bitmap)
43
These data structures can lose consistency upon crash and result
43
These data structures can lose consistency upon crash and result
44
in a corrupted VMDK.
44
in a corrupted VMDK.
45
Therefore, a journal is also added to the VMDK and is replayed
45
Therefore, a journal is also added to the VMDK and is replayed
46
when the VMware reopens the file after a crash.
46
when the VMware reopens the file after a crash.
47
47
48
Since ESXi 6.7 - SESparse is the only snapshot format available.
48
Since ESXi 6.7 - SESparse is the only snapshot format available.
49
49
50
Unfortunately, VMware does not provide documentation regarding the new
50
Unfortunately, VMware does not provide documentation regarding the new
51
seSparse format.
51
seSparse format.
52
52
53
This commit is based on black-box research of the seSparse format.
53
This commit is based on black-box research of the seSparse format.
54
Various in-guest block operations and their effect on the snapshot file
54
Various in-guest block operations and their effect on the snapshot file
55
were tested.
55
were tested.
56
56
57
The only VMware provided source of information (regarding the underlying
57
The only VMware provided source of information (regarding the underlying
58
implementation) was a log file on the ESXi:
58
implementation) was a log file on the ESXi:
59
59
60
/var/log/hostd.log
60
/var/log/hostd.log
61
61
62
Whenever an seSparse snapshot is created - the log is being populated
62
Whenever an seSparse snapshot is created - the log is being populated
63
with seSparse records.
63
with seSparse records.
64
64
65
Relevant log records are of the form:
65
Relevant log records are of the form:
66
66
67
[...] Const Header:
67
[...] Const Header:
68
[...] constMagic = 0xcafebabe
68
[...] constMagic = 0xcafebabe
69
[...] version = 2.1
69
[...] version = 2.1
70
[...] capacity = 204800
70
[...] capacity = 204800
71
[...] grainSize = 8
71
[...] grainSize = 8
72
[...] grainTableSize = 64
72
[...] grainTableSize = 64
73
[...] flags = 0
73
[...] flags = 0
74
[...] Extents:
74
[...] Extents:
75
[...] Header : <1 : 1>
75
[...] Header : <1 : 1>
76
[...] JournalHdr : <2 : 2>
76
[...] JournalHdr : <2 : 2>
77
[...] Journal : <2048 : 2048>
77
[...] Journal : <2048 : 2048>
78
[...] GrainDirectory : <4096 : 2048>
78
[...] GrainDirectory : <4096 : 2048>
79
[...] GrainTables : <6144 : 2048>
79
[...] GrainTables : <6144 : 2048>
80
[...] FreeBitmap : <8192 : 2048>
80
[...] FreeBitmap : <8192 : 2048>
81
[...] BackMap : <10240 : 2048>
81
[...] BackMap : <10240 : 2048>
82
[...] Grain : <12288 : 204800>
82
[...] Grain : <12288 : 204800>
83
[...] Volatile Header:
83
[...] Volatile Header:
84
[...] volatileMagic = 0xcafecafe
84
[...] volatileMagic = 0xcafecafe
85
[...] FreeGTNumber = 0
85
[...] FreeGTNumber = 0
86
[...] nextTxnSeqNumber = 0
86
[...] nextTxnSeqNumber = 0
87
[...] replayJournal = 0
87
[...] replayJournal = 0
88
88
89
The sizes that are seen in the log file are in sectors.
89
The sizes that are seen in the log file are in sectors.
90
Extents are of the following format: <offset : size>
90
Extents are of the following format: <offset : size>
91
91
92
This commit is a strict implementation which enforces:
92
This commit is a strict implementation which enforces:
93
* magics
93
* magics
94
* version number 2.1
94
* version number 2.1
95
* grain size of 8 sectors (4KB)
95
* grain size of 8 sectors (4KB)
96
* grain table size of 64 sectors
96
* grain table size of 64 sectors
97
* zero flags
97
* zero flags
98
* extent locations
98
* extent locations
99
99
100
Additionally, this commit proivdes only a subset of the functionality
100
Additionally, this commit proivdes only a subset of the functionality
101
offered by seSparse's format:
101
offered by seSparse's format:
102
* Read-only
102
* Read-only
103
* No journal replay
103
* No journal replay
104
* No space reclamation
104
* No space reclamation
105
* No unmap support
105
* No unmap support
106
106
107
Hence, journal header, journal, free bitmap and backmap extents are
107
Hence, journal header, journal, free bitmap and backmap extents are
108
unused, only the "classic" (L1 -> L2 -> data) grain access is
108
unused, only the "classic" (L1 -> L2 -> data) grain access is
109
implemented.
109
implemented.
110
110
111
However there are several differences in the grain access itself.
111
However there are several differences in the grain access itself.
112
Grain directory (L1):
112
Grain directory (L1):
113
* Grain directory entries are indexes (not offsets) to grain
113
* Grain directory entries are indexes (not offsets) to grain
114
tables.
114
tables.
115
* Valid grain directory entries have their highest nibble set to
115
* Valid grain directory entries have their highest nibble set to
116
0x1.
116
0x1.
117
* Since grain tables are always located in the beginning of the
117
* Since grain tables are always located in the beginning of the
118
file - the index can fit into 32 bits - so we can use its low
118
file - the index can fit into 32 bits - so we can use its low
119
part if it's valid.
119
part if it's valid.
120
Grain table (L2):
120
Grain table (L2):
121
* Grain table entries are indexes (not offsets) to grains.
121
* Grain table entries are indexes (not offsets) to grains.
122
* If the highest nibble of the entry is:
122
* If the highest nibble of the entry is:
123
0x0:
123
0x0:
124
The grain in not allocated.
124
The grain in not allocated.
125
The rest of the bytes are 0.
125
The rest of the bytes are 0.
126
0x1:
126
0x1:
127
The grain is unmapped - guest sees a zero grain.
127
The grain is unmapped - guest sees a zero grain.
128
The rest of the bits point to the previously mapped grain,
128
The rest of the bits point to the previously mapped grain,
129
see 0x3 case.
129
see 0x3 case.
130
0x2:
130
0x2:
131
The grain is zero.
131
The grain is zero.
132
0x3:
132
0x3:
133
The grain is allocated - to get the index calculate:
133
The grain is allocated - to get the index calculate:
134
((entry & 0x0fff000000000000) >> 48) |
134
((entry & 0x0fff000000000000) >> 48) |
135
((entry & 0x0000ffffffffffff) << 12)
135
((entry & 0x0000ffffffffffff) << 12)
136
* The difference between 0x1 and 0x2 is that 0x1 is an unallocated
136
* The difference between 0x1 and 0x2 is that 0x1 is an unallocated
137
grain which results from the guest using sg_unmap to unmap the
137
grain which results from the guest using sg_unmap to unmap the
138
grain - but the grain itself still exists in the grain extent - a
138
grain - but the grain itself still exists in the grain extent - a
139
space reclamation procedure should delete it.
139
space reclamation procedure should delete it.
140
Unmapping a zero grain has no effect (0x2 will not change to 0x1)
140
Unmapping a zero grain has no effect (0x2 will not change to 0x1)
141
but unmapping an unallocated grain will (0x0 to 0x1) - naturally.
141
but unmapping an unallocated grain will (0x0 to 0x1) - naturally.
142
142
143
In order to implement seSparse some fields had to be changed to support
143
In order to implement seSparse some fields had to be changed to support
144
both 32-bit and 64-bit entry sizes.
144
both 32-bit and 64-bit entry sizes.
145
145
146
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
146
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
147
Reviewed-by: Eyal Moscovici <eyal.moscovici@oracle.com>
147
Reviewed-by: Eyal Moscovici <eyal.moscovici@oracle.com>
148
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
148
Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com>
149
Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com>
149
Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com>
150
Message-id: 20190620091057.47441-4-shmuel.eiderman@oracle.com
150
Message-id: 20190620091057.47441-4-shmuel.eiderman@oracle.com
151
Signed-off-by: Max Reitz <mreitz@redhat.com>
151
Signed-off-by: Max Reitz <mreitz@redhat.com>
152
---
152
---
153
block/vmdk.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++---
153
block/vmdk.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++---
154
1 file changed, 342 insertions(+), 16 deletions(-)
154
1 file changed, 342 insertions(+), 16 deletions(-)
155
155
156
diff --git a/block/vmdk.c b/block/vmdk.c
156
diff --git a/block/vmdk.c b/block/vmdk.c
157
index XXXXXXX..XXXXXXX 100644
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/vmdk.c
158
--- a/block/vmdk.c
159
+++ b/block/vmdk.c
159
+++ b/block/vmdk.c
160
@@ -XXX,XX +XXX,XX @@ typedef struct {
160
@@ -XXX,XX +XXX,XX @@ typedef struct {
161
uint16_t compressAlgorithm;
161
uint16_t compressAlgorithm;
162
} QEMU_PACKED VMDK4Header;
162
} QEMU_PACKED VMDK4Header;
163
163
164
+typedef struct VMDKSESparseConstHeader {
164
+typedef struct VMDKSESparseConstHeader {
165
+ uint64_t magic;
165
+ uint64_t magic;
166
+ uint64_t version;
166
+ uint64_t version;
167
+ uint64_t capacity;
167
+ uint64_t capacity;
168
+ uint64_t grain_size;
168
+ uint64_t grain_size;
169
+ uint64_t grain_table_size;
169
+ uint64_t grain_table_size;
170
+ uint64_t flags;
170
+ uint64_t flags;
171
+ uint64_t reserved1;
171
+ uint64_t reserved1;
172
+ uint64_t reserved2;
172
+ uint64_t reserved2;
173
+ uint64_t reserved3;
173
+ uint64_t reserved3;
174
+ uint64_t reserved4;
174
+ uint64_t reserved4;
175
+ uint64_t volatile_header_offset;
175
+ uint64_t volatile_header_offset;
176
+ uint64_t volatile_header_size;
176
+ uint64_t volatile_header_size;
177
+ uint64_t journal_header_offset;
177
+ uint64_t journal_header_offset;
178
+ uint64_t journal_header_size;
178
+ uint64_t journal_header_size;
179
+ uint64_t journal_offset;
179
+ uint64_t journal_offset;
180
+ uint64_t journal_size;
180
+ uint64_t journal_size;
181
+ uint64_t grain_dir_offset;
181
+ uint64_t grain_dir_offset;
182
+ uint64_t grain_dir_size;
182
+ uint64_t grain_dir_size;
183
+ uint64_t grain_tables_offset;
183
+ uint64_t grain_tables_offset;
184
+ uint64_t grain_tables_size;
184
+ uint64_t grain_tables_size;
185
+ uint64_t free_bitmap_offset;
185
+ uint64_t free_bitmap_offset;
186
+ uint64_t free_bitmap_size;
186
+ uint64_t free_bitmap_size;
187
+ uint64_t backmap_offset;
187
+ uint64_t backmap_offset;
188
+ uint64_t backmap_size;
188
+ uint64_t backmap_size;
189
+ uint64_t grains_offset;
189
+ uint64_t grains_offset;
190
+ uint64_t grains_size;
190
+ uint64_t grains_size;
191
+ uint8_t pad[304];
191
+ uint8_t pad[304];
192
+} QEMU_PACKED VMDKSESparseConstHeader;
192
+} QEMU_PACKED VMDKSESparseConstHeader;
193
+
193
+
194
+typedef struct VMDKSESparseVolatileHeader {
194
+typedef struct VMDKSESparseVolatileHeader {
195
+ uint64_t magic;
195
+ uint64_t magic;
196
+ uint64_t free_gt_number;
196
+ uint64_t free_gt_number;
197
+ uint64_t next_txn_seq_number;
197
+ uint64_t next_txn_seq_number;
198
+ uint64_t replay_journal;
198
+ uint64_t replay_journal;
199
+ uint8_t pad[480];
199
+ uint8_t pad[480];
200
+} QEMU_PACKED VMDKSESparseVolatileHeader;
200
+} QEMU_PACKED VMDKSESparseVolatileHeader;
201
+
201
+
202
#define L2_CACHE_SIZE 16
202
#define L2_CACHE_SIZE 16
203
203
204
typedef struct VmdkExtent {
204
typedef struct VmdkExtent {
205
@@ -XXX,XX +XXX,XX @@ typedef struct VmdkExtent {
205
@@ -XXX,XX +XXX,XX @@ typedef struct VmdkExtent {
206
bool compressed;
206
bool compressed;
207
bool has_marker;
207
bool has_marker;
208
bool has_zero_grain;
208
bool has_zero_grain;
209
+ bool sesparse;
209
+ bool sesparse;
210
+ uint64_t sesparse_l2_tables_offset;
210
+ uint64_t sesparse_l2_tables_offset;
211
+ uint64_t sesparse_clusters_offset;
211
+ uint64_t sesparse_clusters_offset;
212
+ int32_t entry_size;
212
+ int32_t entry_size;
213
int version;
213
int version;
214
int64_t sectors;
214
int64_t sectors;
215
int64_t end_sector;
215
int64_t end_sector;
216
int64_t flat_start_offset;
216
int64_t flat_start_offset;
217
int64_t l1_table_offset;
217
int64_t l1_table_offset;
218
int64_t l1_backup_table_offset;
218
int64_t l1_backup_table_offset;
219
- uint32_t *l1_table;
219
- uint32_t *l1_table;
220
+ void *l1_table;
220
+ void *l1_table;
221
uint32_t *l1_backup_table;
221
uint32_t *l1_backup_table;
222
unsigned int l1_size;
222
unsigned int l1_size;
223
uint32_t l1_entry_sectors;
223
uint32_t l1_entry_sectors;
224
224
225
unsigned int l2_size;
225
unsigned int l2_size;
226
- uint32_t *l2_cache;
226
- uint32_t *l2_cache;
227
+ void *l2_cache;
227
+ void *l2_cache;
228
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
228
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
229
uint32_t l2_cache_counts[L2_CACHE_SIZE];
229
uint32_t l2_cache_counts[L2_CACHE_SIZE];
230
230
231
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
231
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
232
* minimal L2 table size: 512 entries
232
* minimal L2 table size: 512 entries
233
* 8 TB is still more than the maximal value supported for
233
* 8 TB is still more than the maximal value supported for
234
* VMDK3 & VMDK4 which is 2TB.
234
* VMDK3 & VMDK4 which is 2TB.
235
+ * 64TB - for "ESXi seSparse Extent"
235
+ * 64TB - for "ESXi seSparse Extent"
236
+ * minimal cluster size: 512B (default is 4KB)
236
+ * minimal cluster size: 512B (default is 4KB)
237
+ * L2 table size: 4096 entries (const).
237
+ * L2 table size: 4096 entries (const).
238
+ * 64TB is more than the maximal value supported for
238
+ * 64TB is more than the maximal value supported for
239
+ * seSparse VMDKs (which is slightly less than 64TB)
239
+ * seSparse VMDKs (which is slightly less than 64TB)
240
*/
240
*/
241
error_setg(errp, "L1 size too big");
241
error_setg(errp, "L1 size too big");
242
return -EFBIG;
242
return -EFBIG;
243
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
243
@@ -XXX,XX +XXX,XX @@ static int vmdk_add_extent(BlockDriverState *bs,
244
extent->l2_size = l2_size;
244
extent->l2_size = l2_size;
245
extent->cluster_sectors = flat ? sectors : cluster_sectors;
245
extent->cluster_sectors = flat ? sectors : cluster_sectors;
246
extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors);
246
extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors);
247
+ extent->entry_size = sizeof(uint32_t);
247
+ extent->entry_size = sizeof(uint32_t);
248
248
249
if (s->num_extents > 1) {
249
if (s->num_extents > 1) {
250
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
250
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
251
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
251
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
252
int i;
252
int i;
253
253
254
/* read the L1 table */
254
/* read the L1 table */
255
- l1_size = extent->l1_size * sizeof(uint32_t);
255
- l1_size = extent->l1_size * sizeof(uint32_t);
256
+ l1_size = extent->l1_size * extent->entry_size;
256
+ l1_size = extent->l1_size * extent->entry_size;
257
extent->l1_table = g_try_malloc(l1_size);
257
extent->l1_table = g_try_malloc(l1_size);
258
if (l1_size && extent->l1_table == NULL) {
258
if (l1_size && extent->l1_table == NULL) {
259
return -ENOMEM;
259
return -ENOMEM;
260
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
260
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
261
goto fail_l1;
261
goto fail_l1;
262
}
262
}
263
for (i = 0; i < extent->l1_size; i++) {
263
for (i = 0; i < extent->l1_size; i++) {
264
- le32_to_cpus(&extent->l1_table[i]);
264
- le32_to_cpus(&extent->l1_table[i]);
265
+ if (extent->entry_size == sizeof(uint64_t)) {
265
+ if (extent->entry_size == sizeof(uint64_t)) {
266
+ le64_to_cpus((uint64_t *)extent->l1_table + i);
266
+ le64_to_cpus((uint64_t *)extent->l1_table + i);
267
+ } else {
267
+ } else {
268
+ assert(extent->entry_size == sizeof(uint32_t));
268
+ assert(extent->entry_size == sizeof(uint32_t));
269
+ le32_to_cpus((uint32_t *)extent->l1_table + i);
269
+ le32_to_cpus((uint32_t *)extent->l1_table + i);
270
+ }
270
+ }
271
}
271
}
272
272
273
if (extent->l1_backup_table_offset) {
273
if (extent->l1_backup_table_offset) {
274
+ assert(!extent->sesparse);
274
+ assert(!extent->sesparse);
275
extent->l1_backup_table = g_try_malloc(l1_size);
275
extent->l1_backup_table = g_try_malloc(l1_size);
276
if (l1_size && extent->l1_backup_table == NULL) {
276
if (l1_size && extent->l1_backup_table == NULL) {
277
ret = -ENOMEM;
277
ret = -ENOMEM;
278
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
278
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
279
}
279
}
280
280
281
extent->l2_cache =
281
extent->l2_cache =
282
- g_new(uint32_t, extent->l2_size * L2_CACHE_SIZE);
282
- g_new(uint32_t, extent->l2_size * L2_CACHE_SIZE);
283
+ g_malloc(extent->entry_size * extent->l2_size * L2_CACHE_SIZE);
283
+ g_malloc(extent->entry_size * extent->l2_size * L2_CACHE_SIZE);
284
return 0;
284
return 0;
285
fail_l1b:
285
fail_l1b:
286
g_free(extent->l1_backup_table);
286
g_free(extent->l1_backup_table);
287
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
287
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
288
return ret;
288
return ret;
289
}
289
}
290
290
291
+#define SESPARSE_CONST_HEADER_MAGIC UINT64_C(0x00000000cafebabe)
291
+#define SESPARSE_CONST_HEADER_MAGIC UINT64_C(0x00000000cafebabe)
292
+#define SESPARSE_VOLATILE_HEADER_MAGIC UINT64_C(0x00000000cafecafe)
292
+#define SESPARSE_VOLATILE_HEADER_MAGIC UINT64_C(0x00000000cafecafe)
293
+
293
+
294
+/* Strict checks - format not officially documented */
294
+/* Strict checks - format not officially documented */
295
+static int check_se_sparse_const_header(VMDKSESparseConstHeader *header,
295
+static int check_se_sparse_const_header(VMDKSESparseConstHeader *header,
296
+ Error **errp)
296
+ Error **errp)
297
+{
297
+{
298
+ header->magic = le64_to_cpu(header->magic);
298
+ header->magic = le64_to_cpu(header->magic);
299
+ header->version = le64_to_cpu(header->version);
299
+ header->version = le64_to_cpu(header->version);
300
+ header->grain_size = le64_to_cpu(header->grain_size);
300
+ header->grain_size = le64_to_cpu(header->grain_size);
301
+ header->grain_table_size = le64_to_cpu(header->grain_table_size);
301
+ header->grain_table_size = le64_to_cpu(header->grain_table_size);
302
+ header->flags = le64_to_cpu(header->flags);
302
+ header->flags = le64_to_cpu(header->flags);
303
+ header->reserved1 = le64_to_cpu(header->reserved1);
303
+ header->reserved1 = le64_to_cpu(header->reserved1);
304
+ header->reserved2 = le64_to_cpu(header->reserved2);
304
+ header->reserved2 = le64_to_cpu(header->reserved2);
305
+ header->reserved3 = le64_to_cpu(header->reserved3);
305
+ header->reserved3 = le64_to_cpu(header->reserved3);
306
+ header->reserved4 = le64_to_cpu(header->reserved4);
306
+ header->reserved4 = le64_to_cpu(header->reserved4);
307
+
307
+
308
+ header->volatile_header_offset =
308
+ header->volatile_header_offset =
309
+ le64_to_cpu(header->volatile_header_offset);
309
+ le64_to_cpu(header->volatile_header_offset);
310
+ header->volatile_header_size = le64_to_cpu(header->volatile_header_size);
310
+ header->volatile_header_size = le64_to_cpu(header->volatile_header_size);
311
+
311
+
312
+ header->journal_header_offset = le64_to_cpu(header->journal_header_offset);
312
+ header->journal_header_offset = le64_to_cpu(header->journal_header_offset);
313
+ header->journal_header_size = le64_to_cpu(header->journal_header_size);
313
+ header->journal_header_size = le64_to_cpu(header->journal_header_size);
314
+
314
+
315
+ header->journal_offset = le64_to_cpu(header->journal_offset);
315
+ header->journal_offset = le64_to_cpu(header->journal_offset);
316
+ header->journal_size = le64_to_cpu(header->journal_size);
316
+ header->journal_size = le64_to_cpu(header->journal_size);
317
+
317
+
318
+ header->grain_dir_offset = le64_to_cpu(header->grain_dir_offset);
318
+ header->grain_dir_offset = le64_to_cpu(header->grain_dir_offset);
319
+ header->grain_dir_size = le64_to_cpu(header->grain_dir_size);
319
+ header->grain_dir_size = le64_to_cpu(header->grain_dir_size);
320
+
320
+
321
+ header->grain_tables_offset = le64_to_cpu(header->grain_tables_offset);
321
+ header->grain_tables_offset = le64_to_cpu(header->grain_tables_offset);
322
+ header->grain_tables_size = le64_to_cpu(header->grain_tables_size);
322
+ header->grain_tables_size = le64_to_cpu(header->grain_tables_size);
323
+
323
+
324
+ header->free_bitmap_offset = le64_to_cpu(header->free_bitmap_offset);
324
+ header->free_bitmap_offset = le64_to_cpu(header->free_bitmap_offset);
325
+ header->free_bitmap_size = le64_to_cpu(header->free_bitmap_size);
325
+ header->free_bitmap_size = le64_to_cpu(header->free_bitmap_size);
326
+
326
+
327
+ header->backmap_offset = le64_to_cpu(header->backmap_offset);
327
+ header->backmap_offset = le64_to_cpu(header->backmap_offset);
328
+ header->backmap_size = le64_to_cpu(header->backmap_size);
328
+ header->backmap_size = le64_to_cpu(header->backmap_size);
329
+
329
+
330
+ header->grains_offset = le64_to_cpu(header->grains_offset);
330
+ header->grains_offset = le64_to_cpu(header->grains_offset);
331
+ header->grains_size = le64_to_cpu(header->grains_size);
331
+ header->grains_size = le64_to_cpu(header->grains_size);
332
+
332
+
333
+ if (header->magic != SESPARSE_CONST_HEADER_MAGIC) {
333
+ if (header->magic != SESPARSE_CONST_HEADER_MAGIC) {
334
+ error_setg(errp, "Bad const header magic: 0x%016" PRIx64,
334
+ error_setg(errp, "Bad const header magic: 0x%016" PRIx64,
335
+ header->magic);
335
+ header->magic);
336
+ return -EINVAL;
336
+ return -EINVAL;
337
+ }
337
+ }
338
+
338
+
339
+ if (header->version != 0x0000000200000001) {
339
+ if (header->version != 0x0000000200000001) {
340
+ error_setg(errp, "Unsupported version: 0x%016" PRIx64,
340
+ error_setg(errp, "Unsupported version: 0x%016" PRIx64,
341
+ header->version);
341
+ header->version);
342
+ return -ENOTSUP;
342
+ return -ENOTSUP;
343
+ }
343
+ }
344
+
344
+
345
+ if (header->grain_size != 8) {
345
+ if (header->grain_size != 8) {
346
+ error_setg(errp, "Unsupported grain size: %" PRIu64,
346
+ error_setg(errp, "Unsupported grain size: %" PRIu64,
347
+ header->grain_size);
347
+ header->grain_size);
348
+ return -ENOTSUP;
348
+ return -ENOTSUP;
349
+ }
349
+ }
350
+
350
+
351
+ if (header->grain_table_size != 64) {
351
+ if (header->grain_table_size != 64) {
352
+ error_setg(errp, "Unsupported grain table size: %" PRIu64,
352
+ error_setg(errp, "Unsupported grain table size: %" PRIu64,
353
+ header->grain_table_size);
353
+ header->grain_table_size);
354
+ return -ENOTSUP;
354
+ return -ENOTSUP;
355
+ }
355
+ }
356
+
356
+
357
+ if (header->flags != 0) {
357
+ if (header->flags != 0) {
358
+ error_setg(errp, "Unsupported flags: 0x%016" PRIx64,
358
+ error_setg(errp, "Unsupported flags: 0x%016" PRIx64,
359
+ header->flags);
359
+ header->flags);
360
+ return -ENOTSUP;
360
+ return -ENOTSUP;
361
+ }
361
+ }
362
+
362
+
363
+ if (header->reserved1 != 0 || header->reserved2 != 0 ||
363
+ if (header->reserved1 != 0 || header->reserved2 != 0 ||
364
+ header->reserved3 != 0 || header->reserved4 != 0) {
364
+ header->reserved3 != 0 || header->reserved4 != 0) {
365
+ error_setg(errp, "Unsupported reserved bits:"
365
+ error_setg(errp, "Unsupported reserved bits:"
366
+ " 0x%016" PRIx64 " 0x%016" PRIx64
366
+ " 0x%016" PRIx64 " 0x%016" PRIx64
367
+ " 0x%016" PRIx64 " 0x%016" PRIx64,
367
+ " 0x%016" PRIx64 " 0x%016" PRIx64,
368
+ header->reserved1, header->reserved2,
368
+ header->reserved1, header->reserved2,
369
+ header->reserved3, header->reserved4);
369
+ header->reserved3, header->reserved4);
370
+ return -ENOTSUP;
370
+ return -ENOTSUP;
371
+ }
371
+ }
372
+
372
+
373
+ /* check that padding is 0 */
373
+ /* check that padding is 0 */
374
+ if (!buffer_is_zero(header->pad, sizeof(header->pad))) {
374
+ if (!buffer_is_zero(header->pad, sizeof(header->pad))) {
375
+ error_setg(errp, "Unsupported non-zero const header padding");
375
+ error_setg(errp, "Unsupported non-zero const header padding");
376
+ return -ENOTSUP;
376
+ return -ENOTSUP;
377
+ }
377
+ }
378
+
378
+
379
+ return 0;
379
+ return 0;
380
+}
380
+}
381
+
381
+
382
+static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
382
+static int check_se_sparse_volatile_header(VMDKSESparseVolatileHeader *header,
383
+ Error **errp)
383
+ Error **errp)
384
+{
384
+{
385
+ header->magic = le64_to_cpu(header->magic);
385
+ header->magic = le64_to_cpu(header->magic);
386
+ header->free_gt_number = le64_to_cpu(header->free_gt_number);
386
+ header->free_gt_number = le64_to_cpu(header->free_gt_number);
387
+ header->next_txn_seq_number = le64_to_cpu(header->next_txn_seq_number);
387
+ header->next_txn_seq_number = le64_to_cpu(header->next_txn_seq_number);
388
+ header->replay_journal = le64_to_cpu(header->replay_journal);
388
+ header->replay_journal = le64_to_cpu(header->replay_journal);
389
+
389
+
390
+ if (header->magic != SESPARSE_VOLATILE_HEADER_MAGIC) {
390
+ if (header->magic != SESPARSE_VOLATILE_HEADER_MAGIC) {
391
+ error_setg(errp, "Bad volatile header magic: 0x%016" PRIx64,
391
+ error_setg(errp, "Bad volatile header magic: 0x%016" PRIx64,
392
+ header->magic);
392
+ header->magic);
393
+ return -EINVAL;
393
+ return -EINVAL;
394
+ }
394
+ }
395
+
395
+
396
+ if (header->replay_journal) {
396
+ if (header->replay_journal) {
397
+ error_setg(errp, "Image is dirty, Replaying journal not supported");
397
+ error_setg(errp, "Image is dirty, Replaying journal not supported");
398
+ return -ENOTSUP;
398
+ return -ENOTSUP;
399
+ }
399
+ }
400
+
400
+
401
+ /* check that padding is 0 */
401
+ /* check that padding is 0 */
402
+ if (!buffer_is_zero(header->pad, sizeof(header->pad))) {
402
+ if (!buffer_is_zero(header->pad, sizeof(header->pad))) {
403
+ error_setg(errp, "Unsupported non-zero volatile header padding");
403
+ error_setg(errp, "Unsupported non-zero volatile header padding");
404
+ return -ENOTSUP;
404
+ return -ENOTSUP;
405
+ }
405
+ }
406
+
406
+
407
+ return 0;
407
+ return 0;
408
+}
408
+}
409
+
409
+
410
+static int vmdk_open_se_sparse(BlockDriverState *bs,
410
+static int vmdk_open_se_sparse(BlockDriverState *bs,
411
+ BdrvChild *file,
411
+ BdrvChild *file,
412
+ int flags, Error **errp)
412
+ int flags, Error **errp)
413
+{
413
+{
414
+ int ret;
414
+ int ret;
415
+ VMDKSESparseConstHeader const_header;
415
+ VMDKSESparseConstHeader const_header;
416
+ VMDKSESparseVolatileHeader volatile_header;
416
+ VMDKSESparseVolatileHeader volatile_header;
417
+ VmdkExtent *extent;
417
+ VmdkExtent *extent;
418
+
418
+
419
+ ret = bdrv_apply_auto_read_only(bs,
419
+ ret = bdrv_apply_auto_read_only(bs,
420
+ "No write support for seSparse images available", errp);
420
+ "No write support for seSparse images available", errp);
421
+ if (ret < 0) {
421
+ if (ret < 0) {
422
+ return ret;
422
+ return ret;
423
+ }
423
+ }
424
+
424
+
425
+ assert(sizeof(const_header) == SECTOR_SIZE);
425
+ assert(sizeof(const_header) == SECTOR_SIZE);
426
+
426
+
427
+ ret = bdrv_pread(file, 0, &const_header, sizeof(const_header));
427
+ ret = bdrv_pread(file, 0, &const_header, sizeof(const_header));
428
+ if (ret < 0) {
428
+ if (ret < 0) {
429
+ bdrv_refresh_filename(file->bs);
429
+ bdrv_refresh_filename(file->bs);
430
+ error_setg_errno(errp, -ret,
430
+ error_setg_errno(errp, -ret,
431
+ "Could not read const header from file '%s'",
431
+ "Could not read const header from file '%s'",
432
+ file->bs->filename);
432
+ file->bs->filename);
433
+ return ret;
433
+ return ret;
434
+ }
434
+ }
435
+
435
+
436
+ /* check const header */
436
+ /* check const header */
437
+ ret = check_se_sparse_const_header(&const_header, errp);
437
+ ret = check_se_sparse_const_header(&const_header, errp);
438
+ if (ret < 0) {
438
+ if (ret < 0) {
439
+ return ret;
439
+ return ret;
440
+ }
440
+ }
441
+
441
+
442
+ assert(sizeof(volatile_header) == SECTOR_SIZE);
442
+ assert(sizeof(volatile_header) == SECTOR_SIZE);
443
+
443
+
444
+ ret = bdrv_pread(file,
444
+ ret = bdrv_pread(file,
445
+ const_header.volatile_header_offset * SECTOR_SIZE,
445
+ const_header.volatile_header_offset * SECTOR_SIZE,
446
+ &volatile_header, sizeof(volatile_header));
446
+ &volatile_header, sizeof(volatile_header));
447
+ if (ret < 0) {
447
+ if (ret < 0) {
448
+ bdrv_refresh_filename(file->bs);
448
+ bdrv_refresh_filename(file->bs);
449
+ error_setg_errno(errp, -ret,
449
+ error_setg_errno(errp, -ret,
450
+ "Could not read volatile header from file '%s'",
450
+ "Could not read volatile header from file '%s'",
451
+ file->bs->filename);
451
+ file->bs->filename);
452
+ return ret;
452
+ return ret;
453
+ }
453
+ }
454
+
454
+
455
+ /* check volatile header */
455
+ /* check volatile header */
456
+ ret = check_se_sparse_volatile_header(&volatile_header, errp);
456
+ ret = check_se_sparse_volatile_header(&volatile_header, errp);
457
+ if (ret < 0) {
457
+ if (ret < 0) {
458
+ return ret;
458
+ return ret;
459
+ }
459
+ }
460
+
460
+
461
+ ret = vmdk_add_extent(bs, file, false,
461
+ ret = vmdk_add_extent(bs, file, false,
462
+ const_header.capacity,
462
+ const_header.capacity,
463
+ const_header.grain_dir_offset * SECTOR_SIZE,
463
+ const_header.grain_dir_offset * SECTOR_SIZE,
464
+ 0,
464
+ 0,
465
+ const_header.grain_dir_size *
465
+ const_header.grain_dir_size *
466
+ SECTOR_SIZE / sizeof(uint64_t),
466
+ SECTOR_SIZE / sizeof(uint64_t),
467
+ const_header.grain_table_size *
467
+ const_header.grain_table_size *
468
+ SECTOR_SIZE / sizeof(uint64_t),
468
+ SECTOR_SIZE / sizeof(uint64_t),
469
+ const_header.grain_size,
469
+ const_header.grain_size,
470
+ &extent,
470
+ &extent,
471
+ errp);
471
+ errp);
472
+ if (ret < 0) {
472
+ if (ret < 0) {
473
+ return ret;
473
+ return ret;
474
+ }
474
+ }
475
+
475
+
476
+ extent->sesparse = true;
476
+ extent->sesparse = true;
477
+ extent->sesparse_l2_tables_offset = const_header.grain_tables_offset;
477
+ extent->sesparse_l2_tables_offset = const_header.grain_tables_offset;
478
+ extent->sesparse_clusters_offset = const_header.grains_offset;
478
+ extent->sesparse_clusters_offset = const_header.grains_offset;
479
+ extent->entry_size = sizeof(uint64_t);
479
+ extent->entry_size = sizeof(uint64_t);
480
+
480
+
481
+ ret = vmdk_init_tables(bs, extent, errp);
481
+ ret = vmdk_init_tables(bs, extent, errp);
482
+ if (ret) {
482
+ if (ret) {
483
+ /* free extent allocated by vmdk_add_extent */
483
+ /* free extent allocated by vmdk_add_extent */
484
+ vmdk_free_last_extent(bs);
484
+ vmdk_free_last_extent(bs);
485
+ }
485
+ }
486
+
486
+
487
+ return ret;
487
+ return ret;
488
+}
488
+}
489
+
489
+
490
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
490
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
491
QDict *options, Error **errp);
491
QDict *options, Error **errp);
492
492
493
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
493
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
494
* RW [size in sectors] SPARSE "file-name.vmdk"
494
* RW [size in sectors] SPARSE "file-name.vmdk"
495
* RW [size in sectors] VMFS "file-name.vmdk"
495
* RW [size in sectors] VMFS "file-name.vmdk"
496
* RW [size in sectors] VMFSSPARSE "file-name.vmdk"
496
* RW [size in sectors] VMFSSPARSE "file-name.vmdk"
497
+ * RW [size in sectors] SESPARSE "file-name.vmdk"
497
+ * RW [size in sectors] SESPARSE "file-name.vmdk"
498
*/
498
*/
499
flat_offset = -1;
499
flat_offset = -1;
500
matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
500
matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
501
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
501
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
502
502
503
if (sectors <= 0 ||
503
if (sectors <= 0 ||
504
(strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
504
(strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
505
- strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||
505
- strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||
506
+ strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE") &&
506
+ strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE") &&
507
+ strcmp(type, "SESPARSE")) ||
507
+ strcmp(type, "SESPARSE")) ||
508
(strcmp(access, "RW"))) {
508
(strcmp(access, "RW"))) {
509
continue;
509
continue;
510
}
510
}
511
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
511
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
512
return ret;
512
return ret;
513
}
513
}
514
extent = &s->extents[s->num_extents - 1];
514
extent = &s->extents[s->num_extents - 1];
515
+ } else if (!strcmp(type, "SESPARSE")) {
515
+ } else if (!strcmp(type, "SESPARSE")) {
516
+ ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
516
+ ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
517
+ if (ret) {
517
+ if (ret) {
518
+ bdrv_unref_child(bs, extent_file);
518
+ bdrv_unref_child(bs, extent_file);
519
+ return ret;
519
+ return ret;
520
+ }
520
+ }
521
+ extent = &s->extents[s->num_extents - 1];
521
+ extent = &s->extents[s->num_extents - 1];
522
} else {
522
} else {
523
error_setg(errp, "Unsupported extent type '%s'", type);
523
error_setg(errp, "Unsupported extent type '%s'", type);
524
bdrv_unref_child(bs, extent_file);
524
bdrv_unref_child(bs, extent_file);
525
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
525
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
526
if (strcmp(ct, "monolithicFlat") &&
526
if (strcmp(ct, "monolithicFlat") &&
527
strcmp(ct, "vmfs") &&
527
strcmp(ct, "vmfs") &&
528
strcmp(ct, "vmfsSparse") &&
528
strcmp(ct, "vmfsSparse") &&
529
+ strcmp(ct, "seSparse") &&
529
+ strcmp(ct, "seSparse") &&
530
strcmp(ct, "twoGbMaxExtentSparse") &&
530
strcmp(ct, "twoGbMaxExtentSparse") &&
531
strcmp(ct, "twoGbMaxExtentFlat")) {
531
strcmp(ct, "twoGbMaxExtentFlat")) {
532
error_setg(errp, "Unsupported image type '%s'", ct);
532
error_setg(errp, "Unsupported image type '%s'", ct);
533
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
533
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
534
{
534
{
535
unsigned int l1_index, l2_offset, l2_index;
535
unsigned int l1_index, l2_offset, l2_index;
536
int min_index, i, j;
536
int min_index, i, j;
537
- uint32_t min_count, *l2_table;
537
- uint32_t min_count, *l2_table;
538
+ uint32_t min_count;
538
+ uint32_t min_count;
539
+ void *l2_table;
539
+ void *l2_table;
540
bool zeroed = false;
540
bool zeroed = false;
541
int64_t ret;
541
int64_t ret;
542
int64_t cluster_sector;
542
int64_t cluster_sector;
543
+ unsigned int l2_size_bytes = extent->l2_size * extent->entry_size;
543
+ unsigned int l2_size_bytes = extent->l2_size * extent->entry_size;
544
544
545
if (m_data) {
545
if (m_data) {
546
m_data->valid = 0;
546
m_data->valid = 0;
547
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
547
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
548
if (l1_index >= extent->l1_size) {
548
if (l1_index >= extent->l1_size) {
549
return VMDK_ERROR;
549
return VMDK_ERROR;
550
}
550
}
551
- l2_offset = extent->l1_table[l1_index];
551
- l2_offset = extent->l1_table[l1_index];
552
+ if (extent->sesparse) {
552
+ if (extent->sesparse) {
553
+ uint64_t l2_offset_u64;
553
+ uint64_t l2_offset_u64;
554
+
554
+
555
+ assert(extent->entry_size == sizeof(uint64_t));
555
+ assert(extent->entry_size == sizeof(uint64_t));
556
+
556
+
557
+ l2_offset_u64 = ((uint64_t *)extent->l1_table)[l1_index];
557
+ l2_offset_u64 = ((uint64_t *)extent->l1_table)[l1_index];
558
+ if (l2_offset_u64 == 0) {
558
+ if (l2_offset_u64 == 0) {
559
+ l2_offset = 0;
559
+ l2_offset = 0;
560
+ } else if ((l2_offset_u64 & 0xffffffff00000000) != 0x1000000000000000) {
560
+ } else if ((l2_offset_u64 & 0xffffffff00000000) != 0x1000000000000000) {
561
+ /*
561
+ /*
562
+ * Top most nibble is 0x1 if grain table is allocated.
562
+ * Top most nibble is 0x1 if grain table is allocated.
563
+ * strict check - top most 4 bytes must be 0x10000000 since max
563
+ * strict check - top most 4 bytes must be 0x10000000 since max
564
+ * supported size is 64TB for disk - so no more than 64TB / 16MB
564
+ * supported size is 64TB for disk - so no more than 64TB / 16MB
565
+ * grain directories which is smaller than uint32,
565
+ * grain directories which is smaller than uint32,
566
+ * where 16MB is the only supported default grain table coverage.
566
+ * where 16MB is the only supported default grain table coverage.
567
+ */
567
+ */
568
+ return VMDK_ERROR;
568
+ return VMDK_ERROR;
569
+ } else {
569
+ } else {
570
+ l2_offset_u64 = l2_offset_u64 & 0x00000000ffffffff;
570
+ l2_offset_u64 = l2_offset_u64 & 0x00000000ffffffff;
571
+ l2_offset_u64 = extent->sesparse_l2_tables_offset +
571
+ l2_offset_u64 = extent->sesparse_l2_tables_offset +
572
+ l2_offset_u64 * l2_size_bytes / SECTOR_SIZE;
572
+ l2_offset_u64 * l2_size_bytes / SECTOR_SIZE;
573
+ if (l2_offset_u64 > 0x00000000ffffffff) {
573
+ if (l2_offset_u64 > 0x00000000ffffffff) {
574
+ return VMDK_ERROR;
574
+ return VMDK_ERROR;
575
+ }
575
+ }
576
+ l2_offset = (unsigned int)(l2_offset_u64);
576
+ l2_offset = (unsigned int)(l2_offset_u64);
577
+ }
577
+ }
578
+ } else {
578
+ } else {
579
+ assert(extent->entry_size == sizeof(uint32_t));
579
+ assert(extent->entry_size == sizeof(uint32_t));
580
+ l2_offset = ((uint32_t *)extent->l1_table)[l1_index];
580
+ l2_offset = ((uint32_t *)extent->l1_table)[l1_index];
581
+ }
581
+ }
582
if (!l2_offset) {
582
if (!l2_offset) {
583
return VMDK_UNALLOC;
583
return VMDK_UNALLOC;
584
}
584
}
585
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
585
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
586
extent->l2_cache_counts[j] >>= 1;
586
extent->l2_cache_counts[j] >>= 1;
587
}
587
}
588
}
588
}
589
- l2_table = extent->l2_cache + (i * extent->l2_size);
589
- l2_table = extent->l2_cache + (i * extent->l2_size);
590
+ l2_table = (char *)extent->l2_cache + (i * l2_size_bytes);
590
+ l2_table = (char *)extent->l2_cache + (i * l2_size_bytes);
591
goto found;
591
goto found;
592
}
592
}
593
}
593
}
594
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
594
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
595
min_index = i;
595
min_index = i;
596
}
596
}
597
}
597
}
598
- l2_table = extent->l2_cache + (min_index * extent->l2_size);
598
- l2_table = extent->l2_cache + (min_index * extent->l2_size);
599
+ l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
599
+ l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
600
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
600
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
601
if (bdrv_pread(extent->file,
601
if (bdrv_pread(extent->file,
602
(int64_t)l2_offset * 512,
602
(int64_t)l2_offset * 512,
603
l2_table,
603
l2_table,
604
- extent->l2_size * sizeof(uint32_t)
604
- extent->l2_size * sizeof(uint32_t)
605
- ) != extent->l2_size * sizeof(uint32_t)) {
605
- ) != extent->l2_size * sizeof(uint32_t)) {
606
+ l2_size_bytes
606
+ l2_size_bytes
607
+ ) != l2_size_bytes) {
607
+ ) != l2_size_bytes) {
608
return VMDK_ERROR;
608
return VMDK_ERROR;
609
}
609
}
610
610
611
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
611
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
612
extent->l2_cache_counts[min_index] = 1;
612
extent->l2_cache_counts[min_index] = 1;
613
found:
613
found:
614
l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
614
l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
615
- cluster_sector = le32_to_cpu(l2_table[l2_index]);
615
- cluster_sector = le32_to_cpu(l2_table[l2_index]);
616
616
617
- if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) {
617
- if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) {
618
- zeroed = true;
618
- zeroed = true;
619
+ if (extent->sesparse) {
619
+ if (extent->sesparse) {
620
+ cluster_sector = le64_to_cpu(((uint64_t *)l2_table)[l2_index]);
620
+ cluster_sector = le64_to_cpu(((uint64_t *)l2_table)[l2_index]);
621
+ switch (cluster_sector & 0xf000000000000000) {
621
+ switch (cluster_sector & 0xf000000000000000) {
622
+ case 0x0000000000000000:
622
+ case 0x0000000000000000:
623
+ /* unallocated grain */
623
+ /* unallocated grain */
624
+ if (cluster_sector != 0) {
624
+ if (cluster_sector != 0) {
625
+ return VMDK_ERROR;
625
+ return VMDK_ERROR;
626
+ }
626
+ }
627
+ break;
627
+ break;
628
+ case 0x1000000000000000:
628
+ case 0x1000000000000000:
629
+ /* scsi-unmapped grain - fallthrough */
629
+ /* scsi-unmapped grain - fallthrough */
630
+ case 0x2000000000000000:
630
+ case 0x2000000000000000:
631
+ /* zero grain */
631
+ /* zero grain */
632
+ zeroed = true;
632
+ zeroed = true;
633
+ break;
633
+ break;
634
+ case 0x3000000000000000:
634
+ case 0x3000000000000000:
635
+ /* allocated grain */
635
+ /* allocated grain */
636
+ cluster_sector = (((cluster_sector & 0x0fff000000000000) >> 48) |
636
+ cluster_sector = (((cluster_sector & 0x0fff000000000000) >> 48) |
637
+ ((cluster_sector & 0x0000ffffffffffff) << 12));
637
+ ((cluster_sector & 0x0000ffffffffffff) << 12));
638
+ cluster_sector = extent->sesparse_clusters_offset +
638
+ cluster_sector = extent->sesparse_clusters_offset +
639
+ cluster_sector * extent->cluster_sectors;
639
+ cluster_sector * extent->cluster_sectors;
640
+ break;
640
+ break;
641
+ default:
641
+ default:
642
+ return VMDK_ERROR;
642
+ return VMDK_ERROR;
643
+ }
643
+ }
644
+ } else {
644
+ } else {
645
+ cluster_sector = le32_to_cpu(((uint32_t *)l2_table)[l2_index]);
645
+ cluster_sector = le32_to_cpu(((uint32_t *)l2_table)[l2_index]);
646
+
646
+
647
+ if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) {
647
+ if (extent->has_zero_grain && cluster_sector == VMDK_GTE_ZEROED) {
648
+ zeroed = true;
648
+ zeroed = true;
649
+ }
649
+ }
650
}
650
}
651
651
652
if (!cluster_sector || zeroed) {
652
if (!cluster_sector || zeroed) {
653
if (!allocate) {
653
if (!allocate) {
654
return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;
654
return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;
655
}
655
}
656
+ assert(!extent->sesparse);
656
+ assert(!extent->sesparse);
657
657
658
if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) {
658
if (extent->next_cluster_sector >= VMDK_EXTENT_MAX_SECTORS) {
659
return VMDK_ERROR;
659
return VMDK_ERROR;
660
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
660
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
661
m_data->l1_index = l1_index;
661
m_data->l1_index = l1_index;
662
m_data->l2_index = l2_index;
662
m_data->l2_index = l2_index;
663
m_data->l2_offset = l2_offset;
663
m_data->l2_offset = l2_offset;
664
- m_data->l2_cache_entry = &l2_table[l2_index];
664
- m_data->l2_cache_entry = &l2_table[l2_index];
665
+ m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index;
665
+ m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index;
666
}
666
}
667
}
667
}
668
*cluster_offset = cluster_sector << BDRV_SECTOR_BITS;
668
*cluster_offset = cluster_sector << BDRV_SECTOR_BITS;
669
@@ -XXX,XX +XXX,XX @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
669
@@ -XXX,XX +XXX,XX @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
670
if (!extent) {
670
if (!extent) {
671
return -EIO;
671
return -EIO;
672
}
672
}
673
+ if (extent->sesparse) {
673
+ if (extent->sesparse) {
674
+ return -ENOTSUP;
674
+ return -ENOTSUP;
675
+ }
675
+ }
676
offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
676
offset_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
677
n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE
677
n_bytes = MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE
678
- offset_in_cluster);
678
- offset_in_cluster);
679
--
679
--
680
2.21.0
680
2.21.0
681
681
682
682
diff view generated by jsdifflib
...
...
21
Signed-off-by: Pino Toscano <ptoscano@redhat.com>
21
Signed-off-by: Pino Toscano <ptoscano@redhat.com>
22
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Acked-by: Alex Bennée <alex.bennee@linaro.org>
23
Acked-by: Alex Bennée <alex.bennee@linaro.org>
24
Message-id: 20190620200840.17655-1-ptoscano@redhat.com
24
Message-id: 20190620200840.17655-1-ptoscano@redhat.com
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
26
Message-id: 5873173.t2JhDm7DL7@lindworm.usersys.redhat.com
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
---
28
configure | 65 +-
29
configure | 65 +-
29
block/Makefile.objs | 6 +-
30
block/Makefile.objs | 6 +-
30
block/ssh.c | 673 ++++++++++--------
31
block/ssh.c | 652 ++++++++++--------
31
.travis.yml | 4 +-
32
.travis.yml | 4 +-
32
block/trace-events | 14 +-
33
block/trace-events | 14 +-
33
docs/qemu-block-drivers.texi | 2 +-
34
docs/qemu-block-drivers.texi | 2 +-
34
.../dockerfiles/debian-win32-cross.docker | 1 -
35
.../dockerfiles/debian-win32-cross.docker | 1 -
35
.../dockerfiles/debian-win64-cross.docker | 1 -
36
.../dockerfiles/debian-win64-cross.docker | 1 -
36
tests/docker/dockerfiles/fedora.docker | 4 +-
37
tests/docker/dockerfiles/fedora.docker | 4 +-
37
tests/docker/dockerfiles/ubuntu.docker | 2 +-
38
tests/docker/dockerfiles/ubuntu.docker | 2 +-
38
tests/docker/dockerfiles/ubuntu1804.docker | 2 +-
39
tests/docker/dockerfiles/ubuntu1804.docker | 2 +-
39
tests/qemu-iotests/207 | 54 +-
40
tests/qemu-iotests/207 | 54 +-
40
tests/qemu-iotests/207.out | 2 +-
41
tests/qemu-iotests/207.out | 2 +-
41
13 files changed, 470 insertions(+), 360 deletions(-)
42
13 files changed, 449 insertions(+), 360 deletions(-)
42
43
43
diff --git a/configure b/configure
44
diff --git a/configure b/configure
44
index XXXXXXX..XXXXXXX 100755
45
index XXXXXXX..XXXXXXX 100755
45
--- a/configure
46
--- a/configure
46
+++ b/configure
47
+++ b/configure
...
...
366
- int type;
367
- int type;
367
-
368
-
368
- hostkey = libssh2_session_hostkey(s->session, &len, &type);
369
- hostkey = libssh2_session_hostkey(s->session, &len, &type);
369
- if (!hostkey) {
370
- if (!hostkey) {
370
+ int ret;
371
+ int ret;
372
+#ifdef HAVE_LIBSSH_0_8
373
+ enum ssh_known_hosts_e state;
371
+ int r;
374
+ int r;
372
+ ssh_key pubkey;
375
+ ssh_key pubkey;
373
+ enum ssh_keytypes_e pubkey_type;
376
+ enum ssh_keytypes_e pubkey_type;
374
+ unsigned char *server_hash = NULL;
377
+ unsigned char *server_hash = NULL;
375
+ size_t server_hash_len;
378
+ size_t server_hash_len;
376
+ char *fingerprint = NULL;
379
+ char *fingerprint = NULL;
377
+#ifdef HAVE_LIBSSH_0_8
378
+ enum ssh_known_hosts_e state;
379
+
380
+
380
+ state = ssh_session_is_known_server(s->session);
381
+ state = ssh_session_is_known_server(s->session);
381
+ trace_ssh_server_status(state);
382
+ trace_ssh_server_status(state);
382
+
383
+
383
+ switch (state) {
384
+ switch (state) {
...
...
472
+ case SSH_SERVER_KNOWN_CHANGED:
473
+ case SSH_SERVER_KNOWN_CHANGED:
473
ret = -EINVAL;
474
ret = -EINVAL;
474
- session_error_setg(errp, s,
475
- session_error_setg(errp, s,
475
- "host key does not match the one in known_hosts"
476
- "host key does not match the one in known_hosts"
476
- " (found key %s)", found->key);
477
- " (found key %s)", found->key);
477
+ r = ssh_get_publickey(s->session, &pubkey);
478
+ error_setg(errp,
478
+ if (r == 0) {
479
+ "host key does not match the one in known_hosts; this "
479
+ r = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA1,
480
+ "may be a possible attack");
480
+ &server_hash, &server_hash_len);
481
goto out;
481
+ pubkey_type = ssh_key_type(pubkey);
482
- case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
482
+ ssh_key_free(pubkey);
483
+ }
484
+ if (r == 0) {
485
+ fingerprint = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA1,
486
+ server_hash,
487
+ server_hash_len);
488
+ ssh_clean_pubkey_hash(&server_hash);
489
+ }
490
+ if (fingerprint) {
491
+ error_setg(errp,
492
+ "host key (%s key with fingerprint %s) does not match "
493
+ "the one in known_hosts; this may be a possible attack",
494
+ ssh_key_type_to_char(pubkey_type), fingerprint);
495
+ ssh_string_free_char(fingerprint);
496
+ } else {
497
+ error_setg(errp,
498
+ "host key does not match the one in known_hosts; this "
499
+ "may be a possible attack");
500
+ }
501
+ goto out;
502
+ case SSH_SERVER_FOUND_OTHER:
483
+ case SSH_SERVER_FOUND_OTHER:
503
+ ret = -EINVAL;
484
ret = -EINVAL;
485
- session_error_setg(errp, s, "no host key was found in known_hosts");
504
+ error_setg(errp,
486
+ error_setg(errp,
505
+ "host key for this server not found, another type exists");
487
+ "host key for this server not found, another type exists");
506
+ goto out;
488
+ goto out;
507
+ case SSH_SERVER_FILE_NOT_FOUND:
489
+ case SSH_SERVER_FILE_NOT_FOUND:
508
+ ret = -ENOENT;
490
+ ret = -ENOENT;
509
+ error_setg(errp, "known_hosts file not found");
491
+ error_setg(errp, "known_hosts file not found");
510
goto out;
492
goto out;
511
- case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
493
- case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
512
+ case SSH_SERVER_NOT_KNOWN:
494
+ case SSH_SERVER_NOT_KNOWN:
513
ret = -EINVAL;
514
- session_error_setg(errp, s, "no host key was found in known_hosts");
515
+ error_setg(errp, "no host key was found in known_hosts");
516
goto out;
517
- case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
518
+ case SSH_SERVER_ERROR:
519
ret = -EINVAL;
495
ret = -EINVAL;
520
- session_error_setg(errp, s,
496
- session_error_setg(errp, s,
521
- "failure matching the host key with known_hosts");
497
- "failure matching the host key with known_hosts");
498
+ error_setg(errp, "no host key was found in known_hosts");
499
+ goto out;
500
+ case SSH_SERVER_ERROR:
501
+ ret = -EINVAL;
522
+ error_setg(errp, "server error");
502
+ error_setg(errp, "server error");
523
goto out;
503
goto out;
524
default:
504
default:
525
ret = -EINVAL;
505
ret = -EINVAL;
526
- session_error_setg(errp, s, "unknown error matching the host key"
506
- session_error_setg(errp, s, "unknown error matching the host key"
...
...
diff view generated by jsdifflib
1
Tests should place their files into the test directory. This includes
1
Tests should place their files into the test directory. This includes
2
Unix sockets. 205 currently fails to do so, which prevents it from
2
Unix sockets. 205 currently fails to do so, which prevents it from
3
being run concurrently.
3
being run concurrently.
4
4
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20190618210238.9524-1-mreitz@redhat.com
6
Message-id: 20190618210238.9524-1-mreitz@redhat.com
7
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
9
---
10
tests/qemu-iotests/205 | 2 +-
10
tests/qemu-iotests/205 | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
12
13
diff --git a/tests/qemu-iotests/205 b/tests/qemu-iotests/205
13
diff --git a/tests/qemu-iotests/205 b/tests/qemu-iotests/205
14
index XXXXXXX..XXXXXXX 100755
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/205
15
--- a/tests/qemu-iotests/205
16
+++ b/tests/qemu-iotests/205
16
+++ b/tests/qemu-iotests/205
17
@@ -XXX,XX +XXX,XX @@ import iotests
17
@@ -XXX,XX +XXX,XX @@ import iotests
18
import time
18
import time
19
from iotests import qemu_img_create, qemu_io, filter_qemu_io, QemuIoInteractive
19
from iotests import qemu_img_create, qemu_io, filter_qemu_io, QemuIoInteractive
20
20
21
-nbd_sock = 'nbd_sock'
21
-nbd_sock = 'nbd_sock'
22
+nbd_sock = os.path.join(iotests.test_dir, 'nbd_sock')
22
+nbd_sock = os.path.join(iotests.test_dir, 'nbd_sock')
23
nbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock
23
nbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock
24
disk = os.path.join(iotests.test_dir, 'disk')
24
disk = os.path.join(iotests.test_dir, 'disk')
25
25
26
--
26
--
27
2.21.0
27
2.21.0
28
28
29
29
diff view generated by jsdifflib