1
The following changes since commit fb68096da3d35e64c88cd610c1fa42766c58e92a:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Revert "tests: use memfd in vhost-user-test" (2018-02-13 09:51:52 +0000)
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 0a4dc980e6c935e9be745ce3ee1a4c71629ecd00:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-02-13' into queue-block (2018-02-13 17:01:13 +0100)
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches:
15
16
- Fix resize (extending) of short overlays
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
- qemu-storage-daemon: Fix non-string --object properties
15
19
16
----------------------------------------------------------------
20
----------------------------------------------------------------
17
Alberto Garcia (40):
21
Alberto Garcia (1):
18
qcow2: Use g_try_realloc() in qcow2_expand_zero_clusters()
22
qcow2: Add incompatibility note between backing files and raw external data files
19
qcow2: Fix documentation of get_cluster_table()
20
qcow2: Add table size field to Qcow2Cache
21
qcow2: Remove BDS parameter from qcow2_cache_get_table_addr()
22
qcow2: Remove BDS parameter from qcow2_cache_get_table_idx()
23
qcow2: Remove BDS parameter from qcow2_cache_table_release()
24
qcow2: Remove BDS parameter from qcow2_cache_entry_mark_dirty()
25
qcow2: Remove BDS parameter from qcow2_cache_put()
26
qcow2: Remove BDS parameter from qcow2_cache_destroy()
27
qcow2: Remove BDS parameter from qcow2_cache_clean_unused()
28
qcow2: Remove BDS parameter from qcow2_cache_discard()
29
qcow2: Remove BDS parameter from qcow2_cache_is_table_offset()
30
qcow2: Add offset_to_l1_index()
31
qcow2: Add l2_slice_size field to BDRVQcow2State
32
qcow2: Add offset_to_l2_slice_index()
33
qcow2: Update l2_load() to support L2 slices
34
qcow2: Prepare l2_allocate() for adding L2 slice support
35
qcow2: Update l2_allocate() to support L2 slices
36
qcow2: Refactor get_cluster_table()
37
qcow2: Update get_cluster_table() to support L2 slices
38
qcow2: Update qcow2_get_cluster_offset() to support L2 slices
39
qcow2: Update qcow2_alloc_cluster_link_l2() to support L2 slices
40
qcow2: Update handle_copied() to support L2 slices
41
qcow2: Update handle_alloc() to support L2 slices
42
qcow2: Update discard_single_l2() to support L2 slices
43
qcow2: Update zero_single_l2() to support L2 slices
44
qcow2: Prepare qcow2_update_snapshot_refcount() for adding L2 slice support
45
qcow2: Update qcow2_update_snapshot_refcount() to support L2 slices
46
qcow2: Read refcount before L2 table in expand_zero_clusters_in_l1()
47
qcow2: Prepare expand_zero_clusters_in_l1() for adding L2 slice support
48
qcow2: Update expand_zero_clusters_in_l1() to support L2 slices
49
qcow2: Update qcow2_truncate() to support L2 slices
50
qcow2: Rename l2_table in qcow2_alloc_compressed_cluster_offset()
51
qcow2: Rename l2_table in count_contiguous_clusters()
52
qcow2: Rename l2_table in count_contiguous_clusters_unallocated()
53
qcow2: Rename l2_table in count_cow_clusters()
54
qcow2: Allow configuring the L2 slice size
55
iotests: Test valid values of l2-cache-entry-size
56
iotests: Test downgrading an image using a small L2 slice size
57
iotests: Add l2-cache-entry-size to iotest 137
58
23
59
Daniel P. Berrangé (1):
24
Andrzej Jakowski (1):
60
qemu-io: fix EOF Ctrl-D handling in qemu-io readline code
25
nvme: introduce PMR support from NVMe 1.4 spec
61
26
62
Fam Zheng (4):
27
Kevin Wolf (12):
63
iotests: Fix CID for VMDK afl image
28
block: Add flags to BlockDriver.bdrv_co_truncate()
64
qemu-img.texi: Clean up parameter list
29
block: Add flags to bdrv(_co)_truncate()
65
qemu-img: Document --force-share / -U
30
block-backend: Add flags to blk_truncate()
66
docs: Document share-rw property more thoroughly
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
67
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
68
Kevin Wolf (1):
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
69
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-02-13' into queue-block
34
block: truncate: Don't make backing file data visible
70
35
iotests: Filter testfiles out in filter_img_info()
71
Max Reitz (8):
36
iotests: Test committing to short backing file
72
iotests: Use virtio-blk in 155
37
qcow2: Forward ZERO_WRITE flag for full preallocation
73
gluster: Move glfs_close() to create's clean-up
38
qom: Factor out user_creatable_add_dict()
74
gluster: Pull truncation from qemu_gluster_create
39
qemu-storage-daemon: Fix non-string --object properties
75
gluster: Query current size in do_truncate()
76
gluster: Add preallocated truncation
77
sheepdog: Make sd_prealloc() take a BDS
78
sheepdog: Pass old and new size to sd_prealloc()
79
sheepdog: Allow fully preallocated truncation
80
40
81
Paolo Bonzini (1):
41
Paolo Bonzini (1):
82
block: early check for blockers on drive-mirror
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
83
43
84
Vladimir Sementsov-Ogievskiy (1):
44
docs/interop/qcow2.txt | 3 +
85
block: maintain persistent disabled bitmaps
45
hw/block/nvme.h | 2 +
46
include/block/block.h | 5 +-
47
include/block/block_int.h | 10 +-
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
49
include/qom/object_interfaces.h | 16 +++
50
include/sysemu/block-backend.h | 2 +-
51
block.c | 3 +-
52
block/block-backend.c | 4 +-
53
block/commit.c | 4 +-
54
block/crypto.c | 7 +-
55
block/file-posix.c | 6 +-
56
block/file-win32.c | 2 +-
57
block/gluster.c | 1 +
58
block/io.c | 43 ++++++-
59
block/iscsi.c | 2 +-
60
block/mirror.c | 2 +-
61
block/nfs.c | 3 +-
62
block/parallels.c | 6 +-
63
block/qcow.c | 4 +-
64
block/qcow2-cluster.c | 2 +-
65
block/qcow2-refcount.c | 2 +-
66
block/qcow2.c | 73 +++++++++--
67
block/qed.c | 3 +-
68
block/raw-format.c | 6 +-
69
block/rbd.c | 1 +
70
block/sheepdog.c | 4 +-
71
block/ssh.c | 2 +-
72
block/vdi.c | 2 +-
73
block/vhdx-log.c | 2 +-
74
block/vhdx.c | 6 +-
75
block/vmdk.c | 8 +-
76
block/vpc.c | 2 +-
77
blockdev.c | 2 +-
78
hw/block/nvme.c | 109 ++++++++++++++++
79
qemu-img.c | 2 +-
80
qemu-io-cmds.c | 2 +-
81
qemu-storage-daemon.c | 4 +-
82
qom/object_interfaces.c | 31 +++++
83
qom/qom-qmp-cmds.c | 24 +---
84
tests/test-block-iothread.c | 9 +-
85
tests/qemu-iotests/iotests.py | 5 +-
86
hw/block/Makefile.objs | 2 +-
87
hw/block/trace-events | 4 +
88
tests/qemu-iotests/244 | 10 +-
89
tests/qemu-iotests/244.out | 9 +-
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
92
tests/qemu-iotests/group | 1 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
94
create mode 100755 tests/qemu-iotests/274
95
create mode 100644 tests/qemu-iotests/274.out
86
96
87
qapi/block-core.json | 12 +-
88
block/qcow2.h | 33 +-
89
include/block/dirty-bitmap.h | 1 -
90
block/dirty-bitmap.c | 18 -
91
block/gluster.c | 116 +++---
92
block/qcow2-bitmap.c | 12 +-
93
block/qcow2-cache.c | 80 ++--
94
block/qcow2-cluster.c | 519 +++++++++++++------------
95
block/qcow2-refcount.c | 206 +++++-----
96
block/qcow2.c | 63 ++-
97
block/sheepdog.c | 56 ++-
98
blockdev.c | 15 +-
99
qemu-io.c | 27 +-
100
docs/qemu-block-drivers.texi | 10 +
101
qemu-doc.texi | 7 +
102
qemu-img.texi | 74 ++--
103
tests/qemu-iotests/059.out | 2 +-
104
tests/qemu-iotests/061 | 16 +
105
tests/qemu-iotests/061.out | 61 +++
106
tests/qemu-iotests/103 | 17 +
107
tests/qemu-iotests/103.out | 3 +
108
tests/qemu-iotests/137 | 5 +
109
tests/qemu-iotests/137.out | 2 +
110
tests/qemu-iotests/155 | 14 +-
111
tests/qemu-iotests/165 | 2 +-
112
tests/qemu-iotests/176 | 2 +-
113
tests/qemu-iotests/sample_images/afl9.vmdk.bz2 | Bin 178 -> 618 bytes
114
27 files changed, 816 insertions(+), 557 deletions(-)
115
97
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
This reverts commit 76bf133c4 which updated the reference output, and
4
fixed the reference image, because the code path we want to exercise is
5
actually the invalid image size.
6
7
The descriptor block in the image, which includes the CID to verify, has been
8
invalid since the reference image was added. Since commit 9877860e7bd we report
9
this error earlier than the "file too large", so 059.out mismatches.
10
11
The binary change is generated along the operations of:
12
13
$ bunzip2 afl9.vmdk.bz2
14
$ qemu-img create -f vmdk fix.vmdk 1G
15
$ dd if=afl9.vmdk of=fix.vmdk bs=512 count=1 conv=notrunc
16
$ mv fix.vmdk afl9.vmdk
17
$ bzip2 afl9.vmdk
18
19
Signed-off-by: Fam Zheng <famz@redhat.com>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
tests/qemu-iotests/059.out | 2 +-
24
tests/qemu-iotests/sample_images/afl9.vmdk.bz2 | Bin 178 -> 618 bytes
25
2 files changed, 1 insertion(+), 1 deletion(-)
26
27
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/059.out
30
+++ b/tests/qemu-iotests/059.out
31
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
32
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
33
34
=== Testing afl image with a very large capacity ===
35
-qemu-img: Could not open 'TEST_DIR/afl9.IMGFMT': Could not open 'TEST_DIR/afl9.IMGFMT': Invalid argument
36
+qemu-img: Can't get image size 'TEST_DIR/afl9.IMGFMT': File too large
37
*** done
38
diff --git a/tests/qemu-iotests/sample_images/afl9.vmdk.bz2 b/tests/qemu-iotests/sample_images/afl9.vmdk.bz2
39
index XXXXXXX..XXXXXXX 100644
40
GIT binary patch
41
literal 618
42
zcmV-w0+szjT4*^jL0KkKSvgW7ssIN3|NsBH-Q9UpfAhclU70`s-*NE~5QvC~h=_=Y
43
zh>D2n*q*=vygR634445h35k;?00h9835kMW00004$iPepVE{Bqk)uhJ^wfGLr=)3s
44
zhM5CR88jLh7)B;cA*K)*6GmuECPU3o4NWG5O#pg>Ak#xY8Z^<M8Z>CrMt}oD38Ns$
45
z02n}M0LdjZ&}cLPqd+nPKmn$j0iXe(02%-d27nnJriN-uE+X&cz@Bj4BBfd|yV!NB
46
zwqkL}nW3AI5x^jp=t%^F1pxqp)v#n#)j$zcm1xqv(!$2d*5%vF{5RPWnOV8-^tE<(
47
zU~%&}Y0uNu*9Wt=yS^8PkC&gPueZO%IG;aD{l#sG`<Af;l1Pnwpi9I75FkQ`LLhd8
48
z6(9f*2s+N5=%bwp80ddrD6>m4Ho*fsHXdM<jtl*zKvRiTx7Ugy1|Nl<Ns!z;1dvhy
49
z=`SDHh~{u|1ZodC(_lzezQ)I*Kv2z|PZ@!SJjlVzwGdx2iu#W}dI{t+T&dDWT^LPy
50
zg3NouEM=V~7GvZQS1CXy676F6mJXWGgW!KTr+E$OspGYCjWmuwa^<Bc>_(-i7fPIW
51
zA+~n9iy_f)g8B2RILhd%F)dZ5f?7pFLw)@;Ncl<JE}gvMrfh{elT#3gLjY6r8xY4O
52
z)UO#pv=WYptukn<DuoMH2ip%k?V^k!rjQirK^RC<Brw>3Bz9<|!xm0F{45K+gg8#n
53
z4FNAJ!<X|3Vq+lyV4=xZ;>AN0<K=%c4A2ruB!4rGvWm!KFrvd4PyfZ-kxmpO4pfM$
54
EfLnqQYXATM
55
56
literal 178
57
zcmV;j08RfwT4*^jL0KkKS>A08g#Z9x|HJ$H)ZJi0004xF0SE*D03g5s00IDLSQelF
58
ziVX^$pfWNUJrmRhn2k52pQ;Rs0EQC;(S%|!m`2~BZ@b++;etskRJUVl!Kt)wu7?VN
59
zl;%JdqX2?TgsNVJP?87M*MvL1qQnBkCES&?0@MeaN-bL4;bDzxmMm|da4fuh!=#fu
60
g@i9R@5z!av{9tA<GGr!3hi~HUNT&)C8_l7xpl%OKQ2+n{
61
62
--
63
2.13.6
64
65
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Split options out of the "@table @var" section and create a "@table
4
@option", then use whitespaces and blank lines consistently.
5
6
Suggested-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Kashyap Chamarthy <kchamart@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
qemu-img.texi | 66 +++++++++++++++++++++++++++++++++++------------------------
13
1 file changed, 39 insertions(+), 27 deletions(-)
14
15
diff --git a/qemu-img.texi b/qemu-img.texi
16
index XXXXXXX..XXXXXXX 100644
17
--- a/qemu-img.texi
18
+++ b/qemu-img.texi
19
@@ -XXX,XX +XXX,XX @@ The following commands are supported:
20
21
Command parameters:
22
@table @var
23
-@item filename
24
- is a disk image filename
25
-
26
-@item --object @var{objectdef}
27
-
28
-is a QEMU user creatable object definition. See the @code{qemu(1)} manual
29
-page for a description of the object properties. The most common object
30
-type is a @code{secret}, which is used to supply passwords and/or encryption
31
-keys.
32
-
33
-@item --image-opts
34
-
35
-Indicates that the source @var{filename} parameter is to be interpreted as a
36
-full option string, not a plain filename. This parameter is mutually
37
-exclusive with the @var{-f} parameter.
38
-
39
-@item --target-image-opts
40
41
-Indicates that the @var{output_filename} parameter(s) are to be interpreted as
42
-a full option string, not a plain filename. This parameter is mutually
43
-exclusive with the @var{-O} parameters. It is currently required to also use
44
-the @var{-n} parameter to skip image creation. This restriction may be relaxed
45
-in a future release.
46
+@item filename
47
+is a disk image filename
48
49
@item fmt
50
is the disk image format. It is guessed automatically in most cases. See below
51
for a description of the supported disk formats.
52
53
-@item --backing-chain
54
-will enumerate information about backing files in a disk image chain. Refer
55
-below for further description.
56
-
57
@item size
58
is the disk image size in bytes. Optional suffixes @code{k} or @code{K}
59
(kilobyte, 1024) @code{M} (megabyte, 1024k) and @code{G} (gigabyte, 1024M)
60
@@ -XXX,XX +XXX,XX @@ and T (terabyte, 1024G) are supported. @code{b} is ignored.
61
is the destination disk image filename
62
63
@item output_fmt
64
- is the destination format
65
+is the destination format
66
+
67
@item options
68
is a comma separated list of format specific options in a
69
name=value format. Use @code{-o ?} for an overview of the options supported
70
by the used format or see the format descriptions below for details.
71
+
72
@item snapshot_param
73
is param used for internal snapshot, format is
74
'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]'
75
+
76
@item snapshot_id_or_name
77
is deprecated, use snapshot_param instead
78
79
+@end table
80
+
81
+@table @option
82
+
83
+@item --object @var{objectdef}
84
+is a QEMU user creatable object definition. See the @code{qemu(1)} manual
85
+page for a description of the object properties. The most common object
86
+type is a @code{secret}, which is used to supply passwords and/or encryption
87
+keys.
88
+
89
+@item --image-opts
90
+Indicates that the source @var{filename} parameter is to be interpreted as a
91
+full option string, not a plain filename. This parameter is mutually
92
+exclusive with the @var{-f} parameter.
93
+
94
+@item --target-image-opts
95
+Indicates that the @var{output_filename} parameter(s) are to be interpreted as
96
+a full option string, not a plain filename. This parameter is mutually
97
+exclusive with the @var{-O} parameters. It is currently required to also use
98
+the @var{-n} parameter to skip image creation. This restriction may be relaxed
99
+in a future release.
100
+
101
+@item --backing-chain
102
+will enumerate information about backing files in a disk image chain. Refer
103
+below for further description.
104
+
105
@item -c
106
indicates that target image must be compressed (qcow format only)
107
+
108
@item -h
109
with or without a command shows help and lists the supported formats
110
+
111
@item -p
112
display progress bar (compare, convert and rebase commands only).
113
If the @var{-p} option is not used for a command that supports it, the
114
progress is reported when the process receives a @code{SIGUSR1} or
115
@code{SIGINFO} signal.
116
+
117
@item -q
118
Quiet mode - do not print any output (except errors). There's no progress bar
119
in case both @var{-q} and @var{-p} options are used.
120
+
121
@item -S @var{size}
122
indicates the consecutive number of bytes that must contain only zeros
123
for qemu-img to create a sparse image during conversion. This value is rounded
124
down to the nearest 512 bytes. You may use the common size suffixes like
125
@code{k} for kilobytes.
126
+
127
@item -t @var{cache}
128
specifies the cache mode that should be used with the (destination) file. See
129
the documentation of the emulator's @code{-drive cache=...} option for allowed
130
values.
131
+
132
@item -T @var{src_cache}
133
specifies the cache mode that should be used with the source file(s). See
134
the documentation of the emulator's @code{-drive cache=...} option for allowed
135
values.
136
+
137
@end table
138
139
Parameters to snapshot subcommand:
140
--
141
2.13.6
142
143
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Signed-off-by: Fam Zheng <famz@redhat.com>
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Kashyap Chamarthy <kchamart@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
qemu-img.texi | 8 ++++++++
9
1 file changed, 8 insertions(+)
10
11
diff --git a/qemu-img.texi b/qemu-img.texi
12
index XXXXXXX..XXXXXXX 100644
13
--- a/qemu-img.texi
14
+++ b/qemu-img.texi
15
@@ -XXX,XX +XXX,XX @@ exclusive with the @var{-O} parameters. It is currently required to also use
16
the @var{-n} parameter to skip image creation. This restriction may be relaxed
17
in a future release.
18
19
+@item --force-share (-U)
20
+If specified, @code{qemu-img} will open the image in shared mode, allowing
21
+other QEMU processes to open it in write mode. For example, this can be used to
22
+get the image information (with 'info' subcommand) when the image is used by a
23
+running guest. Note that this could produce inconsistent results because of
24
+concurrent metadata changes, etc. This option is only allowed when opening
25
+images in read-only mode.
26
+
27
@item --backing-chain
28
will enumerate information about backing files in a disk image chain. Refer
29
below for further description.
30
--
31
2.13.6
32
33
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Suggested-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Signed-off-by: Fam Zheng <famz@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Kashyap Chamarthy <kchamart@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
docs/qemu-block-drivers.texi | 10 ++++++++++
10
1 file changed, 10 insertions(+)
11
12
diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/qemu-block-drivers.texi
15
+++ b/docs/qemu-block-drivers.texi
16
@@ -XXX,XX +XXX,XX @@ QEMU transparently handles lock handover during shared storage migration. For
17
shared virtual disk images between multiple VMs, the "share-rw" device option
18
should be used.
19
20
+By default, the guest has exclusive write access to its disk image. If the
21
+guest can safely share the disk image with other writers the @code{-device
22
+...,share-rw=on} parameter can be used. This is only safe if the guest is
23
+running software, such as a cluster file system, that coordinates disk accesses
24
+to avoid corruption.
25
+
26
+Note that share-rw=on only declares the guest's ability to share the disk.
27
+Some QEMU features, such as image file formats, require exclusive write access
28
+to the disk image and this is unaffected by the share-rw=on option.
29
+
30
Alternatively, locking can be fully disabled by "locking=off" block device
31
option. In the command line, the option is usually in the form of
32
"file.locking=off" as the protocol driver is normally placed as a "file" child
33
--
34
2.13.6
35
36
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
g_realloc() aborts the program if it fails to allocate the required
3
Backing files and raw external data files are mutually exclusive.
4
amount of memory. We want to detect that scenario and return an error
4
The documentation of the raw external data bit (in autoclear_features)
5
instead, so let's use g_try_realloc().
5
already indicates that, but we should also mention it on the other
6
side.
6
7
8
Suggested-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
block/qcow2-cluster.c | 10 +++++++++-
14
docs/interop/qcow2.txt | 3 +++
11
1 file changed, 9 insertions(+), 1 deletion(-)
15
1 file changed, 3 insertions(+)
12
16
13
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2-cluster.c
19
--- a/docs/interop/qcow2.txt
16
+++ b/block/qcow2-cluster.c
20
+++ b/docs/interop/qcow2.txt
17
@@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
18
int l1_sectors = DIV_ROUND_UP(s->snapshots[i].l1_size *
22
is stored (NB: The string is not null terminated). 0 if the
19
sizeof(uint64_t), BDRV_SECTOR_SIZE);
23
image doesn't have a backing file.
20
24
21
- l1_table = g_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE);
25
+ Note: backing files are incompatible with raw external data
22
+ uint64_t *new_l1_table =
26
+ files (auto-clear feature bit 1).
23
+ g_try_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE);
24
+
27
+
25
+ if (!new_l1_table) {
28
16 - 19: backing_file_size
26
+ ret = -ENOMEM;
29
Length of the backing file name in bytes. Must not be
27
+ goto fail;
30
longer than 1023 bytes. Undefined if the image doesn't have
28
+ }
29
+
30
+ l1_table = new_l1_table;
31
32
ret = bdrv_read(bs->file,
33
s->snapshots[i].l1_table_offset / BDRV_SECTOR_SIZE,
34
--
31
--
35
2.13.6
32
2.25.3
36
33
37
34
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Even if an op blocker is present for BLOCK_OP_TYPE_MIRROR_SOURCE,
3
Test 244 checks the expected behavior of qcow2 external data files
4
it is checked a bit late and the result is that the target is
4
with respect to zero and discarded clusters. Filesystems however
5
created even if drive-mirror subsequently fails. Add an early
5
are free to ignore discard requests, and this seems to be the
6
check to avoid this.
6
case for overlayfs. Relax the tests to skip checks on the
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
7
9
10
This fixes docker tests on RHEL8.
11
12
Cc: Kevin Wolf <kwolf@redhat.com>
13
Cc: qemu-block@nongnu.org
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
17
---
13
blockdev.c | 5 +++++
18
tests/qemu-iotests/244 | 10 ++++++++--
14
1 file changed, 5 insertions(+)
19
tests/qemu-iotests/244.out | 9 ++++++---
20
2 files changed, 14 insertions(+), 5 deletions(-)
15
21
16
diff --git a/blockdev.c b/blockdev.c
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
25
+++ b/tests/qemu-iotests/244
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
27
echo
28
$QEMU_IO -c 'read -P 0 0 1M' \
29
-c 'read -P 0x11 1M 1M' \
30
- -c 'read -P 0 2M 2M' \
31
-c 'read -P 0x11 4M 1M' \
32
-c 'read -P 0 5M 1M' \
33
-f raw "$TEST_IMG.data" |
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
35
-f $IMGFMT "$TEST_IMG" |
36
_filter_qemu_io
37
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
39
+# they can contain stale data in the external data file. Instead, zero
40
+# clusters must be zeroed in the external data file too.
41
echo
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
43
+$QEMU_IO -c 'read -P 0 0 1M' \
44
+ -c 'read -P 0x11 1M 1M' \
45
+ -c 'read -P 0 3M 3M' \
46
+ -f raw "$TEST_IMG".data |
47
+ _filter_qemu_io
48
49
echo -n "qcow2 file size after I/O: "
50
du -b $TEST_IMG | cut -f1
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
17
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
18
--- a/blockdev.c
53
--- a/tests/qemu-iotests/244.out
19
+++ b/blockdev.c
54
+++ b/tests/qemu-iotests/244.out
20
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
21
return;
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
22
}
57
read 1048576/1048576 bytes at offset 1048576
23
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
24
+ /* Early check to avoid creating target */
59
-read 2097152/2097152 bytes at offset 2097152
25
+ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
26
+ return;
61
read 1048576/1048576 bytes at offset 4194304
27
+ }
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
28
+
63
read 1048576/1048576 bytes at offset 5242880
29
aio_context = bdrv_get_aio_context(bs);
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
30
aio_context_acquire(aio_context);
65
read 4194304/4194304 bytes at offset 2097152
31
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
68
-Images are identical.
69
+read 1048576/1048576 bytes at offset 0
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
+read 1048576/1048576 bytes at offset 1048576
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+read 3145728/3145728 bytes at offset 3145728
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
qcow2 file size after I/O: 327680
76
77
=== bdrv_co_block_status test for file and offset=0 ===
32
--
78
--
33
2.13.6
79
2.25.3
34
80
35
81
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Only a few select machine types support floppy drives and there is
4
actually nothing preventing us from using virtio here, so let's do it.
5
6
Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/qemu-iotests/155 | 14 +++++++++-----
12
1 file changed, 9 insertions(+), 5 deletions(-)
13
14
diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/155
17
+++ b/tests/qemu-iotests/155
18
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
19
'file': {'driver': 'file',
20
'filename': source_img}}
21
self.vm.add_blockdev(self.qmp_to_opts(blockdev))
22
- self.vm.add_device('floppy,id=qdev0,drive=source')
23
+ self.vm.add_device('virtio-blk,id=qdev0,drive=source')
24
self.vm.launch()
25
26
self.assertIntactSourceBackingChain()
27
@@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass):
28
def testFull(self):
29
self.runMirror('full')
30
31
- node = self.findBlockNode('target', 'qdev0')
32
+ node = self.findBlockNode('target',
33
+ '/machine/peripheral/qdev0/virtio-backend')
34
self.assertCorrectBackingImage(node, None)
35
self.assertIntactSourceBackingChain()
36
37
def testTop(self):
38
self.runMirror('top')
39
40
- node = self.findBlockNode('target', 'qdev0')
41
+ node = self.findBlockNode('target',
42
+ '/machine/peripheral/qdev0/virtio-backend')
43
self.assertCorrectBackingImage(node, back2_img)
44
self.assertIntactSourceBackingChain()
45
46
def testNone(self):
47
self.runMirror('none')
48
49
- node = self.findBlockNode('target', 'qdev0')
50
+ node = self.findBlockNode('target',
51
+ '/machine/peripheral/qdev0/virtio-backend')
52
self.assertCorrectBackingImage(node, source_img)
53
self.assertIntactSourceBackingChain()
54
55
@@ -XXX,XX +XXX,XX @@ class TestCommit(BaseClass):
56
57
self.vm.event_wait('BLOCK_JOB_COMPLETED')
58
59
- node = self.findBlockNode(None, 'qdev0')
60
+ node = self.findBlockNode(None,
61
+ '/machine/peripheral/qdev0/virtio-backend')
62
self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename',
63
back1_img)
64
self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename',
65
--
66
2.13.6
67
68
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
2
driver callbacks, and a supported_truncate_flags field in
3
glfs_close() is a classical clean-up operation, as can be seen by the
3
BlockDriverState that allows drivers to advertise support for request
4
fact that it is executed even if the truncation before it failed.
4
flags in the context of truncate.
5
Also, moving it to clean-up makes it more clear that if it fails, we do
5
6
not want it to overwrite the current ret value if that signifies an
6
For now, we always pass 0 and no drivers declare support for any flag.
7
error already.
7
8
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
14
---
13
block/gluster.c | 10 ++++++----
15
include/block/block_int.h | 10 +++++++++-
14
1 file changed, 6 insertions(+), 4 deletions(-)
16
block/crypto.c | 3 ++-
15
17
block/file-posix.c | 2 +-
18
block/file-win32.c | 2 +-
19
block/gluster.c | 1 +
20
block/io.c | 8 +++++++-
21
block/iscsi.c | 2 +-
22
block/nfs.c | 3 ++-
23
block/qcow2.c | 2 +-
24
block/qed.c | 1 +
25
block/raw-format.c | 2 +-
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
31
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
35
+++ b/include/block/block_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
*/
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
39
bool exact, PreallocMode prealloc,
40
- Error **errp);
41
+ BdrvRequestFlags flags, Error **errp);
42
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
44
bool has_variable_length;
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
48
unsigned int supported_zero_flags;
49
+ /*
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
63
+++ b/block/crypto.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
65
66
static int coroutine_fn
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
68
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
16
diff --git a/block/gluster.c b/block/gluster.c
100
diff --git a/block/gluster.c b/block/gluster.c
17
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
18
--- a/block/gluster.c
102
--- a/block/gluster.c
19
+++ b/block/gluster.c
103
+++ b/block/gluster.c
20
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_create(const char *filename,
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
21
{
105
int64_t offset,
22
BlockdevOptionsGluster *gconf;
106
bool exact,
23
struct glfs *glfs;
107
PreallocMode prealloc,
24
- struct glfs_fd *fd;
108
+ BdrvRequestFlags flags,
25
+ struct glfs_fd *fd = NULL;
109
Error **errp)
26
int ret = 0;
110
{
27
PreallocMode prealloc;
111
BDRVGlusterState *s = bs->opaque;
28
int64_t total_size = 0;
112
diff --git a/block/io.c b/block/io.c
29
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_create(const char *filename,
113
index XXXXXXX..XXXXXXX 100644
30
break;
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
31
}
125
}
32
126
33
- if (glfs_close(fd) != 0) {
127
if (drv->bdrv_co_truncate) {
34
- ret = -errno;
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
35
- }
129
+ if (flags & ~bs->supported_truncate_flags) {
36
out:
130
+ error_setg(errp, "Block driver does not support requested flags");
37
+ if (fd) {
131
+ ret = -ENOTSUP;
38
+ if (glfs_close(fd) != 0 && ret == 0) {
132
+ goto out;
39
+ ret = -errno;
40
+ }
133
+ }
41
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
42
qapi_free_BlockdevOptionsGluster(gconf);
135
} else if (bs->file && drv->is_filter) {
43
glfs_clear_preopened(glfs);
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
44
return ret;
137
} else {
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
143
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
145
bool exact, PreallocMode prealloc,
146
- Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
148
{
149
IscsiLun *iscsilun = bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
45
--
264
--
46
2.13.6
265
2.25.3
47
266
48
267
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
2
4
3
qcow2_update_snapshot_refcount() increases the refcount of all
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
clusters of a given snapshot. In order to do that it needs to load all
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
its L2 tables and iterate over their entries. Since we'll be loading
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
L2 slices instead of full tables we need to add an extra loop that
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
iterates over all slices of each L2 table.
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block.h | 5 +++--
13
block/block-backend.c | 2 +-
14
block/crypto.c | 2 +-
15
block/io.c | 12 +++++++-----
16
block/parallels.c | 6 +++---
17
block/qcow.c | 4 ++--
18
block/qcow2-refcount.c | 2 +-
19
block/qcow2.c | 15 +++++++++------
20
block/raw-format.c | 2 +-
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
8
26
9
This function doesn't need any additional changes so apart from that
27
diff --git a/include/block/block.h b/include/block/block.h
10
this patch simply updates the variable name from l2_table to l2_slice.
28
index XXXXXXX..XXXXXXX 100644
11
29
--- a/include/block/block.h
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
30
+++ b/include/block/block.h
13
Message-id: 5f4db199b9637f4833b58487135124d70add8cf0.1517840877.git.berto@igalia.com
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
32
void bdrv_refresh_filename(BlockDriverState *bs);
15
Reviewed-by: Eric Blake <eblake@redhat.com>
33
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
17
---
35
- PreallocMode prealloc, Error **errp);
18
block/qcow2-refcount.c | 32 ++++++++++++++++++--------------
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
19
1 file changed, 18 insertions(+), 14 deletions(-)
37
+ Error **errp);
20
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
39
- PreallocMode prealloc, Error **errp);
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
43
int64_t bdrv_getlength(BlockDriverState *bs);
44
diff --git a/block/block-backend.c b/block/block-backend.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-backend.c
47
+++ b/block/block-backend.c
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
49
return -ENOMEDIUM;
50
}
51
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
54
}
55
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
57
diff --git a/block/crypto.c b/block/crypto.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
60
+++ b/block/crypto.c
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
62
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
68
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
76
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
81
{
82
BlockDriverState *bs = child->bs;
83
BlockDriver *drv = bs->drv;
84
BdrvTrackedRequest req;
85
- BdrvRequestFlags flags = 0;
86
int64_t old_size, new_bytes;
87
int ret;
88
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
90
}
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
92
} else if (bs->file && drv->is_filter) {
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
95
} else {
96
error_setg(errp, "Image format driver does not support resize");
97
ret = -ENOTSUP;
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
99
int64_t offset;
100
bool exact;
101
PreallocMode prealloc;
102
+ BdrvRequestFlags flags;
103
Error **errp;
104
int ret;
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
107
{
108
TruncateCo *tco = opaque;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
110
- tco->prealloc, tco->errp);
111
+ tco->prealloc, tco->flags, tco->errp);
112
aio_wait_kick();
113
}
114
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
116
- PreallocMode prealloc, Error **errp)
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
118
{
119
Coroutine *co;
120
TruncateCo tco = {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
21
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
22
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-refcount.c
184
--- a/block/qcow2-refcount.c
24
+++ b/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
25
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
26
int64_t l1_table_offset, int l1_size, int addend)
187
}
27
{
188
28
BDRVQcow2State *s = bs->opaque;
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
29
- uint64_t *l1_table, *l2_table, l2_offset, entry, l1_size2, refcount;
190
- PREALLOC_MODE_OFF, &local_err);
30
+ uint64_t *l1_table, *l2_slice, l2_offset, entry, l1_size2, refcount;
191
+ PREALLOC_MODE_OFF, 0, &local_err);
31
bool l1_allocated = false;
192
if (ret < 0) {
32
int64_t old_entry, old_l2_offset;
193
error_report_err(local_err);
33
+ unsigned slice, slice_size2, n_slices;
194
goto resize_fail;
34
int i, j, l1_modified = 0, nb_csectors;
195
diff --git a/block/qcow2.c b/block/qcow2.c
35
int ret;
196
index XXXXXXX..XXXXXXX 100644
36
197
--- a/block/qcow2.c
37
assert(addend >= -1 && addend <= 1);
198
+++ b/block/qcow2.c
38
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
39
- l2_table = NULL;
200
mode = PREALLOC_MODE_OFF;
40
+ l2_slice = NULL;
201
}
41
l1_table = NULL;
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
42
l1_size2 = l1_size * sizeof(uint64_t);
203
- mode, errp);
43
+ slice_size2 = s->l2_slice_size * sizeof(uint64_t);
204
+ mode, 0, errp);
44
+ n_slices = s->cluster_size / slice_size2;
205
if (ret < 0) {
45
206
return ret;
46
s->cache_discards = true;
207
}
47
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
48
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
49
goto fail;
225
goto fail;
50
}
226
}
51
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
52
- {
228
new_file_size = allocation_start +
53
+ for (slice = 0; slice < n_slices; slice++) {
229
nb_new_data_clusters * s->cluster_size;
54
ret = qcow2_cache_get(bs, s->l2_table_cache,
230
/* Image file grows, so @exact does not matter */
55
- l2_offset,
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
56
- (void **) &l2_table);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
57
+ l2_offset + slice * slice_size2,
233
+ errp);
58
+ (void **) &l2_slice);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
254
error_report_err(local_err);
255
goto fail;
256
diff --git a/block/raw-format.c b/block/raw-format.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/raw-format.c
259
+++ b/block/raw-format.c
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
261
262
s->size = offset;
263
offset += s->offset;
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
266
}
267
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
274
goto exit;
275
}
276
ret = bdrv_truncate(bs->file, new_file_size, false,
277
- PREALLOC_MODE_OFF, NULL);
278
+ PREALLOC_MODE_OFF, 0, NULL);
59
if (ret < 0) {
279
if (ret < 0) {
60
goto fail;
280
goto exit;
61
}
281
}
62
282
diff --git a/block/vhdx.c b/block/vhdx.c
63
- for (j = 0; j < s->l2_size; j++) {
283
index XXXXXXX..XXXXXXX 100644
64
+ for (j = 0; j < s->l2_slice_size; j++) {
284
--- a/block/vhdx.c
65
uint64_t cluster_index;
285
+++ b/block/vhdx.c
66
uint64_t offset;
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
67
287
}
68
- entry = be64_to_cpu(l2_table[j]);
288
69
+ entry = be64_to_cpu(l2_slice[j]);
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
70
old_entry = entry;
290
- PREALLOC_MODE_OFF, NULL);
71
entry &= ~QCOW_OFLAG_COPIED;
291
+ PREALLOC_MODE_OFF, 0, NULL);
72
offset = entry & L2E_OFFSET_MASK;
292
}
73
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
293
74
case QCOW2_CLUSTER_NORMAL:
294
/*
75
case QCOW2_CLUSTER_ZERO_ALLOC:
295
diff --git a/block/vmdk.c b/block/vmdk.c
76
if (offset_into_cluster(s, offset)) {
296
index XXXXXXX..XXXXXXX 100644
77
+ /* Here l2_index means table (not slice) index */
297
--- a/block/vmdk.c
78
+ int l2_index = slice * s->l2_slice_size + j;
298
+++ b/block/vmdk.c
79
qcow2_signal_corruption(
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
80
bs, true, -1, -1, "Cluster "
81
"allocation offset %#" PRIx64
82
" unaligned (L2 offset: %#"
83
PRIx64 ", L2 index: %#x)",
84
- offset, l2_offset, j);
85
+ offset, l2_offset, l2_index);
86
ret = -EIO;
87
goto fail;
88
}
89
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
90
qcow2_cache_set_dependency(bs, s->l2_table_cache,
91
s->refcount_block_cache);
92
}
93
- l2_table[j] = cpu_to_be64(entry);
94
+ l2_slice[j] = cpu_to_be64(entry);
95
qcow2_cache_entry_mark_dirty(s->l2_table_cache,
96
- l2_table);
97
+ l2_slice);
98
}
99
}
100
101
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
102
-
103
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
104
}
300
}
105
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
106
if (addend != 0) {
302
ret = bdrv_truncate(s->extents[i].file, length, false,
107
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
303
- PREALLOC_MODE_OFF, NULL);
108
304
+ PREALLOC_MODE_OFF, 0, NULL);
109
ret = bdrv_flush(bs);
305
if (ret < 0) {
110
fail:
306
return ret;
111
- if (l2_table) {
307
}
112
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
113
+ if (l2_slice) {
309
index XXXXXXX..XXXXXXX 100644
114
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
310
--- a/tests/test-block-iothread.c
115
}
311
+++ b/tests/test-block-iothread.c
116
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
117
s->cache_discards = false;
313
int ret;
314
315
/* Normal success path */
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
318
g_assert_cmpint(ret, ==, 0);
319
320
/* Early error: Negative offset */
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
323
g_assert_cmpint(ret, ==, -EINVAL);
324
325
/* Error: Read-only image */
326
c->bs->read_only = true;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
328
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
331
g_assert_cmpint(ret, ==, -EACCES);
332
333
c->bs->read_only = false;
118
--
334
--
119
2.13.6
335
2.25.3
120
336
121
337
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Now that node level interface bdrv_truncate() supports passing request
2
2
flags to the block driver, expose this on the BlockBackend level, too.
3
To maintain load/store disabled bitmap there is new approach:
3
4
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
- deprecate @autoload flag of block-dirty-bitmap-add, make it ignored
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
- store enabled bitmaps as "auto" to qcow2
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
- store disabled bitmaps without "auto" flag to qcow2
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
- on qcow2 open load "auto" bitmaps as enabled and others
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
as disabled (except in_use bitmaps)
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
11
Also, adjust iotests 165 and 176 appropriately.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-id: 20180202160752.143796-1-vsementsov@virtuozzo.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
10
---
17
qapi/block-core.json | 6 +++---
11
include/sysemu/block-backend.h | 2 +-
18
block/qcow2.h | 2 +-
12
block.c | 3 ++-
19
include/block/dirty-bitmap.h | 1 -
13
block/block-backend.c | 4 ++--
20
block/dirty-bitmap.c | 18 ------------------
14
block/commit.c | 4 ++--
21
block/qcow2-bitmap.c | 12 +++++++-----
15
block/crypto.c | 2 +-
22
block/qcow2.c | 2 +-
16
block/mirror.c | 2 +-
23
blockdev.c | 10 ++--------
17
block/qcow2.c | 4 ++--
24
qemu-doc.texi | 7 +++++++
18
block/qed.c | 2 +-
25
tests/qemu-iotests/165 | 2 +-
19
block/vdi.c | 2 +-
26
tests/qemu-iotests/176 | 2 +-
20
block/vhdx.c | 4 ++--
27
10 files changed, 23 insertions(+), 39 deletions(-)
21
block/vmdk.c | 6 +++---
28
22
block/vpc.c | 2 +-
29
diff --git a/qapi/block-core.json b/qapi/block-core.json
23
blockdev.c | 2 +-
30
index XXXXXXX..XXXXXXX 100644
24
qemu-img.c | 2 +-
31
--- a/qapi/block-core.json
25
qemu-io-cmds.c | 2 +-
32
+++ b/qapi/block-core.json
26
15 files changed, 22 insertions(+), 21 deletions(-)
33
@@ -XXX,XX +XXX,XX @@
27
34
# Qcow2 disks support persistent bitmaps. Default is false for
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
35
# block-dirty-bitmap-add. (Since: 2.10)
29
index XXXXXXX..XXXXXXX 100644
36
#
30
--- a/include/sysemu/block-backend.h
37
-# @autoload: the bitmap will be automatically loaded when the image it is stored
31
+++ b/include/sysemu/block-backend.h
38
-# in is opened. This flag may only be specified for persistent
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
39
-# bitmaps. Default is false for block-dirty-bitmap-add. (Since: 2.10)
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
40
+# @autoload: ignored and deprecated since 2.12.
34
int bytes);
41
+# Currently, all dirty tracking bitmaps are loaded from Qcow2 on
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
42
+# open.
36
- PreallocMode prealloc, Error **errp);
43
#
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
44
# Since: 2.4
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
45
##
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
46
diff --git a/block/qcow2.h b/block/qcow2.h
40
int64_t pos, int size);
47
index XXXXXXX..XXXXXXX 100644
41
diff --git a/block.c b/block.c
48
--- a/block/qcow2.h
42
index XXXXXXX..XXXXXXX 100644
49
+++ b/block/qcow2.h
43
--- a/block.c
50
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table);
44
+++ b/block.c
51
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
52
void **refcount_table,
46
int64_t size;
53
int64_t *refcount_table_size);
47
int ret;
54
-bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp);
48
55
+bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp);
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
56
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
57
void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp);
51
+ &local_err);
58
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
52
if (ret < 0 && ret != -ENOTSUP) {
59
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
53
error_propagate(errp, local_err);
60
index XXXXXXX..XXXXXXX 100644
54
return ret;
61
--- a/include/block/dirty-bitmap.h
55
diff --git a/block/block-backend.c b/block/block-backend.c
62
+++ b/include/block/dirty-bitmap.h
56
index XXXXXXX..XXXXXXX 100644
63
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
57
--- a/block/block-backend.c
64
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
58
+++ b/block/block-backend.c
65
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
66
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
67
-void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload);
68
void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
69
bool persistent);
70
71
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/block/dirty-bitmap.c
74
+++ b/block/dirty-bitmap.c
75
@@ -XXX,XX +XXX,XX @@ struct BdrvDirtyBitmap {
76
Such operations must fail and both the image
77
and this bitmap must remain unchanged while
78
this flag is set. */
79
- bool autoload; /* For persistent bitmaps: bitmap must be
80
- autoloaded on image opening */
81
bool persistent; /* bitmap must be saved to owner disk image */
82
QLIST_ENTRY(BdrvDirtyBitmap) list;
83
};
84
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
85
g_free(bitmap->name);
86
bitmap->name = NULL;
87
bitmap->persistent = false;
88
- bitmap->autoload = false;
89
}
60
}
90
61
91
/* Called with BQL taken. */
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
92
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
63
- PreallocMode prealloc, Error **errp)
93
bitmap->successor = NULL;
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
94
successor->persistent = bitmap->persistent;
65
{
95
bitmap->persistent = false;
66
if (!blk_is_available(blk)) {
96
- successor->autoload = bitmap->autoload;
67
error_setg(errp, "No medium inserted");
97
- bitmap->autoload = false;
68
return -ENOMEDIUM;
98
bdrv_release_dirty_bitmap(bs, bitmap);
69
}
99
70
100
return successor;
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
101
@@ -XXX,XX +XXX,XX @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
102
}
73
}
103
74
104
/* Called with BQL taken. */
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
105
-void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload)
76
diff --git a/block/commit.c b/block/commit.c
106
-{
77
index XXXXXXX..XXXXXXX 100644
107
- qemu_mutex_lock(bitmap->mutex);
78
--- a/block/commit.c
108
- bitmap->autoload = autoload;
79
+++ b/block/commit.c
109
- qemu_mutex_unlock(bitmap->mutex);
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
110
-}
81
}
111
-
82
112
-bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap)
83
if (base_len < len) {
113
-{
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
114
- return bitmap->autoload;
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
115
-}
86
if (ret) {
116
-
87
goto out;
117
-/* Called with BQL taken. */
88
}
118
void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
119
{
90
* grow the backing file image if possible. If not possible,
120
qemu_mutex_lock(bitmap->mutex);
91
* we must return an error */
121
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
92
if (length > backing_length) {
122
index XXXXXXX..XXXXXXX 100644
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
123
--- a/block/qcow2-bitmap.c
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
124
+++ b/block/qcow2-bitmap.c
95
&local_err);
125
@@ -XXX,XX +XXX,XX @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
96
if (ret < 0) {
126
bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value);
97
error_report_err(local_err);
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
127
}
108
}
128
109
129
-/* qcow2_load_autoloading_dirty_bitmaps()
110
130
+/* qcow2_load_dirty_bitmaps()
111
diff --git a/block/mirror.c b/block/mirror.c
131
* Return value is a hint for caller: true means that the Qcow2 header was
112
index XXXXXXX..XXXXXXX 100644
132
* updated. (false doesn't mean that the header should be updated by the
113
--- a/block/mirror.c
133
* caller, it just means that updating was not needed or the image cannot be
114
+++ b/block/mirror.c
134
* written to).
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
135
* On failure the function returns false.
116
136
*/
117
if (s->bdev_length > base_length) {
137
-bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp)
118
ret = blk_truncate(s->target, s->bdev_length, false,
138
+bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
119
- PREALLOC_MODE_OFF, NULL);
139
{
120
+ PREALLOC_MODE_OFF, 0, NULL);
140
BDRVQcow2State *s = bs->opaque;
121
if (ret < 0) {
141
Qcow2BitmapList *bm_list;
122
goto immediate_exit;
142
@@ -XXX,XX +XXX,XX @@ bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp)
143
}
144
145
QSIMPLEQ_FOREACH(bm, bm_list, entry) {
146
- if ((bm->flags & BME_FLAG_AUTO) && !(bm->flags & BME_FLAG_IN_USE)) {
147
+ if (!(bm->flags & BME_FLAG_IN_USE)) {
148
BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
149
if (bitmap == NULL) {
150
goto fail;
151
}
123
}
152
153
+ if (!(bm->flags & BME_FLAG_AUTO)) {
154
+ bdrv_disable_dirty_bitmap(bitmap);
155
+ }
156
bdrv_dirty_bitmap_set_persistance(bitmap, true);
157
- bdrv_dirty_bitmap_set_autoload(bitmap, true);
158
bm->flags |= BME_FLAG_IN_USE;
159
created_dirty_bitmaps =
160
g_slist_append(created_dirty_bitmaps, bitmap);
161
@@ -XXX,XX +XXX,XX @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
162
bm->table.size = 0;
163
QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry);
164
}
165
- bm->flags = bdrv_dirty_bitmap_get_autoload(bitmap) ? BME_FLAG_AUTO : 0;
166
+ bm->flags = bdrv_dirty_bitmap_enabled(bitmap) ? BME_FLAG_AUTO : 0;
167
bm->granularity_bits = ctz32(bdrv_dirty_bitmap_granularity(bitmap));
168
bm->dirty_bitmap = bitmap;
169
}
170
diff --git a/block/qcow2.c b/block/qcow2.c
124
diff --git a/block/qcow2.c b/block/qcow2.c
171
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
172
--- a/block/qcow2.c
126
--- a/block/qcow2.c
173
+++ b/block/qcow2.c
127
+++ b/block/qcow2.c
174
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
175
s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
129
176
}
130
/* Okay, now that we have a valid image, let's give it the right size */
177
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
178
- if (qcow2_load_autoloading_dirty_bitmaps(bs, &local_err)) {
132
- errp);
179
+ if (qcow2_load_dirty_bitmaps(bs, &local_err)) {
133
+ 0, errp);
180
update_header = false;
134
if (ret < 0) {
181
}
135
error_prepend(errp, "Could not resize image: ");
182
if (local_err != NULL) {
136
goto out;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
192
diff --git a/block/vmdk.c b/block/vmdk.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
216
* for description file */
217
if (desc_offset == 0) {
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
220
if (ret < 0) {
221
goto exit;
222
}
223
diff --git a/block/vpc.c b/block/vpc.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/vpc.c
226
+++ b/block/vpc.c
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
228
/* Add footer to total size */
229
total_size += HEADER_SIZE;
230
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
233
if (ret < 0) {
234
return ret;
235
}
183
diff --git a/blockdev.c b/blockdev.c
236
diff --git a/blockdev.c b/blockdev.c
184
index XXXXXXX..XXXXXXX 100644
237
index XXXXXXX..XXXXXXX 100644
185
--- a/blockdev.c
238
--- a/blockdev.c
186
+++ b/blockdev.c
239
+++ b/blockdev.c
187
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
188
if (!has_persistent) {
241
}
189
persistent = false;
242
190
}
243
bdrv_drained_begin(bs);
191
- if (!has_autoload) {
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
192
- autoload = false;
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
193
- }
246
bdrv_drained_end(bs);
194
247
195
- if (has_autoload && !persistent) {
248
out:
196
- error_setg(errp, "Autoload flag must be used only for persistent "
249
diff --git a/qemu-img.c b/qemu-img.c
197
- "bitmaps");
250
index XXXXXXX..XXXXXXX 100644
198
- return;
251
--- a/qemu-img.c
199
+ if (has_autoload) {
252
+++ b/qemu-img.c
200
+ warn_report("Autoload option is deprecated and its value is ignored");
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
201
}
254
* resizing, so pass @exact=true. It is of no use to report
202
255
* success when the image has not actually been resized.
203
if (persistent &&
256
*/
204
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
205
}
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
206
259
if (!ret) {
207
bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
260
qprintf(quiet, "Image resized.\n");
208
- bdrv_dirty_bitmap_set_autoload(bitmap, autoload);
261
} else {
209
}
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
210
263
index XXXXXXX..XXXXXXX 100644
211
void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
264
--- a/qemu-io-cmds.c
212
diff --git a/qemu-doc.texi b/qemu-doc.texi
265
+++ b/qemu-io-cmds.c
213
index XXXXXXX..XXXXXXX 100644
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
214
--- a/qemu-doc.texi
267
* exact=true. It is better to err on the "emit more errors" side
215
+++ b/qemu-doc.texi
268
* than to be overly permissive.
216
@@ -XXX,XX +XXX,XX @@ used and it will be removed with no replacement.
269
*/
217
The ``convert -s snapshot_id_or_name'' argument is obsoleted
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
218
by the ``convert -l snapshot_param'' argument instead.
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
219
272
if (ret < 0) {
220
+@section QEMU Machine Protocol (QMP) commands
273
error_report_err(local_err);
221
+
274
return ret;
222
+@subsection block-dirty-bitmap-add "autoload" parameter (since 2.12.0)
223
+
224
+"autoload" parameter is now ignored. All bitmaps are automatically loaded
225
+from qcow2 images.
226
+
227
@section System emulator human monitor commands
228
229
@subsection host_net_add (since 2.10.0)
230
diff --git a/tests/qemu-iotests/165 b/tests/qemu-iotests/165
231
index XXXXXXX..XXXXXXX 100755
232
--- a/tests/qemu-iotests/165
233
+++ b/tests/qemu-iotests/165
234
@@ -XXX,XX +XXX,XX @@ class TestPersistentDirtyBitmap(iotests.QMPTestCase):
235
236
def qmpAddBitmap(self):
237
self.vm.qmp('block-dirty-bitmap-add', node='drive0',
238
- name='bitmap0', persistent=True, autoload=True)
239
+ name='bitmap0', persistent=True)
240
241
def test_persistent(self):
242
self.vm = self.mkVm()
243
diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176
244
index XXXXXXX..XXXXXXX 100755
245
--- a/tests/qemu-iotests/176
246
+++ b/tests/qemu-iotests/176
247
@@ -XXX,XX +XXX,XX @@ case $reason in
248
"file": { "driver": "file", "filename": "$TEST_IMG" } } }
249
{ "execute": "block-dirty-bitmap-add",
250
"arguments": { "node": "drive0", "name": "bitmap0",
251
- "persistent": true, "autoload": true } }
252
+ "persistent": true } }
253
{ "execute": "quit" }
254
EOF
255
    ;;
256
--
275
--
257
2.13.6
276
2.25.3
258
277
259
278
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
undo any previous preallocation, but just adds the zero flag to all
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
request to the data file is made instead.
2
6
3
At the moment it doesn't really make a difference whether we call
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
qcow2_get_refcount() before of after reading the L2 table, but if we
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
5
want to support L2 slices we'll need to read the refcount first.
6
7
This patch simply changes the order of those two operations to prepare
8
for that. The patch with the actual semantic changes will be easier to
9
read because of this.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Message-id: 947a91d934053a2dbfef979aeb9568f57ef57c5d.1517840877.git.berto@igalia.com
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
12
---
17
block/qcow2-cluster.c | 12 ++++++------
13
block/qcow2-cluster.c | 2 +-
18
1 file changed, 6 insertions(+), 6 deletions(-)
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
15
2 files changed, 35 insertions(+), 1 deletion(-)
19
16
20
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2-cluster.c
19
--- a/block/qcow2-cluster.c
23
+++ b/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
24
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
25
goto fail;
22
/* Caller must pass aligned values, except at image end */
26
}
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
27
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
28
+ ret = qcow2_get_refcount(bs, l2_offset >> s->cluster_bits,
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
29
+ &l2_refcount);
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
27
28
/* The zero flag is only supported by version 3 and newer */
29
if (s->qcow_version < 3) {
30
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
35
36
bs->supported_zero_flags = header.version >= 3 ?
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
40
/* Repair image if dirty */
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
43
g_assert_not_reached();
44
}
45
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
48
+
49
+ /*
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
52
+ * at the end of the image (which it is here).
53
+ */
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
30
+ if (ret < 0) {
55
+ if (ret < 0) {
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
31
+ goto fail;
57
+ goto fail;
32
+ }
58
+ }
33
+
59
+
34
if (is_active_l1) {
60
+ /* Write explicit zeros for the unaligned head */
35
/* get active L2 tables from cache */
61
+ if (zero_start > old_length) {
36
ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
62
+ uint64_t len = zero_start - old_length;
37
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
38
goto fail;
64
+ QEMUIOVector qiov;
39
}
65
+ qemu_iovec_init_buf(&qiov, buf, len);
40
66
+
41
- ret = qcow2_get_refcount(bs, l2_offset >> s->cluster_bits,
67
+ qemu_co_mutex_unlock(&s->lock);
42
- &l2_refcount);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
43
- if (ret < 0) {
69
+ qemu_co_mutex_lock(&s->lock);
44
- goto fail;
70
+
45
- }
71
+ qemu_vfree(buf);
46
-
72
+ if (ret < 0) {
47
for (j = 0; j < s->l2_size; j++) {
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
48
uint64_t l2_entry = be64_to_cpu(l2_table[j]);
74
+ goto fail;
49
int64_t offset = l2_entry & L2E_OFFSET_MASK;
75
+ }
76
+ }
77
+ }
78
+
79
if (prealloc != PREALLOC_MODE_OFF) {
80
/* Flush metadata before actually changing the image size */
81
ret = qcow2_write_caches(bs);
50
--
82
--
51
2.13.6
83
2.25.3
52
84
53
85
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
The raw format driver can simply forward the flag and let its bs->file
2
child take care of actually providing the zeros.
2
3
3
By using qemu_do_cluster_truncate() in qemu_cluster_truncate(), we now
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
automatically have preallocated truncation.
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block/gluster.c | 17 +----------------
11
block/raw-format.c | 4 +++-
11
1 file changed, 1 insertion(+), 16 deletions(-)
12
1 file changed, 3 insertions(+), 1 deletion(-)
12
13
13
diff --git a/block/gluster.c b/block/gluster.c
14
diff --git a/block/raw-format.c b/block/raw-format.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/block/gluster.c
16
--- a/block/raw-format.c
16
+++ b/block/gluster.c
17
+++ b/block/raw-format.c
17
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
18
static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
19
19
PreallocMode prealloc, Error **errp)
20
s->size = offset;
20
{
21
offset += s->offset;
21
- int ret;
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
22
BDRVGlusterState *s = bs->opaque;
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
23
-
24
- if (prealloc != PREALLOC_MODE_OFF) {
25
- error_setg(errp, "Unsupported preallocation mode '%s'",
26
- PreallocMode_str(prealloc));
27
- return -ENOTSUP;
28
- }
29
-
30
- ret = glfs_ftruncate(s->fd, offset);
31
- if (ret < 0) {
32
- ret = -errno;
33
- error_setg_errno(errp, -ret, "Failed to truncate file");
34
- return ret;
35
- }
36
-
37
- return 0;
38
+ return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp);
39
}
24
}
40
25
41
static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
30
bs->file->bs->supported_zero_flags);
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
32
+ BDRV_REQ_ZERO_WRITE;
33
34
if (bs->probed && !bdrv_is_read_only(bs)) {
35
bdrv_refresh_filename(bs->file->bs);
42
--
36
--
43
2.13.6
37
2.25.3
44
38
45
39
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
2
OS, so we can advertise the flag and just ignore it.
2
3
3
Pull out the truncation code from the qemu_cluster_create() function so
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
we can later reuse it in qemu_gluster_truncate().
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block/gluster.c | 74 +++++++++++++++++++++++++++++++--------------------------
11
block/file-posix.c | 4 ++++
11
1 file changed, 40 insertions(+), 34 deletions(-)
12
1 file changed, 4 insertions(+)
12
13
13
diff --git a/block/gluster.c b/block/gluster.c
14
diff --git a/block/file-posix.c b/block/file-posix.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/block/gluster.c
16
--- a/block/file-posix.c
16
+++ b/block/gluster.c
17
+++ b/block/file-posix.c
17
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
18
}
19
#endif
19
#endif
20
20
21
+static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
22
+ PreallocMode prealloc, Error **errp)
22
+ if (S_ISREG(st.st_mode)) {
23
+{
23
+ /* When extending regular files, we get zeros from the OS */
24
+ switch (prealloc) {
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
25
+#ifdef CONFIG_GLUSTERFS_FALLOCATE
26
+ case PREALLOC_MODE_FALLOC:
27
+ if (glfs_fallocate(fd, 0, 0, offset)) {
28
+ error_setg_errno(errp, errno, "Could not preallocate data");
29
+ return -errno;
30
+ }
31
+ break;
32
+#endif /* CONFIG_GLUSTERFS_FALLOCATE */
33
+#ifdef CONFIG_GLUSTERFS_ZEROFILL
34
+ case PREALLOC_MODE_FULL:
35
+ if (glfs_ftruncate(fd, offset)) {
36
+ error_setg_errno(errp, errno, "Could not resize file");
37
+ return -errno;
38
+ }
39
+ if (glfs_zerofill(fd, 0, offset)) {
40
+ error_setg_errno(errp, errno, "Could not zerofill the new area");
41
+ return -errno;
42
+ }
43
+ break;
44
+#endif /* CONFIG_GLUSTERFS_ZEROFILL */
45
+ case PREALLOC_MODE_OFF:
46
+ if (glfs_ftruncate(fd, offset)) {
47
+ error_setg_errno(errp, errno, "Could not resize file");
48
+ return -errno;
49
+ }
50
+ break;
51
+ default:
52
+ error_setg(errp, "Unsupported preallocation mode: %s",
53
+ PreallocMode_str(prealloc));
54
+ return -EINVAL;
55
+ }
25
+ }
56
+
26
ret = 0;
57
+ return 0;
27
fail:
58
+}
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
59
+
60
static int qemu_gluster_create(const char *filename,
61
QemuOpts *opts, Error **errp)
62
{
63
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_create(const char *filename,
64
goto out;
65
}
66
67
- switch (prealloc) {
68
-#ifdef CONFIG_GLUSTERFS_FALLOCATE
69
- case PREALLOC_MODE_FALLOC:
70
- if (glfs_fallocate(fd, 0, 0, total_size)) {
71
- error_setg(errp, "Could not preallocate data for the new file");
72
- ret = -errno;
73
- }
74
- break;
75
-#endif /* CONFIG_GLUSTERFS_FALLOCATE */
76
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
77
- case PREALLOC_MODE_FULL:
78
- if (!glfs_ftruncate(fd, total_size)) {
79
- if (glfs_zerofill(fd, 0, total_size)) {
80
- error_setg(errp, "Could not zerofill the new file");
81
- ret = -errno;
82
- }
83
- } else {
84
- error_setg(errp, "Could not resize file");
85
- ret = -errno;
86
- }
87
- break;
88
-#endif /* CONFIG_GLUSTERFS_ZEROFILL */
89
- case PREALLOC_MODE_OFF:
90
- if (glfs_ftruncate(fd, total_size) != 0) {
91
- ret = -errno;
92
- error_setg(errp, "Could not resize file");
93
- }
94
- break;
95
- default:
96
- ret = -EINVAL;
97
- error_setg(errp, "Unsupported preallocation mode: %s",
98
- PreallocMode_str(prealloc));
99
- break;
100
- }
101
+ ret = qemu_gluster_do_truncate(fd, total_size, prealloc, errp);
102
103
out:
104
if (fd) {
105
--
29
--
106
2.13.6
30
2.25.3
107
31
108
32
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
When extending the size of an image that has a backing file larger than
2
its old size, make sure that the backing file data doesn't become
3
visible in the guest, but the added area is properly zeroed out.
2
4
3
We want to use this function in sd_truncate() later on, so taking a
5
Consider the following scenario where the overlay is shorter than its
4
filename is not exactly ideal.
6
backing file:
5
7
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
base.qcow2: AAAAAAAA
7
Reviewed-by: Eric Blake <eblake@redhat.com>
9
overlay.qcow2: BBBB
10
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
29
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
35
---
10
block/sheepdog.c | 29 +++++++++++++++++++++--------
36
block/io.c | 25 +++++++++++++++++++++++++
11
1 file changed, 21 insertions(+), 8 deletions(-)
37
1 file changed, 25 insertions(+)
12
38
13
diff --git a/block/sheepdog.c b/block/sheepdog.c
39
diff --git a/block/io.c b/block/io.c
14
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
15
--- a/block/sheepdog.c
41
--- a/block/io.c
16
+++ b/block/sheepdog.c
42
+++ b/block/io.c
17
@@ -XXX,XX +XXX,XX @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot,
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
18
return 0;
19
}
20
21
-static int sd_prealloc(const char *filename, Error **errp)
22
+static int sd_prealloc(BlockDriverState *bs, Error **errp)
23
{
24
BlockBackend *blk = NULL;
25
- BDRVSheepdogState *base = NULL;
26
+ BDRVSheepdogState *base = bs->opaque;
27
unsigned long buf_size;
28
uint32_t idx, max_idx;
29
uint32_t object_size;
30
@@ -XXX,XX +XXX,XX @@ static int sd_prealloc(const char *filename, Error **errp)
31
void *buf = NULL;
32
int ret;
33
34
- blk = blk_new_open(filename, NULL, NULL,
35
- BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
36
- if (blk == NULL) {
37
- ret = -EIO;
38
+ blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
39
+ BLK_PERM_ALL);
40
+
41
+ ret = blk_insert_bs(blk, bs, errp);
42
+ if (ret < 0) {
43
goto out_with_err_set;
44
}
45
46
@@ -XXX,XX +XXX,XX @@ static int sd_prealloc(const char *filename, Error **errp)
47
goto out;
44
goto out;
48
}
45
}
49
46
50
- base = blk_bs(blk)->opaque;
47
+ /*
51
object_size = (UINT32_C(1) << base->inode.block_size_shift);
48
+ * If the image has a backing file that is large enough that it would
52
buf_size = MIN(object_size, SD_DATA_OBJ_SIZE);
49
+ * provide data for the new area, we cannot leave it unallocated because
53
buf = g_malloc0(buf_size);
50
+ * then the backing file content would become visible. Instead, zero-fill
54
@@ -XXX,XX +XXX,XX @@ static int sd_create(const char *filename, QemuOpts *opts,
51
+ * the new area.
55
}
52
+ *
56
53
+ * Note that if the image has a backing file, but was opened without the
57
if (prealloc) {
54
+ * backing file, taking care of keeping things consistent with that backing
58
- ret = sd_prealloc(filename, errp);
55
+ * file is the user's responsibility.
59
+ BlockDriverState *bs;
56
+ */
60
+ QDict *opts;
57
+ if (new_bytes && bs->backing) {
58
+ int64_t backing_len;
61
+
59
+
62
+ opts = qdict_new();
60
+ backing_len = bdrv_getlength(backing_bs(bs));
63
+ qdict_put_str(opts, "driver", "sheepdog");
61
+ if (backing_len < 0) {
64
+ bs = bdrv_open(filename, NULL, opts, BDRV_O_PROTOCOL | BDRV_O_RDWR,
62
+ ret = backing_len;
65
+ errp);
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
66
+ if (!bs) {
67
+ goto out;
64
+ goto out;
68
+ }
65
+ }
69
+
66
+
70
+ ret = sd_prealloc(bs, errp);
67
+ if (backing_len > old_size) {
68
+ flags |= BDRV_REQ_ZERO_WRITE;
69
+ }
70
+ }
71
+
71
+
72
+ bdrv_unref(bs);
72
if (drv->bdrv_co_truncate) {
73
}
73
if (flags & ~bs->supported_truncate_flags) {
74
out:
74
error_setg(errp, "Block driver does not support requested flags");
75
g_free(backing_file);
76
--
75
--
77
2.13.6
76
2.25.3
78
77
79
78
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
We want to keep TEST_IMG for the full path of the main test image, but
2
filter_testfiles() must be called for other test images before replacing
3
other things like the image format because the test directory path could
4
contain the format as a substring.
2
5
3
Instead of expecting the current size to be 0, query it and allocate
6
Insert a filter_testfiles() call between both.
4
only the area [current_size, offset) if preallocation is requested.
5
7
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
block/gluster.c | 21 +++++++++++++++++++--
14
tests/qemu-iotests/iotests.py | 5 +++--
11
1 file changed, 19 insertions(+), 2 deletions(-)
15
1 file changed, 3 insertions(+), 2 deletions(-)
12
16
13
diff --git a/block/gluster.c b/block/gluster.c
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/block/gluster.c
19
--- a/tests/qemu-iotests/iotests.py
16
+++ b/block/gluster.c
20
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
18
static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
22
for line in output.split('\n'):
19
PreallocMode prealloc, Error **errp)
23
if 'disk size' in line or 'actual-size' in line:
20
{
24
continue
21
+ int64_t current_length;
25
- line = line.replace(filename, 'TEST_IMG') \
22
+
26
- .replace(imgfmt, 'IMGFMT')
23
+ current_length = glfs_lseek(fd, 0, SEEK_END);
27
+ line = line.replace(filename, 'TEST_IMG')
24
+ if (current_length < 0) {
28
+ line = filter_testfiles(line)
25
+ error_setg_errno(errp, errno, "Failed to determine current size");
29
+ line = line.replace(imgfmt, 'IMGFMT')
26
+ return -errno;
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
27
+ }
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
28
+
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
29
+ if (current_length > offset && prealloc != PREALLOC_MODE_OFF) {
30
+ error_setg(errp, "Cannot use preallocation for shrinking files");
31
+ return -ENOTSUP;
32
+ }
33
+
34
+ if (current_length == offset) {
35
+ return 0;
36
+ }
37
+
38
switch (prealloc) {
39
#ifdef CONFIG_GLUSTERFS_FALLOCATE
40
case PREALLOC_MODE_FALLOC:
41
- if (glfs_fallocate(fd, 0, 0, offset)) {
42
+ if (glfs_fallocate(fd, 0, current_length, offset - current_length)) {
43
error_setg_errno(errp, errno, "Could not preallocate data");
44
return -errno;
45
}
46
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
47
error_setg_errno(errp, errno, "Could not resize file");
48
return -errno;
49
}
50
- if (glfs_zerofill(fd, 0, offset)) {
51
+ if (glfs_zerofill(fd, current_length, offset - current_length)) {
52
error_setg_errno(errp, errno, "Could not zerofill the new area");
53
return -errno;
54
}
55
--
33
--
56
2.13.6
34
2.25.3
57
35
58
36
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
qemu-io puts the TTY into non-canonical mode, which means no EOF processing is
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
done and thus getchar() will never return the EOF constant. Instead we have to
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
query the TTY attributes to determine the configured EOF character (usually
6
Ctrl-D / 0x4), and then explicitly check for that value. This fixes the
7
regression that prevented Ctrl-D from triggering an exit of qemu-io that has
8
existed since readline was first added in
9
10
commit 0cf17e181798063c3824c8200ba46f25f54faa1a
11
Author: Stefan Hajnoczi <stefanha@redhat.com>
12
Date: Thu Nov 14 11:54:17 2013 +0100
13
14
qemu-io: use readline.c
15
16
It also ensures that a newline is printed when exiting, to complete the
17
line output by the "qemu-io> " prompt.
18
19
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
6
---
23
qemu-io.c | 27 ++++++++++++++++++++++++++-
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
24
1 file changed, 26 insertions(+), 1 deletion(-)
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 424 insertions(+)
11
create mode 100755 tests/qemu-iotests/274
12
create mode 100644 tests/qemu-iotests/274.out
25
13
26
diff --git a/qemu-io.c b/qemu-io.c
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/274
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python3
21
+#
22
+# Copyright (C) 2019 Red Hat, Inc.
23
+#
24
+# This program is free software; you can redistribute it and/or modify
25
+# it under the terms of the GNU General Public License as published by
26
+# the Free Software Foundation; either version 2 of the License, or
27
+# (at your option) any later version.
28
+#
29
+# This program is distributed in the hope that it will be useful,
30
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+# GNU General Public License for more details.
33
+#
34
+# You should have received a copy of the GNU General Public License
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+#
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
40
+
41
+import iotests
42
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
44
+iotests.verify_platform(['linux'])
45
+
46
+size_short = 1 * 1024 * 1024
47
+size_long = 2 * 1024 * 1024
48
+size_diff = size_long - size_short
49
+
50
+def create_chain() -> None:
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
52
+ str(size_long))
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
54
+ str(size_short))
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
56
+ str(size_long))
57
+
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
59
+
60
+def create_vm() -> iotests.VM:
61
+ vm = iotests.VM()
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
66
+ % iotests.imgfmt)
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
68
+ return vm
69
+
70
+with iotests.FilePath('base') as base, \
71
+ iotests.FilePath('mid') as mid, \
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
137
+
138
+ iotests.log('== Resize tests ==')
139
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
162
+ top_size_old)
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
164
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
176
new file mode 100644
177
index XXXXXXX..XXXXXXX
178
--- /dev/null
179
+++ b/tests/qemu-iotests/274.out
180
@@ -XXX,XX +XXX,XX @@
181
+== Commit tests ==
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
183
+
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
185
+
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
187
+
188
+wrote 2097152/2097152 bytes at offset 0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+
191
+=== Check visible data ===
192
+read 1048576/1048576 bytes at offset 0
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
+
195
+read 1048576/1048576 bytes at offset 1048576
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
27
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
28
--- a/qemu-io.c
451
--- a/tests/qemu-iotests/group
29
+++ b/qemu-io.c
452
+++ b/tests/qemu-iotests/group
30
@@ -XXX,XX +XXX,XX @@
453
@@ -XXX,XX +XXX,XX @@
31
#include "qemu/osdep.h"
454
270 rw backing quick
32
#include <getopt.h>
455
272 rw
33
#include <libgen.h>
456
273 backing quick
34
+#ifndef _WIN32
457
+274 rw backing
35
+#include <termios.h>
458
277 rw quick
36
+#endif
459
279 rw backing quick
37
460
280 rw migration quick
38
#include "qapi/error.h"
39
#include "qemu-io.h"
40
@@ -XXX,XX +XXX,XX @@ static bool imageOpts;
41
42
static ReadLineState *readline_state;
43
44
+static int ttyEOF;
45
+
46
+static int get_eof_char(void)
47
+{
48
+#ifdef _WIN32
49
+ return 0x4; /* Ctrl-D */
50
+#else
51
+ struct termios tty;
52
+ if (tcgetattr(STDIN_FILENO, &tty) != 0) {
53
+ if (errno == ENOTTY) {
54
+ return 0x0; /* just expect read() == 0 */
55
+ } else {
56
+ return 0x4; /* Ctrl-D */
57
+ }
58
+ }
59
+
60
+ return tty.c_cc[VEOF];
61
+#endif
62
+}
63
+
64
static int close_f(BlockBackend *blk, int argc, char **argv)
65
{
66
blk_unref(qemuio_blk);
67
@@ -XXX,XX +XXX,XX @@ static char *fetchline_readline(void)
68
readline_start(readline_state, get_prompt(), 0, readline_func, &line);
69
while (!line) {
70
int ch = getchar();
71
- if (ch == EOF) {
72
+ if (ttyEOF != 0x0 && ch == ttyEOF) {
73
+ printf("\n");
74
break;
75
}
76
readline_handle_byte(readline_state, ch);
77
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
78
qemuio_add_command(&close_cmd);
79
80
if (isatty(STDIN_FILENO)) {
81
+ ttyEOF = get_eof_char();
82
readline_state = readline_init(readline_printf_func,
83
readline_flush_func,
84
NULL,
85
--
461
--
86
2.13.6
462
2.25.3
87
463
88
464
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
sd_prealloc() will now preallocate the area [old_size, new_size). As
4
before, it rounds to buf_size and may thus overshoot and preallocate
5
areas that were not requested to be preallocated. For image creation,
6
this is no change in behavior. For truncation, this is in accordance
7
with the documentation for preallocated truncation.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/sheepdog.c | 16 +++++-----------
14
1 file changed, 5 insertions(+), 11 deletions(-)
15
16
diff --git a/block/sheepdog.c b/block/sheepdog.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/sheepdog.c
19
+++ b/block/sheepdog.c
20
@@ -XXX,XX +XXX,XX @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot,
21
return 0;
22
}
23
24
-static int sd_prealloc(BlockDriverState *bs, Error **errp)
25
+static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size,
26
+ Error **errp)
27
{
28
BlockBackend *blk = NULL;
29
BDRVSheepdogState *base = bs->opaque;
30
unsigned long buf_size;
31
uint32_t idx, max_idx;
32
uint32_t object_size;
33
- int64_t vdi_size;
34
void *buf = NULL;
35
int ret;
36
37
@@ -XXX,XX +XXX,XX @@ static int sd_prealloc(BlockDriverState *bs, Error **errp)
38
39
blk_set_allow_write_beyond_eof(blk, true);
40
41
- vdi_size = blk_getlength(blk);
42
- if (vdi_size < 0) {
43
- ret = vdi_size;
44
- goto out;
45
- }
46
-
47
object_size = (UINT32_C(1) << base->inode.block_size_shift);
48
buf_size = MIN(object_size, SD_DATA_OBJ_SIZE);
49
buf = g_malloc0(buf_size);
50
51
- max_idx = DIV_ROUND_UP(vdi_size, buf_size);
52
+ max_idx = DIV_ROUND_UP(new_size, buf_size);
53
54
- for (idx = 0; idx < max_idx; idx++) {
55
+ for (idx = old_size / buf_size; idx < max_idx; idx++) {
56
/*
57
* The created image can be a cloned image, so we need to read
58
* a data from the source image.
59
@@ -XXX,XX +XXX,XX @@ static int sd_create(const char *filename, QemuOpts *opts,
60
goto out;
61
}
62
63
- ret = sd_prealloc(bs, errp);
64
+ ret = sd_prealloc(bs, 0, s->inode.vdi_size, errp);
65
66
bdrv_unref(bs);
67
}
68
--
69
2.13.6
70
71
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
2
image is possibly preallocated and then the zero flag is added to all
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
2
6
3
The qcow2_truncate() code is mostly independent from whether
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
4
we're using L2 slices or full L2 tables, but in full and
8
and if the protocol driver can ensure that the new area reads as zeros,
5
falloc preallocation modes new L2 tables are allocated using
9
we can skip setting the zero flag in the qcow2 layer.
6
qcow2_alloc_cluster_link_l2(). Therefore the code needs to be
7
modified to ensure that all nb_clusters that are processed in each
8
call can be allocated with just one L2 slice.
9
10
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Unfortunately, the same approach doesn't work for metadata
11
Message-id: 1fd7d272b5e7b66254a090b74cf2bed1cc334c0e.1517840877.git.berto@igalia.com
12
preallocation, so we'll still set the zero flag there.
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
19
---
16
block/qcow2.c | 6 +++---
20
block/qcow2.c | 22 +++++++++++++++++++---
17
1 file changed, 3 insertions(+), 3 deletions(-)
21
tests/qemu-iotests/274.out | 4 ++--
22
2 files changed, 21 insertions(+), 5 deletions(-)
18
23
19
diff --git a/block/qcow2.c b/block/qcow2.c
24
diff --git a/block/qcow2.c b/block/qcow2.c
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
26
--- a/block/qcow2.c
22
+++ b/block/qcow2.c
27
+++ b/block/qcow2.c
23
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
24
host_offset = allocation_start;
29
/* Allocate the data area */
25
guest_offset = old_length;
30
new_file_size = allocation_start +
26
while (nb_new_data_clusters) {
31
nb_new_data_clusters * s->cluster_size;
27
- int64_t guest_cluster = guest_offset >> s->cluster_bits;
32
- /* Image file grows, so @exact does not matter */
28
- int64_t nb_clusters = MIN(nb_new_data_clusters,
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
29
- s->l2_size - guest_cluster % s->l2_size);
34
- errp);
30
+ int64_t nb_clusters = MIN(
35
+ /*
31
+ nb_new_data_clusters,
36
+ * Image file grows, so @exact does not matter.
32
+ s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset));
37
+ *
33
QCowL2Meta allocation = {
38
+ * If we need to zero out the new area, try first whether the protocol
34
.offset = guest_offset,
39
+ * driver can already take care of this.
35
.alloc_offset = host_offset,
40
+ */
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
43
+ BDRV_REQ_ZERO_WRITE, NULL);
44
+ if (ret >= 0) {
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
46
+ }
47
+ } else {
48
+ ret = -1;
49
+ }
50
+ if (ret < 0) {
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
52
+ errp);
53
+ }
54
if (ret < 0) {
55
error_prepend(errp, "Failed to resize underlying file: ");
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tests/qemu-iotests/274.out
60
+++ b/tests/qemu-iotests/274.out
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
63
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
67
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
36
--
79
--
37
2.13.6
80
2.25.3
38
81
39
82
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
Reviewed-by: Eric Blake <eblake@redhat.com>
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
8
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
15
---
7
block/sheepdog.c | 15 ++++++++++++---
16
hw/block/nvme.h | 2 +
8
1 file changed, 12 insertions(+), 3 deletions(-)
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
9
22
10
diff --git a/block/sheepdog.c b/block/sheepdog.c
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
11
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
12
--- a/block/sheepdog.c
25
--- a/hw/block/nvme.h
13
+++ b/block/sheepdog.c
26
+++ b/hw/block/nvme.h
14
@@ -XXX,XX +XXX,XX @@ static int sd_truncate(BlockDriverState *bs, int64_t offset,
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
15
int ret, fd;
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
16
unsigned int datalen;
29
17
uint64_t max_vdi_size;
30
char *serial;
18
+ int64_t old_size = s->inode.vdi_size;
31
+ HostMemoryBackend *pmrdev;
19
32
+
20
- if (prealloc != PREALLOC_MODE_OFF) {
33
NvmeNamespace *namespaces;
21
+ if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_FULL) {
34
NvmeSQueue **sq;
22
error_setg(errp, "Unsupported preallocation mode '%s'",
35
NvmeCQueue **cq;
23
PreallocMode_str(prealloc));
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
24
return -ENOTSUP;
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/nvme.h
39
+++ b/include/block/nvme.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
41
uint64_t acq;
42
uint32_t cmbloc;
43
uint32_t cmbsz;
44
+ uint8_t padding[3520]; /* not used by QEMU */
45
+ uint32_t pmrcap;
46
+ uint32_t pmrctl;
47
+ uint32_t pmrsts;
48
+ uint32_t pmrebs;
49
+ uint32_t pmrswtp;
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
25
}
309
}
26
310
27
max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS;
311
if (addr < sizeof(n->bar)) {
28
- if (offset < s->inode.vdi_size) {
312
+ /*
29
+ if (offset < old_size) {
313
+ * When PMRWBM bit 1 is set then read from
30
error_setg(errp, "shrinking is not supported");
314
+ * from PMRSTS should ensure prior writes
31
return -EINVAL;
315
+ * made it to persistent media
32
} else if (offset > max_vdi_size) {
316
+ */
33
@@ -XXX,XX +XXX,XX @@ static int sd_truncate(BlockDriverState *bs, int64_t offset,
317
+ if (addr == 0xE08 &&
34
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
35
if (ret < 0) {
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
36
error_setg_errno(errp, -ret, "failed to update an inode");
320
+ 0, n->pmrdev->size);
37
+ return ret;
321
+ }
322
memcpy(&val, ptr + addr, size);
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
327
return;
38
}
328
}
39
329
+
40
- return ret;
330
+ if (!n->cmb_size_mb && n->pmrdev) {
41
+ if (prealloc == PREALLOC_MODE_FULL) {
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
42
+ ret = sd_prealloc(bs, old_size, offset, errp);
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
43
+ if (ret < 0) {
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
44
+ return ret;
334
+ g_free(path);
335
+ return;
45
+ }
336
+ }
337
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
340
+ return;
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
46
+ }
344
+ }
47
+
345
+
48
+ return 0;
346
blkconf_blocksizes(&n->conf);
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
348
false, errp)) {
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
352
353
+ } else if (n->pmrdev) {
354
+ /* Controller Capabilities register */
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
356
+
357
+ /* PMR Capabities register */
358
+ n->bar.pmrcap = 0;
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
363
+ /* Turn on bit 1 support */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
367
+
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
398
}
399
400
for (i = 0; i < n->num_namespaces; i++) {
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
402
if (n->cmb_size_mb) {
403
g_free(n->cmbuf);
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
49
}
410
}
50
411
51
/*
412
static Property nvme_props[] = {
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
420
index XXXXXXX..XXXXXXX 100644
421
--- a/hw/block/Makefile.objs
422
+++ b/hw/block/Makefile.objs
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
424
common-obj-$(CONFIG_XEN) += xen-block.o
425
common-obj-$(CONFIG_ECC) += ecc.o
426
common-obj-$(CONFIG_ONENAND) += onenand.o
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
428
common-obj-$(CONFIG_SWIM) += swim.o
429
430
common-obj-$(CONFIG_SH4) += tc58128.o
431
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
435
436
obj-y += dataplane/
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
438
index XXXXXXX..XXXXXXX 100644
439
--- a/hw/block/trace-events
440
+++ b/hw/block/trace-events
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
52
--
452
--
53
2.13.6
453
2.25.3
54
454
55
455
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function has not been returning the offset of the L2 table since
4
commit 3948d1d4876065160583e79533bf604481063833
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-id: b498733b6706a859a03678d74ecbd26aeba129aa.1517840876.git.berto@igalia.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/qcow2-cluster.c | 3 +--
13
1 file changed, 1 insertion(+), 2 deletions(-)
14
15
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2-cluster.c
18
+++ b/block/qcow2-cluster.c
19
@@ -XXX,XX +XXX,XX @@ fail:
20
* for a given disk offset, load (and allocate if needed)
21
* the l2 table.
22
*
23
- * the l2 table offset in the qcow2 file and the cluster index
24
- * in the l2 table are given to the caller.
25
+ * the cluster index in the l2 table is given to the caller.
26
*
27
* Returns 0 on success, -errno in failure case
28
*/
29
--
30
2.13.6
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The table size in the qcow2 cache is currently equal to the cluster
4
size. This doesn't allow us to use the cache memory efficiently,
5
particularly with large cluster sizes, so we need to be able to have
6
smaller cache tables that are independent from the cluster size. This
7
patch adds a new field to Qcow2Cache that we can use instead of the
8
cluster size.
9
10
The current table size is still being initialized to the cluster size,
11
so there are no semantic changes yet, but this patch will allow us to
12
prepare the rest of the code and simplify a few function calls.
13
14
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Message-id: 67a1bf9e55f417005c567bead95a018dc34bc687.1517840876.git.berto@igalia.com
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
block/qcow2-cache.c | 29 ++++++++++++++---------------
21
1 file changed, 14 insertions(+), 15 deletions(-)
22
23
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2-cache.c
26
+++ b/block/qcow2-cache.c
27
@@ -XXX,XX +XXX,XX @@ struct Qcow2Cache {
28
Qcow2CachedTable *entries;
29
struct Qcow2Cache *depends;
30
int size;
31
+ int table_size;
32
bool depends_on_flush;
33
void *table_array;
34
uint64_t lru_counter;
35
@@ -XXX,XX +XXX,XX @@ struct Qcow2Cache {
36
static inline void *qcow2_cache_get_table_addr(BlockDriverState *bs,
37
Qcow2Cache *c, int table)
38
{
39
- BDRVQcow2State *s = bs->opaque;
40
- return (uint8_t *) c->table_array + (size_t) table * s->cluster_size;
41
+ return (uint8_t *) c->table_array + (size_t) table * c->table_size;
42
}
43
44
static inline int qcow2_cache_get_table_idx(BlockDriverState *bs,
45
Qcow2Cache *c, void *table)
46
{
47
- BDRVQcow2State *s = bs->opaque;
48
ptrdiff_t table_offset = (uint8_t *) table - (uint8_t *) c->table_array;
49
- int idx = table_offset / s->cluster_size;
50
- assert(idx >= 0 && idx < c->size && table_offset % s->cluster_size == 0);
51
+ int idx = table_offset / c->table_size;
52
+ assert(idx >= 0 && idx < c->size && table_offset % c->table_size == 0);
53
return idx;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
57
{
58
/* Using MADV_DONTNEED to discard memory is a Linux-specific feature */
59
#ifdef CONFIG_LINUX
60
- BDRVQcow2State *s = bs->opaque;
61
void *t = qcow2_cache_get_table_addr(bs, c, i);
62
int align = getpagesize();
63
- size_t mem_size = (size_t) s->cluster_size * num_tables;
64
+ size_t mem_size = (size_t) c->table_size * num_tables;
65
size_t offset = QEMU_ALIGN_UP((uintptr_t) t, align) - (uintptr_t) t;
66
size_t length = QEMU_ALIGN_DOWN(mem_size - offset, align);
67
if (mem_size > offset && length > 0) {
68
@@ -XXX,XX +XXX,XX @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
69
70
c = g_new0(Qcow2Cache, 1);
71
c->size = num_tables;
72
+ c->table_size = s->cluster_size;
73
c->entries = g_try_new0(Qcow2CachedTable, num_tables);
74
c->table_array = qemu_try_blockalign(bs->file->bs,
75
- (size_t) num_tables * s->cluster_size);
76
+ (size_t) num_tables * c->table_size);
77
78
if (!c->entries || !c->table_array) {
79
qemu_vfree(c->table_array);
80
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
81
82
if (c == s->refcount_block_cache) {
83
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_BLOCK,
84
- c->entries[i].offset, s->cluster_size);
85
+ c->entries[i].offset, c->table_size);
86
} else if (c == s->l2_table_cache) {
87
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2,
88
- c->entries[i].offset, s->cluster_size);
89
+ c->entries[i].offset, c->table_size);
90
} else {
91
ret = qcow2_pre_write_overlap_check(bs, 0,
92
- c->entries[i].offset, s->cluster_size);
93
+ c->entries[i].offset, c->table_size);
94
}
95
96
if (ret < 0) {
97
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
98
}
99
100
ret = bdrv_pwrite(bs->file, c->entries[i].offset,
101
- qcow2_cache_get_table_addr(bs, c, i), s->cluster_size);
102
+ qcow2_cache_get_table_addr(bs, c, i), c->table_size);
103
if (ret < 0) {
104
return ret;
105
}
106
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
107
trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache,
108
offset, read_from_disk);
109
110
- if (offset_into_cluster(s, offset)) {
111
+ if (!QEMU_IS_ALIGNED(offset, c->table_size)) {
112
qcow2_signal_corruption(bs, true, -1, -1, "Cannot get entry from %s "
113
"cache: Offset %#" PRIx64 " is unaligned",
114
qcow2_cache_get_name(s, c), offset);
115
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
116
}
117
118
/* Check if the table is already cached */
119
- i = lookup_index = (offset / s->cluster_size * 4) % c->size;
120
+ i = lookup_index = (offset / c->table_size * 4) % c->size;
121
do {
122
const Qcow2CachedTable *t = &c->entries[i];
123
if (t->offset == offset) {
124
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
125
126
ret = bdrv_pread(bs->file, offset,
127
qcow2_cache_get_table_addr(bs, c, i),
128
- s->cluster_size);
129
+ c->table_size);
130
if (ret < 0) {
131
return ret;
132
}
133
--
134
2.13.6
135
136
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to get the
4
cache table size (since it was equal to the cluster size). This is no
5
longer necessary so this parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: e1f943a9e89e1deb876f45de1bb22419ccdb6ad3.1517840876.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cache.c | 13 ++++++-------
14
1 file changed, 6 insertions(+), 7 deletions(-)
15
16
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cache.c
19
+++ b/block/qcow2-cache.c
20
@@ -XXX,XX +XXX,XX @@ struct Qcow2Cache {
21
uint64_t cache_clean_lru_counter;
22
};
23
24
-static inline void *qcow2_cache_get_table_addr(BlockDriverState *bs,
25
- Qcow2Cache *c, int table)
26
+static inline void *qcow2_cache_get_table_addr(Qcow2Cache *c, int table)
27
{
28
return (uint8_t *) c->table_array + (size_t) table * c->table_size;
29
}
30
@@ -XXX,XX +XXX,XX @@ static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
31
{
32
/* Using MADV_DONTNEED to discard memory is a Linux-specific feature */
33
#ifdef CONFIG_LINUX
34
- void *t = qcow2_cache_get_table_addr(bs, c, i);
35
+ void *t = qcow2_cache_get_table_addr(c, i);
36
int align = getpagesize();
37
size_t mem_size = (size_t) c->table_size * num_tables;
38
size_t offset = QEMU_ALIGN_UP((uintptr_t) t, align) - (uintptr_t) t;
39
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
40
}
41
42
ret = bdrv_pwrite(bs->file, c->entries[i].offset,
43
- qcow2_cache_get_table_addr(bs, c, i), c->table_size);
44
+ qcow2_cache_get_table_addr(c, i), c->table_size);
45
if (ret < 0) {
46
return ret;
47
}
48
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
49
}
50
51
ret = bdrv_pread(bs->file, offset,
52
- qcow2_cache_get_table_addr(bs, c, i),
53
+ qcow2_cache_get_table_addr(c, i),
54
c->table_size);
55
if (ret < 0) {
56
return ret;
57
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
58
/* And return the right table */
59
found:
60
c->entries[i].ref++;
61
- *table = qcow2_cache_get_table_addr(bs, c, i);
62
+ *table = qcow2_cache_get_table_addr(c, i);
63
64
trace_qcow2_cache_get_done(qemu_coroutine_self(),
65
c == s->l2_table_cache, i);
66
@@ -XXX,XX +XXX,XX @@ void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
67
68
for (i = 0; i < c->size; i++) {
69
if (c->entries[i].offset == offset) {
70
- return qcow2_cache_get_table_addr(bs, c, i);
71
+ return qcow2_cache_get_table_addr(c, i);
72
}
73
}
74
return NULL;
75
--
76
2.13.6
77
78
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to get the
4
cache table size (since it was equal to the cluster size). This is no
5
longer necessary so this parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: da3575d47c9a181a2cfd4715e53dd84a2c651017.1517840876.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cache.c | 9 ++++-----
14
1 file changed, 4 insertions(+), 5 deletions(-)
15
16
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cache.c
19
+++ b/block/qcow2-cache.c
20
@@ -XXX,XX +XXX,XX @@ static inline void *qcow2_cache_get_table_addr(Qcow2Cache *c, int table)
21
return (uint8_t *) c->table_array + (size_t) table * c->table_size;
22
}
23
24
-static inline int qcow2_cache_get_table_idx(BlockDriverState *bs,
25
- Qcow2Cache *c, void *table)
26
+static inline int qcow2_cache_get_table_idx(Qcow2Cache *c, void *table)
27
{
28
ptrdiff_t table_offset = (uint8_t *) table - (uint8_t *) c->table_array;
29
int idx = table_offset / c->table_size;
30
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
31
32
void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table)
33
{
34
- int i = qcow2_cache_get_table_idx(bs, c, *table);
35
+ int i = qcow2_cache_get_table_idx(c, *table);
36
37
c->entries[i].ref--;
38
*table = NULL;
39
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table)
40
void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
41
void *table)
42
{
43
- int i = qcow2_cache_get_table_idx(bs, c, table);
44
+ int i = qcow2_cache_get_table_idx(c, table);
45
assert(c->entries[i].offset != 0);
46
c->entries[i].dirty = true;
47
}
48
@@ -XXX,XX +XXX,XX @@ void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
49
50
void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table)
51
{
52
- int i = qcow2_cache_get_table_idx(bs, c, table);
53
+ int i = qcow2_cache_get_table_idx(c, table);
54
55
assert(c->entries[i].ref == 0);
56
57
--
58
2.13.6
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to get the
4
cache table size (since it was equal to the cluster size). This is no
5
longer necessary so this parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 7c1b262344375d52544525f85bbbf0548d5ba575.1517840876.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cache.c | 9 ++++-----
14
1 file changed, 4 insertions(+), 5 deletions(-)
15
16
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cache.c
19
+++ b/block/qcow2-cache.c
20
@@ -XXX,XX +XXX,XX @@ static inline const char *qcow2_cache_get_name(BDRVQcow2State *s, Qcow2Cache *c)
21
}
22
}
23
24
-static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
25
- int i, int num_tables)
26
+static void qcow2_cache_table_release(Qcow2Cache *c, int i, int num_tables)
27
{
28
/* Using MADV_DONTNEED to discard memory is a Linux-specific feature */
29
#ifdef CONFIG_LINUX
30
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_clean_unused(BlockDriverState *bs, Qcow2Cache *c)
31
}
32
33
if (to_clean > 0) {
34
- qcow2_cache_table_release(bs, c, i - to_clean, to_clean);
35
+ qcow2_cache_table_release(c, i - to_clean, to_clean);
36
}
37
}
38
39
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c)
40
c->entries[i].lru_counter = 0;
41
}
42
43
- qcow2_cache_table_release(bs, c, 0, c->size);
44
+ qcow2_cache_table_release(c, 0, c->size);
45
46
c->lru_counter = 0;
47
48
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table)
49
c->entries[i].lru_counter = 0;
50
c->entries[i].dirty = false;
51
52
- qcow2_cache_table_release(bs, c, i, 1);
53
+ qcow2_cache_table_release(c, i, 1);
54
}
55
--
56
2.13.6
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to pass it
4
to qcow2_cache_get_table_idx(). This is no longer necessary so this
5
parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 5c40516a91782b083c1428b7b6a41bb9e2679bfb.1517840876.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2.h | 3 +--
14
block/qcow2-cache.c | 3 +--
15
block/qcow2-cluster.c | 12 ++++++------
16
block/qcow2-refcount.c | 14 ++++++--------
17
4 files changed, 14 insertions(+), 18 deletions(-)
18
19
diff --git a/block/qcow2.h b/block/qcow2.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.h
22
+++ b/block/qcow2.h
23
@@ -XXX,XX +XXX,XX @@ int qcow2_read_snapshots(BlockDriverState *bs);
24
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);
25
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
26
27
-void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
28
- void *table);
29
+void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
30
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
31
int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
32
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
33
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block/qcow2-cache.c
36
+++ b/block/qcow2-cache.c
37
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table)
38
assert(c->entries[i].ref >= 0);
39
}
40
41
-void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
42
- void *table)
43
+void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table)
44
{
45
int i = qcow2_cache_get_table_idx(c, table);
46
assert(c->entries[i].offset != 0);
47
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/qcow2-cluster.c
50
+++ b/block/qcow2-cluster.c
51
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
52
BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
53
54
trace_qcow2_l2_allocate_write_l2(bs, l1_index);
55
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
56
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
57
ret = qcow2_cache_flush(bs, s->l2_table_cache);
58
if (ret < 0) {
59
goto fail;
60
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
61
/* compressed clusters never have the copied flag */
62
63
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
64
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
65
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
66
l2_table[l2_index] = cpu_to_be64(cluster_offset);
67
qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
68
69
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
70
if (ret < 0) {
71
goto err;
72
}
73
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
74
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
75
76
assert(l2_index + m->nb_clusters <= s->l2_size);
77
for (i = 0; i < m->nb_clusters; i++) {
78
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
79
}
80
81
/* First remove L2 entries */
82
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
83
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
84
if (!full_discard && s->qcow_version >= 3) {
85
l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
86
} else {
87
@@ -XXX,XX +XXX,XX @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
88
continue;
89
}
90
91
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
92
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
93
if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
94
l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
95
qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
96
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
97
98
if (is_active_l1) {
99
if (l2_dirty) {
100
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);
101
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
102
qcow2_cache_depends_on_flush(s->l2_table_cache);
103
}
104
qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
105
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/block/qcow2-refcount.c
108
+++ b/block/qcow2-refcount.c
109
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
110
111
/* Now the new refcount block needs to be written to disk */
112
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE);
113
- qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, *refcount_block);
114
+ qcow2_cache_entry_mark_dirty(s->refcount_block_cache, *refcount_block);
115
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
116
if (ret < 0) {
117
goto fail;
118
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
119
goto fail;
120
}
121
memset(refblock_data, 0, s->cluster_size);
122
- qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache,
123
+ qcow2_cache_entry_mark_dirty(s->refcount_block_cache,
124
refblock_data);
125
126
new_table[i] = block_offset;
127
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
128
s->set_refcount(refblock_data, j, 1);
129
}
130
131
- qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache,
132
+ qcow2_cache_entry_mark_dirty(s->refcount_block_cache,
133
refblock_data);
134
}
135
136
@@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
137
}
138
old_table_index = table_index;
139
140
- qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache,
141
- refcount_block);
142
+ qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refcount_block);
143
144
/* we can update the count and save it */
145
block_index = cluster_index & (s->refcount_block_size - 1);
146
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
147
s->refcount_block_cache);
148
}
149
l2_table[j] = cpu_to_be64(entry);
150
- qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache,
151
- l2_table);
152
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
153
}
154
}
155
156
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
157
}
158
s->set_refcount(refblock, block_index, 0);
159
160
- qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, refblock);
161
+ qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refblock);
162
163
qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
164
165
--
166
2.13.6
167
168
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
The QMP handler qmp_object_add() and the implementation of --object in
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
2
5
3
Now that the code is ready to handle L2 slices we can finally add an
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
4
option to allow configuring their size.
7
new function user_creatable_add_dict() that can get an additional
8
parameter. The handling of "props" is only required for compatibility
9
and not required for the qemu-storage-daemon command line, so it stays
10
in qmp_object_add().
5
11
6
An L2 slice is the portion of an L2 table that is read by the qcow2
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
cache. Until now the cache was always reading full L2 tables, and
13
---
8
since the L2 table size is equal to the cluster size this was not very
14
include/qom/object_interfaces.h | 12 ++++++++++++
9
efficient with large clusters. Here's a more detailed explanation of
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
10
why it makes sense to have smaller cache entries in order to load L2
16
qom/qom-qmp-cmds.c | 24 +-----------------------
11
data:
17
3 files changed, 40 insertions(+), 23 deletions(-)
12
18
13
https://lists.gnu.org/archive/html/qemu-block/2017-09/msg00635.html
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
14
15
This patch introduces a new command-line option to the qcow2 driver
16
named l2-cache-entry-size (cf. l2-cache-size). The cache entry size
17
has the same restrictions as the cluster size: it must be a power of
18
two and it has the same range of allowed values, with the additional
19
requirement that it must not be larger than the cluster size.
20
21
The L2 cache entry size (L2 slice size) remains equal to the cluster
22
size for now by default, so this feature must be explicitly enabled.
23
Although my tests show that 4KB slices consistently improve
24
performance and give the best results, let's wait and make more tests
25
with different cluster sizes before deciding on an optimal default.
26
27
Now that the cache entry size is not necessarily equal to the cluster
28
size we need to reflect that in the MIN_L2_CACHE_SIZE documentation.
29
That minimum value is a requirement of the COW algorithm: we need to
30
read two L2 slices (and not two L2 tables) in order to do COW, see
31
l2_allocate() for the actual code.
32
33
Signed-off-by: Alberto Garcia <berto@igalia.com>
34
Reviewed-by: Eric Blake <eblake@redhat.com>
35
Reviewed-by: Max Reitz <mreitz@redhat.com>
36
Message-id: c73e5611ff4a9ec5d20de68a6c289553a13d2354.1517840877.git.berto@igalia.com
37
Signed-off-by: Max Reitz <mreitz@redhat.com>
38
---
39
qapi/block-core.json | 6 ++++++
40
block/qcow2.h | 6 ++++--
41
block/qcow2-cache.c | 10 ++++++++--
42
block/qcow2.c | 34 +++++++++++++++++++++++++++-------
43
4 files changed, 45 insertions(+), 11 deletions(-)
44
45
diff --git a/qapi/block-core.json b/qapi/block-core.json
46
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
47
--- a/qapi/block-core.json
21
--- a/include/qom/object_interfaces.h
48
+++ b/qapi/block-core.json
22
+++ b/include/qom/object_interfaces.h
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
24
const QDict *qdict,
25
Visitor *v, Error **errp);
26
27
+/**
28
+ * user_creatable_add_dict:
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
32
+ * Create an instance of the user creatable object that is defined by
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
45
+++ b/qom/object_interfaces.c
49
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
50
# @l2-cache-size: the maximum size of the L2 table cache in
47
#include "qapi/qmp/qerror.h"
51
# bytes (since 2.2)
48
#include "qapi/qmp/qjson.h"
52
#
49
#include "qapi/qmp/qstring.h"
53
+# @l2-cache-entry-size: the size of each entry in the L2 cache in
50
+#include "qapi/qobject-input-visitor.h"
54
+# bytes. It must be a power of two between 512
51
#include "qom/object_interfaces.h"
55
+# and the cluster size. The default value is
52
#include "qemu/help_option.h"
56
+# the cluster size (since 2.12)
53
#include "qemu/module.h"
57
+#
54
@@ -XXX,XX +XXX,XX @@ out:
58
# @refcount-cache-size: the maximum size of the refcount block cache
55
return obj;
59
# in bytes (since 2.2)
60
#
61
@@ -XXX,XX +XXX,XX @@
62
'*overlap-check': 'Qcow2OverlapChecks',
63
'*cache-size': 'int',
64
'*l2-cache-size': 'int',
65
+ '*l2-cache-entry-size': 'int',
66
'*refcount-cache-size': 'int',
67
'*cache-clean-interval': 'int',
68
'*encrypt': 'BlockdevQcow2Encryption' } }
69
diff --git a/block/qcow2.h b/block/qcow2.h
70
index XXXXXXX..XXXXXXX 100644
71
--- a/block/qcow2.h
72
+++ b/block/qcow2.h
73
@@ -XXX,XX +XXX,XX @@
74
#define MAX_CLUSTER_BITS 21
75
76
/* Must be at least 2 to cover COW */
77
-#define MIN_L2_CACHE_SIZE 2 /* clusters */
78
+#define MIN_L2_CACHE_SIZE 2 /* cache entries */
79
80
/* Must be at least 4 to cover all cases of refcount table growth */
81
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
82
@@ -XXX,XX +XXX,XX @@
83
#define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2"
84
#define QCOW2_OPT_CACHE_SIZE "cache-size"
85
#define QCOW2_OPT_L2_CACHE_SIZE "l2-cache-size"
86
+#define QCOW2_OPT_L2_CACHE_ENTRY_SIZE "l2-cache-entry-size"
87
#define QCOW2_OPT_REFCOUNT_CACHE_SIZE "refcount-cache-size"
88
#define QCOW2_OPT_CACHE_CLEAN_INTERVAL "cache-clean-interval"
89
90
@@ -XXX,XX +XXX,XX @@ void qcow2_free_snapshots(BlockDriverState *bs);
91
int qcow2_read_snapshots(BlockDriverState *bs);
92
93
/* qcow2-cache.c functions */
94
-Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);
95
+Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
96
+ unsigned table_size);
97
int qcow2_cache_destroy(Qcow2Cache *c);
98
99
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
100
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/qcow2-cache.c
103
+++ b/block/qcow2-cache.c
104
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_clean_unused(Qcow2Cache *c)
105
c->cache_clean_lru_counter = c->lru_counter;
106
}
56
}
107
57
108
-Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
109
+Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
59
+{
110
+ unsigned table_size)
60
+ Visitor *v;
111
{
61
+ Object *obj;
112
BDRVQcow2State *s = bs->opaque;
62
+ g_autofree char *type = NULL;
113
Qcow2Cache *c;
63
+ g_autofree char *id = NULL;
114
115
+ assert(num_tables > 0);
116
+ assert(is_power_of_2(table_size));
117
+ assert(table_size >= (1 << MIN_CLUSTER_BITS));
118
+ assert(table_size <= s->cluster_size);
119
+
64
+
120
c = g_new0(Qcow2Cache, 1);
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
121
c->size = num_tables;
66
+ if (!type) {
122
- c->table_size = s->cluster_size;
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
123
+ c->table_size = table_size;
124
c->entries = g_try_new0(Qcow2CachedTable, num_tables);
125
c->table_array = qemu_try_blockalign(bs->file->bs,
126
(size_t) num_tables * c->table_size);
127
diff --git a/block/qcow2.c b/block/qcow2.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/block/qcow2.c
130
+++ b/block/qcow2.c
131
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_runtime_opts = {
132
.help = "Maximum L2 table cache size",
133
},
134
{
135
+ .name = QCOW2_OPT_L2_CACHE_ENTRY_SIZE,
136
+ .type = QEMU_OPT_SIZE,
137
+ .help = "Size of each entry in the L2 cache",
138
+ },
139
+ {
140
.name = QCOW2_OPT_REFCOUNT_CACHE_SIZE,
141
.type = QEMU_OPT_SIZE,
142
.help = "Maximum refcount block cache size",
143
@@ -XXX,XX +XXX,XX @@ static void qcow2_attach_aio_context(BlockDriverState *bs,
144
145
static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
146
uint64_t *l2_cache_size,
147
+ uint64_t *l2_cache_entry_size,
148
uint64_t *refcount_cache_size, Error **errp)
149
{
150
BDRVQcow2State *s = bs->opaque;
151
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
152
*refcount_cache_size = qemu_opt_get_size(opts,
153
QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
154
155
+ *l2_cache_entry_size = qemu_opt_get_size(
156
+ opts, QCOW2_OPT_L2_CACHE_ENTRY_SIZE, s->cluster_size);
157
+
158
if (combined_cache_size_set) {
159
if (l2_cache_size_set && refcount_cache_size_set) {
160
error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
161
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
162
/ DEFAULT_L2_REFCOUNT_SIZE_RATIO;
163
}
164
}
165
+
166
+ if (*l2_cache_entry_size < (1 << MIN_CLUSTER_BITS) ||
167
+ *l2_cache_entry_size > s->cluster_size ||
168
+ !is_power_of_2(*l2_cache_entry_size)) {
169
+ error_setg(errp, "L2 cache entry size must be a power of two "
170
+ "between %d and the cluster size (%d)",
171
+ 1 << MIN_CLUSTER_BITS, s->cluster_size);
172
+ return;
68
+ return;
173
+ }
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
86
{
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
90
+++ b/qom/qom-qmp-cmds.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "qapi/qapi-commands-qom.h"
93
#include "qapi/qmp/qdict.h"
94
#include "qapi/qmp/qerror.h"
95
-#include "qapi/qobject-input-visitor.h"
96
#include "qemu/cutils.h"
97
#include "qom/object_interfaces.h"
98
#include "qom/qom-qobject.h"
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
126
}
127
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
130
- visit_free(v);
131
- object_unref(obj);
132
+ user_creatable_add_dict(qdict, errp);
174
}
133
}
175
134
176
typedef struct Qcow2ReopenState {
135
void qmp_object_del(const char *id, Error **errp)
177
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
178
QemuOpts *opts = NULL;
179
const char *opt_overlap_check, *opt_overlap_check_template;
180
int overlap_check_template = 0;
181
- uint64_t l2_cache_size, refcount_cache_size;
182
+ uint64_t l2_cache_size, l2_cache_entry_size, refcount_cache_size;
183
int i;
184
const char *encryptfmt;
185
QDict *encryptopts = NULL;
186
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
187
}
188
189
/* get L2 table/refcount block cache size from command line options */
190
- read_cache_sizes(bs, opts, &l2_cache_size, &refcount_cache_size,
191
- &local_err);
192
+ read_cache_sizes(bs, opts, &l2_cache_size, &l2_cache_entry_size,
193
+ &refcount_cache_size, &local_err);
194
if (local_err) {
195
error_propagate(errp, local_err);
196
ret = -EINVAL;
197
goto fail;
198
}
199
200
- l2_cache_size /= s->cluster_size;
201
+ l2_cache_size /= l2_cache_entry_size;
202
if (l2_cache_size < MIN_L2_CACHE_SIZE) {
203
l2_cache_size = MIN_L2_CACHE_SIZE;
204
}
205
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
206
}
207
}
208
209
- r->l2_slice_size = s->cluster_size / sizeof(uint64_t);
210
- r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
211
- r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
212
+ r->l2_slice_size = l2_cache_entry_size / sizeof(uint64_t);
213
+ r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size,
214
+ l2_cache_entry_size);
215
+ r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size,
216
+ s->cluster_size);
217
if (r->l2_table_cache == NULL || r->refcount_block_cache == NULL) {
218
error_setg(errp, "Could not allocate metadata caches");
219
ret = -ENOMEM;
220
--
136
--
221
2.13.6
137
2.25.3
222
138
223
139
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
After processing the option string with the keyval parser, we get a
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
2
4
3
This function was only using the BlockDriverState parameter to pass it
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
to qcow2_cache_get_table_idx(). This is no longer necessary so this
6
expects a QDict where all properties already have the QType that matches
5
parameter can be removed.
7
the data type required by the QOM object type.
6
8
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Change the --object implementation in qemu-storage-daemon so that it
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
directly instead and pass it a new keyval boolean that decides which
10
Message-id: 6f98155489054a457563da77cdad1a66ebb3e896.1517840876.git.berto@igalia.com
12
visitor must be used.
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
16
---
13
block/qcow2.h | 2 +-
17
include/qom/object_interfaces.h | 6 +++++-
14
block/qcow2-cache.c | 2 +-
18
qemu-storage-daemon.c | 4 +---
15
block/qcow2-cluster.c | 28 ++++++++++++++--------------
19
qom/object_interfaces.c | 8 ++++++--
16
block/qcow2-refcount.c | 30 +++++++++++++++---------------
20
qom/qom-qmp-cmds.c | 2 +-
17
4 files changed, 31 insertions(+), 31 deletions(-)
21
4 files changed, 13 insertions(+), 7 deletions(-)
18
22
19
diff --git a/block/qcow2.h b/block/qcow2.h
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.h
25
--- a/include/qom/object_interfaces.h
22
+++ b/block/qcow2.h
26
+++ b/include/qom/object_interfaces.h
23
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
24
void **table);
28
/**
25
int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
29
* user_creatable_add_dict:
26
void **table);
30
* @qdict: the object definition
27
-void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
28
+void qcow2_cache_put(Qcow2Cache *c, void **table);
32
+ * assume that all @qdict values are strings); otherwise, use
29
void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
33
+ * the normal QObject visitor (i.e. assume all @qdict values
30
uint64_t offset);
34
+ * have the QType expected by the QOM object type)
31
void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table);
35
* @errp: if an error occurs, a pointer to an area to store the error
32
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
33
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
34
--- a/block/qcow2-cache.c
49
--- a/qemu-storage-daemon.c
35
+++ b/block/qcow2-cache.c
50
+++ b/qemu-storage-daemon.c
36
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
37
return qcow2_cache_do_get(bs, c, offset, table, false);
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
38
}
76
}
39
77
40
-void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table)
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
41
+void qcow2_cache_put(Qcow2Cache *c, void **table)
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
42
{
80
{
43
int i = qcow2_cache_get_table_idx(c, *table);
81
Visitor *v;
44
82
Object *obj;
45
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
84
}
85
qdict_del(qdict, "id");
86
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
88
+ if (keyval) {
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
90
+ } else {
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
92
+ }
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
46
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
47
--- a/block/qcow2-cluster.c
98
--- a/qom/qom-qmp-cmds.c
48
+++ b/block/qcow2-cluster.c
99
+++ b/qom/qom-qmp-cmds.c
49
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
50
101
qobject_unref(pdict);
51
memcpy(l2_table, old_table, s->cluster_size);
52
53
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &old_table);
54
+ qcow2_cache_put(s->l2_table_cache, (void **) &old_table);
55
}
102
}
56
103
57
/* write the l2 table to the file */
104
- user_creatable_add_dict(qdict, errp);
58
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
105
+ user_creatable_add_dict(qdict, false, errp);
59
fail:
60
trace_qcow2_l2_allocate_done(bs, l1_index, ret);
61
if (l2_table != NULL) {
62
- qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
63
+ qcow2_cache_put(s->l2_table_cache, (void **) table);
64
}
65
s->l1_table[l1_index] = old_l2_offset;
66
if (l2_offset > 0) {
67
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
68
abort();
69
}
70
71
- qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
72
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
73
74
bytes_available = (int64_t)c * s->cluster_size;
75
76
@@ -XXX,XX +XXX,XX @@ out:
77
return type;
78
79
fail:
80
- qcow2_cache_put(bs, s->l2_table_cache, (void **)&l2_table);
81
+ qcow2_cache_put(s->l2_table_cache, (void **)&l2_table);
82
return ret;
83
}
106
}
84
107
85
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
108
void qmp_object_del(const char *id, Error **errp)
86
* allocated. */
87
cluster_offset = be64_to_cpu(l2_table[l2_index]);
88
if (cluster_offset & L2E_OFFSET_MASK) {
89
- qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
90
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
91
return 0;
92
}
93
94
cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
95
if (cluster_offset < 0) {
96
- qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
97
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
98
return 0;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
102
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
103
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
104
l2_table[l2_index] = cpu_to_be64(cluster_offset);
105
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
106
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
107
108
return cluster_offset;
109
}
110
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
111
}
112
113
114
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
115
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
116
117
/*
118
* If this was a COW, we need to decrease the refcount of the old cluster.
119
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
120
121
/* Cleanup */
122
out:
123
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
124
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
125
126
/* Only return a host offset if we actually made progress. Otherwise we
127
* would make requirements for handle_alloc() that it can't fulfill */
128
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
129
keep_old_clusters = true;
130
}
131
132
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
133
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
134
135
if (!alloc_cluster_offset) {
136
/* Allocate, if necessary at a given offset in the image file */
137
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
138
qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
139
}
140
141
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
142
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
143
144
return nb_clusters;
145
}
146
@@ -XXX,XX +XXX,XX @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
147
}
148
}
149
150
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
151
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
152
153
return nb_clusters;
154
}
155
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
156
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
157
qcow2_cache_depends_on_flush(s->l2_table_cache);
158
}
159
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
160
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
161
} else {
162
if (l2_dirty) {
163
ret = qcow2_pre_write_overlap_check(bs,
164
@@ -XXX,XX +XXX,XX @@ fail:
165
if (!is_active_l1) {
166
qemu_vfree(l2_table);
167
} else {
168
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
169
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
170
}
171
}
172
return ret;
173
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/block/qcow2-refcount.c
176
+++ b/block/qcow2-refcount.c
177
@@ -XXX,XX +XXX,XX @@ int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
178
block_index = cluster_index & (s->refcount_block_size - 1);
179
*refcount = s->get_refcount(refcount_block, block_index);
180
181
- qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
182
+ qcow2_cache_put(s->refcount_block_cache, &refcount_block);
183
184
return 0;
185
}
186
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
187
return -EAGAIN;
188
}
189
190
- qcow2_cache_put(bs, s->refcount_block_cache, refcount_block);
191
+ qcow2_cache_put(s->refcount_block_cache, refcount_block);
192
193
/*
194
* If we come here, we need to grow the refcount table. Again, a new
195
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
196
197
fail:
198
if (*refcount_block != NULL) {
199
- qcow2_cache_put(bs, s->refcount_block_cache, refcount_block);
200
+ qcow2_cache_put(s->refcount_block_cache, refcount_block);
201
}
202
return ret;
203
}
204
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
205
refblock_data);
206
}
207
208
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock_data);
209
+ qcow2_cache_put(s->refcount_block_cache, &refblock_data);
210
}
211
212
assert(block_offset == table_offset);
213
@@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
214
/* Load the refcount block and allocate it if needed */
215
if (table_index != old_table_index) {
216
if (refcount_block) {
217
- qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
218
+ qcow2_cache_put(s->refcount_block_cache, &refcount_block);
219
}
220
ret = alloc_refcount_block(bs, cluster_index, &refcount_block);
221
if (ret < 0) {
222
@@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
223
table = qcow2_cache_is_table_offset(bs, s->refcount_block_cache,
224
offset);
225
if (table != NULL) {
226
- qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
227
+ qcow2_cache_put(s->refcount_block_cache, &refcount_block);
228
qcow2_cache_discard(bs, s->refcount_block_cache, table);
229
}
230
231
@@ -XXX,XX +XXX,XX @@ fail:
232
233
/* Write last changed block to disk */
234
if (refcount_block) {
235
- qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
236
+ qcow2_cache_put(s->refcount_block_cache, &refcount_block);
237
}
238
239
/*
240
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
241
}
242
}
243
244
- qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);
245
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
246
247
if (addend != 0) {
248
ret = qcow2_update_cluster_refcount(bs, l2_offset >>
249
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
250
ret = bdrv_flush(bs);
251
fail:
252
if (l2_table) {
253
- qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
254
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
255
}
256
257
s->cache_discards = false;
258
@@ -XXX,XX +XXX,XX @@ static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
259
new_reftable_size, new_refblock,
260
new_refblock_empty, allocated, errp);
261
if (ret < 0) {
262
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
263
+ qcow2_cache_put(s->refcount_block_cache, &refblock);
264
return ret;
265
}
266
267
@@ -XXX,XX +XXX,XX @@ static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
268
if (new_refcount_bits < 64 && refcount >> new_refcount_bits) {
269
uint64_t offset;
270
271
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
272
+ qcow2_cache_put(s->refcount_block_cache, &refblock);
273
274
offset = ((reftable_index << s->refcount_block_bits)
275
+ refblock_index) << s->cluster_bits;
276
@@ -XXX,XX +XXX,XX @@ static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
277
new_refblock_empty = new_refblock_empty && refcount == 0;
278
}
279
280
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
281
+ qcow2_cache_put(s->refcount_block_cache, &refblock);
282
} else {
283
/* No refblock means every refcount is 0 */
284
for (refblock_index = 0; refblock_index < s->refcount_block_size;
285
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
286
offset_to_reftable_index(s, discard_block_offs),
287
discard_block_offs,
288
s->get_refcount(refblock, block_index));
289
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
290
+ qcow2_cache_put(s->refcount_block_cache, &refblock);
291
return -EINVAL;
292
}
293
s->set_refcount(refblock, block_index, 0);
294
295
qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refblock);
296
297
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
298
+ qcow2_cache_put(s->refcount_block_cache, &refblock);
299
300
if (cluster_index < s->free_cluster_index) {
301
s->free_cluster_index = cluster_index;
302
@@ -XXX,XX +XXX,XX @@ int qcow2_shrink_reftable(BlockDriverState *bs)
303
} else {
304
unused_block = buffer_is_zero(refblock, s->cluster_size);
305
}
306
- qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
307
+ qcow2_cache_put(s->refcount_block_cache, &refblock);
308
309
reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
310
}
311
--
109
--
312
2.13.6
110
2.25.3
313
111
314
112
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was never using the BlockDriverState parameter so it can
4
be safely removed.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 49c74fe8b3aead9056e61a85b145ce787d06262b.1517840876.git.berto@igalia.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/qcow2.h | 2 +-
13
block/qcow2-cache.c | 2 +-
14
block/qcow2.c | 16 ++++++++--------
15
3 files changed, 10 insertions(+), 10 deletions(-)
16
17
diff --git a/block/qcow2.h b/block/qcow2.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2.h
20
+++ b/block/qcow2.h
21
@@ -XXX,XX +XXX,XX @@ int qcow2_read_snapshots(BlockDriverState *bs);
22
23
/* qcow2-cache.c functions */
24
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);
25
-int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
26
+int qcow2_cache_destroy(Qcow2Cache *c);
27
28
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
29
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
30
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2-cache.c
33
+++ b/block/qcow2-cache.c
34
@@ -XXX,XX +XXX,XX @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
35
return c;
36
}
37
38
-int qcow2_cache_destroy(BlockDriverState *bs, Qcow2Cache *c)
39
+int qcow2_cache_destroy(Qcow2Cache *c)
40
{
41
int i;
42
43
diff --git a/block/qcow2.c b/block/qcow2.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/block/qcow2.c
46
+++ b/block/qcow2.c
47
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_commit(BlockDriverState *bs,
48
int i;
49
50
if (s->l2_table_cache) {
51
- qcow2_cache_destroy(bs, s->l2_table_cache);
52
+ qcow2_cache_destroy(s->l2_table_cache);
53
}
54
if (s->refcount_block_cache) {
55
- qcow2_cache_destroy(bs, s->refcount_block_cache);
56
+ qcow2_cache_destroy(s->refcount_block_cache);
57
}
58
s->l2_table_cache = r->l2_table_cache;
59
s->refcount_block_cache = r->refcount_block_cache;
60
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_abort(BlockDriverState *bs,
61
Qcow2ReopenState *r)
62
{
63
if (r->l2_table_cache) {
64
- qcow2_cache_destroy(bs, r->l2_table_cache);
65
+ qcow2_cache_destroy(r->l2_table_cache);
66
}
67
if (r->refcount_block_cache) {
68
- qcow2_cache_destroy(bs, r->refcount_block_cache);
69
+ qcow2_cache_destroy(r->refcount_block_cache);
70
}
71
qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
72
}
73
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
74
s->l1_table = NULL;
75
cache_clean_timer_del(bs);
76
if (s->l2_table_cache) {
77
- qcow2_cache_destroy(bs, s->l2_table_cache);
78
+ qcow2_cache_destroy(s->l2_table_cache);
79
}
80
if (s->refcount_block_cache) {
81
- qcow2_cache_destroy(bs, s->refcount_block_cache);
82
+ qcow2_cache_destroy(s->refcount_block_cache);
83
}
84
qcrypto_block_free(s->crypto);
85
qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
86
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
87
}
88
89
cache_clean_timer_del(bs);
90
- qcow2_cache_destroy(bs, s->l2_table_cache);
91
- qcow2_cache_destroy(bs, s->refcount_block_cache);
92
+ qcow2_cache_destroy(s->l2_table_cache);
93
+ qcow2_cache_destroy(s->refcount_block_cache);
94
95
qcrypto_block_free(s->crypto);
96
s->crypto = NULL;
97
--
98
2.13.6
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to pass it
4
to qcow2_cache_table_release(). This is no longer necessary so this
5
parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: b74f17591af52f201de0ea3a3b2dd0a81932334d.1517840876.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2.h | 2 +-
14
block/qcow2-cache.c | 2 +-
15
block/qcow2.c | 4 ++--
16
3 files changed, 4 insertions(+), 4 deletions(-)
17
18
diff --git a/block/qcow2.h b/block/qcow2.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2.h
21
+++ b/block/qcow2.h
22
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
23
Qcow2Cache *dependency);
24
void qcow2_cache_depends_on_flush(Qcow2Cache *c);
25
26
-void qcow2_cache_clean_unused(BlockDriverState *bs, Qcow2Cache *c);
27
+void qcow2_cache_clean_unused(Qcow2Cache *c);
28
int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c);
29
30
int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
31
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/qcow2-cache.c
34
+++ b/block/qcow2-cache.c
35
@@ -XXX,XX +XXX,XX @@ static inline bool can_clean_entry(Qcow2Cache *c, int i)
36
t->lru_counter <= c->cache_clean_lru_counter;
37
}
38
39
-void qcow2_cache_clean_unused(BlockDriverState *bs, Qcow2Cache *c)
40
+void qcow2_cache_clean_unused(Qcow2Cache *c)
41
{
42
int i = 0;
43
while (i < c->size) {
44
diff --git a/block/qcow2.c b/block/qcow2.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/qcow2.c
47
+++ b/block/qcow2.c
48
@@ -XXX,XX +XXX,XX @@ static void cache_clean_timer_cb(void *opaque)
49
{
50
BlockDriverState *bs = opaque;
51
BDRVQcow2State *s = bs->opaque;
52
- qcow2_cache_clean_unused(bs, s->l2_table_cache);
53
- qcow2_cache_clean_unused(bs, s->refcount_block_cache);
54
+ qcow2_cache_clean_unused(s->l2_table_cache);
55
+ qcow2_cache_clean_unused(s->refcount_block_cache);
56
timer_mod(s->cache_clean_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
57
(int64_t) s->cache_clean_interval * 1000);
58
}
59
--
60
2.13.6
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to pass it
4
to qcow2_cache_get_table_idx() and qcow2_cache_table_release(). This
5
is no longer necessary so this parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 9724f7e38e763ad3be32627c6b7fe8df9edb1476.1517840877.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2.h | 2 +-
14
block/qcow2-cache.c | 2 +-
15
block/qcow2-refcount.c | 6 +++---
16
3 files changed, 5 insertions(+), 5 deletions(-)
17
18
diff --git a/block/qcow2.h b/block/qcow2.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2.h
21
+++ b/block/qcow2.h
22
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
23
void qcow2_cache_put(Qcow2Cache *c, void **table);
24
void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
25
uint64_t offset);
26
-void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table);
27
+void qcow2_cache_discard(Qcow2Cache *c, void *table);
28
29
/* qcow2-bitmap.c functions */
30
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
31
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/qcow2-cache.c
34
+++ b/block/qcow2-cache.c
35
@@ -XXX,XX +XXX,XX @@ void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
36
return NULL;
37
}
38
39
-void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table)
40
+void qcow2_cache_discard(Qcow2Cache *c, void *table)
41
{
42
int i = qcow2_cache_get_table_idx(c, table);
43
44
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/qcow2-refcount.c
47
+++ b/block/qcow2-refcount.c
48
@@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
49
offset);
50
if (table != NULL) {
51
qcow2_cache_put(s->refcount_block_cache, &refcount_block);
52
- qcow2_cache_discard(bs, s->refcount_block_cache, table);
53
+ qcow2_cache_discard(s->refcount_block_cache, table);
54
}
55
56
table = qcow2_cache_is_table_offset(bs, s->l2_table_cache, offset);
57
if (table != NULL) {
58
- qcow2_cache_discard(bs, s->l2_table_cache, table);
59
+ qcow2_cache_discard(s->l2_table_cache, table);
60
}
61
62
if (s->discard_passthrough[type]) {
63
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
64
discard_block_offs);
65
if (refblock) {
66
/* discard refblock from the cache if refblock is cached */
67
- qcow2_cache_discard(bs, s->refcount_block_cache, refblock);
68
+ qcow2_cache_discard(s->refcount_block_cache, refblock);
69
}
70
update_refcount_discard(bs, discard_block_offs, s->cluster_size);
71
72
--
73
2.13.6
74
75
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function was only using the BlockDriverState parameter to pass it
4
to qcow2_cache_get_table_addr(). This is no longer necessary so this
5
parameter can be removed.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: eb0ed90affcf302e5a954bafb5931b5215483d3a.1517840877.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2.h | 3 +--
14
block/qcow2-cache.c | 3 +--
15
block/qcow2-refcount.c | 6 +++---
16
3 files changed, 5 insertions(+), 7 deletions(-)
17
18
diff --git a/block/qcow2.h b/block/qcow2.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2.h
21
+++ b/block/qcow2.h
22
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
23
int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
24
void **table);
25
void qcow2_cache_put(Qcow2Cache *c, void **table);
26
-void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
27
- uint64_t offset);
28
+void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset);
29
void qcow2_cache_discard(Qcow2Cache *c, void *table);
30
31
/* qcow2-bitmap.c functions */
32
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/qcow2-cache.c
35
+++ b/block/qcow2-cache.c
36
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table)
37
c->entries[i].dirty = true;
38
}
39
40
-void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
41
- uint64_t offset)
42
+void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset)
43
{
44
int i;
45
46
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block/qcow2-refcount.c
49
+++ b/block/qcow2-refcount.c
50
@@ -XXX,XX +XXX,XX @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
51
if (refcount == 0) {
52
void *table;
53
54
- table = qcow2_cache_is_table_offset(bs, s->refcount_block_cache,
55
+ table = qcow2_cache_is_table_offset(s->refcount_block_cache,
56
offset);
57
if (table != NULL) {
58
qcow2_cache_put(s->refcount_block_cache, &refcount_block);
59
qcow2_cache_discard(s->refcount_block_cache, table);
60
}
61
62
- table = qcow2_cache_is_table_offset(bs, s->l2_table_cache, offset);
63
+ table = qcow2_cache_is_table_offset(s->l2_table_cache, offset);
64
if (table != NULL) {
65
qcow2_cache_discard(s->l2_table_cache, table);
66
}
67
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
68
s->free_cluster_index = cluster_index;
69
}
70
71
- refblock = qcow2_cache_is_table_offset(bs, s->refcount_block_cache,
72
+ refblock = qcow2_cache_is_table_offset(s->refcount_block_cache,
73
discard_block_offs);
74
if (refblock) {
75
/* discard refblock from the cache if refblock is cached */
76
--
77
2.13.6
78
79
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Similar to offset_to_l2_index(), this function returns the index in
4
the L1 table for a given guest offset. This is only used in a couple
5
of places and it's not a particularly complex calculation, but it
6
makes the code a bit more readable.
7
8
Although in the qcow2_get_cluster_offset() case the old code was
9
taking advantage of the l1_bits variable, we're going to get rid of
10
the other uses of l1_bits in a later patch anyway, so it doesn't make
11
sense to keep it just for this.
12
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Message-id: a5f626fed526b7459a0425fad06d823d18df8522.1517840877.git.berto@igalia.com
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/qcow2.h | 5 +++++
20
block/qcow2-cluster.c | 4 ++--
21
2 files changed, 7 insertions(+), 2 deletions(-)
22
23
diff --git a/block/qcow2.h b/block/qcow2.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2.h
26
+++ b/block/qcow2.h
27
@@ -XXX,XX +XXX,XX @@ static inline int64_t size_to_l1(BDRVQcow2State *s, int64_t size)
28
return (size + (1ULL << shift) - 1) >> shift;
29
}
30
31
+static inline int offset_to_l1_index(BDRVQcow2State *s, uint64_t offset)
32
+{
33
+ return offset >> (s->l2_bits + s->cluster_bits);
34
+}
35
+
36
static inline int offset_to_l2_index(BDRVQcow2State *s, int64_t offset)
37
{
38
return (offset >> s->cluster_bits) & (s->l2_size - 1);
39
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2-cluster.c
42
+++ b/block/qcow2-cluster.c
43
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
44
45
/* seek to the l2 offset in the l1 table */
46
47
- l1_index = offset >> l1_bits;
48
+ l1_index = offset_to_l1_index(s, offset);
49
if (l1_index >= s->l1_size) {
50
type = QCOW2_CLUSTER_UNALLOCATED;
51
goto out;
52
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
53
54
/* seek to the l2 offset in the l1 table */
55
56
- l1_index = offset >> (s->l2_bits + s->cluster_bits);
57
+ l1_index = offset_to_l1_index(s, offset);
58
if (l1_index >= s->l1_size) {
59
ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
60
if (ret < 0) {
61
--
62
2.13.6
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The BDRVQcow2State structure contains an l2_size field, which stores
4
the number of 64-bit entries in an L2 table.
5
6
For efficiency reasons we want to be able to load slices instead of
7
full L2 tables, so we need to know how many entries an L2 slice can
8
hold.
9
10
An L2 slice is the portion of an L2 table that is loaded by the qcow2
11
cache. At the moment that cache can only load complete tables,
12
therefore an L2 slice has the same size as an L2 table (one cluster)
13
and l2_size == l2_slice_size.
14
15
Later we'll allow smaller slices, but until then we have to use this
16
new l2_slice_size field to make the rest of the code ready for that.
17
18
Signed-off-by: Alberto Garcia <berto@igalia.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Message-id: adb048595f9fb5dfb110c802a8b3c3be3b937f37.1517840877.git.berto@igalia.com
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
block/qcow2.h | 1 +
25
block/qcow2.c | 3 +++
26
2 files changed, 4 insertions(+)
27
28
diff --git a/block/qcow2.h b/block/qcow2.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/qcow2.h
31
+++ b/block/qcow2.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
33
int cluster_bits;
34
int cluster_size;
35
int cluster_sectors;
36
+ int l2_slice_size;
37
int l2_bits;
38
int l2_size;
39
int l1_size;
40
diff --git a/block/qcow2.c b/block/qcow2.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/qcow2.c
43
+++ b/block/qcow2.c
44
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
45
typedef struct Qcow2ReopenState {
46
Qcow2Cache *l2_table_cache;
47
Qcow2Cache *refcount_block_cache;
48
+ int l2_slice_size; /* Number of entries in a slice of the L2 table */
49
bool use_lazy_refcounts;
50
int overlap_check;
51
bool discard_passthrough[QCOW2_DISCARD_MAX];
52
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
53
}
54
}
55
56
+ r->l2_slice_size = s->cluster_size / sizeof(uint64_t);
57
r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
58
r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
59
if (r->l2_table_cache == NULL || r->refcount_block_cache == NULL) {
60
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_commit(BlockDriverState *bs,
61
}
62
s->l2_table_cache = r->l2_table_cache;
63
s->refcount_block_cache = r->refcount_block_cache;
64
+ s->l2_slice_size = r->l2_slice_size;
65
66
s->overlap_check = r->overlap_check;
67
s->use_lazy_refcounts = r->use_lazy_refcounts;
68
--
69
2.13.6
70
71
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Similar to offset_to_l2_index(), this function takes a guest offset
4
and returns the index in the L2 slice that contains its L2 entry.
5
6
An L2 slice has currently the same size as an L2 table (one cluster),
7
so both functions return the same value for now.
8
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-id: a1c45c5c5a76146dd1712d8d1e7b409ad539c718.1517840877.git.berto@igalia.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/qcow2.h | 5 +++++
16
1 file changed, 5 insertions(+)
17
18
diff --git a/block/qcow2.h b/block/qcow2.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2.h
21
+++ b/block/qcow2.h
22
@@ -XXX,XX +XXX,XX @@ static inline int offset_to_l2_index(BDRVQcow2State *s, int64_t offset)
23
return (offset >> s->cluster_bits) & (s->l2_size - 1);
24
}
25
26
+static inline int offset_to_l2_slice_index(BDRVQcow2State *s, int64_t offset)
27
+{
28
+ return (offset >> s->cluster_bits) & (s->l2_slice_size - 1);
29
+}
30
+
31
static inline int64_t align_offset(int64_t offset, int n)
32
{
33
offset = (offset + n - 1) & ~(n - 1);
34
--
35
2.13.6
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Each entry in the qcow2 L2 cache stores a full L2 table (which uses a
4
complete cluster in the qcow2 image). A cluster is usually too large
5
to be used efficiently as the size for a cache entry, so we want to
6
decouple both values by allowing smaller cache entries. Therefore the
7
qcow2 L2 cache will no longer return full L2 tables but slices
8
instead.
9
10
This patch updates l2_load() so it can handle L2 slices correctly.
11
Apart from the offset of the L2 table (which we already had) we also
12
need the guest offset in order to calculate which one of the slices
13
we need.
14
15
An L2 slice has currently the same size as an L2 table (one cluster),
16
so for now this function will load exactly the same data as before.
17
18
This patch also removes a stale comment about the return value being
19
a pointer to the L2 table. This function returns an error code since
20
55c17e9821c474d5fcdebdc82ed2fc096777d611.
21
22
Signed-off-by: Alberto Garcia <berto@igalia.com>
23
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Reviewed-by: Max Reitz <mreitz@redhat.com>
25
Message-id: b830aa1fc5b6f8e3cb331d006853fe22facca847.1517840877.git.berto@igalia.com
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
block/qcow2-cluster.c | 28 +++++++++++++++++-----------
29
1 file changed, 17 insertions(+), 11 deletions(-)
30
31
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/qcow2-cluster.c
34
+++ b/block/qcow2-cluster.c
35
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
36
/*
37
* l2_load
38
*
39
- * Loads a L2 table into memory. If the table is in the cache, the cache
40
- * is used; otherwise the L2 table is loaded from the image file.
41
+ * @bs: The BlockDriverState
42
+ * @offset: A guest offset, used to calculate what slice of the L2
43
+ * table to load.
44
+ * @l2_offset: Offset to the L2 table in the image file.
45
+ * @l2_slice: Location to store the pointer to the L2 slice.
46
*
47
- * Returns a pointer to the L2 table on success, or NULL if the read from
48
- * the image file failed.
49
+ * Loads a L2 slice into memory (L2 slices are the parts of L2 tables
50
+ * that are loaded by the qcow2 cache). If the slice is in the cache,
51
+ * the cache is used; otherwise the L2 slice is loaded from the image
52
+ * file.
53
*/
54
-
55
-static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
56
- uint64_t **l2_table)
57
+static int l2_load(BlockDriverState *bs, uint64_t offset,
58
+ uint64_t l2_offset, uint64_t **l2_slice)
59
{
60
BDRVQcow2State *s = bs->opaque;
61
+ int start_of_slice = sizeof(uint64_t) *
62
+ (offset_to_l2_index(s, offset) - offset_to_l2_slice_index(s, offset));
63
64
- return qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
65
- (void **)l2_table);
66
+ return qcow2_cache_get(bs, s->l2_table_cache, l2_offset + start_of_slice,
67
+ (void **)l2_slice);
68
}
69
70
/*
71
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
72
73
/* load the l2 table in memory */
74
75
- ret = l2_load(bs, l2_offset, &l2_table);
76
+ ret = l2_load(bs, offset, l2_offset, &l2_table);
77
if (ret < 0) {
78
return ret;
79
}
80
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
81
82
if (s->l1_table[l1_index] & QCOW_OFLAG_COPIED) {
83
/* load the l2 table in memory */
84
- ret = l2_load(bs, l2_offset, &l2_table);
85
+ ret = l2_load(bs, offset, l2_offset, &l2_table);
86
if (ret < 0) {
87
return ret;
88
}
89
--
90
2.13.6
91
92
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Adding support for L2 slices to l2_allocate() needs (among other
4
things) an extra loop that iterates over all slices of a new L2 table.
5
6
Putting all changes in one patch would make it hard to read because
7
all semantic changes would be mixed with pure indentation changes.
8
9
To make things easier this patch simply creates a new block and
10
changes the indentation of all lines of code inside it. Thus, all
11
modifications in this patch are cosmetic. There are no semantic
12
changes and no variables are renamed yet. The next patch will take
13
care of that.
14
15
Signed-off-by: Alberto Garcia <berto@igalia.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Message-id: d0d7dca8520db304524f52f49d8157595a707a35.1517840877.git.berto@igalia.com
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
---
21
block/qcow2-cluster.c | 53 ++++++++++++++++++++++++++++-----------------------
22
1 file changed, 29 insertions(+), 24 deletions(-)
23
24
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2-cluster.c
27
+++ b/block/qcow2-cluster.c
28
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
29
/* allocate a new entry in the l2 cache */
30
31
trace_qcow2_l2_allocate_get_empty(bs, l1_index);
32
- ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table);
33
- if (ret < 0) {
34
- goto fail;
35
- }
36
+ {
37
+ ret = qcow2_cache_get_empty(bs, s->l2_table_cache,
38
+ l2_offset,
39
+ (void **) table);
40
+ if (ret < 0) {
41
+ goto fail;
42
+ }
43
44
- l2_table = *table;
45
+ l2_table = *table;
46
47
- if ((old_l2_offset & L1E_OFFSET_MASK) == 0) {
48
- /* if there was no old l2 table, clear the new table */
49
- memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
50
- } else {
51
- uint64_t* old_table;
52
+ if ((old_l2_offset & L1E_OFFSET_MASK) == 0) {
53
+ /* if there was no old l2 table, clear the new table */
54
+ memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
55
+ } else {
56
+ uint64_t *old_table;
57
58
- /* if there was an old l2 table, read it from the disk */
59
- BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ);
60
- ret = qcow2_cache_get(bs, s->l2_table_cache,
61
- old_l2_offset & L1E_OFFSET_MASK,
62
- (void**) &old_table);
63
- if (ret < 0) {
64
- goto fail;
65
+ /* if there was an old l2 table, read it from the disk */
66
+ BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ);
67
+ ret = qcow2_cache_get(bs, s->l2_table_cache,
68
+ old_l2_offset & L1E_OFFSET_MASK,
69
+ (void **) &old_table);
70
+ if (ret < 0) {
71
+ goto fail;
72
+ }
73
+
74
+ memcpy(l2_table, old_table, s->cluster_size);
75
+
76
+ qcow2_cache_put(s->l2_table_cache, (void **) &old_table);
77
}
78
79
- memcpy(l2_table, old_table, s->cluster_size);
80
+ /* write the l2 table to the file */
81
+ BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
82
83
- qcow2_cache_put(s->l2_table_cache, (void **) &old_table);
84
+ trace_qcow2_l2_allocate_write_l2(bs, l1_index);
85
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
86
}
87
88
- /* write the l2 table to the file */
89
- BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
90
-
91
- trace_qcow2_l2_allocate_write_l2(bs, l1_index);
92
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
93
ret = qcow2_cache_flush(bs, s->l2_table_cache);
94
if (ret < 0) {
95
goto fail;
96
--
97
2.13.6
98
99
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This patch updates l2_allocate() to support the qcow2 cache returning
4
L2 slices instead of full L2 tables.
5
6
The old code simply gets an L2 table from the cache and initializes it
7
with zeroes or with the contents of an existing table. With a cache
8
that returns slices instead of tables the idea remains the same, but
9
the code must now iterate over all the slices that are contained in an
10
L2 table.
11
12
Since now we're operating with slices the function can no longer
13
return the newly-allocated table, so it's up to the caller to retrieve
14
the appropriate L2 slice after calling l2_allocate() (note that with
15
this patch the caller is still loading full L2 tables, but we'll deal
16
with that in a separate patch).
17
18
Signed-off-by: Alberto Garcia <berto@igalia.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Message-id: 20fc0415bf0e011e29f6487ec86eb06a11f37445.1517840877.git.berto@igalia.com
21
Reviewed-by: Max Reitz <mreitz@redhat.com>
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
block/qcow2-cluster.c | 56 +++++++++++++++++++++++++++++++--------------------
25
1 file changed, 34 insertions(+), 22 deletions(-)
26
27
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/qcow2-cluster.c
30
+++ b/block/qcow2-cluster.c
31
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
32
*
33
*/
34
35
-static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
36
+static int l2_allocate(BlockDriverState *bs, int l1_index)
37
{
38
BDRVQcow2State *s = bs->opaque;
39
uint64_t old_l2_offset;
40
- uint64_t *l2_table = NULL;
41
+ uint64_t *l2_slice = NULL;
42
+ unsigned slice, slice_size2, n_slices;
43
int64_t l2_offset;
44
int ret;
45
46
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
47
48
/* allocate a new entry in the l2 cache */
49
50
+ slice_size2 = s->l2_slice_size * sizeof(uint64_t);
51
+ n_slices = s->cluster_size / slice_size2;
52
+
53
trace_qcow2_l2_allocate_get_empty(bs, l1_index);
54
- {
55
+ for (slice = 0; slice < n_slices; slice++) {
56
ret = qcow2_cache_get_empty(bs, s->l2_table_cache,
57
- l2_offset,
58
- (void **) table);
59
+ l2_offset + slice * slice_size2,
60
+ (void **) &l2_slice);
61
if (ret < 0) {
62
goto fail;
63
}
64
65
- l2_table = *table;
66
-
67
if ((old_l2_offset & L1E_OFFSET_MASK) == 0) {
68
- /* if there was no old l2 table, clear the new table */
69
- memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
70
+ /* if there was no old l2 table, clear the new slice */
71
+ memset(l2_slice, 0, slice_size2);
72
} else {
73
- uint64_t *old_table;
74
+ uint64_t *old_slice;
75
+ uint64_t old_l2_slice_offset =
76
+ (old_l2_offset & L1E_OFFSET_MASK) + slice * slice_size2;
77
78
- /* if there was an old l2 table, read it from the disk */
79
+ /* if there was an old l2 table, read a slice from the disk */
80
BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ);
81
- ret = qcow2_cache_get(bs, s->l2_table_cache,
82
- old_l2_offset & L1E_OFFSET_MASK,
83
- (void **) &old_table);
84
+ ret = qcow2_cache_get(bs, s->l2_table_cache, old_l2_slice_offset,
85
+ (void **) &old_slice);
86
if (ret < 0) {
87
goto fail;
88
}
89
90
- memcpy(l2_table, old_table, s->cluster_size);
91
+ memcpy(l2_slice, old_slice, slice_size2);
92
93
- qcow2_cache_put(s->l2_table_cache, (void **) &old_table);
94
+ qcow2_cache_put(s->l2_table_cache, (void **) &old_slice);
95
}
96
97
- /* write the l2 table to the file */
98
+ /* write the l2 slice to the file */
99
BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
100
101
trace_qcow2_l2_allocate_write_l2(bs, l1_index);
102
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
103
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
104
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
105
}
106
107
ret = qcow2_cache_flush(bs, s->l2_table_cache);
108
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
109
goto fail;
110
}
111
112
- *table = l2_table;
113
trace_qcow2_l2_allocate_done(bs, l1_index, 0);
114
return 0;
115
116
fail:
117
trace_qcow2_l2_allocate_done(bs, l1_index, ret);
118
- if (l2_table != NULL) {
119
- qcow2_cache_put(s->l2_table_cache, (void **) table);
120
+ if (l2_slice != NULL) {
121
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
122
}
123
s->l1_table[l1_index] = old_l2_offset;
124
if (l2_offset > 0) {
125
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
126
}
127
} else {
128
/* First allocate a new L2 table (and do COW if needed) */
129
- ret = l2_allocate(bs, l1_index, &l2_table);
130
+ ret = l2_allocate(bs, l1_index);
131
if (ret < 0) {
132
return ret;
133
}
134
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
135
qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
136
QCOW2_DISCARD_OTHER);
137
}
138
+
139
+ /* Get the offset of the newly-allocated l2 table */
140
+ l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
141
+ assert(offset_into_cluster(s, l2_offset) == 0);
142
+ /* Load the l2 table in memory */
143
+ ret = l2_load(bs, offset, l2_offset, &l2_table);
144
+ if (ret < 0) {
145
+ return ret;
146
+ }
147
}
148
149
/* find the cluster offset for the given disk offset */
150
--
151
2.13.6
152
153
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
After the previous patch we're now always using l2_load() in
4
get_cluster_table() regardless of whether a new L2 table has to be
5
allocated or not.
6
7
This patch refactors that part of the code to use one single l2_load()
8
call.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: ce31758c4a1fadccea7a6ccb93951eb01d95fd4c.1517840877.git.berto@igalia.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 21 +++++++--------------
17
1 file changed, 7 insertions(+), 14 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
24
return -EIO;
25
}
26
27
- /* seek the l2 table of the given l2 offset */
28
-
29
- if (s->l1_table[l1_index] & QCOW_OFLAG_COPIED) {
30
- /* load the l2 table in memory */
31
- ret = l2_load(bs, offset, l2_offset, &l2_table);
32
- if (ret < 0) {
33
- return ret;
34
- }
35
- } else {
36
+ if (!(s->l1_table[l1_index] & QCOW_OFLAG_COPIED)) {
37
/* First allocate a new L2 table (and do COW if needed) */
38
ret = l2_allocate(bs, l1_index);
39
if (ret < 0) {
40
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
41
/* Get the offset of the newly-allocated l2 table */
42
l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
43
assert(offset_into_cluster(s, l2_offset) == 0);
44
- /* Load the l2 table in memory */
45
- ret = l2_load(bs, offset, l2_offset, &l2_table);
46
- if (ret < 0) {
47
- return ret;
48
- }
49
+ }
50
+
51
+ /* load the l2 table in memory */
52
+ ret = l2_load(bs, offset, l2_offset, &l2_table);
53
+ if (ret < 0) {
54
+ return ret;
55
}
56
57
/* find the cluster offset for the given disk offset */
58
--
59
2.13.6
60
61
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This patch updates get_cluster_table() to return L2 slices instead of
4
full L2 tables.
5
6
The code itself needs almost no changes, it only needs to call
7
offset_to_l2_slice_index() instead of offset_to_l2_index(). This patch
8
also renames all the relevant variables and the documentation.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 64cf064c0021ba315d3f3032da0f95db1b615f33.1517840877.git.berto@igalia.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 16 ++++++++--------
17
1 file changed, 8 insertions(+), 8 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ fail:
24
* get_cluster_table
25
*
26
* for a given disk offset, load (and allocate if needed)
27
- * the l2 table.
28
+ * the appropriate slice of its l2 table.
29
*
30
- * the cluster index in the l2 table is given to the caller.
31
+ * the cluster index in the l2 slice is given to the caller.
32
*
33
* Returns 0 on success, -errno in failure case
34
*/
35
static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
36
- uint64_t **new_l2_table,
37
+ uint64_t **new_l2_slice,
38
int *new_l2_index)
39
{
40
BDRVQcow2State *s = bs->opaque;
41
unsigned int l2_index;
42
uint64_t l1_index, l2_offset;
43
- uint64_t *l2_table = NULL;
44
+ uint64_t *l2_slice = NULL;
45
int ret;
46
47
/* seek to the l2 offset in the l1 table */
48
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
49
assert(offset_into_cluster(s, l2_offset) == 0);
50
}
51
52
- /* load the l2 table in memory */
53
- ret = l2_load(bs, offset, l2_offset, &l2_table);
54
+ /* load the l2 slice in memory */
55
+ ret = l2_load(bs, offset, l2_offset, &l2_slice);
56
if (ret < 0) {
57
return ret;
58
}
59
60
/* find the cluster offset for the given disk offset */
61
62
- l2_index = offset_to_l2_index(s, offset);
63
+ l2_index = offset_to_l2_slice_index(s, offset);
64
65
- *new_l2_table = l2_table;
66
+ *new_l2_slice = l2_slice;
67
*new_l2_index = l2_index;
68
69
return 0;
70
--
71
2.13.6
72
73
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
qcow2_get_cluster_offset() checks how many contiguous bytes are
4
available at a given offset. The returned number of bytes is limited
5
by the amount that can be addressed without having to load more than
6
one L2 table.
7
8
Since we'll be loading L2 slices instead of full tables this patch
9
changes the limit accordingly using the size of the L2 slice for the
10
calculations instead of the full table size.
11
12
One consequence of this is that with small L2 slices operations such
13
as 'qemu-img map' will need to iterate in more steps because each
14
qcow2_get_cluster_offset() call will potentially return a smaller
15
number. However the code is already prepared for that so this doesn't
16
break semantics.
17
18
The l2_table variable is also renamed to l2_slice to reflect this, and
19
offset_to_l2_index() is replaced with offset_to_l2_slice_index().
20
21
Signed-off-by: Alberto Garcia <berto@igalia.com>
22
Reviewed-by: Eric Blake <eblake@redhat.com>
23
Reviewed-by: Max Reitz <mreitz@redhat.com>
24
Message-id: 6b602260acb33da56ed6af9611731cb7acd110eb.1517840877.git.berto@igalia.com
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
block/qcow2-cluster.c | 30 +++++++++++++++---------------
28
1 file changed, 15 insertions(+), 15 deletions(-)
29
30
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2-cluster.c
33
+++ b/block/qcow2-cluster.c
34
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
35
{
36
BDRVQcow2State *s = bs->opaque;
37
unsigned int l2_index;
38
- uint64_t l1_index, l2_offset, *l2_table;
39
- int l1_bits, c;
40
+ uint64_t l1_index, l2_offset, *l2_slice;
41
+ int c;
42
unsigned int offset_in_cluster;
43
uint64_t bytes_available, bytes_needed, nb_clusters;
44
QCow2ClusterType type;
45
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
46
offset_in_cluster = offset_into_cluster(s, offset);
47
bytes_needed = (uint64_t) *bytes + offset_in_cluster;
48
49
- l1_bits = s->l2_bits + s->cluster_bits;
50
-
51
/* compute how many bytes there are between the start of the cluster
52
- * containing offset and the end of the l1 entry */
53
- bytes_available = (1ULL << l1_bits) - (offset & ((1ULL << l1_bits) - 1))
54
- + offset_in_cluster;
55
+ * containing offset and the end of the l2 slice that contains
56
+ * the entry pointing to it */
57
+ bytes_available =
58
+ ((uint64_t) (s->l2_slice_size - offset_to_l2_slice_index(s, offset)))
59
+ << s->cluster_bits;
60
61
if (bytes_needed > bytes_available) {
62
bytes_needed = bytes_available;
63
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
64
return -EIO;
65
}
66
67
- /* load the l2 table in memory */
68
+ /* load the l2 slice in memory */
69
70
- ret = l2_load(bs, offset, l2_offset, &l2_table);
71
+ ret = l2_load(bs, offset, l2_offset, &l2_slice);
72
if (ret < 0) {
73
return ret;
74
}
75
76
/* find the cluster offset for the given disk offset */
77
78
- l2_index = offset_to_l2_index(s, offset);
79
- *cluster_offset = be64_to_cpu(l2_table[l2_index]);
80
+ l2_index = offset_to_l2_slice_index(s, offset);
81
+ *cluster_offset = be64_to_cpu(l2_slice[l2_index]);
82
83
nb_clusters = size_to_clusters(s, bytes_needed);
84
/* bytes_needed <= *bytes + offset_in_cluster, both of which are unsigned
85
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
86
case QCOW2_CLUSTER_UNALLOCATED:
87
/* how many empty clusters ? */
88
c = count_contiguous_clusters_unallocated(nb_clusters,
89
- &l2_table[l2_index], type);
90
+ &l2_slice[l2_index], type);
91
*cluster_offset = 0;
92
break;
93
case QCOW2_CLUSTER_ZERO_ALLOC:
94
case QCOW2_CLUSTER_NORMAL:
95
/* how many allocated clusters ? */
96
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
97
- &l2_table[l2_index], QCOW_OFLAG_ZERO);
98
+ &l2_slice[l2_index], QCOW_OFLAG_ZERO);
99
*cluster_offset &= L2E_OFFSET_MASK;
100
if (offset_into_cluster(s, *cluster_offset)) {
101
qcow2_signal_corruption(bs, true, -1, -1,
102
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
103
abort();
104
}
105
106
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
107
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
108
109
bytes_available = (int64_t)c * s->cluster_size;
110
111
@@ -XXX,XX +XXX,XX @@ out:
112
return type;
113
114
fail:
115
- qcow2_cache_put(s->l2_table_cache, (void **)&l2_table);
116
+ qcow2_cache_put(s->l2_table_cache, (void **)&l2_slice);
117
return ret;
118
}
119
120
--
121
2.13.6
122
123
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
There's a loop in this function that iterates over the L2 entries in a
4
table, so now we need to assert that it remains within the limits of
5
an L2 slice.
6
7
Apart from that, this function doesn't need any additional changes, so
8
this patch simply updates the variable name from l2_table to l2_slice.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: f9846a1c2efc51938e877e2a25852d9ab14797ff.1517840877.git.berto@igalia.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 16 ++++++++--------
17
1 file changed, 8 insertions(+), 8 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
24
{
25
BDRVQcow2State *s = bs->opaque;
26
int i, j = 0, l2_index, ret;
27
- uint64_t *old_cluster, *l2_table;
28
+ uint64_t *old_cluster, *l2_slice;
29
uint64_t cluster_offset = m->alloc_offset;
30
31
trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
32
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
33
s->refcount_block_cache);
34
}
35
36
- ret = get_cluster_table(bs, m->offset, &l2_table, &l2_index);
37
+ ret = get_cluster_table(bs, m->offset, &l2_slice, &l2_index);
38
if (ret < 0) {
39
goto err;
40
}
41
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
42
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
43
44
- assert(l2_index + m->nb_clusters <= s->l2_size);
45
+ assert(l2_index + m->nb_clusters <= s->l2_slice_size);
46
for (i = 0; i < m->nb_clusters; i++) {
47
/* if two concurrent writes happen to the same unallocated cluster
48
* each write allocates separate cluster and writes data concurrently.
49
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
50
* cluster the second one has to do RMW (which is done above by
51
* perform_cow()), update l2 table with its cluster pointer and free
52
* old cluster. This is what this loop does */
53
- if (l2_table[l2_index + i] != 0) {
54
- old_cluster[j++] = l2_table[l2_index + i];
55
+ if (l2_slice[l2_index + i] != 0) {
56
+ old_cluster[j++] = l2_slice[l2_index + i];
57
}
58
59
- l2_table[l2_index + i] = cpu_to_be64((cluster_offset +
60
+ l2_slice[l2_index + i] = cpu_to_be64((cluster_offset +
61
(i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
62
}
63
64
65
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
66
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
67
68
/*
69
* If this was a COW, we need to decrease the refcount of the old cluster.
70
--
71
2.13.6
72
73
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
handle_copied() loads an L2 table and limits the number of checked
4
clusters to the amount that fits inside that table. Since we'll be
5
loading L2 slices instead of full tables we need to update that limit.
6
7
Apart from that, this function doesn't need any additional changes, so
8
this patch simply updates the variable name from l2_table to l2_slice.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 541ac001a7d6b86bab2392554bee53c2b312148c.1517840877.git.berto@igalia.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 16 ++++++++--------
17
1 file changed, 8 insertions(+), 8 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
24
BDRVQcow2State *s = bs->opaque;
25
int l2_index;
26
uint64_t cluster_offset;
27
- uint64_t *l2_table;
28
+ uint64_t *l2_slice;
29
uint64_t nb_clusters;
30
unsigned int keep_clusters;
31
int ret;
32
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
33
== offset_into_cluster(s, *host_offset));
34
35
/*
36
- * Calculate the number of clusters to look for. We stop at L2 table
37
+ * Calculate the number of clusters to look for. We stop at L2 slice
38
* boundaries to keep things simple.
39
*/
40
nb_clusters =
41
size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);
42
43
- l2_index = offset_to_l2_index(s, guest_offset);
44
- nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
45
+ l2_index = offset_to_l2_slice_index(s, guest_offset);
46
+ nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index);
47
assert(nb_clusters <= INT_MAX);
48
49
/* Find L2 entry for the first involved cluster */
50
- ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
51
+ ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index);
52
if (ret < 0) {
53
return ret;
54
}
55
56
- cluster_offset = be64_to_cpu(l2_table[l2_index]);
57
+ cluster_offset = be64_to_cpu(l2_slice[l2_index]);
58
59
/* Check how many clusters are already allocated and don't need COW */
60
if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
61
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
62
/* We keep all QCOW_OFLAG_COPIED clusters */
63
keep_clusters =
64
count_contiguous_clusters(nb_clusters, s->cluster_size,
65
- &l2_table[l2_index],
66
+ &l2_slice[l2_index],
67
QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
68
assert(keep_clusters <= nb_clusters);
69
70
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
71
72
/* Cleanup */
73
out:
74
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
75
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
76
77
/* Only return a host offset if we actually made progress. Otherwise we
78
* would make requirements for handle_alloc() that it can't fulfill */
79
--
80
2.13.6
81
82
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
handle_alloc() loads an L2 table and limits the number of checked
4
clusters to the amount that fits inside that table. Since we'll be
5
loading L2 slices instead of full tables we need to update that limit.
6
7
Apart from that, this function doesn't need any additional changes, so
8
this patch simply updates the variable name from l2_table to l2_slice.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: b243299c7136f7014c5af51665431ddbf5e99afd.1517840877.git.berto@igalia.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 18 +++++++++---------
17
1 file changed, 9 insertions(+), 9 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
24
{
25
BDRVQcow2State *s = bs->opaque;
26
int l2_index;
27
- uint64_t *l2_table;
28
+ uint64_t *l2_slice;
29
uint64_t entry;
30
uint64_t nb_clusters;
31
int ret;
32
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
33
assert(*bytes > 0);
34
35
/*
36
- * Calculate the number of clusters to look for. We stop at L2 table
37
+ * Calculate the number of clusters to look for. We stop at L2 slice
38
* boundaries to keep things simple.
39
*/
40
nb_clusters =
41
size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);
42
43
- l2_index = offset_to_l2_index(s, guest_offset);
44
- nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
45
+ l2_index = offset_to_l2_slice_index(s, guest_offset);
46
+ nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index);
47
assert(nb_clusters <= INT_MAX);
48
49
/* Find L2 entry for the first involved cluster */
50
- ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
51
+ ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index);
52
if (ret < 0) {
53
return ret;
54
}
55
56
- entry = be64_to_cpu(l2_table[l2_index]);
57
+ entry = be64_to_cpu(l2_slice[l2_index]);
58
59
/* For the moment, overwrite compressed clusters one by one */
60
if (entry & QCOW_OFLAG_COMPRESSED) {
61
nb_clusters = 1;
62
} else {
63
- nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
64
+ nb_clusters = count_cow_clusters(s, nb_clusters, l2_slice, l2_index);
65
}
66
67
/* This function is only called when there were no non-COW clusters, so if
68
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
69
* nb_clusters already to a range of COW clusters */
70
preallocated_nb_clusters =
71
count_contiguous_clusters(nb_clusters, s->cluster_size,
72
- &l2_table[l2_index], QCOW_OFLAG_COPIED);
73
+ &l2_slice[l2_index], QCOW_OFLAG_COPIED);
74
assert(preallocated_nb_clusters > 0);
75
76
nb_clusters = preallocated_nb_clusters;
77
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
78
keep_old_clusters = true;
79
}
80
81
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
82
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
83
84
if (!alloc_cluster_offset) {
85
/* Allocate, if necessary at a given offset in the image file */
86
--
87
2.13.6
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
discard_single_l2() limits the number of clusters to be discarded
4
to the amount that fits inside an L2 table. Since we'll be loading
5
L2 slices instead of full tables we need to update that limit. The
6
function is renamed to discard_in_l2_slice() for clarity.
7
8
Apart from that, this function doesn't need any additional changes, so
9
this patch simply updates the variable name from l2_table to l2_slice.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 1cb44a5b68be5334cb01b97a3db3a3c5a43396e5.1517840877.git.berto@igalia.com
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 32 ++++++++++++++++----------------
17
1 file changed, 16 insertions(+), 16 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
24
25
/*
26
* This discards as many clusters of nb_clusters as possible at once (i.e.
27
- * all clusters in the same L2 table) and returns the number of discarded
28
+ * all clusters in the same L2 slice) and returns the number of discarded
29
* clusters.
30
*/
31
-static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
32
- uint64_t nb_clusters, enum qcow2_discard_type type,
33
- bool full_discard)
34
+static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
35
+ uint64_t nb_clusters,
36
+ enum qcow2_discard_type type, bool full_discard)
37
{
38
BDRVQcow2State *s = bs->opaque;
39
- uint64_t *l2_table;
40
+ uint64_t *l2_slice;
41
int l2_index;
42
int ret;
43
int i;
44
45
- ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
46
+ ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
47
if (ret < 0) {
48
return ret;
49
}
50
51
- /* Limit nb_clusters to one L2 table */
52
- nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
53
+ /* Limit nb_clusters to one L2 slice */
54
+ nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index);
55
assert(nb_clusters <= INT_MAX);
56
57
for (i = 0; i < nb_clusters; i++) {
58
uint64_t old_l2_entry;
59
60
- old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);
61
+ old_l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
62
63
/*
64
* If full_discard is false, make sure that a discarded area reads back
65
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
66
}
67
68
/* First remove L2 entries */
69
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
70
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
71
if (!full_discard && s->qcow_version >= 3) {
72
- l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
73
+ l2_slice[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
74
} else {
75
- l2_table[l2_index + i] = cpu_to_be64(0);
76
+ l2_slice[l2_index + i] = cpu_to_be64(0);
77
}
78
79
/* Then decrease the refcount */
80
qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
81
}
82
83
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
84
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
85
86
return nb_clusters;
87
}
88
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
89
90
s->cache_discards = true;
91
92
- /* Each L2 table is handled by its own loop iteration */
93
+ /* Each L2 slice is handled by its own loop iteration */
94
while (nb_clusters > 0) {
95
- cleared = discard_single_l2(bs, offset, nb_clusters, type,
96
- full_discard);
97
+ cleared = discard_in_l2_slice(bs, offset, nb_clusters, type,
98
+ full_discard);
99
if (cleared < 0) {
100
ret = cleared;
101
goto fail;
102
--
103
2.13.6
104
105
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
zero_single_l2() limits the number of clusters to be zeroed to the
4
amount that fits inside an L2 table. Since we'll be loading L2 slices
5
instead of full tables we need to update that limit. The function is
6
renamed to zero_in_l2_slice() for clarity.
7
8
Apart from that, this function doesn't need any additional changes, so
9
this patch simply updates the variable name from l2_table to l2_slice.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Message-id: ebc16e7e79fa6969d8975ef487d679794de4fbcc.1517840877.git.berto@igalia.com
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 28 ++++++++++++++--------------
17
1 file changed, 14 insertions(+), 14 deletions(-)
18
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-cluster.c
22
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ fail:
24
25
/*
26
* This zeroes as many clusters of nb_clusters as possible at once (i.e.
27
- * all clusters in the same L2 table) and returns the number of zeroed
28
+ * all clusters in the same L2 slice) and returns the number of zeroed
29
* clusters.
30
*/
31
-static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
32
- uint64_t nb_clusters, int flags)
33
+static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
34
+ uint64_t nb_clusters, int flags)
35
{
36
BDRVQcow2State *s = bs->opaque;
37
- uint64_t *l2_table;
38
+ uint64_t *l2_slice;
39
int l2_index;
40
int ret;
41
int i;
42
bool unmap = !!(flags & BDRV_REQ_MAY_UNMAP);
43
44
- ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
45
+ ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
46
if (ret < 0) {
47
return ret;
48
}
49
50
- /* Limit nb_clusters to one L2 table */
51
- nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
52
+ /* Limit nb_clusters to one L2 slice */
53
+ nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index);
54
assert(nb_clusters <= INT_MAX);
55
56
for (i = 0; i < nb_clusters; i++) {
57
uint64_t old_offset;
58
QCow2ClusterType cluster_type;
59
60
- old_offset = be64_to_cpu(l2_table[l2_index + i]);
61
+ old_offset = be64_to_cpu(l2_slice[l2_index + i]);
62
63
/*
64
* Minimize L2 changes if the cluster already reads back as
65
@@ -XXX,XX +XXX,XX @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset,
66
continue;
67
}
68
69
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
70
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
71
if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
72
- l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
73
+ l2_slice[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
74
qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
75
} else {
76
- l2_table[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO);
77
+ l2_slice[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO);
78
}
79
}
80
81
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
82
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
83
84
return nb_clusters;
85
}
86
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
87
return -ENOTSUP;
88
}
89
90
- /* Each L2 table is handled by its own loop iteration */
91
+ /* Each L2 slice is handled by its own loop iteration */
92
nb_clusters = size_to_clusters(s, bytes);
93
94
s->cache_discards = true;
95
96
while (nb_clusters > 0) {
97
- cleared = zero_single_l2(bs, offset, nb_clusters, flags);
98
+ cleared = zero_in_l2_slice(bs, offset, nb_clusters, flags);
99
if (cleared < 0) {
100
ret = cleared;
101
goto fail;
102
--
103
2.13.6
104
105
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Adding support for L2 slices to qcow2_update_snapshot_refcount() needs
4
(among other things) an extra loop that iterates over all slices of
5
each L2 table.
6
7
Putting all changes in one patch would make it hard to read because
8
all semantic changes would be mixed with pure indentation changes.
9
10
To make things easier this patch simply creates a new block and
11
changes the indentation of all lines of code inside it. Thus, all
12
modifications in this patch are cosmetic. There are no semantic
13
changes and no variables are renamed yet. The next patch will take
14
care of that.
15
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Message-id: 8ffaa5e55bd51121f80e498f4045b64902a94293.1517840877.git.berto@igalia.com
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
block/qcow2-refcount.c | 144 +++++++++++++++++++++++++------------------------
23
1 file changed, 75 insertions(+), 69 deletions(-)
24
25
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2-refcount.c
28
+++ b/block/qcow2-refcount.c
29
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
30
goto fail;
31
}
32
33
- ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
34
- (void**) &l2_table);
35
- if (ret < 0) {
36
- goto fail;
37
- }
38
+ {
39
+ ret = qcow2_cache_get(bs, s->l2_table_cache,
40
+ l2_offset,
41
+ (void **) &l2_table);
42
+ if (ret < 0) {
43
+ goto fail;
44
+ }
45
46
- for (j = 0; j < s->l2_size; j++) {
47
- uint64_t cluster_index;
48
- uint64_t offset;
49
-
50
- entry = be64_to_cpu(l2_table[j]);
51
- old_entry = entry;
52
- entry &= ~QCOW_OFLAG_COPIED;
53
- offset = entry & L2E_OFFSET_MASK;
54
-
55
- switch (qcow2_get_cluster_type(entry)) {
56
- case QCOW2_CLUSTER_COMPRESSED:
57
- nb_csectors = ((entry >> s->csize_shift) &
58
- s->csize_mask) + 1;
59
- if (addend != 0) {
60
- ret = update_refcount(bs,
61
- (entry & s->cluster_offset_mask) & ~511,
62
+ for (j = 0; j < s->l2_size; j++) {
63
+ uint64_t cluster_index;
64
+ uint64_t offset;
65
+
66
+ entry = be64_to_cpu(l2_table[j]);
67
+ old_entry = entry;
68
+ entry &= ~QCOW_OFLAG_COPIED;
69
+ offset = entry & L2E_OFFSET_MASK;
70
+
71
+ switch (qcow2_get_cluster_type(entry)) {
72
+ case QCOW2_CLUSTER_COMPRESSED:
73
+ nb_csectors = ((entry >> s->csize_shift) &
74
+ s->csize_mask) + 1;
75
+ if (addend != 0) {
76
+ ret = update_refcount(
77
+ bs, (entry & s->cluster_offset_mask) & ~511,
78
nb_csectors * 512, abs(addend), addend < 0,
79
QCOW2_DISCARD_SNAPSHOT);
80
- if (ret < 0) {
81
+ if (ret < 0) {
82
+ goto fail;
83
+ }
84
+ }
85
+ /* compressed clusters are never modified */
86
+ refcount = 2;
87
+ break;
88
+
89
+ case QCOW2_CLUSTER_NORMAL:
90
+ case QCOW2_CLUSTER_ZERO_ALLOC:
91
+ if (offset_into_cluster(s, offset)) {
92
+ qcow2_signal_corruption(
93
+ bs, true, -1, -1, "Cluster "
94
+ "allocation offset %#" PRIx64
95
+ " unaligned (L2 offset: %#"
96
+ PRIx64 ", L2 index: %#x)",
97
+ offset, l2_offset, j);
98
+ ret = -EIO;
99
goto fail;
100
}
101
- }
102
- /* compressed clusters are never modified */
103
- refcount = 2;
104
- break;
105
-
106
- case QCOW2_CLUSTER_NORMAL:
107
- case QCOW2_CLUSTER_ZERO_ALLOC:
108
- if (offset_into_cluster(s, offset)) {
109
- qcow2_signal_corruption(bs, true, -1, -1, "Cluster "
110
- "allocation offset %#" PRIx64
111
- " unaligned (L2 offset: %#"
112
- PRIx64 ", L2 index: %#x)",
113
- offset, l2_offset, j);
114
- ret = -EIO;
115
- goto fail;
116
- }
117
118
- cluster_index = offset >> s->cluster_bits;
119
- assert(cluster_index);
120
- if (addend != 0) {
121
- ret = qcow2_update_cluster_refcount(bs,
122
- cluster_index, abs(addend), addend < 0,
123
- QCOW2_DISCARD_SNAPSHOT);
124
+ cluster_index = offset >> s->cluster_bits;
125
+ assert(cluster_index);
126
+ if (addend != 0) {
127
+ ret = qcow2_update_cluster_refcount(
128
+ bs, cluster_index, abs(addend), addend < 0,
129
+ QCOW2_DISCARD_SNAPSHOT);
130
+ if (ret < 0) {
131
+ goto fail;
132
+ }
133
+ }
134
+
135
+ ret = qcow2_get_refcount(bs, cluster_index, &refcount);
136
if (ret < 0) {
137
goto fail;
138
}
139
- }
140
+ break;
141
142
- ret = qcow2_get_refcount(bs, cluster_index, &refcount);
143
- if (ret < 0) {
144
- goto fail;
145
- }
146
- break;
147
-
148
- case QCOW2_CLUSTER_ZERO_PLAIN:
149
- case QCOW2_CLUSTER_UNALLOCATED:
150
- refcount = 0;
151
- break;
152
+ case QCOW2_CLUSTER_ZERO_PLAIN:
153
+ case QCOW2_CLUSTER_UNALLOCATED:
154
+ refcount = 0;
155
+ break;
156
157
- default:
158
- abort();
159
- }
160
+ default:
161
+ abort();
162
+ }
163
164
- if (refcount == 1) {
165
- entry |= QCOW_OFLAG_COPIED;
166
- }
167
- if (entry != old_entry) {
168
- if (addend > 0) {
169
- qcow2_cache_set_dependency(bs, s->l2_table_cache,
170
- s->refcount_block_cache);
171
+ if (refcount == 1) {
172
+ entry |= QCOW_OFLAG_COPIED;
173
+ }
174
+ if (entry != old_entry) {
175
+ if (addend > 0) {
176
+ qcow2_cache_set_dependency(bs, s->l2_table_cache,
177
+ s->refcount_block_cache);
178
+ }
179
+ l2_table[j] = cpu_to_be64(entry);
180
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache,
181
+ l2_table);
182
}
183
- l2_table[j] = cpu_to_be64(entry);
184
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
185
}
186
- }
187
188
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
189
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
190
+
191
+ }
192
193
if (addend != 0) {
194
ret = qcow2_update_cluster_refcount(bs, l2_offset >>
195
--
196
2.13.6
197
198
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Adding support for L2 slices to expand_zero_clusters_in_l1() needs
4
(among other things) an extra loop that iterates over all slices of
5
each L2 table.
6
7
Putting all changes in one patch would make it hard to read because
8
all semantic changes would be mixed with pure indentation changes.
9
10
To make things easier this patch simply creates a new block and
11
changes the indentation of all lines of code inside it. Thus, all
12
modifications in this patch are cosmetic. There are no semantic
13
changes and no variables are renamed yet. The next patch will take
14
care of that.
15
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Message-id: c2ae9f31ed5b6e591477ad4654448badd1c89d73.1517840877.git.berto@igalia.com
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
block/qcow2-cluster.c | 187 ++++++++++++++++++++++++++------------------------
23
1 file changed, 96 insertions(+), 91 deletions(-)
24
25
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2-cluster.c
28
+++ b/block/qcow2-cluster.c
29
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
30
goto fail;
31
}
32
33
- if (is_active_l1) {
34
- /* get active L2 tables from cache */
35
- ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
36
- (void **)&l2_table);
37
- } else {
38
- /* load inactive L2 tables from disk */
39
- ret = bdrv_read(bs->file, l2_offset / BDRV_SECTOR_SIZE,
40
- (void *)l2_table, s->cluster_sectors);
41
- }
42
- if (ret < 0) {
43
- goto fail;
44
- }
45
-
46
- for (j = 0; j < s->l2_size; j++) {
47
- uint64_t l2_entry = be64_to_cpu(l2_table[j]);
48
- int64_t offset = l2_entry & L2E_OFFSET_MASK;
49
- QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
50
-
51
- if (cluster_type != QCOW2_CLUSTER_ZERO_PLAIN &&
52
- cluster_type != QCOW2_CLUSTER_ZERO_ALLOC) {
53
- continue;
54
+ {
55
+ if (is_active_l1) {
56
+ /* get active L2 tables from cache */
57
+ ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
58
+ (void **)&l2_table);
59
+ } else {
60
+ /* load inactive L2 tables from disk */
61
+ ret = bdrv_read(bs->file, l2_offset / BDRV_SECTOR_SIZE,
62
+ (void *)l2_table, s->cluster_sectors);
63
+ }
64
+ if (ret < 0) {
65
+ goto fail;
66
}
67
68
- if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
69
- if (!bs->backing) {
70
- /* not backed; therefore we can simply deallocate the
71
- * cluster */
72
- l2_table[j] = 0;
73
- l2_dirty = true;
74
+ for (j = 0; j < s->l2_size; j++) {
75
+ uint64_t l2_entry = be64_to_cpu(l2_table[j]);
76
+ int64_t offset = l2_entry & L2E_OFFSET_MASK;
77
+ QCow2ClusterType cluster_type =
78
+ qcow2_get_cluster_type(l2_entry);
79
+
80
+ if (cluster_type != QCOW2_CLUSTER_ZERO_PLAIN &&
81
+ cluster_type != QCOW2_CLUSTER_ZERO_ALLOC) {
82
continue;
83
}
84
85
- offset = qcow2_alloc_clusters(bs, s->cluster_size);
86
- if (offset < 0) {
87
- ret = offset;
88
- goto fail;
89
- }
90
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
91
+ if (!bs->backing) {
92
+ /* not backed; therefore we can simply deallocate the
93
+ * cluster */
94
+ l2_table[j] = 0;
95
+ l2_dirty = true;
96
+ continue;
97
+ }
98
+
99
+ offset = qcow2_alloc_clusters(bs, s->cluster_size);
100
+ if (offset < 0) {
101
+ ret = offset;
102
+ goto fail;
103
+ }
104
105
- if (l2_refcount > 1) {
106
- /* For shared L2 tables, set the refcount accordingly (it is
107
- * already 1 and needs to be l2_refcount) */
108
- ret = qcow2_update_cluster_refcount(bs,
109
- offset >> s->cluster_bits,
110
+ if (l2_refcount > 1) {
111
+ /* For shared L2 tables, set the refcount accordingly
112
+ * (it is already 1 and needs to be l2_refcount) */
113
+ ret = qcow2_update_cluster_refcount(
114
+ bs, offset >> s->cluster_bits,
115
refcount_diff(1, l2_refcount), false,
116
QCOW2_DISCARD_OTHER);
117
- if (ret < 0) {
118
- qcow2_free_clusters(bs, offset, s->cluster_size,
119
- QCOW2_DISCARD_OTHER);
120
- goto fail;
121
+ if (ret < 0) {
122
+ qcow2_free_clusters(bs, offset, s->cluster_size,
123
+ QCOW2_DISCARD_OTHER);
124
+ goto fail;
125
+ }
126
}
127
}
128
- }
129
130
- if (offset_into_cluster(s, offset)) {
131
- qcow2_signal_corruption(bs, true, -1, -1,
132
- "Cluster allocation offset "
133
- "%#" PRIx64 " unaligned (L2 offset: %#"
134
- PRIx64 ", L2 index: %#x)", offset,
135
- l2_offset, j);
136
- if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
137
- qcow2_free_clusters(bs, offset, s->cluster_size,
138
- QCOW2_DISCARD_ALWAYS);
139
+ if (offset_into_cluster(s, offset)) {
140
+ qcow2_signal_corruption(
141
+ bs, true, -1, -1,
142
+ "Cluster allocation offset "
143
+ "%#" PRIx64 " unaligned (L2 offset: %#"
144
+ PRIx64 ", L2 index: %#x)", offset,
145
+ l2_offset, j);
146
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
147
+ qcow2_free_clusters(bs, offset, s->cluster_size,
148
+ QCOW2_DISCARD_ALWAYS);
149
+ }
150
+ ret = -EIO;
151
+ goto fail;
152
}
153
- ret = -EIO;
154
- goto fail;
155
- }
156
157
- ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
158
- if (ret < 0) {
159
- if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
160
- qcow2_free_clusters(bs, offset, s->cluster_size,
161
- QCOW2_DISCARD_ALWAYS);
162
+ ret = qcow2_pre_write_overlap_check(bs, 0, offset,
163
+ s->cluster_size);
164
+ if (ret < 0) {
165
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
166
+ qcow2_free_clusters(bs, offset, s->cluster_size,
167
+ QCOW2_DISCARD_ALWAYS);
168
+ }
169
+ goto fail;
170
}
171
- goto fail;
172
- }
173
174
- ret = bdrv_pwrite_zeroes(bs->file, offset, s->cluster_size, 0);
175
- if (ret < 0) {
176
- if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
177
- qcow2_free_clusters(bs, offset, s->cluster_size,
178
- QCOW2_DISCARD_ALWAYS);
179
+ ret = bdrv_pwrite_zeroes(bs->file, offset, s->cluster_size, 0);
180
+ if (ret < 0) {
181
+ if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
182
+ qcow2_free_clusters(bs, offset, s->cluster_size,
183
+ QCOW2_DISCARD_ALWAYS);
184
+ }
185
+ goto fail;
186
}
187
- goto fail;
188
- }
189
190
- if (l2_refcount == 1) {
191
- l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
192
- } else {
193
- l2_table[j] = cpu_to_be64(offset);
194
+ if (l2_refcount == 1) {
195
+ l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
196
+ } else {
197
+ l2_table[j] = cpu_to_be64(offset);
198
+ }
199
+ l2_dirty = true;
200
}
201
- l2_dirty = true;
202
- }
203
204
- if (is_active_l1) {
205
- if (l2_dirty) {
206
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
207
- qcow2_cache_depends_on_flush(s->l2_table_cache);
208
- }
209
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
210
- } else {
211
- if (l2_dirty) {
212
- ret = qcow2_pre_write_overlap_check(bs,
213
- QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2, l2_offset,
214
- s->cluster_size);
215
- if (ret < 0) {
216
- goto fail;
217
+ if (is_active_l1) {
218
+ if (l2_dirty) {
219
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
220
+ qcow2_cache_depends_on_flush(s->l2_table_cache);
221
}
222
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
223
+ } else {
224
+ if (l2_dirty) {
225
+ ret = qcow2_pre_write_overlap_check(
226
+ bs, QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2,
227
+ l2_offset, s->cluster_size);
228
+ if (ret < 0) {
229
+ goto fail;
230
+ }
231
232
- ret = bdrv_write(bs->file, l2_offset / BDRV_SECTOR_SIZE,
233
- (void *)l2_table, s->cluster_sectors);
234
- if (ret < 0) {
235
- goto fail;
236
+ ret = bdrv_write(bs->file, l2_offset / BDRV_SECTOR_SIZE,
237
+ (void *)l2_table, s->cluster_sectors);
238
+ if (ret < 0) {
239
+ goto fail;
240
+ }
241
}
242
}
243
}
244
--
245
2.13.6
246
247
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
expand_zero_clusters_in_l1() expands zero clusters as a necessary step
4
to downgrade qcow2 images to a version that doesn't support metadata
5
zero clusters. This function takes an L1 table (which may or may not
6
be active) and iterates over all its L2 tables looking for zero
7
clusters.
8
9
Since we'll be loading L2 slices instead of full tables we need to add
10
an extra loop that iterates over all slices of each L2 table, and we
11
should also use the slice size when allocating the buffer used when
12
the L1 table is not active.
13
14
This function doesn't need any additional changes so apart from that
15
this patch simply updates the variable name from l2_table to l2_slice.
16
17
Finally, and since we have to touch the bdrv_read() / bdrv_write()
18
calls anyway, this patch takes the opportunity to replace them with
19
the byte-based bdrv_pread() / bdrv_pwrite().
20
21
Signed-off-by: Alberto Garcia <berto@igalia.com>
22
Reviewed-by: Eric Blake <eblake@redhat.com>
23
Reviewed-by: Max Reitz <mreitz@redhat.com>
24
Message-id: 43590976f730501688096cff103f2923b72b0f32.1517840877.git.berto@igalia.com
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
block/qcow2-cluster.c | 51 ++++++++++++++++++++++++++++-----------------------
28
1 file changed, 28 insertions(+), 23 deletions(-)
29
30
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2-cluster.c
33
+++ b/block/qcow2-cluster.c
34
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
35
{
36
BDRVQcow2State *s = bs->opaque;
37
bool is_active_l1 = (l1_table == s->l1_table);
38
- uint64_t *l2_table = NULL;
39
+ uint64_t *l2_slice = NULL;
40
+ unsigned slice, slice_size2, n_slices;
41
int ret;
42
int i, j;
43
44
+ slice_size2 = s->l2_slice_size * sizeof(uint64_t);
45
+ n_slices = s->cluster_size / slice_size2;
46
+
47
if (!is_active_l1) {
48
/* inactive L2 tables require a buffer to be stored in when loading
49
* them from disk */
50
- l2_table = qemu_try_blockalign(bs->file->bs, s->cluster_size);
51
- if (l2_table == NULL) {
52
+ l2_slice = qemu_try_blockalign(bs->file->bs, slice_size2);
53
+ if (l2_slice == NULL) {
54
return -ENOMEM;
55
}
56
}
57
58
for (i = 0; i < l1_size; i++) {
59
uint64_t l2_offset = l1_table[i] & L1E_OFFSET_MASK;
60
- bool l2_dirty = false;
61
uint64_t l2_refcount;
62
63
if (!l2_offset) {
64
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
65
goto fail;
66
}
67
68
- {
69
+ for (slice = 0; slice < n_slices; slice++) {
70
+ uint64_t slice_offset = l2_offset + slice * slice_size2;
71
+ bool l2_dirty = false;
72
if (is_active_l1) {
73
/* get active L2 tables from cache */
74
- ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
75
- (void **)&l2_table);
76
+ ret = qcow2_cache_get(bs, s->l2_table_cache, slice_offset,
77
+ (void **)&l2_slice);
78
} else {
79
/* load inactive L2 tables from disk */
80
- ret = bdrv_read(bs->file, l2_offset / BDRV_SECTOR_SIZE,
81
- (void *)l2_table, s->cluster_sectors);
82
+ ret = bdrv_pread(bs->file, slice_offset, l2_slice, slice_size2);
83
}
84
if (ret < 0) {
85
goto fail;
86
}
87
88
- for (j = 0; j < s->l2_size; j++) {
89
- uint64_t l2_entry = be64_to_cpu(l2_table[j]);
90
+ for (j = 0; j < s->l2_slice_size; j++) {
91
+ uint64_t l2_entry = be64_to_cpu(l2_slice[j]);
92
int64_t offset = l2_entry & L2E_OFFSET_MASK;
93
QCow2ClusterType cluster_type =
94
qcow2_get_cluster_type(l2_entry);
95
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
96
if (!bs->backing) {
97
/* not backed; therefore we can simply deallocate the
98
* cluster */
99
- l2_table[j] = 0;
100
+ l2_slice[j] = 0;
101
l2_dirty = true;
102
continue;
103
}
104
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
105
}
106
107
if (offset_into_cluster(s, offset)) {
108
+ int l2_index = slice * s->l2_slice_size + j;
109
qcow2_signal_corruption(
110
bs, true, -1, -1,
111
"Cluster allocation offset "
112
"%#" PRIx64 " unaligned (L2 offset: %#"
113
PRIx64 ", L2 index: %#x)", offset,
114
- l2_offset, j);
115
+ l2_offset, l2_index);
116
if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
117
qcow2_free_clusters(bs, offset, s->cluster_size,
118
QCOW2_DISCARD_ALWAYS);
119
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
120
}
121
122
if (l2_refcount == 1) {
123
- l2_table[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
124
+ l2_slice[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
125
} else {
126
- l2_table[j] = cpu_to_be64(offset);
127
+ l2_slice[j] = cpu_to_be64(offset);
128
}
129
l2_dirty = true;
130
}
131
132
if (is_active_l1) {
133
if (l2_dirty) {
134
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
135
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
136
qcow2_cache_depends_on_flush(s->l2_table_cache);
137
}
138
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
139
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
140
} else {
141
if (l2_dirty) {
142
ret = qcow2_pre_write_overlap_check(
143
bs, QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2,
144
- l2_offset, s->cluster_size);
145
+ slice_offset, slice_size2);
146
if (ret < 0) {
147
goto fail;
148
}
149
150
- ret = bdrv_write(bs->file, l2_offset / BDRV_SECTOR_SIZE,
151
- (void *)l2_table, s->cluster_sectors);
152
+ ret = bdrv_pwrite(bs->file, slice_offset,
153
+ l2_slice, slice_size2);
154
if (ret < 0) {
155
goto fail;
156
}
157
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
158
ret = 0;
159
160
fail:
161
- if (l2_table) {
162
+ if (l2_slice) {
163
if (!is_active_l1) {
164
- qemu_vfree(l2_table);
165
+ qemu_vfree(l2_slice);
166
} else {
167
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
168
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
169
}
170
}
171
return ret;
172
--
173
2.13.6
174
175
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function doesn't need any changes to support L2 slices, but since
4
it's now dealing with slices instead of full tables, the l2_table
5
variable is renamed for clarity.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 0c5d4b9bf163aa3b49ec19cc512a50d83563f2ad.1517840877.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cluster.c | 16 ++++++++--------
14
1 file changed, 8 insertions(+), 8 deletions(-)
15
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cluster.c
19
+++ b/block/qcow2-cluster.c
20
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
21
{
22
BDRVQcow2State *s = bs->opaque;
23
int l2_index, ret;
24
- uint64_t *l2_table;
25
+ uint64_t *l2_slice;
26
int64_t cluster_offset;
27
int nb_csectors;
28
29
- ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
30
+ ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
31
if (ret < 0) {
32
return 0;
33
}
34
35
/* Compression can't overwrite anything. Fail if the cluster was already
36
* allocated. */
37
- cluster_offset = be64_to_cpu(l2_table[l2_index]);
38
+ cluster_offset = be64_to_cpu(l2_slice[l2_index]);
39
if (cluster_offset & L2E_OFFSET_MASK) {
40
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
41
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
42
return 0;
43
}
44
45
cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
46
if (cluster_offset < 0) {
47
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
48
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
49
return 0;
50
}
51
52
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
53
/* compressed clusters never have the copied flag */
54
55
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
56
- qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
57
- l2_table[l2_index] = cpu_to_be64(cluster_offset);
58
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_table);
59
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
60
+ l2_slice[l2_index] = cpu_to_be64(cluster_offset);
61
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
62
63
return cluster_offset;
64
}
65
--
66
2.13.6
67
68
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function doesn't need any changes to support L2 slices, but since
4
it's now dealing with slices intead of full tables, the l2_table
5
variable is renamed for clarity.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 812b0c3505bb1687e51285dccf1a94f0cecb1f74.1517840877.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cluster.c | 8 ++++----
14
1 file changed, 4 insertions(+), 4 deletions(-)
15
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cluster.c
19
+++ b/block/qcow2-cluster.c
20
@@ -XXX,XX +XXX,XX @@ fail:
21
}
22
23
/*
24
- * Checks how many clusters in a given L2 table are contiguous in the image
25
+ * Checks how many clusters in a given L2 slice are contiguous in the image
26
* file. As soon as one of the flags in the bitmask stop_flags changes compared
27
* to the first cluster, the search is stopped and the cluster is not counted
28
* as contiguous. (This allows it, for example, to stop at the first compressed
29
* cluster which may require a different handling)
30
*/
31
static int count_contiguous_clusters(int nb_clusters, int cluster_size,
32
- uint64_t *l2_table, uint64_t stop_flags)
33
+ uint64_t *l2_slice, uint64_t stop_flags)
34
{
35
int i;
36
QCow2ClusterType first_cluster_type;
37
uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
38
- uint64_t first_entry = be64_to_cpu(l2_table[0]);
39
+ uint64_t first_entry = be64_to_cpu(l2_slice[0]);
40
uint64_t offset = first_entry & mask;
41
42
if (!offset) {
43
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
44
first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
45
46
for (i = 0; i < nb_clusters; i++) {
47
- uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
48
+ uint64_t l2_entry = be64_to_cpu(l2_slice[i]) & mask;
49
if (offset + (uint64_t) i * cluster_size != l2_entry) {
50
break;
51
}
52
--
53
2.13.6
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function doesn't need any changes to support L2 slices, but since
4
it's now dealing with slices instead of full tables, the l2_table
5
variable is renamed for clarity.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 78bcc54bc632574dd0b900a77a00a1b6ffc359e6.1517840877.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cluster.c | 6 +++---
14
1 file changed, 3 insertions(+), 3 deletions(-)
15
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cluster.c
19
+++ b/block/qcow2-cluster.c
20
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(int nb_clusters, int cluster_size,
21
22
/*
23
* Checks how many consecutive unallocated clusters in a given L2
24
- * table have the same cluster type.
25
+ * slice have the same cluster type.
26
*/
27
static int count_contiguous_clusters_unallocated(int nb_clusters,
28
- uint64_t *l2_table,
29
+ uint64_t *l2_slice,
30
QCow2ClusterType wanted_type)
31
{
32
int i;
33
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters_unallocated(int nb_clusters,
34
assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN ||
35
wanted_type == QCOW2_CLUSTER_UNALLOCATED);
36
for (i = 0; i < nb_clusters; i++) {
37
- uint64_t entry = be64_to_cpu(l2_table[i]);
38
+ uint64_t entry = be64_to_cpu(l2_slice[i]);
39
QCow2ClusterType type = qcow2_get_cluster_type(entry);
40
41
if (type != wanted_type) {
42
--
43
2.13.6
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This function doesn't need any changes to support L2 slices, but since
4
it's now dealing with slices intead of full tables, the l2_table
5
variable is renamed for clarity.
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 6107001fc79e6739242f1de7d191375e4f130aac.1517840877.git.berto@igalia.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cluster.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-cluster.c
19
+++ b/block/qcow2-cluster.c
20
@@ -XXX,XX +XXX,XX @@ err:
21
* which must copy from the backing file)
22
*/
23
static int count_cow_clusters(BDRVQcow2State *s, int nb_clusters,
24
- uint64_t *l2_table, int l2_index)
25
+ uint64_t *l2_slice, int l2_index)
26
{
27
int i;
28
29
for (i = 0; i < nb_clusters; i++) {
30
- uint64_t l2_entry = be64_to_cpu(l2_table[l2_index + i]);
31
+ uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
32
QCow2ClusterType cluster_type = qcow2_get_cluster_type(l2_entry);
33
34
switch(cluster_type) {
35
--
36
2.13.6
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The l2-cache-entry-size setting can only contain values that are
4
powers of two between 512 and the cluster size.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-id: bd3547b670b8d0af11480c760991a22bcae5b48c.1517840877.git.berto@igalia.com
10
[mreitz: Changed non-power-of-two test value from 300 to 4242]
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/103 | 17 +++++++++++++++++
14
tests/qemu-iotests/103.out | 3 +++
15
2 files changed, 20 insertions(+)
16
17
diff --git a/tests/qemu-iotests/103 b/tests/qemu-iotests/103
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/103
20
+++ b/tests/qemu-iotests/103
21
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "open -o cache-size=1M,refcount-cache-size=2M $TEST_IMG" 2>&1 \
22
$QEMU_IO -c "open -o cache-size=0,l2-cache-size=0,refcount-cache-size=0 $TEST_IMG" \
23
2>&1 | _filter_testdir | _filter_imgfmt
24
25
+# Invalid cache entry sizes
26
+$QEMU_IO -c "open -o l2-cache-entry-size=256 $TEST_IMG" \
27
+ 2>&1 | _filter_testdir | _filter_imgfmt
28
+$QEMU_IO -c "open -o l2-cache-entry-size=4242 $TEST_IMG" \
29
+ 2>&1 | _filter_testdir | _filter_imgfmt
30
+$QEMU_IO -c "open -o l2-cache-entry-size=128k $TEST_IMG" \
31
+ 2>&1 | _filter_testdir | _filter_imgfmt
32
+
33
echo
34
echo '=== Testing valid option combinations ==='
35
echo
36
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "open -o l2-cache-size=1M,refcount-cache-size=0.25M $TEST_IMG" \
37
-c 'read -P 42 0 64k' \
38
| _filter_qemu_io
39
40
+# Valid cache entry sizes
41
+$QEMU_IO -c "open -o l2-cache-entry-size=512 $TEST_IMG" \
42
+ 2>&1 | _filter_testdir | _filter_imgfmt
43
+$QEMU_IO -c "open -o l2-cache-entry-size=16k $TEST_IMG" \
44
+ 2>&1 | _filter_testdir | _filter_imgfmt
45
+$QEMU_IO -c "open -o l2-cache-entry-size=64k $TEST_IMG" \
46
+ 2>&1 | _filter_testdir | _filter_imgfmt
47
+
48
+
49
echo
50
echo '=== Testing minimal L2 cache and COW ==='
51
echo
52
diff --git a/tests/qemu-iotests/103.out b/tests/qemu-iotests/103.out
53
index XXXXXXX..XXXXXXX 100644
54
--- a/tests/qemu-iotests/103.out
55
+++ b/tests/qemu-iotests/103.out
56
@@ -XXX,XX +XXX,XX @@ can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cach
57
can't open device TEST_DIR/t.IMGFMT: l2-cache-size may not exceed cache-size
58
can't open device TEST_DIR/t.IMGFMT: refcount-cache-size may not exceed cache-size
59
can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
60
+can't open device TEST_DIR/t.IMGFMT: L2 cache entry size must be a power of two between 512 and the cluster size (65536)
61
+can't open device TEST_DIR/t.IMGFMT: L2 cache entry size must be a power of two between 512 and the cluster size (65536)
62
+can't open device TEST_DIR/t.IMGFMT: L2 cache entry size must be a power of two between 512 and the cluster size (65536)
63
64
=== Testing valid option combinations ===
65
66
--
67
2.13.6
68
69
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
expand_zero_clusters_in_l1() is used when downgrading qcow2 images
4
from v3 to v2 (compat=0.10). This is one of the functions that needed
5
more changes to support L2 slices, so this patch extends iotest 061 to
6
test downgrading a qcow2 image using a smaller slice size.
7
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 3e5662dce5e4926c8fabbad4c0b9142b2a506dd4.1517840877.git.berto@igalia.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/061 | 16 ++++++++++++
15
tests/qemu-iotests/061.out | 61 ++++++++++++++++++++++++++++++++++++++++++++++
16
2 files changed, 77 insertions(+)
17
18
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/061
21
+++ b/tests/qemu-iotests/061
22
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
23
_check_test_img
24
25
echo
26
+echo "=== Testing version downgrade with zero expansion and 4K cache entries ==="
27
+echo
28
+IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
29
+$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
30
+$QEMU_IO -c "write -z 32M 128k" "$TEST_IMG" | _filter_qemu_io
31
+$QEMU_IO -c map "$TEST_IMG" | _filter_qemu_io
32
+$PYTHON qcow2.py "$TEST_IMG" dump-header
33
+$QEMU_IMG amend -o "compat=0.10" --image-opts \
34
+ driver=qcow2,file.filename=$TEST_IMG,l2-cache-entry-size=4096
35
+$PYTHON qcow2.py "$TEST_IMG" dump-header
36
+$QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
37
+$QEMU_IO -c "read -P 0 32M 128k" "$TEST_IMG" | _filter_qemu_io
38
+$QEMU_IO -c map "$TEST_IMG" | _filter_qemu_io
39
+_check_test_img
40
+
41
+echo
42
echo "=== Testing dirty version downgrade ==="
43
echo
44
IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
45
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
46
index XXXXXXX..XXXXXXX 100644
47
--- a/tests/qemu-iotests/061.out
48
+++ b/tests/qemu-iotests/061.out
49
@@ -XXX,XX +XXX,XX @@ read 131072/131072 bytes at offset 0
50
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
51
No errors were found on the image.
52
53
+=== Testing version downgrade with zero expansion and 4K cache entries ===
54
+
55
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
56
+wrote 131072/131072 bytes at offset 0
57
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
58
+wrote 131072/131072 bytes at offset 33554432
59
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
60
+128 KiB (0x20000) bytes allocated at offset 0 bytes (0x0)
61
+31.875 MiB (0x1fe0000) bytes not allocated at offset 128 KiB (0x20000)
62
+128 KiB (0x20000) bytes allocated at offset 32 MiB (0x2000000)
63
+31.875 MiB (0x1fe0000) bytes not allocated at offset 32.125 MiB (0x2020000)
64
+magic 0x514649fb
65
+version 3
66
+backing_file_offset 0x0
67
+backing_file_size 0x0
68
+cluster_bits 16
69
+size 67108864
70
+crypt_method 0
71
+l1_size 1
72
+l1_table_offset 0x30000
73
+refcount_table_offset 0x10000
74
+refcount_table_clusters 1
75
+nb_snapshots 0
76
+snapshot_offset 0x0
77
+incompatible_features 0x0
78
+compatible_features 0x1
79
+autoclear_features 0x0
80
+refcount_order 4
81
+header_length 104
82
+
83
+Header extension:
84
+magic 0x6803f857
85
+length 144
86
+data <binary>
87
+
88
+magic 0x514649fb
89
+version 2
90
+backing_file_offset 0x0
91
+backing_file_size 0x0
92
+cluster_bits 16
93
+size 67108864
94
+crypt_method 0
95
+l1_size 1
96
+l1_table_offset 0x30000
97
+refcount_table_offset 0x10000
98
+refcount_table_clusters 1
99
+nb_snapshots 0
100
+snapshot_offset 0x0
101
+incompatible_features 0x0
102
+compatible_features 0x0
103
+autoclear_features 0x0
104
+refcount_order 4
105
+header_length 72
106
+
107
+read 131072/131072 bytes at offset 0
108
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
109
+read 131072/131072 bytes at offset 33554432
110
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
111
+64 MiB (0x4000000) bytes not allocated at offset 0 bytes (0x0)
112
+No errors were found on the image.
113
+
114
=== Testing dirty version downgrade ===
115
116
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
117
--
118
2.13.6
119
120
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This test tries reopening a qcow2 image with valid and invalid
4
options. This patch adds l2-cache-entry-size to the set.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 3d3b7d2dbfc020deaef60fb58739b0801eb9517c.1517840877.git.berto@igalia.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/137 | 5 +++++
13
tests/qemu-iotests/137.out | 2 ++
14
2 files changed, 7 insertions(+)
15
16
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/137
19
+++ b/tests/qemu-iotests/137
20
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
21
-c "reopen -o overlap-check.inactive-l2=off" \
22
-c "reopen -o cache-size=1M" \
23
-c "reopen -o l2-cache-size=512k" \
24
+ -c "reopen -o l2-cache-entry-size=512" \
25
+ -c "reopen -o l2-cache-entry-size=4k" \
26
+ -c "reopen -o l2-cache-entry-size=64k" \
27
-c "reopen -o refcount-cache-size=128k" \
28
-c "reopen -o cache-clean-interval=5" \
29
-c "reopen -o cache-clean-interval=0" \
30
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
31
-c "reopen -o cache-size=1M,l2-cache-size=2M" \
32
-c "reopen -o cache-size=1M,refcount-cache-size=2M" \
33
-c "reopen -o l2-cache-size=256T" \
34
+ -c "reopen -o l2-cache-entry-size=33k" \
35
+ -c "reopen -o l2-cache-entry-size=128k" \
36
-c "reopen -o refcount-cache-size=256T" \
37
-c "reopen -o overlap-check=constant,overlap-check.template=all" \
38
-c "reopen -o overlap-check=blubb" \
39
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
40
index XXXXXXX..XXXXXXX 100644
41
--- a/tests/qemu-iotests/137.out
42
+++ b/tests/qemu-iotests/137.out
43
@@ -XXX,XX +XXX,XX @@ cache-size, l2-cache-size and refcount-cache-size may not be set the same time
44
l2-cache-size may not exceed cache-size
45
refcount-cache-size may not exceed cache-size
46
L2 cache size too big
47
+L2 cache entry size must be a power of two between 512 and the cluster size (65536)
48
+L2 cache entry size must be a power of two between 512 and the cluster size (65536)
49
L2 cache size too big
50
Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-check.template' ('all')
51
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
52
--
53
2.13.6
54
55
diff view generated by jsdifflib