]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.bin/mkimg/qcow.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / usr.bin / mkimg / qcow.c
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 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <sys/endian.h>
32 #include <sys/errno.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include "image.h"
40 #include "format.h"
41 #include "mkimg.h"
42
43 /* Default cluster sizes. */
44 #define QCOW1_CLSTR_LOG2SZ      12      /* 4KB */
45 #define QCOW2_CLSTR_LOG2SZ      16      /* 64KB */
46
47 /* Flag bits in cluster offsets */
48 #define QCOW_CLSTR_COMPRESSED   (1ULL << 62)
49 #define QCOW_CLSTR_COPIED       (1ULL << 63)
50
51 struct qcow_header {
52         uint32_t        magic;
53 #define QCOW_MAGIC              0x514649fb
54         uint32_t        version;
55 #define QCOW_VERSION_1          1
56 #define QCOW_VERSION_2          2
57         uint64_t        path_offset;
58         uint32_t        path_length;
59         uint32_t        clstr_log2sz;   /* v2 only */
60         uint64_t        disk_size;
61         union {
62                 struct {
63                         uint8_t         clstr_log2sz;
64                         uint8_t         l2_log2sz;
65                         uint16_t        _pad;
66                         uint32_t        encryption;
67                         uint64_t        l1_offset;
68                 } v1;
69                 struct {
70                         uint32_t        encryption;
71                         uint32_t        l1_entries;
72                         uint64_t        l1_offset;
73                         uint64_t        refcnt_offset;
74                         uint32_t        refcnt_clstrs;
75                         uint32_t        snapshot_count;
76                         uint64_t        snapshot_offset;
77                 } v2;
78         } u;
79 };
80
81 static u_int clstr_log2sz;
82
83 static uint64_t
84 round_clstr(uint64_t ofs)
85 {
86         uint64_t clstrsz;
87
88         clstrsz = 1UL << clstr_log2sz;
89         return ((ofs + clstrsz - 1) & ~(clstrsz - 1));
90 }
91
92 static int
93 qcow_resize(lba_t imgsz, u_int version)
94 {
95         uint64_t imagesz;
96
97         switch (version) {
98         case QCOW_VERSION_1:
99                 clstr_log2sz = QCOW1_CLSTR_LOG2SZ;
100                 break;
101         case QCOW_VERSION_2:
102                 clstr_log2sz = QCOW2_CLSTR_LOG2SZ;
103                 break;
104         default:
105                 return (EDOOFUS);
106         }
107
108         imagesz = round_clstr(imgsz * secsz);
109
110         if (verbose)
111                 fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n",
112                     (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz));
113
114         return (image_set_size(imagesz / secsz));
115 }
116
117 static int
118 qcow1_resize(lba_t imgsz)
119 {
120
121         return (qcow_resize(imgsz, QCOW_VERSION_1));
122 }
123
124 static int
125 qcow2_resize(lba_t imgsz)
126 {
127
128         return (qcow_resize(imgsz, QCOW_VERSION_2));
129 }
130
131 static int
132 qcow_write(int fd, u_int version)
133 {
134         struct qcow_header *hdr;
135         uint64_t *l1tbl, *l2tbl, *rctbl;
136         uint16_t *rcblk;
137         uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz;
138         uint64_t clstr_rcblks, clstr_rctblsz;
139         uint64_t n, imagesz, nclstrs, ofs, ofsflags;
140         lba_t blk, blkofs, blk_imgsz;
141         u_int l1clno, l2clno, rcclno;
142         u_int blk_clstrsz, refcnt_clstrs;
143         u_int clstrsz, l1idx, l2idx;
144         int error;
145
146         if (clstr_log2sz == 0)
147                 return (EDOOFUS);
148
149         clstrsz = 1U << clstr_log2sz;
150         blk_clstrsz = clstrsz / secsz;
151         blk_imgsz = image_get_size();
152         imagesz = blk_imgsz * secsz;
153         clstr_imgsz = imagesz >> clstr_log2sz;
154         clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz;
155         clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz;
156         nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1;
157         clstr_rcblks = clstr_rctblsz = 0;
158         do {
159                 n = clstr_rcblks + clstr_rctblsz;
160                 clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
161                 clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
162         } while (n < (clstr_rcblks + clstr_rctblsz));
163
164         /*
165          * We got all the sizes in clusters. Start the layout.
166          * 0 - header
167          * 1 - L1 table
168          * 2 - RC table (v2 only)
169          * 3 - L2 tables
170          * 4 - RC block (v2 only)
171          * 5 - data
172          */
173
174         l1clno = 1;
175         rcclno = 0;
176         rctbl = l2tbl = l1tbl = NULL;
177         rcblk = NULL;
178
179         hdr = calloc(1, clstrsz);
180         if (hdr == NULL)
181                 return (errno);
182
183         be32enc(&hdr->magic, QCOW_MAGIC);
184         be32enc(&hdr->version, version);
185         be64enc(&hdr->disk_size, imagesz);
186         switch (version) {
187         case QCOW_VERSION_1:
188                 ofsflags = 0;
189                 l2clno = l1clno + clstr_l1tblsz;
190                 hdr->u.v1.clstr_log2sz = clstr_log2sz;
191                 hdr->u.v1.l2_log2sz = clstr_log2sz - 3;
192                 be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno);
193                 break;
194         case QCOW_VERSION_2:
195                 ofsflags = QCOW_CLSTR_COPIED;
196                 rcclno = l1clno + clstr_l1tblsz;
197                 l2clno = rcclno + clstr_rctblsz;
198                 be32enc(&hdr->clstr_log2sz, clstr_log2sz);
199                 be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls);
200                 be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno);
201                 be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno);
202                 refcnt_clstrs = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
203                 be32enc(&hdr->u.v2.refcnt_clstrs, refcnt_clstrs);
204                 break;
205         default:
206                 return (EDOOFUS);
207         }
208
209         if (sparse_write(fd, hdr, clstrsz) < 0) {
210                 error = errno;
211                 goto out;
212         }
213
214         free(hdr);
215         hdr = NULL;
216
217         ofs = clstrsz * l2clno;
218         nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz;
219
220         l1tbl = calloc(1, clstrsz * clstr_l1tblsz);
221         if (l1tbl == NULL) {
222                 error = ENOMEM;
223                 goto out;
224         }
225
226         for (n = 0; n < clstr_imgsz; n++) {
227                 blk = n * blk_clstrsz;
228                 if (image_data(blk, blk_clstrsz)) {
229                         nclstrs++;
230                         l1idx = n >> (clstr_log2sz - 3);
231                         if (l1tbl[l1idx] == 0) {
232                                 be64enc(l1tbl + l1idx, ofs + ofsflags);
233                                 ofs += clstrsz;
234                                 nclstrs++;
235                         }
236                 }
237         }
238
239         if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) {
240                 error = errno;
241                 goto out;
242         }
243
244         clstr_rcblks = 0;
245         do {
246                 n = clstr_rcblks;
247                 clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
248         } while (n < clstr_rcblks);
249
250         if (rcclno > 0) {
251                 rctbl = calloc(1, clstrsz * clstr_rctblsz);
252                 if (rctbl == NULL) {
253                         error = ENOMEM;
254                         goto out;
255                 }
256                 for (n = 0; n < clstr_rcblks; n++) {
257                         be64enc(rctbl + n, ofs);
258                         ofs += clstrsz;
259                         nclstrs++;
260                 }
261                 if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) {
262                         error = errno;
263                         goto out;
264                 }
265                 free(rctbl);
266                 rctbl = NULL;
267         }
268
269         l2tbl = malloc(clstrsz);
270         if (l2tbl == NULL) {
271                 error = ENOMEM;
272                 goto out;
273         }
274
275         for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) {
276                 if (l1tbl[l1idx] == 0)
277                         continue;
278                 memset(l2tbl, 0, clstrsz);
279                 blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3);
280                 for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) {
281                         blk = blkofs + (lba_t)l2idx * blk_clstrsz;
282                         if (blk >= blk_imgsz)
283                                 break;
284                         if (image_data(blk, blk_clstrsz)) {
285                                 be64enc(l2tbl + l2idx, ofs + ofsflags);
286                                 ofs += clstrsz;
287                         }
288                 }
289                 if (sparse_write(fd, l2tbl, clstrsz) < 0) {
290                         error = errno;
291                         goto out;
292                 }
293         }
294
295         free(l2tbl);
296         l2tbl = NULL;
297         free(l1tbl);
298         l1tbl = NULL;
299
300         if (rcclno > 0) {
301                 rcblk = calloc(1, clstrsz * clstr_rcblks);
302                 if (rcblk == NULL) {
303                         error = ENOMEM;
304                         goto out;
305                 }
306                 for (n = 0; n < nclstrs; n++)
307                         be16enc(rcblk + n, 1);
308                 if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) {
309                         error = errno;
310                         goto out;
311                 }
312                 free(rcblk);
313                 rcblk = NULL;
314         }
315
316         error = 0;
317         for (n = 0; n < clstr_imgsz; n++) {
318                 blk = n * blk_clstrsz;
319                 if (image_data(blk, blk_clstrsz)) {
320                         error = image_copyout_region(fd, blk, blk_clstrsz);
321                         if (error)
322                                 break;
323                 }
324         }
325         if (!error)
326                 error = image_copyout_done(fd);
327
328  out:
329         if (rcblk != NULL)
330                 free(rcblk);
331         if (l2tbl != NULL)
332                 free(l2tbl);
333         if (rctbl != NULL)
334                 free(rctbl);
335         if (l1tbl != NULL)
336                 free(l1tbl);
337         if (hdr != NULL)
338                 free(hdr);
339         return (error);
340 }
341
342 static int
343 qcow1_write(int fd)
344 {
345
346         return (qcow_write(fd, QCOW_VERSION_1));
347 }
348
349 static int
350 qcow2_write(int fd)
351 {
352
353         return (qcow_write(fd, QCOW_VERSION_2));
354 }
355
356 static struct mkimg_format qcow1_format = {
357         .name = "qcow",
358         .description = "QEMU Copy-On-Write, version 1",
359         .resize = qcow1_resize,
360         .write = qcow1_write,
361 };
362 FORMAT_DEFINE(qcow1_format);
363
364 static struct mkimg_format qcow2_format = {
365         .name = "qcow2",
366         .description = "QEMU Copy-On-Write, version 2",
367         .resize = qcow2_resize,
368         .write = qcow2_write,
369 };
370 FORMAT_DEFINE(qcow2_format);