1 /*-
2 * Copyright (c) 2014 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 #include <sys/errno.h>
29 #include <assert.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "endian.h"
35 #include "image.h"
36 #include "format.h"
37 #include "mkimg.h"
38
39 /* Default cluster sizes. */
40 #define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */
41 #define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */
42
43 /* Flag bits in cluster offsets */
44 #define QCOW_CLSTR_COMPRESSED (1ULL << 62)
45 #define QCOW_CLSTR_COPIED (1ULL << 63)
46
47 struct qcow_header {
48 uint32_t magic;
49 #define QCOW_MAGIC 0x514649fb
50 uint32_t version;
51 #define QCOW_VERSION_1 1
52 #define QCOW_VERSION_2 2
53 uint64_t path_offset;
54 uint32_t path_length;
55 uint32_t clstr_log2sz; /* v2 only */
56 uint64_t disk_size;
57 union {
58 struct {
59 uint8_t clstr_log2sz;
60 uint8_t l2_log2sz;
61 uint16_t _pad;
62 uint32_t encryption;
63 uint64_t l1_offset;
64 } v1;
65 struct {
66 uint32_t encryption;
67 uint32_t l1_entries;
68 uint64_t l1_offset;
69 uint64_t refcnt_offset;
70 uint32_t refcnt_clstrs;
71 uint32_t snapshot_count;
72 uint64_t snapshot_offset;
73 } v2;
74 } u;
75 };
76
77 static u_int clstr_log2sz;
78
79 static uint64_t
round_clstr(uint64_t ofs)80 round_clstr(uint64_t ofs)
81 {
82 uint64_t clstrsz;
83
84 clstrsz = 1UL << clstr_log2sz;
85 return ((ofs + clstrsz - 1) & ~(clstrsz - 1));
86 }
87
88 static int
qcow_resize(lba_t imgsz,u_int version)89 qcow_resize(lba_t imgsz, u_int version)
90 {
91 uint64_t imagesz;
92
93 switch (version) {
94 case QCOW_VERSION_1:
95 clstr_log2sz = QCOW1_CLSTR_LOG2SZ;
96 break;
97 case QCOW_VERSION_2:
98 clstr_log2sz = QCOW2_CLSTR_LOG2SZ;
99 break;
100 default:
101 assert(0);
102 }
103
104 imagesz = round_clstr(imgsz * secsz);
105
106 if (verbose)
107 fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n",
108 (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz));
109
110 return (image_set_size(imagesz / secsz));
111 }
112
113 static int
qcow1_resize(lba_t imgsz)114 qcow1_resize(lba_t imgsz)
115 {
116
117 return (qcow_resize(imgsz, QCOW_VERSION_1));
118 }
119
120 static int
qcow2_resize(lba_t imgsz)121 qcow2_resize(lba_t imgsz)
122 {
123
124 return (qcow_resize(imgsz, QCOW_VERSION_2));
125 }
126
127 static int
qcow_write(int fd,u_int version)128 qcow_write(int fd, u_int version)
129 {
130 struct qcow_header *hdr;
131 uint64_t *l1tbl, *l2tbl, *rctbl;
132 uint16_t *rcblk;
133 uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz;
134 uint64_t clstr_rcblks, clstr_rctblsz;
135 uint64_t n, imagesz, nclstrs, ofs, ofsflags;
136 lba_t blk, blkofs, blk_imgsz;
137 u_int l1clno, l2clno, rcclno;
138 u_int blk_clstrsz, refcnt_clstrs;
139 u_int clstrsz, l1idx, l2idx;
140 int error;
141
142 assert(clstr_log2sz != 0);
143
144 clstrsz = 1U << clstr_log2sz;
145 blk_clstrsz = clstrsz / secsz;
146 blk_imgsz = image_get_size();
147 imagesz = blk_imgsz * secsz;
148 clstr_imgsz = imagesz >> clstr_log2sz;
149 clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz;
150 clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz;
151 nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1;
152 clstr_rcblks = clstr_rctblsz = 0;
153 do {
154 n = clstr_rcblks + clstr_rctblsz;
155 clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
156 clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
157 } while (n < (clstr_rcblks + clstr_rctblsz));
158
159 /*
160 * We got all the sizes in clusters. Start the layout.
161 * 0 - header
162 * 1 - L1 table
163 * 2 - RC table (v2 only)
164 * 3 - L2 tables
165 * 4 - RC block (v2 only)
166 * 5 - data
167 */
168
169 l1clno = 1;
170 rcclno = 0;
171 rctbl = l2tbl = l1tbl = NULL;
172 rcblk = NULL;
173
174 hdr = calloc(1, clstrsz);
175 if (hdr == NULL)
176 return (errno);
177
178 be32enc(&hdr->magic, QCOW_MAGIC);
179 be32enc(&hdr->version, version);
180 be64enc(&hdr->disk_size, imagesz);
181 switch (version) {
182 case QCOW_VERSION_1:
183 ofsflags = 0;
184 l2clno = l1clno + clstr_l1tblsz;
185 hdr->u.v1.clstr_log2sz = clstr_log2sz;
186 hdr->u.v1.l2_log2sz = clstr_log2sz - 3;
187 be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno);
188 break;
189 case QCOW_VERSION_2:
190 ofsflags = QCOW_CLSTR_COPIED;
191 rcclno = l1clno + clstr_l1tblsz;
192 l2clno = rcclno + clstr_rctblsz;
193 be32enc(&hdr->clstr_log2sz, clstr_log2sz);
194 be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls);
195 be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno);
196 be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno);
197 refcnt_clstrs = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
198 be32enc(&hdr->u.v2.refcnt_clstrs, refcnt_clstrs);
199 break;
200 default:
201 assert(0);
202 }
203
204 if (sparse_write(fd, hdr, clstrsz) < 0) {
205 error = errno;
206 goto out;
207 }
208
209 free(hdr);
210 hdr = NULL;
211
212 ofs = clstrsz * l2clno;
213 nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz;
214
215 l1tbl = calloc(clstr_l1tblsz, clstrsz);
216 if (l1tbl == NULL) {
217 error = ENOMEM;
218 goto out;
219 }
220
221 for (n = 0; n < clstr_imgsz; n++) {
222 blk = n * blk_clstrsz;
223 if (image_data(blk, blk_clstrsz)) {
224 nclstrs++;
225 l1idx = n >> (clstr_log2sz - 3);
226 if (l1tbl[l1idx] == 0) {
227 be64enc(l1tbl + l1idx, ofs + ofsflags);
228 ofs += clstrsz;
229 nclstrs++;
230 }
231 }
232 }
233
234 if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) {
235 error = errno;
236 goto out;
237 }
238
239 clstr_rcblks = 0;
240 do {
241 n = clstr_rcblks;
242 clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
243 } while (n < clstr_rcblks);
244
245 if (rcclno > 0) {
246 rctbl = calloc(clstr_rctblsz, clstrsz);
247 if (rctbl == NULL) {
248 error = ENOMEM;
249 goto out;
250 }
251 for (n = 0; n < clstr_rcblks; n++) {
252 be64enc(rctbl + n, ofs);
253 ofs += clstrsz;
254 nclstrs++;
255 }
256 if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) {
257 error = errno;
258 goto out;
259 }
260 free(rctbl);
261 rctbl = NULL;
262 }
263
264 l2tbl = malloc(clstrsz);
265 if (l2tbl == NULL) {
266 error = ENOMEM;
267 goto out;
268 }
269
270 for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) {
271 if (l1tbl[l1idx] == 0)
272 continue;
273 memset(l2tbl, 0, clstrsz);
274 blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3);
275 for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) {
276 blk = blkofs + (lba_t)l2idx * blk_clstrsz;
277 if (blk >= blk_imgsz)
278 break;
279 if (image_data(blk, blk_clstrsz)) {
280 be64enc(l2tbl + l2idx, ofs + ofsflags);
281 ofs += clstrsz;
282 }
283 }
284 if (sparse_write(fd, l2tbl, clstrsz) < 0) {
285 error = errno;
286 goto out;
287 }
288 }
289
290 free(l2tbl);
291 l2tbl = NULL;
292 free(l1tbl);
293 l1tbl = NULL;
294
295 if (rcclno > 0) {
296 rcblk = calloc(clstr_rcblks, clstrsz);
297 if (rcblk == NULL) {
298 error = ENOMEM;
299 goto out;
300 }
301 for (n = 0; n < nclstrs; n++)
302 be16enc(rcblk + n, 1);
303 if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) {
304 error = errno;
305 goto out;
306 }
307 free(rcblk);
308 rcblk = NULL;
309 }
310
311 error = 0;
312 for (n = 0; n < clstr_imgsz; n++) {
313 blk = n * blk_clstrsz;
314 if (image_data(blk, blk_clstrsz)) {
315 error = image_copyout_region(fd, blk, blk_clstrsz);
316 if (error)
317 break;
318 }
319 }
320 if (!error)
321 error = image_copyout_done(fd);
322
323 out:
324 if (rcblk != NULL)
325 free(rcblk);
326 if (l2tbl != NULL)
327 free(l2tbl);
328 if (rctbl != NULL)
329 free(rctbl);
330 if (l1tbl != NULL)
331 free(l1tbl);
332 if (hdr != NULL)
333 free(hdr);
334 return (error);
335 }
336
337 static int
qcow1_write(int fd)338 qcow1_write(int fd)
339 {
340
341 return (qcow_write(fd, QCOW_VERSION_1));
342 }
343
344 static int
qcow2_write(int fd)345 qcow2_write(int fd)
346 {
347
348 return (qcow_write(fd, QCOW_VERSION_2));
349 }
350
351 static struct mkimg_format qcow1_format = {
352 .name = "qcow",
353 .description = "QEMU Copy-On-Write, version 1",
354 .resize = qcow1_resize,
355 .write = qcow1_write,
356 };
357 FORMAT_DEFINE(qcow1_format);
358
359 static struct mkimg_format qcow2_format = {
360 .name = "qcow2",
361 .description = "QEMU Copy-On-Write, version 2",
362 .resize = qcow2_resize,
363 .write = qcow2_write,
364 };
365 FORMAT_DEFINE(qcow2_format);
366