xref: /qemu/block/parallels.c (revision 5df022cf)
1019d6b8fSAnthony Liguori /*
2019d6b8fSAnthony Liguori  * Block driver for Parallels disk image format
3019d6b8fSAnthony Liguori  *
4019d6b8fSAnthony Liguori  * Copyright (c) 2007 Alex Beregszaszi
5cc5690f2SDenis V. Lunev  * Copyright (c) 2015 Denis V. Lunev <den@openvz.org>
6019d6b8fSAnthony Liguori  *
7cc5690f2SDenis V. Lunev  * This code was originally based on comparing different disk images created
8cc5690f2SDenis V. Lunev  * by Parallels. Currently it is based on opened OpenVZ sources
9cc5690f2SDenis V. Lunev  * available at
10cc5690f2SDenis V. Lunev  *     http://git.openvz.org/?p=ploop;a=summary
11019d6b8fSAnthony Liguori  *
12019d6b8fSAnthony Liguori  * Permission is hereby granted, free of charge, to any person obtaining a copy
13019d6b8fSAnthony Liguori  * of this software and associated documentation files (the "Software"), to deal
14019d6b8fSAnthony Liguori  * in the Software without restriction, including without limitation the rights
15019d6b8fSAnthony Liguori  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16019d6b8fSAnthony Liguori  * copies of the Software, and to permit persons to whom the Software is
17019d6b8fSAnthony Liguori  * furnished to do so, subject to the following conditions:
18019d6b8fSAnthony Liguori  *
19019d6b8fSAnthony Liguori  * The above copyright notice and this permission notice shall be included in
20019d6b8fSAnthony Liguori  * all copies or substantial portions of the Software.
21019d6b8fSAnthony Liguori  *
22019d6b8fSAnthony Liguori  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23019d6b8fSAnthony Liguori  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24019d6b8fSAnthony Liguori  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25019d6b8fSAnthony Liguori  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26019d6b8fSAnthony Liguori  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27019d6b8fSAnthony Liguori  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28019d6b8fSAnthony Liguori  * THE SOFTWARE.
29019d6b8fSAnthony Liguori  */
30922a01a0SMarkus Armbruster 
3180c71a24SPeter Maydell #include "qemu/osdep.h"
32baefd977SVladimir Sementsov-Ogievskiy #include "qemu/error-report.h"
33da34e65cSMarkus Armbruster #include "qapi/error.h"
34737e150eSPaolo Bonzini #include "block/block_int.h"
35609f45eaSMax Reitz #include "block/qdict.h"
368942764fSKevin Wolf #include "sysemu/block-backend.h"
371de7afc9SPaolo Bonzini #include "qemu/module.h"
38922a01a0SMarkus Armbruster #include "qemu/option.h"
391511b490SKevin Wolf #include "qapi/qmp/qdict.h"
401511b490SKevin Wolf #include "qapi/qobject-input-visitor.h"
411511b490SKevin Wolf #include "qapi/qapi-visit-block-core.h"
4258369e22SPaolo Bonzini #include "qemu/bswap.h"
430d31c7c2SDenis V. Lunev #include "qemu/bitmap.h"
44*5df022cfSPeter Maydell #include "qemu/memalign.h"
451d0f37cfSJeff Cody #include "migration/blocker.h"
4690fe66f0SKlim Kireev #include "parallels.h"
47019d6b8fSAnthony Liguori 
48019d6b8fSAnthony Liguori /**************************************************************/
49019d6b8fSAnthony Liguori 
50019d6b8fSAnthony Liguori #define HEADER_MAGIC "WithoutFreeSpace"
51d25d5980SDenis V. Lunev #define HEADER_MAGIC2 "WithouFreSpacExt"
52019d6b8fSAnthony Liguori #define HEADER_VERSION 2
536dd6b9f1SDenis V. Lunev #define HEADER_INUSE_MAGIC  (0x746F6E59)
54555a608cSKlim Kireev #define MAX_PARALLELS_IMAGE_FACTOR (1ull << 32)
55019d6b8fSAnthony Liguori 
56f7abe0ecSMarc-André Lureau static QEnumLookup prealloc_mode_lookup = {
57f7abe0ecSMarc-André Lureau     .array = (const char *const[]) {
58d6179011SDenis V. Lunev         "falloc",
59d6179011SDenis V. Lunev         "truncate",
60f7abe0ecSMarc-André Lureau     },
61f7abe0ecSMarc-André Lureau     .size = PRL_PREALLOC_MODE__MAX
62d6179011SDenis V. Lunev };
63d6179011SDenis V. Lunev 
64d6179011SDenis V. Lunev #define PARALLELS_OPT_PREALLOC_MODE     "prealloc-mode"
65d6179011SDenis V. Lunev #define PARALLELS_OPT_PREALLOC_SIZE     "prealloc-size"
66d6179011SDenis V. Lunev 
67d6179011SDenis V. Lunev static QemuOptsList parallels_runtime_opts = {
68d6179011SDenis V. Lunev     .name = "parallels",
69d6179011SDenis V. Lunev     .head = QTAILQ_HEAD_INITIALIZER(parallels_runtime_opts.head),
70d6179011SDenis V. Lunev     .desc = {
71d6179011SDenis V. Lunev         {
72d6179011SDenis V. Lunev             .name = PARALLELS_OPT_PREALLOC_SIZE,
73d6179011SDenis V. Lunev             .type = QEMU_OPT_SIZE,
74d6179011SDenis V. Lunev             .help = "Preallocation size on image expansion",
75ff5bbe56SEdgar Kaziahmedov             .def_value_str = "128M",
76d6179011SDenis V. Lunev         },
77d6179011SDenis V. Lunev         {
78d6179011SDenis V. Lunev             .name = PARALLELS_OPT_PREALLOC_MODE,
79d6179011SDenis V. Lunev             .type = QEMU_OPT_STRING,
80d6179011SDenis V. Lunev             .help = "Preallocation mode on image expansion "
81d6179011SDenis V. Lunev                     "(allowed values: falloc, truncate)",
82d6179011SDenis V. Lunev             .def_value_str = "falloc",
83d6179011SDenis V. Lunev         },
84d6179011SDenis V. Lunev         { /* end of list */ },
85d6179011SDenis V. Lunev     },
86d6179011SDenis V. Lunev };
87d6179011SDenis V. Lunev 
881511b490SKevin Wolf static QemuOptsList parallels_create_opts = {
891511b490SKevin Wolf     .name = "parallels-create-opts",
901511b490SKevin Wolf     .head = QTAILQ_HEAD_INITIALIZER(parallels_create_opts.head),
911511b490SKevin Wolf     .desc = {
921511b490SKevin Wolf         {
931511b490SKevin Wolf             .name = BLOCK_OPT_SIZE,
941511b490SKevin Wolf             .type = QEMU_OPT_SIZE,
951511b490SKevin Wolf             .help = "Virtual disk size",
961511b490SKevin Wolf         },
971511b490SKevin Wolf         {
981511b490SKevin Wolf             .name = BLOCK_OPT_CLUSTER_SIZE,
991511b490SKevin Wolf             .type = QEMU_OPT_SIZE,
1001511b490SKevin Wolf             .help = "Parallels image cluster size",
1011511b490SKevin Wolf             .def_value_str = stringify(DEFAULT_CLUSTER_SIZE),
1021511b490SKevin Wolf         },
1031511b490SKevin Wolf         { /* end of list */ }
1041511b490SKevin Wolf     }
1051511b490SKevin Wolf };
1061511b490SKevin Wolf 
107d6179011SDenis V. Lunev 
108555cc9d9SDenis V. Lunev static int64_t bat2sect(BDRVParallelsState *s, uint32_t idx)
109555cc9d9SDenis V. Lunev {
110dd97cdc0SDenis V. Lunev     return (uint64_t)le32_to_cpu(s->bat_bitmap[idx]) * s->off_multiplier;
111555cc9d9SDenis V. Lunev }
112555cc9d9SDenis V. Lunev 
1132d68e22eSDenis V. Lunev static uint32_t bat_entry_off(uint32_t idx)
1142d68e22eSDenis V. Lunev {
1152d68e22eSDenis V. Lunev     return sizeof(ParallelsHeader) + sizeof(uint32_t) * idx;
1162d68e22eSDenis V. Lunev }
1172d68e22eSDenis V. Lunev 
11829442569SRoman Kagan static int64_t seek_to_sector(BDRVParallelsState *s, int64_t sector_num)
119019d6b8fSAnthony Liguori {
120c34d2451SDavid Woodhouse     uint32_t index, offset;
121019d6b8fSAnthony Liguori 
122019d6b8fSAnthony Liguori     index = sector_num / s->tracks;
123019d6b8fSAnthony Liguori     offset = sector_num % s->tracks;
124019d6b8fSAnthony Liguori 
1259d8b88f6SChristoph Hellwig     /* not allocated */
126369f7de9SDenis V. Lunev     if ((index >= s->bat_size) || (s->bat_bitmap[index] == 0)) {
127019d6b8fSAnthony Liguori         return -1;
128369f7de9SDenis V. Lunev     }
129555cc9d9SDenis V. Lunev     return bat2sect(s, index) + offset;
130019d6b8fSAnthony Liguori }
131019d6b8fSAnthony Liguori 
1329de9da17SRoman Kagan static int cluster_remainder(BDRVParallelsState *s, int64_t sector_num,
1339de9da17SRoman Kagan         int nb_sectors)
1349de9da17SRoman Kagan {
1359de9da17SRoman Kagan     int ret = s->tracks - sector_num % s->tracks;
1369de9da17SRoman Kagan     return MIN(nb_sectors, ret);
1379de9da17SRoman Kagan }
1389de9da17SRoman Kagan 
1396953d920SDenis V. Lunev static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
1406953d920SDenis V. Lunev                             int nb_sectors, int *pnum)
1416953d920SDenis V. Lunev {
1426953d920SDenis V. Lunev     int64_t start_off = -2, prev_end_off = -2;
1436953d920SDenis V. Lunev 
1446953d920SDenis V. Lunev     *pnum = 0;
1456953d920SDenis V. Lunev     while (nb_sectors > 0 || start_off == -2) {
1466953d920SDenis V. Lunev         int64_t offset = seek_to_sector(s, sector_num);
1476953d920SDenis V. Lunev         int to_end;
1486953d920SDenis V. Lunev 
1496953d920SDenis V. Lunev         if (start_off == -2) {
1506953d920SDenis V. Lunev             start_off = offset;
1516953d920SDenis V. Lunev             prev_end_off = offset;
1526953d920SDenis V. Lunev         } else if (offset != prev_end_off) {
1536953d920SDenis V. Lunev             break;
1546953d920SDenis V. Lunev         }
1556953d920SDenis V. Lunev 
1566953d920SDenis V. Lunev         to_end = cluster_remainder(s, sector_num, nb_sectors);
1576953d920SDenis V. Lunev         nb_sectors -= to_end;
1586953d920SDenis V. Lunev         sector_num += to_end;
1596953d920SDenis V. Lunev         *pnum += to_end;
1606953d920SDenis V. Lunev 
1616953d920SDenis V. Lunev         if (offset > 0) {
1626953d920SDenis V. Lunev             prev_end_off += to_end;
1636953d920SDenis V. Lunev         }
1646953d920SDenis V. Lunev     }
1656953d920SDenis V. Lunev     return start_off;
1666953d920SDenis V. Lunev }
1676953d920SDenis V. Lunev 
168ddd2ef2cSDenis V. Lunev static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
169ddd2ef2cSDenis V. Lunev                                  int nb_sectors, int *pnum)
1705a41e1faSDenis V. Lunev {
171bda4cdcbSEric Blake     int ret = 0;
1725a41e1faSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
173d8b83e37SDenis V. Lunev     int64_t pos, space, idx, to_allocate, i, len;
174ddd2ef2cSDenis V. Lunev 
175ddd2ef2cSDenis V. Lunev     pos = block_status(s, sector_num, nb_sectors, pnum);
176ddd2ef2cSDenis V. Lunev     if (pos > 0) {
177ddd2ef2cSDenis V. Lunev         return pos;
178ddd2ef2cSDenis V. Lunev     }
1795a41e1faSDenis V. Lunev 
1805a41e1faSDenis V. Lunev     idx = sector_num / s->tracks;
181969401feSLaurent Vivier     to_allocate = DIV_ROUND_UP(sector_num + *pnum, s->tracks) - idx;
18286d1bd70SMax Reitz 
18386d1bd70SMax Reitz     /* This function is called only by parallels_co_writev(), which will never
18486d1bd70SMax Reitz      * pass a sector_num at or beyond the end of the image (because the block
18586d1bd70SMax Reitz      * layer never passes such a sector_num to that function). Therefore, idx
18686d1bd70SMax Reitz      * is always below s->bat_size.
18786d1bd70SMax Reitz      * block_status() will limit *pnum so that sector_num + *pnum will not
18886d1bd70SMax Reitz      * exceed the image end. Therefore, idx + to_allocate cannot exceed
18986d1bd70SMax Reitz      * s->bat_size.
19086d1bd70SMax Reitz      * Note that s->bat_size is an unsigned int, therefore idx + to_allocate
19186d1bd70SMax Reitz      * will always fit into a uint32_t. */
19286d1bd70SMax Reitz     assert(idx < s->bat_size && idx + to_allocate <= s->bat_size);
19386d1bd70SMax Reitz 
194ddd2ef2cSDenis V. Lunev     space = to_allocate * s->tracks;
195d8b83e37SDenis V. Lunev     len = bdrv_getlength(bs->file->bs);
196d8b83e37SDenis V. Lunev     if (len < 0) {
197d8b83e37SDenis V. Lunev         return len;
198d8b83e37SDenis V. Lunev     }
199d8b83e37SDenis V. Lunev     if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) {
200ddd2ef2cSDenis V. Lunev         space += s->prealloc_size;
201bda4cdcbSEric Blake         /*
202bda4cdcbSEric Blake          * We require the expanded size to read back as zero. If the
203bda4cdcbSEric Blake          * user permitted truncation, we try that; but if it fails, we
204bda4cdcbSEric Blake          * force the safer-but-slower fallocate.
205bda4cdcbSEric Blake          */
206bda4cdcbSEric Blake         if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
207bda4cdcbSEric Blake             ret = bdrv_truncate(bs->file,
208bda4cdcbSEric Blake                                 (s->data_end + space) << BDRV_SECTOR_BITS,
209bda4cdcbSEric Blake                                 false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE,
210bda4cdcbSEric Blake                                 NULL);
211bda4cdcbSEric Blake             if (ret == -ENOTSUP) {
212bda4cdcbSEric Blake                 s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
213bda4cdcbSEric Blake             }
214bda4cdcbSEric Blake         }
21519f5dc15SDenis V. Lunev         if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
216720ff280SKevin Wolf             ret = bdrv_pwrite_zeroes(bs->file,
21774021bc4SEric Blake                                      s->data_end << BDRV_SECTOR_BITS,
21874021bc4SEric Blake                                      space << BDRV_SECTOR_BITS, 0);
2195a41e1faSDenis V. Lunev         }
2205a41e1faSDenis V. Lunev         if (ret < 0) {
2215a41e1faSDenis V. Lunev             return ret;
2225a41e1faSDenis V. Lunev         }
22319f5dc15SDenis V. Lunev     }
224ddd2ef2cSDenis V. Lunev 
225bcbb3866SEdgar Kaziakhmedov     /* Try to read from backing to fill empty clusters
226bcbb3866SEdgar Kaziakhmedov      * FIXME: 1. previous write_zeroes may be redundant
227bcbb3866SEdgar Kaziakhmedov      *        2. most of data we read from backing will be rewritten by
228bcbb3866SEdgar Kaziakhmedov      *           parallels_co_writev. On aligned-to-cluster write we do not need
229bcbb3866SEdgar Kaziakhmedov      *           this read at all.
230bcbb3866SEdgar Kaziakhmedov      *        3. it would be good to combine write of data from backing and new
231bcbb3866SEdgar Kaziakhmedov      *           data into one write call */
232bcbb3866SEdgar Kaziakhmedov     if (bs->backing) {
233bcbb3866SEdgar Kaziakhmedov         int64_t nb_cow_sectors = to_allocate * s->tracks;
234bcbb3866SEdgar Kaziakhmedov         int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
235a4072543SVladimir Sementsov-Ogievskiy         void *buf = qemu_blockalign(bs, nb_cow_bytes);
236bcbb3866SEdgar Kaziakhmedov 
237a4072543SVladimir Sementsov-Ogievskiy         ret = bdrv_co_pread(bs->backing, idx * s->tracks * BDRV_SECTOR_SIZE,
238a4072543SVladimir Sementsov-Ogievskiy                             nb_cow_bytes, buf, 0);
239bcbb3866SEdgar Kaziakhmedov         if (ret < 0) {
240a4072543SVladimir Sementsov-Ogievskiy             qemu_vfree(buf);
241bcbb3866SEdgar Kaziakhmedov             return ret;
242bcbb3866SEdgar Kaziakhmedov         }
243bcbb3866SEdgar Kaziakhmedov 
244d08c2a24SEric Blake         ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE,
245a4072543SVladimir Sementsov-Ogievskiy                               nb_cow_bytes, buf, 0);
246a4072543SVladimir Sementsov-Ogievskiy         qemu_vfree(buf);
247bcbb3866SEdgar Kaziakhmedov         if (ret < 0) {
248bcbb3866SEdgar Kaziakhmedov             return ret;
249bcbb3866SEdgar Kaziakhmedov         }
250bcbb3866SEdgar Kaziakhmedov     }
251bcbb3866SEdgar Kaziakhmedov 
252ddd2ef2cSDenis V. Lunev     for (i = 0; i < to_allocate; i++) {
253ddd2ef2cSDenis V. Lunev         s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
25419f5dc15SDenis V. Lunev         s->data_end += s->tracks;
255ddd2ef2cSDenis V. Lunev         bitmap_set(s->bat_dirty_bmap,
256c9f6856dSVladimir Sementsov-Ogievskiy                    bat_entry_off(idx + i) / s->bat_dirty_block, 1);
257ddd2ef2cSDenis V. Lunev     }
2585a41e1faSDenis V. Lunev 
259ddd2ef2cSDenis V. Lunev     return bat2sect(s, idx) + sector_num % s->tracks;
2605a41e1faSDenis V. Lunev }
2615a41e1faSDenis V. Lunev 
2620d31c7c2SDenis V. Lunev 
2630d31c7c2SDenis V. Lunev static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
2640d31c7c2SDenis V. Lunev {
2650d31c7c2SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
2660d31c7c2SDenis V. Lunev     unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
2670d31c7c2SDenis V. Lunev     unsigned long bit;
2680d31c7c2SDenis V. Lunev 
2690d31c7c2SDenis V. Lunev     qemu_co_mutex_lock(&s->lock);
2700d31c7c2SDenis V. Lunev 
2710d31c7c2SDenis V. Lunev     bit = find_first_bit(s->bat_dirty_bmap, size);
2720d31c7c2SDenis V. Lunev     while (bit < size) {
2730d31c7c2SDenis V. Lunev         uint32_t off = bit * s->bat_dirty_block;
2740d31c7c2SDenis V. Lunev         uint32_t to_write = s->bat_dirty_block;
2750d31c7c2SDenis V. Lunev         int ret;
2760d31c7c2SDenis V. Lunev 
2770d31c7c2SDenis V. Lunev         if (off + to_write > s->header_size) {
2780d31c7c2SDenis V. Lunev             to_write = s->header_size - off;
2790d31c7c2SDenis V. Lunev         }
280d9ca2ea2SKevin Wolf         ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off,
2819a4f4c31SKevin Wolf                           to_write);
2820d31c7c2SDenis V. Lunev         if (ret < 0) {
2830d31c7c2SDenis V. Lunev             qemu_co_mutex_unlock(&s->lock);
2840d31c7c2SDenis V. Lunev             return ret;
2850d31c7c2SDenis V. Lunev         }
2860d31c7c2SDenis V. Lunev         bit = find_next_bit(s->bat_dirty_bmap, size, bit + 1);
2870d31c7c2SDenis V. Lunev     }
2880d31c7c2SDenis V. Lunev     bitmap_zero(s->bat_dirty_bmap, size);
2890d31c7c2SDenis V. Lunev 
2900d31c7c2SDenis V. Lunev     qemu_co_mutex_unlock(&s->lock);
2910d31c7c2SDenis V. Lunev     return 0;
2920d31c7c2SDenis V. Lunev }
2930d31c7c2SDenis V. Lunev 
2940d31c7c2SDenis V. Lunev 
2958e0cf59dSEric Blake static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
2968e0cf59dSEric Blake                                                   bool want_zero,
2978e0cf59dSEric Blake                                                   int64_t offset,
2988e0cf59dSEric Blake                                                   int64_t bytes,
2998e0cf59dSEric Blake                                                   int64_t *pnum,
3008e0cf59dSEric Blake                                                   int64_t *map,
3018e0cf59dSEric Blake                                                   BlockDriverState **file)
302dd3bed16SRoman Kagan {
303dd3bed16SRoman Kagan     BDRVParallelsState *s = bs->opaque;
3048e0cf59dSEric Blake     int count;
305dd3bed16SRoman Kagan 
3068e0cf59dSEric Blake     assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
307dd3bed16SRoman Kagan     qemu_co_mutex_lock(&s->lock);
3088e0cf59dSEric Blake     offset = block_status(s, offset >> BDRV_SECTOR_BITS,
3098e0cf59dSEric Blake                           bytes >> BDRV_SECTOR_BITS, &count);
310dd3bed16SRoman Kagan     qemu_co_mutex_unlock(&s->lock);
311dd3bed16SRoman Kagan 
3128e0cf59dSEric Blake     *pnum = count * BDRV_SECTOR_SIZE;
313dd3bed16SRoman Kagan     if (offset < 0) {
314dd3bed16SRoman Kagan         return 0;
315dd3bed16SRoman Kagan     }
316dd3bed16SRoman Kagan 
3178e0cf59dSEric Blake     *map = offset * BDRV_SECTOR_SIZE;
318ddf4987dSFam Zheng     *file = bs->file->bs;
3198e0cf59dSEric Blake     return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
320dd3bed16SRoman Kagan }
321dd3bed16SRoman Kagan 
3225a41e1faSDenis V. Lunev static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
323e18a58b4SEric Blake                                             int64_t sector_num, int nb_sectors,
324e18a58b4SEric Blake                                             QEMUIOVector *qiov, int flags)
3255a41e1faSDenis V. Lunev {
3265a41e1faSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
3275a41e1faSDenis V. Lunev     uint64_t bytes_done = 0;
3285a41e1faSDenis V. Lunev     QEMUIOVector hd_qiov;
3295a41e1faSDenis V. Lunev     int ret = 0;
3305a41e1faSDenis V. Lunev 
331e18a58b4SEric Blake     assert(!flags);
3325a41e1faSDenis V. Lunev     qemu_iovec_init(&hd_qiov, qiov->niov);
3335a41e1faSDenis V. Lunev 
3345a41e1faSDenis V. Lunev     while (nb_sectors > 0) {
3355a41e1faSDenis V. Lunev         int64_t position;
3365a41e1faSDenis V. Lunev         int n, nbytes;
3375a41e1faSDenis V. Lunev 
3385a41e1faSDenis V. Lunev         qemu_co_mutex_lock(&s->lock);
339ddd2ef2cSDenis V. Lunev         position = allocate_clusters(bs, sector_num, nb_sectors, &n);
3405a41e1faSDenis V. Lunev         qemu_co_mutex_unlock(&s->lock);
3415a41e1faSDenis V. Lunev         if (position < 0) {
3425a41e1faSDenis V. Lunev             ret = (int)position;
3435a41e1faSDenis V. Lunev             break;
3445a41e1faSDenis V. Lunev         }
3455a41e1faSDenis V. Lunev 
3465a41e1faSDenis V. Lunev         nbytes = n << BDRV_SECTOR_BITS;
3475a41e1faSDenis V. Lunev 
3485a41e1faSDenis V. Lunev         qemu_iovec_reset(&hd_qiov);
3495a41e1faSDenis V. Lunev         qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
3505a41e1faSDenis V. Lunev 
351d08c2a24SEric Blake         ret = bdrv_co_pwritev(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
352d08c2a24SEric Blake                               &hd_qiov, 0);
3535a41e1faSDenis V. Lunev         if (ret < 0) {
3545a41e1faSDenis V. Lunev             break;
3555a41e1faSDenis V. Lunev         }
3565a41e1faSDenis V. Lunev 
3575a41e1faSDenis V. Lunev         nb_sectors -= n;
3585a41e1faSDenis V. Lunev         sector_num += n;
3595a41e1faSDenis V. Lunev         bytes_done += nbytes;
3605a41e1faSDenis V. Lunev     }
3615a41e1faSDenis V. Lunev 
3625a41e1faSDenis V. Lunev     qemu_iovec_destroy(&hd_qiov);
3635a41e1faSDenis V. Lunev     return ret;
3645a41e1faSDenis V. Lunev }
3655a41e1faSDenis V. Lunev 
366481fb9cfSDenis V. Lunev static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
367481fb9cfSDenis V. Lunev         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
368019d6b8fSAnthony Liguori {
36929442569SRoman Kagan     BDRVParallelsState *s = bs->opaque;
370481fb9cfSDenis V. Lunev     uint64_t bytes_done = 0;
371481fb9cfSDenis V. Lunev     QEMUIOVector hd_qiov;
372481fb9cfSDenis V. Lunev     int ret = 0;
373481fb9cfSDenis V. Lunev 
374481fb9cfSDenis V. Lunev     qemu_iovec_init(&hd_qiov, qiov->niov);
37529442569SRoman Kagan 
376019d6b8fSAnthony Liguori     while (nb_sectors > 0) {
377481fb9cfSDenis V. Lunev         int64_t position;
378481fb9cfSDenis V. Lunev         int n, nbytes;
379481fb9cfSDenis V. Lunev 
380481fb9cfSDenis V. Lunev         qemu_co_mutex_lock(&s->lock);
3816953d920SDenis V. Lunev         position = block_status(s, sector_num, nb_sectors, &n);
382481fb9cfSDenis V. Lunev         qemu_co_mutex_unlock(&s->lock);
383481fb9cfSDenis V. Lunev 
384481fb9cfSDenis V. Lunev         nbytes = n << BDRV_SECTOR_BITS;
385481fb9cfSDenis V. Lunev 
386481fb9cfSDenis V. Lunev         qemu_iovec_reset(&hd_qiov);
387481fb9cfSDenis V. Lunev         qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
388481fb9cfSDenis V. Lunev 
389bcbb3866SEdgar Kaziakhmedov         if (position < 0) {
390bcbb3866SEdgar Kaziakhmedov             if (bs->backing) {
391d08c2a24SEric Blake                 ret = bdrv_co_preadv(bs->backing, sector_num * BDRV_SECTOR_SIZE,
392d08c2a24SEric Blake                                      nbytes, &hd_qiov, 0);
393bcbb3866SEdgar Kaziakhmedov                 if (ret < 0) {
394bcbb3866SEdgar Kaziakhmedov                     break;
395bcbb3866SEdgar Kaziakhmedov                 }
396bcbb3866SEdgar Kaziakhmedov             } else {
397bcbb3866SEdgar Kaziakhmedov                 qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
398bcbb3866SEdgar Kaziakhmedov             }
399bcbb3866SEdgar Kaziakhmedov         } else {
400d08c2a24SEric Blake             ret = bdrv_co_preadv(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
401d08c2a24SEric Blake                                  &hd_qiov, 0);
402481fb9cfSDenis V. Lunev             if (ret < 0) {
403481fb9cfSDenis V. Lunev                 break;
4049d8b88f6SChristoph Hellwig             }
405019d6b8fSAnthony Liguori         }
406019d6b8fSAnthony Liguori 
407481fb9cfSDenis V. Lunev         nb_sectors -= n;
408481fb9cfSDenis V. Lunev         sector_num += n;
409481fb9cfSDenis V. Lunev         bytes_done += nbytes;
410481fb9cfSDenis V. Lunev     }
411481fb9cfSDenis V. Lunev 
412481fb9cfSDenis V. Lunev     qemu_iovec_destroy(&hd_qiov);
4132914caa0SPaolo Bonzini     return ret;
4142914caa0SPaolo Bonzini }
4152914caa0SPaolo Bonzini 
41649ad6467SDenis V. Lunev 
4172fd61638SPaolo Bonzini static int coroutine_fn parallels_co_check(BlockDriverState *bs,
4182fd61638SPaolo Bonzini                                            BdrvCheckResult *res,
41949ad6467SDenis V. Lunev                                            BdrvCheckMode fix)
42049ad6467SDenis V. Lunev {
42149ad6467SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
42249ad6467SDenis V. Lunev     int64_t size, prev_off, high_off;
42349ad6467SDenis V. Lunev     int ret;
42449ad6467SDenis V. Lunev     uint32_t i;
42549ad6467SDenis V. Lunev     bool flush_bat = false;
42649ad6467SDenis V. Lunev 
4279a4f4c31SKevin Wolf     size = bdrv_getlength(bs->file->bs);
42849ad6467SDenis V. Lunev     if (size < 0) {
42949ad6467SDenis V. Lunev         res->check_errors++;
43049ad6467SDenis V. Lunev         return size;
43149ad6467SDenis V. Lunev     }
43249ad6467SDenis V. Lunev 
4332fd61638SPaolo Bonzini     qemu_co_mutex_lock(&s->lock);
4346dd6b9f1SDenis V. Lunev     if (s->header_unclean) {
4356dd6b9f1SDenis V. Lunev         fprintf(stderr, "%s image was not closed correctly\n",
4366dd6b9f1SDenis V. Lunev                 fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
4376dd6b9f1SDenis V. Lunev         res->corruptions++;
4386dd6b9f1SDenis V. Lunev         if (fix & BDRV_FIX_ERRORS) {
4396dd6b9f1SDenis V. Lunev             /* parallels_close will do the job right */
4406dd6b9f1SDenis V. Lunev             res->corruptions_fixed++;
4416dd6b9f1SDenis V. Lunev             s->header_unclean = false;
4426dd6b9f1SDenis V. Lunev         }
4436dd6b9f1SDenis V. Lunev     }
4446dd6b9f1SDenis V. Lunev 
44549ad6467SDenis V. Lunev     res->bfi.total_clusters = s->bat_size;
44649ad6467SDenis V. Lunev     res->bfi.compressed_clusters = 0; /* compression is not supported */
44749ad6467SDenis V. Lunev 
44849ad6467SDenis V. Lunev     high_off = 0;
44949ad6467SDenis V. Lunev     prev_off = 0;
45049ad6467SDenis V. Lunev     for (i = 0; i < s->bat_size; i++) {
45149ad6467SDenis V. Lunev         int64_t off = bat2sect(s, i) << BDRV_SECTOR_BITS;
45249ad6467SDenis V. Lunev         if (off == 0) {
45349ad6467SDenis V. Lunev             prev_off = 0;
45449ad6467SDenis V. Lunev             continue;
45549ad6467SDenis V. Lunev         }
45649ad6467SDenis V. Lunev 
45749ad6467SDenis V. Lunev         /* cluster outside the image */
45849ad6467SDenis V. Lunev         if (off > size) {
45949ad6467SDenis V. Lunev             fprintf(stderr, "%s cluster %u is outside image\n",
46049ad6467SDenis V. Lunev                     fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
46149ad6467SDenis V. Lunev             res->corruptions++;
46249ad6467SDenis V. Lunev             if (fix & BDRV_FIX_ERRORS) {
46349ad6467SDenis V. Lunev                 prev_off = 0;
46449ad6467SDenis V. Lunev                 s->bat_bitmap[i] = 0;
46549ad6467SDenis V. Lunev                 res->corruptions_fixed++;
46649ad6467SDenis V. Lunev                 flush_bat = true;
46749ad6467SDenis V. Lunev                 continue;
46849ad6467SDenis V. Lunev             }
46949ad6467SDenis V. Lunev         }
47049ad6467SDenis V. Lunev 
47149ad6467SDenis V. Lunev         res->bfi.allocated_clusters++;
47249ad6467SDenis V. Lunev         if (off > high_off) {
47349ad6467SDenis V. Lunev             high_off = off;
47449ad6467SDenis V. Lunev         }
47549ad6467SDenis V. Lunev 
476e0b5207fSVladimir Sementsov-Ogievskiy         if (prev_off != 0 && (prev_off + s->cluster_size) != off) {
47749ad6467SDenis V. Lunev             res->bfi.fragmented_clusters++;
47849ad6467SDenis V. Lunev         }
47949ad6467SDenis V. Lunev         prev_off = off;
48049ad6467SDenis V. Lunev     }
48149ad6467SDenis V. Lunev 
4822fd61638SPaolo Bonzini     ret = 0;
48349ad6467SDenis V. Lunev     if (flush_bat) {
484d9ca2ea2SKevin Wolf         ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
48549ad6467SDenis V. Lunev         if (ret < 0) {
48649ad6467SDenis V. Lunev             res->check_errors++;
4872fd61638SPaolo Bonzini             goto out;
48849ad6467SDenis V. Lunev         }
48949ad6467SDenis V. Lunev     }
49049ad6467SDenis V. Lunev 
491e0b5207fSVladimir Sementsov-Ogievskiy     res->image_end_offset = high_off + s->cluster_size;
49249ad6467SDenis V. Lunev     if (size > res->image_end_offset) {
49349ad6467SDenis V. Lunev         int64_t count;
494e0b5207fSVladimir Sementsov-Ogievskiy         count = DIV_ROUND_UP(size - res->image_end_offset, s->cluster_size);
49549ad6467SDenis V. Lunev         fprintf(stderr, "%s space leaked at the end of the image %" PRId64 "\n",
49649ad6467SDenis V. Lunev                 fix & BDRV_FIX_LEAKS ? "Repairing" : "ERROR",
49749ad6467SDenis V. Lunev                 size - res->image_end_offset);
49849ad6467SDenis V. Lunev         res->leaks += count;
49949ad6467SDenis V. Lunev         if (fix & BDRV_FIX_LEAKS) {
500ed3d2ec9SMax Reitz             Error *local_err = NULL;
501e8d04f92SMax Reitz 
502e8d04f92SMax Reitz             /*
503e8d04f92SMax Reitz              * In order to really repair the image, we must shrink it.
504e8d04f92SMax Reitz              * That means we have to pass exact=true.
505e8d04f92SMax Reitz              */
506e8d04f92SMax Reitz             ret = bdrv_truncate(bs->file, res->image_end_offset, true,
5077b8e4857SKevin Wolf                                 PREALLOC_MODE_OFF, 0, &local_err);
50849ad6467SDenis V. Lunev             if (ret < 0) {
509ed3d2ec9SMax Reitz                 error_report_err(local_err);
51049ad6467SDenis V. Lunev                 res->check_errors++;
5112fd61638SPaolo Bonzini                 goto out;
51249ad6467SDenis V. Lunev             }
51349ad6467SDenis V. Lunev             res->leaks_fixed += count;
51449ad6467SDenis V. Lunev         }
51549ad6467SDenis V. Lunev     }
51649ad6467SDenis V. Lunev 
5172fd61638SPaolo Bonzini out:
5182fd61638SPaolo Bonzini     qemu_co_mutex_unlock(&s->lock);
5192fd61638SPaolo Bonzini     return ret;
52049ad6467SDenis V. Lunev }
52149ad6467SDenis V. Lunev 
52249ad6467SDenis V. Lunev 
5231511b490SKevin Wolf static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
524efc75e2aSStefan Hajnoczi                                             Error **errp)
52574cf6c50SDenis V. Lunev {
5261511b490SKevin Wolf     BlockdevCreateOptionsParallels *parallels_opts;
5271511b490SKevin Wolf     BlockDriverState *bs;
5281511b490SKevin Wolf     BlockBackend *blk;
52974cf6c50SDenis V. Lunev     int64_t total_size, cl_size;
530369f7de9SDenis V. Lunev     uint32_t bat_entries, bat_sectors;
53174cf6c50SDenis V. Lunev     ParallelsHeader header;
5321511b490SKevin Wolf     uint8_t tmp[BDRV_SECTOR_SIZE];
53374cf6c50SDenis V. Lunev     int ret;
53474cf6c50SDenis V. Lunev 
5351511b490SKevin Wolf     assert(opts->driver == BLOCKDEV_DRIVER_PARALLELS);
5361511b490SKevin Wolf     parallels_opts = &opts->u.parallels;
5371511b490SKevin Wolf 
5381511b490SKevin Wolf     /* Sanity checks */
5391511b490SKevin Wolf     total_size = parallels_opts->size;
5401511b490SKevin Wolf 
5411511b490SKevin Wolf     if (parallels_opts->has_cluster_size) {
5421511b490SKevin Wolf         cl_size = parallels_opts->cluster_size;
5431511b490SKevin Wolf     } else {
5441511b490SKevin Wolf         cl_size = DEFAULT_CLUSTER_SIZE;
5451511b490SKevin Wolf     }
5461511b490SKevin Wolf 
5472332d825SKevin Wolf     /* XXX What is the real limit here? This is an insanely large maximum. */
5482332d825SKevin Wolf     if (cl_size >= INT64_MAX / MAX_PARALLELS_IMAGE_FACTOR) {
5492332d825SKevin Wolf         error_setg(errp, "Cluster size is too large");
5502332d825SKevin Wolf         return -EINVAL;
5512332d825SKevin Wolf     }
552555a608cSKlim Kireev     if (total_size >= MAX_PARALLELS_IMAGE_FACTOR * cl_size) {
5531511b490SKevin Wolf         error_setg(errp, "Image size is too large for this cluster size");
554555a608cSKlim Kireev         return -E2BIG;
555555a608cSKlim Kireev     }
55674cf6c50SDenis V. Lunev 
5571511b490SKevin Wolf     if (!QEMU_IS_ALIGNED(total_size, BDRV_SECTOR_SIZE)) {
5581511b490SKevin Wolf         error_setg(errp, "Image size must be a multiple of 512 bytes");
5591511b490SKevin Wolf         return -EINVAL;
56074cf6c50SDenis V. Lunev     }
56174cf6c50SDenis V. Lunev 
5621511b490SKevin Wolf     if (!QEMU_IS_ALIGNED(cl_size, BDRV_SECTOR_SIZE)) {
5631511b490SKevin Wolf         error_setg(errp, "Cluster size must be a multiple of 512 bytes");
5641511b490SKevin Wolf         return -EINVAL;
5651511b490SKevin Wolf     }
5661511b490SKevin Wolf 
5671511b490SKevin Wolf     /* Create BlockBackend to write to the image */
5681511b490SKevin Wolf     bs = bdrv_open_blockdev_ref(parallels_opts->file, errp);
5691511b490SKevin Wolf     if (bs == NULL) {
5708942764fSKevin Wolf         return -EIO;
57174cf6c50SDenis V. Lunev     }
5728942764fSKevin Wolf 
573a3aeeab5SEric Blake     blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
574a3aeeab5SEric Blake                           errp);
575a3aeeab5SEric Blake     if (!blk) {
576a3aeeab5SEric Blake         ret = -EPERM;
5771511b490SKevin Wolf         goto out;
5781511b490SKevin Wolf     }
5791511b490SKevin Wolf     blk_set_allow_write_beyond_eof(blk, true);
5801511b490SKevin Wolf 
5811511b490SKevin Wolf     /* Create image format */
582369f7de9SDenis V. Lunev     bat_entries = DIV_ROUND_UP(total_size, cl_size);
5832d68e22eSDenis V. Lunev     bat_sectors = DIV_ROUND_UP(bat_entry_off(bat_entries), cl_size);
584369f7de9SDenis V. Lunev     bat_sectors = (bat_sectors *  cl_size) >> BDRV_SECTOR_BITS;
58574cf6c50SDenis V. Lunev 
58674cf6c50SDenis V. Lunev     memset(&header, 0, sizeof(header));
58774cf6c50SDenis V. Lunev     memcpy(header.magic, HEADER_MAGIC2, sizeof(header.magic));
58874cf6c50SDenis V. Lunev     header.version = cpu_to_le32(HEADER_VERSION);
58974cf6c50SDenis V. Lunev     /* don't care much about geometry, it is not used on image level */
590908b1c84SKlim Kireev     header.heads = cpu_to_le32(HEADS_NUMBER);
591908b1c84SKlim Kireev     header.cylinders = cpu_to_le32(total_size / BDRV_SECTOR_SIZE
592908b1c84SKlim Kireev                                    / HEADS_NUMBER / SEC_IN_CYL);
59374cf6c50SDenis V. Lunev     header.tracks = cpu_to_le32(cl_size >> BDRV_SECTOR_BITS);
594369f7de9SDenis V. Lunev     header.bat_entries = cpu_to_le32(bat_entries);
59574cf6c50SDenis V. Lunev     header.nb_sectors = cpu_to_le64(DIV_ROUND_UP(total_size, BDRV_SECTOR_SIZE));
596369f7de9SDenis V. Lunev     header.data_off = cpu_to_le32(bat_sectors);
59774cf6c50SDenis V. Lunev 
59874cf6c50SDenis V. Lunev     /* write all the data */
59974cf6c50SDenis V. Lunev     memset(tmp, 0, sizeof(tmp));
60074cf6c50SDenis V. Lunev     memcpy(tmp, &header, sizeof(header));
60174cf6c50SDenis V. Lunev 
6021511b490SKevin Wolf     ret = blk_pwrite(blk, 0, tmp, BDRV_SECTOR_SIZE, 0);
60374cf6c50SDenis V. Lunev     if (ret < 0) {
60474cf6c50SDenis V. Lunev         goto exit;
60574cf6c50SDenis V. Lunev     }
6061511b490SKevin Wolf     ret = blk_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
607983a1600SEric Blake                             (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
60874cf6c50SDenis V. Lunev     if (ret < 0) {
60974cf6c50SDenis V. Lunev         goto exit;
61074cf6c50SDenis V. Lunev     }
61174cf6c50SDenis V. Lunev 
6121511b490SKevin Wolf     ret = 0;
6131511b490SKevin Wolf out:
6141511b490SKevin Wolf     blk_unref(blk);
6151511b490SKevin Wolf     bdrv_unref(bs);
61674cf6c50SDenis V. Lunev     return ret;
61774cf6c50SDenis V. Lunev 
61874cf6c50SDenis V. Lunev exit:
61974cf6c50SDenis V. Lunev     error_setg_errno(errp, -ret, "Failed to create Parallels image");
6201511b490SKevin Wolf     goto out;
6211511b490SKevin Wolf }
6221511b490SKevin Wolf 
623b92902dfSMaxim Levitsky static int coroutine_fn parallels_co_create_opts(BlockDriver *drv,
624b92902dfSMaxim Levitsky                                                  const char *filename,
6251511b490SKevin Wolf                                                  QemuOpts *opts,
6261511b490SKevin Wolf                                                  Error **errp)
6271511b490SKevin Wolf {
6281511b490SKevin Wolf     BlockdevCreateOptions *create_options = NULL;
6291511b490SKevin Wolf     BlockDriverState *bs = NULL;
63092adf9dbSMarkus Armbruster     QDict *qdict;
6311511b490SKevin Wolf     Visitor *v;
6321511b490SKevin Wolf     int ret;
6331511b490SKevin Wolf 
6341511b490SKevin Wolf     static const QDictRenames opt_renames[] = {
6351511b490SKevin Wolf         { BLOCK_OPT_CLUSTER_SIZE,       "cluster-size" },
6361511b490SKevin Wolf         { NULL, NULL },
6371511b490SKevin Wolf     };
6381511b490SKevin Wolf 
6391511b490SKevin Wolf     /* Parse options and convert legacy syntax */
6401511b490SKevin Wolf     qdict = qemu_opts_to_qdict_filtered(opts, NULL, &parallels_create_opts,
6411511b490SKevin Wolf                                         true);
6421511b490SKevin Wolf 
6431511b490SKevin Wolf     if (!qdict_rename_keys(qdict, opt_renames, errp)) {
6441511b490SKevin Wolf         ret = -EINVAL;
64574cf6c50SDenis V. Lunev         goto done;
64674cf6c50SDenis V. Lunev     }
64774cf6c50SDenis V. Lunev 
6481511b490SKevin Wolf     /* Create and open the file (protocol layer) */
649668f62ecSMarkus Armbruster     ret = bdrv_create_file(filename, opts, errp);
6501511b490SKevin Wolf     if (ret < 0) {
6511511b490SKevin Wolf         goto done;
6521511b490SKevin Wolf     }
6531511b490SKevin Wolf 
6541511b490SKevin Wolf     bs = bdrv_open(filename, NULL, NULL,
6551511b490SKevin Wolf                    BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
6561511b490SKevin Wolf     if (bs == NULL) {
6571511b490SKevin Wolf         ret = -EIO;
6581511b490SKevin Wolf         goto done;
6591511b490SKevin Wolf     }
6601511b490SKevin Wolf 
6611511b490SKevin Wolf     /* Now get the QAPI type BlockdevCreateOptions */
6621511b490SKevin Wolf     qdict_put_str(qdict, "driver", "parallels");
6631511b490SKevin Wolf     qdict_put_str(qdict, "file", bs->node_name);
6641511b490SKevin Wolf 
665af91062eSMarkus Armbruster     v = qobject_input_visitor_new_flat_confused(qdict, errp);
666af91062eSMarkus Armbruster     if (!v) {
6671511b490SKevin Wolf         ret = -EINVAL;
6681511b490SKevin Wolf         goto done;
6691511b490SKevin Wolf     }
6701511b490SKevin Wolf 
671b11a093cSMarkus Armbruster     visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp);
6721511b490SKevin Wolf     visit_free(v);
673b11a093cSMarkus Armbruster     if (!create_options) {
6741511b490SKevin Wolf         ret = -EINVAL;
6751511b490SKevin Wolf         goto done;
6761511b490SKevin Wolf     }
6771511b490SKevin Wolf 
6781511b490SKevin Wolf     /* Silently round up sizes */
6791511b490SKevin Wolf     create_options->u.parallels.size =
6801511b490SKevin Wolf         ROUND_UP(create_options->u.parallels.size, BDRV_SECTOR_SIZE);
6811511b490SKevin Wolf     create_options->u.parallels.cluster_size =
6821511b490SKevin Wolf         ROUND_UP(create_options->u.parallels.cluster_size, BDRV_SECTOR_SIZE);
6831511b490SKevin Wolf 
6841511b490SKevin Wolf     /* Create the Parallels image (format layer) */
6851511b490SKevin Wolf     ret = parallels_co_create(create_options, errp);
6861511b490SKevin Wolf     if (ret < 0) {
6871511b490SKevin Wolf         goto done;
6881511b490SKevin Wolf     }
6891511b490SKevin Wolf     ret = 0;
6901511b490SKevin Wolf 
6911511b490SKevin Wolf done:
692cb3e7f08SMarc-André Lureau     qobject_unref(qdict);
6931511b490SKevin Wolf     bdrv_unref(bs);
6941511b490SKevin Wolf     qapi_free_BlockdevCreateOptions(create_options);
6951511b490SKevin Wolf     return ret;
6961511b490SKevin Wolf }
6971511b490SKevin Wolf 
69823d6bd3bSDenis V. Lunev 
69923d6bd3bSDenis V. Lunev static int parallels_probe(const uint8_t *buf, int buf_size,
70023d6bd3bSDenis V. Lunev                            const char *filename)
70123d6bd3bSDenis V. Lunev {
70223d6bd3bSDenis V. Lunev     const ParallelsHeader *ph = (const void *)buf;
70323d6bd3bSDenis V. Lunev 
70423d6bd3bSDenis V. Lunev     if (buf_size < sizeof(ParallelsHeader)) {
70523d6bd3bSDenis V. Lunev         return 0;
70623d6bd3bSDenis V. Lunev     }
70723d6bd3bSDenis V. Lunev 
70823d6bd3bSDenis V. Lunev     if ((!memcmp(ph->magic, HEADER_MAGIC, 16) ||
70923d6bd3bSDenis V. Lunev            !memcmp(ph->magic, HEADER_MAGIC2, 16)) &&
71023d6bd3bSDenis V. Lunev            (le32_to_cpu(ph->version) == HEADER_VERSION)) {
71123d6bd3bSDenis V. Lunev         return 100;
71223d6bd3bSDenis V. Lunev     }
71323d6bd3bSDenis V. Lunev 
71423d6bd3bSDenis V. Lunev     return 0;
71523d6bd3bSDenis V. Lunev }
71623d6bd3bSDenis V. Lunev 
7176dd6b9f1SDenis V. Lunev static int parallels_update_header(BlockDriverState *bs)
7186dd6b9f1SDenis V. Lunev {
7196dd6b9f1SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
7209a4f4c31SKevin Wolf     unsigned size = MAX(bdrv_opt_mem_align(bs->file->bs),
7219a4f4c31SKevin Wolf                         sizeof(ParallelsHeader));
7226dd6b9f1SDenis V. Lunev 
7236dd6b9f1SDenis V. Lunev     if (size > s->header_size) {
7246dd6b9f1SDenis V. Lunev         size = s->header_size;
7256dd6b9f1SDenis V. Lunev     }
726d9ca2ea2SKevin Wolf     return bdrv_pwrite_sync(bs->file, 0, s->header, size);
7276dd6b9f1SDenis V. Lunev }
7286dd6b9f1SDenis V. Lunev 
72923d6bd3bSDenis V. Lunev static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
73023d6bd3bSDenis V. Lunev                           Error **errp)
73123d6bd3bSDenis V. Lunev {
73223d6bd3bSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
73323d6bd3bSDenis V. Lunev     ParallelsHeader ph;
73419f5dc15SDenis V. Lunev     int ret, size, i;
735d6179011SDenis V. Lunev     QemuOpts *opts = NULL;
736d6179011SDenis V. Lunev     Error *local_err = NULL;
737d6179011SDenis V. Lunev     char *buf;
73823d6bd3bSDenis V. Lunev 
7398b1869daSMax Reitz     bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
7408b1869daSMax Reitz                                BDRV_CHILD_IMAGE, false, errp);
7414e4bf5c4SKevin Wolf     if (!bs->file) {
7424e4bf5c4SKevin Wolf         return -EINVAL;
7434e4bf5c4SKevin Wolf     }
7444e4bf5c4SKevin Wolf 
745cf2ab8fcSKevin Wolf     ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
74623d6bd3bSDenis V. Lunev     if (ret < 0) {
74723d6bd3bSDenis V. Lunev         goto fail;
74823d6bd3bSDenis V. Lunev     }
74923d6bd3bSDenis V. Lunev 
75023d6bd3bSDenis V. Lunev     bs->total_sectors = le64_to_cpu(ph.nb_sectors);
75123d6bd3bSDenis V. Lunev 
75223d6bd3bSDenis V. Lunev     if (le32_to_cpu(ph.version) != HEADER_VERSION) {
75323d6bd3bSDenis V. Lunev         goto fail_format;
75423d6bd3bSDenis V. Lunev     }
75523d6bd3bSDenis V. Lunev     if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {
75623d6bd3bSDenis V. Lunev         s->off_multiplier = 1;
75723d6bd3bSDenis V. Lunev         bs->total_sectors = 0xffffffff & bs->total_sectors;
75823d6bd3bSDenis V. Lunev     } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {
75923d6bd3bSDenis V. Lunev         s->off_multiplier = le32_to_cpu(ph.tracks);
76023d6bd3bSDenis V. Lunev     } else {
76123d6bd3bSDenis V. Lunev         goto fail_format;
76223d6bd3bSDenis V. Lunev     }
76323d6bd3bSDenis V. Lunev 
76423d6bd3bSDenis V. Lunev     s->tracks = le32_to_cpu(ph.tracks);
76523d6bd3bSDenis V. Lunev     if (s->tracks == 0) {
76623d6bd3bSDenis V. Lunev         error_setg(errp, "Invalid image: Zero sectors per track");
76723d6bd3bSDenis V. Lunev         ret = -EINVAL;
76823d6bd3bSDenis V. Lunev         goto fail;
76923d6bd3bSDenis V. Lunev     }
77023d6bd3bSDenis V. Lunev     if (s->tracks > INT32_MAX/513) {
77123d6bd3bSDenis V. Lunev         error_setg(errp, "Invalid image: Too big cluster");
77223d6bd3bSDenis V. Lunev         ret = -EFBIG;
77323d6bd3bSDenis V. Lunev         goto fail;
77423d6bd3bSDenis V. Lunev     }
775e0b5207fSVladimir Sementsov-Ogievskiy     s->cluster_size = s->tracks << BDRV_SECTOR_BITS;
77623d6bd3bSDenis V. Lunev 
77723d6bd3bSDenis V. Lunev     s->bat_size = le32_to_cpu(ph.bat_entries);
77823d6bd3bSDenis V. Lunev     if (s->bat_size > INT_MAX / sizeof(uint32_t)) {
77923d6bd3bSDenis V. Lunev         error_setg(errp, "Catalog too large");
78023d6bd3bSDenis V. Lunev         ret = -EFBIG;
78123d6bd3bSDenis V. Lunev         goto fail;
78223d6bd3bSDenis V. Lunev     }
78323d6bd3bSDenis V. Lunev 
7842d68e22eSDenis V. Lunev     size = bat_entry_off(s->bat_size);
7859a4f4c31SKevin Wolf     s->header_size = ROUND_UP(size, bdrv_opt_mem_align(bs->file->bs));
7869a4f4c31SKevin Wolf     s->header = qemu_try_blockalign(bs->file->bs, s->header_size);
78723d6bd3bSDenis V. Lunev     if (s->header == NULL) {
78823d6bd3bSDenis V. Lunev         ret = -ENOMEM;
78923d6bd3bSDenis V. Lunev         goto fail;
79023d6bd3bSDenis V. Lunev     }
79119f5dc15SDenis V. Lunev     s->data_end = le32_to_cpu(ph.data_off);
79219f5dc15SDenis V. Lunev     if (s->data_end == 0) {
79319f5dc15SDenis V. Lunev         s->data_end = ROUND_UP(bat_entry_off(s->bat_size), BDRV_SECTOR_SIZE);
79419f5dc15SDenis V. Lunev     }
79519f5dc15SDenis V. Lunev     if (s->data_end < s->header_size) {
79623d6bd3bSDenis V. Lunev         /* there is not enough unused space to fit to block align between BAT
79723d6bd3bSDenis V. Lunev            and actual data. We can't avoid read-modify-write... */
79823d6bd3bSDenis V. Lunev         s->header_size = size;
79923d6bd3bSDenis V. Lunev     }
80023d6bd3bSDenis V. Lunev 
801cf2ab8fcSKevin Wolf     ret = bdrv_pread(bs->file, 0, s->header, s->header_size);
80223d6bd3bSDenis V. Lunev     if (ret < 0) {
80323d6bd3bSDenis V. Lunev         goto fail;
80423d6bd3bSDenis V. Lunev     }
80523d6bd3bSDenis V. Lunev     s->bat_bitmap = (uint32_t *)(s->header + 1);
80623d6bd3bSDenis V. Lunev 
80719f5dc15SDenis V. Lunev     for (i = 0; i < s->bat_size; i++) {
80819f5dc15SDenis V. Lunev         int64_t off = bat2sect(s, i);
80919f5dc15SDenis V. Lunev         if (off >= s->data_end) {
81019f5dc15SDenis V. Lunev             s->data_end = off + s->tracks;
81119f5dc15SDenis V. Lunev         }
81219f5dc15SDenis V. Lunev     }
81319f5dc15SDenis V. Lunev 
8146dd6b9f1SDenis V. Lunev     if (le32_to_cpu(ph.inuse) == HEADER_INUSE_MAGIC) {
8156dd6b9f1SDenis V. Lunev         /* Image was not closed correctly. The check is mandatory */
8166dd6b9f1SDenis V. Lunev         s->header_unclean = true;
8176dd6b9f1SDenis V. Lunev         if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) {
8186dd6b9f1SDenis V. Lunev             error_setg(errp, "parallels: Image was not closed correctly; "
8196dd6b9f1SDenis V. Lunev                        "cannot be opened read/write");
8206dd6b9f1SDenis V. Lunev             ret = -EACCES;
8216dd6b9f1SDenis V. Lunev             goto fail;
8226dd6b9f1SDenis V. Lunev         }
8236dd6b9f1SDenis V. Lunev     }
8246dd6b9f1SDenis V. Lunev 
825c6ecec43SMarkus Armbruster     opts = qemu_opts_create(&parallels_runtime_opts, NULL, 0, errp);
826c6ecec43SMarkus Armbruster     if (!opts) {
827d6179011SDenis V. Lunev         goto fail_options;
828d6179011SDenis V. Lunev     }
829d6179011SDenis V. Lunev 
830a5f9b9dfSMarkus Armbruster     if (!qemu_opts_absorb_qdict(opts, options, errp)) {
831d6179011SDenis V. Lunev         goto fail_options;
832d6179011SDenis V. Lunev     }
833d6179011SDenis V. Lunev 
834d6179011SDenis V. Lunev     s->prealloc_size =
835d6179011SDenis V. Lunev         qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
836d6179011SDenis V. Lunev     s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
837d6179011SDenis V. Lunev     buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
838bda4cdcbSEric Blake     /* prealloc_mode can be downgraded later during allocate_clusters */
839f7abe0ecSMarc-André Lureau     s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf,
84006c60b6cSMarkus Armbruster                                        PRL_PREALLOC_MODE_FALLOCATE,
84106c60b6cSMarkus Armbruster                                        &local_err);
842d6179011SDenis V. Lunev     g_free(buf);
843d6179011SDenis V. Lunev     if (local_err != NULL) {
8444bc6d7eeSMarkus Armbruster         error_propagate(errp, local_err);
845d6179011SDenis V. Lunev         goto fail_options;
846d6179011SDenis V. Lunev     }
847dc62da88SDenis V. Lunev 
848baefd977SVladimir Sementsov-Ogievskiy     if (ph.ext_off) {
849baefd977SVladimir Sementsov-Ogievskiy         if (flags & BDRV_O_RDWR) {
850baefd977SVladimir Sementsov-Ogievskiy             /*
851baefd977SVladimir Sementsov-Ogievskiy              * It's unsafe to open image RW if there is an extension (as we
852baefd977SVladimir Sementsov-Ogievskiy              * don't support it). But parallels driver in QEMU historically
853baefd977SVladimir Sementsov-Ogievskiy              * ignores the extension, so print warning and don't care.
854baefd977SVladimir Sementsov-Ogievskiy              */
855baefd977SVladimir Sementsov-Ogievskiy             warn_report("Format Extension ignored in RW mode");
856baefd977SVladimir Sementsov-Ogievskiy         } else {
857baefd977SVladimir Sementsov-Ogievskiy             ret = parallels_read_format_extension(
858baefd977SVladimir Sementsov-Ogievskiy                     bs, le64_to_cpu(ph.ext_off) << BDRV_SECTOR_BITS, errp);
859baefd977SVladimir Sementsov-Ogievskiy             if (ret < 0) {
860baefd977SVladimir Sementsov-Ogievskiy                 goto fail;
861baefd977SVladimir Sementsov-Ogievskiy             }
862baefd977SVladimir Sementsov-Ogievskiy         }
863baefd977SVladimir Sementsov-Ogievskiy     }
864baefd977SVladimir Sementsov-Ogievskiy 
8656c7d390bSJeff Cody     if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_INACTIVE)) {
8666dd6b9f1SDenis V. Lunev         s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC);
8676dd6b9f1SDenis V. Lunev         ret = parallels_update_header(bs);
8686dd6b9f1SDenis V. Lunev         if (ret < 0) {
8696dd6b9f1SDenis V. Lunev             goto fail;
8706dd6b9f1SDenis V. Lunev         }
8716dd6b9f1SDenis V. Lunev     }
8726dd6b9f1SDenis V. Lunev 
873038adc2fSWei Yang     s->bat_dirty_block = 4 * qemu_real_host_page_size;
8740d31c7c2SDenis V. Lunev     s->bat_dirty_bmap =
8750d31c7c2SDenis V. Lunev         bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
8760d31c7c2SDenis V. Lunev 
877a94750d9SEmanuele Giuseppe Esposito     /* Disable migration until bdrv_activate method is added */
8781d0f37cfSJeff Cody     error_setg(&s->migration_blocker, "The Parallels format used by node '%s' "
8791d0f37cfSJeff Cody                "does not support live migration",
8801d0f37cfSJeff Cody                bdrv_get_device_or_node_name(bs));
881386f6c07SMarkus Armbruster     ret = migrate_add_blocker(s->migration_blocker, errp);
882386f6c07SMarkus Armbruster     if (ret < 0) {
8831d0f37cfSJeff Cody         error_free(s->migration_blocker);
8841d0f37cfSJeff Cody         goto fail;
8851d0f37cfSJeff Cody     }
88623d6bd3bSDenis V. Lunev     qemu_co_mutex_init(&s->lock);
88723d6bd3bSDenis V. Lunev     return 0;
88823d6bd3bSDenis V. Lunev 
88923d6bd3bSDenis V. Lunev fail_format:
89023d6bd3bSDenis V. Lunev     error_setg(errp, "Image not in Parallels format");
8914bc6d7eeSMarkus Armbruster fail_options:
89223d6bd3bSDenis V. Lunev     ret = -EINVAL;
89323d6bd3bSDenis V. Lunev fail:
89423d6bd3bSDenis V. Lunev     qemu_vfree(s->header);
89523d6bd3bSDenis V. Lunev     return ret;
89623d6bd3bSDenis V. Lunev }
89723d6bd3bSDenis V. Lunev 
89823d6bd3bSDenis V. Lunev 
899019d6b8fSAnthony Liguori static void parallels_close(BlockDriverState *bs)
900019d6b8fSAnthony Liguori {
901019d6b8fSAnthony Liguori     BDRVParallelsState *s = bs->opaque;
9026dd6b9f1SDenis V. Lunev 
9036c7d390bSJeff Cody     if ((bs->open_flags & BDRV_O_RDWR) && !(bs->open_flags & BDRV_O_INACTIVE)) {
9046dd6b9f1SDenis V. Lunev         s->header->inuse = 0;
9056dd6b9f1SDenis V. Lunev         parallels_update_header(bs);
906e8d04f92SMax Reitz 
907e8d04f92SMax Reitz         /* errors are ignored, so we might as well pass exact=true */
908e8d04f92SMax Reitz         bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
9097b8e4857SKevin Wolf                       PREALLOC_MODE_OFF, 0, NULL);
91019f5dc15SDenis V. Lunev     }
91119f5dc15SDenis V. Lunev 
9120d31c7c2SDenis V. Lunev     g_free(s->bat_dirty_bmap);
9139eae9ccaSDenis V. Lunev     qemu_vfree(s->header);
9141d0f37cfSJeff Cody 
9151d0f37cfSJeff Cody     migrate_del_blocker(s->migration_blocker);
9161d0f37cfSJeff Cody     error_free(s->migration_blocker);
917019d6b8fSAnthony Liguori }
918019d6b8fSAnthony Liguori 
919019d6b8fSAnthony Liguori static BlockDriver bdrv_parallels = {
920019d6b8fSAnthony Liguori     .format_name	= "parallels",
921019d6b8fSAnthony Liguori     .instance_size	= sizeof(BDRVParallelsState),
922019d6b8fSAnthony Liguori     .bdrv_probe		= parallels_probe,
9231dec5a70SChristoph Hellwig     .bdrv_open		= parallels_open,
924019d6b8fSAnthony Liguori     .bdrv_close		= parallels_close,
92569dca43dSMax Reitz     .bdrv_child_perm          = bdrv_default_perms,
9268e0cf59dSEric Blake     .bdrv_co_block_status     = parallels_co_block_status,
927d0e61ce5SDenis V. Lunev     .bdrv_has_zero_init       = bdrv_has_zero_init_1,
9280d31c7c2SDenis V. Lunev     .bdrv_co_flush_to_os      = parallels_co_flush_to_os,
929481fb9cfSDenis V. Lunev     .bdrv_co_readv  = parallels_co_readv,
9305a41e1faSDenis V. Lunev     .bdrv_co_writev = parallels_co_writev,
931d67066d8SMax Reitz     .is_format      = true,
932bcbb3866SEdgar Kaziakhmedov     .supports_backing = true,
9331511b490SKevin Wolf     .bdrv_co_create      = parallels_co_create,
934efc75e2aSStefan Hajnoczi     .bdrv_co_create_opts = parallels_co_create_opts,
9352fd61638SPaolo Bonzini     .bdrv_co_check  = parallels_co_check,
93674cf6c50SDenis V. Lunev     .create_opts    = &parallels_create_opts,
937019d6b8fSAnthony Liguori };
938019d6b8fSAnthony Liguori 
939019d6b8fSAnthony Liguori static void bdrv_parallels_init(void)
940019d6b8fSAnthony Liguori {
941019d6b8fSAnthony Liguori     bdrv_register(&bdrv_parallels);
942019d6b8fSAnthony Liguori }
943019d6b8fSAnthony Liguori 
944019d6b8fSAnthony Liguori block_init(bdrv_parallels_init);
945