xref: /qemu/block/parallels.c (revision 1f051dcb)
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"
445df022cfSPeter 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 
bat2sect(BDRVParallelsState * s,uint32_t idx)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 
bat_entry_off(uint32_t idx)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 
seek_to_sector(BDRVParallelsState * s,int64_t sector_num)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 
cluster_remainder(BDRVParallelsState * s,int64_t sector_num,int nb_sectors)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 
host_cluster_index(BDRVParallelsState * s,int64_t off)1396bb8bc63SAlexander Ivanov static uint32_t host_cluster_index(BDRVParallelsState *s, int64_t off)
1406bb8bc63SAlexander Ivanov {
1416bb8bc63SAlexander Ivanov     off -= s->data_start << BDRV_SECTOR_BITS;
1426bb8bc63SAlexander Ivanov     return off / s->cluster_size;
1436bb8bc63SAlexander Ivanov }
1446bb8bc63SAlexander Ivanov 
block_status(BDRVParallelsState * s,int64_t sector_num,int nb_sectors,int * pnum)1456953d920SDenis V. Lunev static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
1466953d920SDenis V. Lunev                             int nb_sectors, int *pnum)
1476953d920SDenis V. Lunev {
1486953d920SDenis V. Lunev     int64_t start_off = -2, prev_end_off = -2;
1496953d920SDenis V. Lunev 
1506953d920SDenis V. Lunev     *pnum = 0;
1516953d920SDenis V. Lunev     while (nb_sectors > 0 || start_off == -2) {
1526953d920SDenis V. Lunev         int64_t offset = seek_to_sector(s, sector_num);
1536953d920SDenis V. Lunev         int to_end;
1546953d920SDenis V. Lunev 
1556953d920SDenis V. Lunev         if (start_off == -2) {
1566953d920SDenis V. Lunev             start_off = offset;
1576953d920SDenis V. Lunev             prev_end_off = offset;
1586953d920SDenis V. Lunev         } else if (offset != prev_end_off) {
1596953d920SDenis V. Lunev             break;
1606953d920SDenis V. Lunev         }
1616953d920SDenis V. Lunev 
1626953d920SDenis V. Lunev         to_end = cluster_remainder(s, sector_num, nb_sectors);
1636953d920SDenis V. Lunev         nb_sectors -= to_end;
1646953d920SDenis V. Lunev         sector_num += to_end;
1656953d920SDenis V. Lunev         *pnum += to_end;
1666953d920SDenis V. Lunev 
1676953d920SDenis V. Lunev         if (offset > 0) {
1686953d920SDenis V. Lunev             prev_end_off += to_end;
1696953d920SDenis V. Lunev         }
1706953d920SDenis V. Lunev     }
1716953d920SDenis V. Lunev     return start_off;
1726953d920SDenis V. Lunev }
1736953d920SDenis V. Lunev 
parallels_set_bat_entry(BDRVParallelsState * s,uint32_t index,uint32_t offset)174b64b29b9SAlexander Ivanov static void parallels_set_bat_entry(BDRVParallelsState *s,
175b64b29b9SAlexander Ivanov                                     uint32_t index, uint32_t offset)
176b64b29b9SAlexander Ivanov {
177b64b29b9SAlexander Ivanov     s->bat_bitmap[index] = cpu_to_le32(offset);
178b64b29b9SAlexander Ivanov     bitmap_set(s->bat_dirty_bmap, bat_entry_off(index) / s->bat_dirty_block, 1);
179b64b29b9SAlexander Ivanov }
180b64b29b9SAlexander Ivanov 
mark_used(BlockDriverState * bs,unsigned long * bitmap,uint32_t bitmap_size,int64_t off,uint32_t count)18173194d3fSDenis V. Lunev static int mark_used(BlockDriverState *bs, unsigned long *bitmap,
18273194d3fSDenis V. Lunev                      uint32_t bitmap_size, int64_t off, uint32_t count)
183a398275eSDenis V. Lunev {
184a398275eSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
185a398275eSDenis V. Lunev     uint32_t cluster_index = host_cluster_index(s, off);
18673194d3fSDenis V. Lunev     unsigned long next_used;
18773194d3fSDenis V. Lunev     if (cluster_index + count > bitmap_size) {
188a398275eSDenis V. Lunev         return -E2BIG;
189a398275eSDenis V. Lunev     }
19073194d3fSDenis V. Lunev     next_used = find_next_bit(bitmap, bitmap_size, cluster_index);
19173194d3fSDenis V. Lunev     if (next_used < cluster_index + count) {
192a398275eSDenis V. Lunev         return -EBUSY;
193a398275eSDenis V. Lunev     }
19473194d3fSDenis V. Lunev     bitmap_set(bitmap, cluster_index, count);
195a398275eSDenis V. Lunev     return 0;
196a398275eSDenis V. Lunev }
197a398275eSDenis V. Lunev 
198e185100fSDenis V. Lunev /*
199e185100fSDenis V. Lunev  * Collect used bitmap. The image can contain errors, we should fill the
200e185100fSDenis V. Lunev  * bitmap anyway, as much as we can. This information will be used for
201e185100fSDenis V. Lunev  * error resolution.
202e185100fSDenis V. Lunev  */
parallels_fill_used_bitmap(BlockDriverState * bs)2031f051dcbSKevin Wolf static int GRAPH_RDLOCK parallels_fill_used_bitmap(BlockDriverState *bs)
204e185100fSDenis V. Lunev {
205e185100fSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
206e185100fSDenis V. Lunev     int64_t payload_bytes;
207e185100fSDenis V. Lunev     uint32_t i;
208e185100fSDenis V. Lunev     int err = 0;
209e185100fSDenis V. Lunev 
210e185100fSDenis V. Lunev     payload_bytes = bdrv_getlength(bs->file->bs);
211e185100fSDenis V. Lunev     if (payload_bytes < 0) {
212e185100fSDenis V. Lunev         return payload_bytes;
213e185100fSDenis V. Lunev     }
214e185100fSDenis V. Lunev     payload_bytes -= s->data_start * BDRV_SECTOR_SIZE;
215e185100fSDenis V. Lunev     if (payload_bytes < 0) {
216e185100fSDenis V. Lunev         return -EINVAL;
217e185100fSDenis V. Lunev     }
218e185100fSDenis V. Lunev 
219e185100fSDenis V. Lunev     s->used_bmap_size = DIV_ROUND_UP(payload_bytes, s->cluster_size);
220e185100fSDenis V. Lunev     if (s->used_bmap_size == 0) {
221e185100fSDenis V. Lunev         return 0;
222e185100fSDenis V. Lunev     }
223e185100fSDenis V. Lunev     s->used_bmap = bitmap_try_new(s->used_bmap_size);
224e185100fSDenis V. Lunev     if (s->used_bmap == NULL) {
225e185100fSDenis V. Lunev         return -ENOMEM;
226e185100fSDenis V. Lunev     }
227e185100fSDenis V. Lunev 
228e185100fSDenis V. Lunev     for (i = 0; i < s->bat_size; i++) {
229e185100fSDenis V. Lunev         int err2;
230e185100fSDenis V. Lunev         int64_t host_off = bat2sect(s, i) << BDRV_SECTOR_BITS;
231e185100fSDenis V. Lunev         if (host_off == 0) {
232e185100fSDenis V. Lunev             continue;
233e185100fSDenis V. Lunev         }
234e185100fSDenis V. Lunev 
23573194d3fSDenis V. Lunev         err2 = mark_used(bs, s->used_bmap, s->used_bmap_size, host_off, 1);
236e185100fSDenis V. Lunev         if (err2 < 0 && err == 0) {
237e185100fSDenis V. Lunev             err = err2;
238e185100fSDenis V. Lunev         }
239e185100fSDenis V. Lunev     }
240e185100fSDenis V. Lunev     return err;
241e185100fSDenis V. Lunev }
242e185100fSDenis V. Lunev 
parallels_free_used_bitmap(BlockDriverState * bs)243e185100fSDenis V. Lunev static void parallels_free_used_bitmap(BlockDriverState *bs)
244e185100fSDenis V. Lunev {
245e185100fSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
246e185100fSDenis V. Lunev     s->used_bmap_size = 0;
247e185100fSDenis V. Lunev     g_free(s->used_bmap);
248e185100fSDenis V. Lunev }
249e185100fSDenis V. Lunev 
250c2b8e315SKevin Wolf static int64_t coroutine_fn GRAPH_RDLOCK
allocate_clusters(BlockDriverState * bs,int64_t sector_num,int nb_sectors,int * pnum)251c2b8e315SKevin Wolf allocate_clusters(BlockDriverState *bs, int64_t sector_num,
252ddd2ef2cSDenis V. Lunev                   int nb_sectors, int *pnum)
2535a41e1faSDenis V. Lunev {
254bda4cdcbSEric Blake     int ret = 0;
2555a41e1faSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
2563ac10d19SDenis V. Lunev     int64_t i, pos, idx, to_allocate, first_free, host_off;
257ddd2ef2cSDenis V. Lunev 
258ddd2ef2cSDenis V. Lunev     pos = block_status(s, sector_num, nb_sectors, pnum);
259ddd2ef2cSDenis V. Lunev     if (pos > 0) {
260ddd2ef2cSDenis V. Lunev         return pos;
261ddd2ef2cSDenis V. Lunev     }
2625a41e1faSDenis V. Lunev 
2635a41e1faSDenis V. Lunev     idx = sector_num / s->tracks;
264969401feSLaurent Vivier     to_allocate = DIV_ROUND_UP(sector_num + *pnum, s->tracks) - idx;
26586d1bd70SMax Reitz 
266a338dcbbSAlexander Ivanov     /*
267a338dcbbSAlexander Ivanov      * This function is called only by parallels_co_writev(), which will never
26886d1bd70SMax Reitz      * pass a sector_num at or beyond the end of the image (because the block
26986d1bd70SMax Reitz      * layer never passes such a sector_num to that function). Therefore, idx
27086d1bd70SMax Reitz      * is always below s->bat_size.
27186d1bd70SMax Reitz      * block_status() will limit *pnum so that sector_num + *pnum will not
27286d1bd70SMax Reitz      * exceed the image end. Therefore, idx + to_allocate cannot exceed
27386d1bd70SMax Reitz      * s->bat_size.
27486d1bd70SMax Reitz      * Note that s->bat_size is an unsigned int, therefore idx + to_allocate
275a338dcbbSAlexander Ivanov      * will always fit into a uint32_t.
276a338dcbbSAlexander Ivanov      */
27786d1bd70SMax Reitz     assert(idx < s->bat_size && idx + to_allocate <= s->bat_size);
27886d1bd70SMax Reitz 
2793ac10d19SDenis V. Lunev     first_free = find_first_zero_bit(s->used_bmap, s->used_bmap_size);
2803ac10d19SDenis V. Lunev     if (first_free == s->used_bmap_size) {
281eeb1e6dcSDenis V. Lunev         uint32_t new_usedsize;
28266d201ddSDenis V. Lunev         int64_t bytes = to_allocate * s->cluster_size;
28366d201ddSDenis V. Lunev         bytes += s->prealloc_size * BDRV_SECTOR_SIZE;
284eeb1e6dcSDenis V. Lunev 
2853ac10d19SDenis V. Lunev         host_off = s->data_end * BDRV_SECTOR_SIZE;
2863ac10d19SDenis V. Lunev 
287bda4cdcbSEric Blake         /*
288bda4cdcbSEric Blake          * We require the expanded size to read back as zero. If the
289bda4cdcbSEric Blake          * user permitted truncation, we try that; but if it fails, we
290bda4cdcbSEric Blake          * force the safer-but-slower fallocate.
291bda4cdcbSEric Blake          */
292bda4cdcbSEric Blake         if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
29366d201ddSDenis V. Lunev             ret = bdrv_co_truncate(bs->file, host_off + bytes,
29450688be0SAlberto Faria                                    false, PREALLOC_MODE_OFF,
29550688be0SAlberto Faria                                    BDRV_REQ_ZERO_WRITE, NULL);
296bda4cdcbSEric Blake             if (ret == -ENOTSUP) {
297bda4cdcbSEric Blake                 s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
298bda4cdcbSEric Blake             }
299bda4cdcbSEric Blake         }
30019f5dc15SDenis V. Lunev         if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
30166d201ddSDenis V. Lunev             ret = bdrv_co_pwrite_zeroes(bs->file, host_off, bytes, 0);
3025a41e1faSDenis V. Lunev         }
3035a41e1faSDenis V. Lunev         if (ret < 0) {
3045a41e1faSDenis V. Lunev             return ret;
3055a41e1faSDenis V. Lunev         }
306eeb1e6dcSDenis V. Lunev 
30766d201ddSDenis V. Lunev         new_usedsize = s->used_bmap_size + bytes / s->cluster_size;
308eeb1e6dcSDenis V. Lunev         s->used_bmap = bitmap_zero_extend(s->used_bmap, s->used_bmap_size,
309eeb1e6dcSDenis V. Lunev                                           new_usedsize);
310eeb1e6dcSDenis V. Lunev         s->used_bmap_size = new_usedsize;
3113ac10d19SDenis V. Lunev     } else {
3123ac10d19SDenis V. Lunev         int64_t next_used;
3133ac10d19SDenis V. Lunev         next_used = find_next_bit(s->used_bmap, s->used_bmap_size, first_free);
3143ac10d19SDenis V. Lunev 
3153ac10d19SDenis V. Lunev         /* Not enough continuous clusters in the middle, adjust the size */
3163ac10d19SDenis V. Lunev         if (next_used - first_free < to_allocate) {
3173ac10d19SDenis V. Lunev             to_allocate = next_used - first_free;
3183ac10d19SDenis V. Lunev             *pnum = (idx + to_allocate) * s->tracks - sector_num;
3193ac10d19SDenis V. Lunev         }
3203ac10d19SDenis V. Lunev 
3213ac10d19SDenis V. Lunev         host_off = s->data_start * BDRV_SECTOR_SIZE;
3223ac10d19SDenis V. Lunev         host_off += first_free * s->cluster_size;
3233ac10d19SDenis V. Lunev 
3243ac10d19SDenis V. Lunev         /*
3253ac10d19SDenis V. Lunev          * No need to preallocate if we are using tail area from the above
3263ac10d19SDenis V. Lunev          * branch. In the other case we are likely re-using hole. Preallocate
3273ac10d19SDenis V. Lunev          * the space if required by the prealloc_mode.
3283ac10d19SDenis V. Lunev          */
3293ac10d19SDenis V. Lunev         if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE &&
3303ac10d19SDenis V. Lunev                 host_off < s->data_end * BDRV_SECTOR_SIZE) {
3313ac10d19SDenis V. Lunev             ret = bdrv_co_pwrite_zeroes(bs->file, host_off,
3323ac10d19SDenis V. Lunev                                         s->cluster_size * to_allocate, 0);
3333ac10d19SDenis V. Lunev             if (ret < 0) {
3343ac10d19SDenis V. Lunev                 return ret;
3353ac10d19SDenis V. Lunev             }
3363ac10d19SDenis V. Lunev         }
33719f5dc15SDenis V. Lunev     }
338ddd2ef2cSDenis V. Lunev 
339a338dcbbSAlexander Ivanov     /*
340a338dcbbSAlexander Ivanov      * Try to read from backing to fill empty clusters
341bcbb3866SEdgar Kaziakhmedov      * FIXME: 1. previous write_zeroes may be redundant
342bcbb3866SEdgar Kaziakhmedov      *        2. most of data we read from backing will be rewritten by
343bcbb3866SEdgar Kaziakhmedov      *           parallels_co_writev. On aligned-to-cluster write we do not need
344bcbb3866SEdgar Kaziakhmedov      *           this read at all.
345bcbb3866SEdgar Kaziakhmedov      *        3. it would be good to combine write of data from backing and new
346a338dcbbSAlexander Ivanov      *           data into one write call.
347a338dcbbSAlexander Ivanov      */
348bcbb3866SEdgar Kaziakhmedov     if (bs->backing) {
349bcbb3866SEdgar Kaziakhmedov         int64_t nb_cow_sectors = to_allocate * s->tracks;
350bcbb3866SEdgar Kaziakhmedov         int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
351a4072543SVladimir Sementsov-Ogievskiy         void *buf = qemu_blockalign(bs, nb_cow_bytes);
352bcbb3866SEdgar Kaziakhmedov 
353a4072543SVladimir Sementsov-Ogievskiy         ret = bdrv_co_pread(bs->backing, idx * s->tracks * BDRV_SECTOR_SIZE,
354a4072543SVladimir Sementsov-Ogievskiy                             nb_cow_bytes, buf, 0);
355bcbb3866SEdgar Kaziakhmedov         if (ret < 0) {
356a4072543SVladimir Sementsov-Ogievskiy             qemu_vfree(buf);
357bcbb3866SEdgar Kaziakhmedov             return ret;
358bcbb3866SEdgar Kaziakhmedov         }
359bcbb3866SEdgar Kaziakhmedov 
360eba088f9SHanna Reitz         ret = bdrv_co_pwrite(bs->file, s->data_end * BDRV_SECTOR_SIZE,
361a4072543SVladimir Sementsov-Ogievskiy                              nb_cow_bytes, buf, 0);
362a4072543SVladimir Sementsov-Ogievskiy         qemu_vfree(buf);
363bcbb3866SEdgar Kaziakhmedov         if (ret < 0) {
364bcbb3866SEdgar Kaziakhmedov             return ret;
365bcbb3866SEdgar Kaziakhmedov         }
366bcbb3866SEdgar Kaziakhmedov     }
367bcbb3866SEdgar Kaziakhmedov 
3683ac10d19SDenis V. Lunev     ret = mark_used(bs, s->used_bmap, s->used_bmap_size, host_off, to_allocate);
369eeb1e6dcSDenis V. Lunev     if (ret < 0) {
370eeb1e6dcSDenis V. Lunev         /* Image consistency is broken. Alarm! */
371eeb1e6dcSDenis V. Lunev         return ret;
372eeb1e6dcSDenis V. Lunev     }
373ddd2ef2cSDenis V. Lunev     for (i = 0; i < to_allocate; i++) {
3743ac10d19SDenis V. Lunev         parallels_set_bat_entry(s, idx + i,
3753ac10d19SDenis V. Lunev                 host_off / BDRV_SECTOR_SIZE / s->off_multiplier);
3763ac10d19SDenis V. Lunev         host_off += s->cluster_size;
3773ac10d19SDenis V. Lunev     }
3783ac10d19SDenis V. Lunev     if (host_off > s->data_end * BDRV_SECTOR_SIZE) {
3793ac10d19SDenis V. Lunev         s->data_end = host_off / BDRV_SECTOR_SIZE;
380ddd2ef2cSDenis V. Lunev     }
3815a41e1faSDenis V. Lunev 
382ddd2ef2cSDenis V. Lunev     return bat2sect(s, idx) + sector_num % s->tracks;
3835a41e1faSDenis V. Lunev }
3845a41e1faSDenis V. Lunev 
3850d31c7c2SDenis V. Lunev 
386b9b10c35SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
parallels_co_flush_to_os(BlockDriverState * bs)387b9b10c35SKevin Wolf parallels_co_flush_to_os(BlockDriverState *bs)
3880d31c7c2SDenis V. Lunev {
3890d31c7c2SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
3900d31c7c2SDenis V. Lunev     unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
3910d31c7c2SDenis V. Lunev     unsigned long bit;
3920d31c7c2SDenis V. Lunev 
3930d31c7c2SDenis V. Lunev     qemu_co_mutex_lock(&s->lock);
3940d31c7c2SDenis V. Lunev 
3950d31c7c2SDenis V. Lunev     bit = find_first_bit(s->bat_dirty_bmap, size);
3960d31c7c2SDenis V. Lunev     while (bit < size) {
3970d31c7c2SDenis V. Lunev         uint32_t off = bit * s->bat_dirty_block;
3980d31c7c2SDenis V. Lunev         uint32_t to_write = s->bat_dirty_block;
3990d31c7c2SDenis V. Lunev         int ret;
4000d31c7c2SDenis V. Lunev 
4010d31c7c2SDenis V. Lunev         if (off + to_write > s->header_size) {
4020d31c7c2SDenis V. Lunev             to_write = s->header_size - off;
4030d31c7c2SDenis V. Lunev         }
40450688be0SAlberto Faria         ret = bdrv_co_pwrite(bs->file, off, to_write,
40550688be0SAlberto Faria                              (uint8_t *)s->header + off, 0);
4060d31c7c2SDenis V. Lunev         if (ret < 0) {
4070d31c7c2SDenis V. Lunev             qemu_co_mutex_unlock(&s->lock);
4080d31c7c2SDenis V. Lunev             return ret;
4090d31c7c2SDenis V. Lunev         }
4100d31c7c2SDenis V. Lunev         bit = find_next_bit(s->bat_dirty_bmap, size, bit + 1);
4110d31c7c2SDenis V. Lunev     }
4120d31c7c2SDenis V. Lunev     bitmap_zero(s->bat_dirty_bmap, size);
4130d31c7c2SDenis V. Lunev 
4140d31c7c2SDenis V. Lunev     qemu_co_mutex_unlock(&s->lock);
4150d31c7c2SDenis V. Lunev     return 0;
4160d31c7c2SDenis V. Lunev }
4170d31c7c2SDenis V. Lunev 
41879a55866SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
parallels_co_block_status(BlockDriverState * bs,bool want_zero,int64_t offset,int64_t bytes,int64_t * pnum,int64_t * map,BlockDriverState ** file)41979a55866SKevin Wolf parallels_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
42079a55866SKevin Wolf                           int64_t bytes, int64_t *pnum, int64_t *map,
4218e0cf59dSEric Blake                           BlockDriverState **file)
422dd3bed16SRoman Kagan {
423dd3bed16SRoman Kagan     BDRVParallelsState *s = bs->opaque;
4248e0cf59dSEric Blake     int count;
425dd3bed16SRoman Kagan 
4268e0cf59dSEric Blake     assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
427dd3bed16SRoman Kagan     qemu_co_mutex_lock(&s->lock);
4288e0cf59dSEric Blake     offset = block_status(s, offset >> BDRV_SECTOR_BITS,
4298e0cf59dSEric Blake                           bytes >> BDRV_SECTOR_BITS, &count);
430dd3bed16SRoman Kagan     qemu_co_mutex_unlock(&s->lock);
431dd3bed16SRoman Kagan 
4328e0cf59dSEric Blake     *pnum = count * BDRV_SECTOR_SIZE;
433dd3bed16SRoman Kagan     if (offset < 0) {
434dd3bed16SRoman Kagan         return 0;
435dd3bed16SRoman Kagan     }
436dd3bed16SRoman Kagan 
4378e0cf59dSEric Blake     *map = offset * BDRV_SECTOR_SIZE;
438ddf4987dSFam Zheng     *file = bs->file->bs;
4398e0cf59dSEric Blake     return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
440dd3bed16SRoman Kagan }
441dd3bed16SRoman Kagan 
4427b1fb72eSKevin Wolf static int coroutine_fn GRAPH_RDLOCK
parallels_co_writev(BlockDriverState * bs,int64_t sector_num,int nb_sectors,QEMUIOVector * qiov,int flags)4437b1fb72eSKevin Wolf parallels_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
444e18a58b4SEric Blake                     QEMUIOVector *qiov, int flags)
4455a41e1faSDenis V. Lunev {
4465a41e1faSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
4475a41e1faSDenis V. Lunev     uint64_t bytes_done = 0;
4485a41e1faSDenis V. Lunev     QEMUIOVector hd_qiov;
4495a41e1faSDenis V. Lunev     int ret = 0;
4505a41e1faSDenis V. Lunev 
4515a41e1faSDenis V. Lunev     qemu_iovec_init(&hd_qiov, qiov->niov);
4525a41e1faSDenis V. Lunev 
4535a41e1faSDenis V. Lunev     while (nb_sectors > 0) {
4545a41e1faSDenis V. Lunev         int64_t position;
4555a41e1faSDenis V. Lunev         int n, nbytes;
4565a41e1faSDenis V. Lunev 
4575a41e1faSDenis V. Lunev         qemu_co_mutex_lock(&s->lock);
458ddd2ef2cSDenis V. Lunev         position = allocate_clusters(bs, sector_num, nb_sectors, &n);
4595a41e1faSDenis V. Lunev         qemu_co_mutex_unlock(&s->lock);
4605a41e1faSDenis V. Lunev         if (position < 0) {
4615a41e1faSDenis V. Lunev             ret = (int)position;
4625a41e1faSDenis V. Lunev             break;
4635a41e1faSDenis V. Lunev         }
4645a41e1faSDenis V. Lunev 
4655a41e1faSDenis V. Lunev         nbytes = n << BDRV_SECTOR_BITS;
4665a41e1faSDenis V. Lunev 
4675a41e1faSDenis V. Lunev         qemu_iovec_reset(&hd_qiov);
4685a41e1faSDenis V. Lunev         qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
4695a41e1faSDenis V. Lunev 
470d08c2a24SEric Blake         ret = bdrv_co_pwritev(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
471d08c2a24SEric Blake                               &hd_qiov, 0);
4725a41e1faSDenis V. Lunev         if (ret < 0) {
4735a41e1faSDenis V. Lunev             break;
4745a41e1faSDenis V. Lunev         }
4755a41e1faSDenis V. Lunev 
4765a41e1faSDenis V. Lunev         nb_sectors -= n;
4775a41e1faSDenis V. Lunev         sector_num += n;
4785a41e1faSDenis V. Lunev         bytes_done += nbytes;
4795a41e1faSDenis V. Lunev     }
4805a41e1faSDenis V. Lunev 
4815a41e1faSDenis V. Lunev     qemu_iovec_destroy(&hd_qiov);
4825a41e1faSDenis V. Lunev     return ret;
4835a41e1faSDenis V. Lunev }
4845a41e1faSDenis V. Lunev 
485b9b10c35SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
parallels_co_readv(BlockDriverState * bs,int64_t sector_num,int nb_sectors,QEMUIOVector * qiov)486b9b10c35SKevin Wolf parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
487b9b10c35SKevin Wolf                    QEMUIOVector *qiov)
488019d6b8fSAnthony Liguori {
48929442569SRoman Kagan     BDRVParallelsState *s = bs->opaque;
490481fb9cfSDenis V. Lunev     uint64_t bytes_done = 0;
491481fb9cfSDenis V. Lunev     QEMUIOVector hd_qiov;
492481fb9cfSDenis V. Lunev     int ret = 0;
493481fb9cfSDenis V. Lunev 
494481fb9cfSDenis V. Lunev     qemu_iovec_init(&hd_qiov, qiov->niov);
49529442569SRoman Kagan 
496019d6b8fSAnthony Liguori     while (nb_sectors > 0) {
497481fb9cfSDenis V. Lunev         int64_t position;
498481fb9cfSDenis V. Lunev         int n, nbytes;
499481fb9cfSDenis V. Lunev 
500481fb9cfSDenis V. Lunev         qemu_co_mutex_lock(&s->lock);
5016953d920SDenis V. Lunev         position = block_status(s, sector_num, nb_sectors, &n);
502481fb9cfSDenis V. Lunev         qemu_co_mutex_unlock(&s->lock);
503481fb9cfSDenis V. Lunev 
504481fb9cfSDenis V. Lunev         nbytes = n << BDRV_SECTOR_BITS;
505481fb9cfSDenis V. Lunev 
506481fb9cfSDenis V. Lunev         qemu_iovec_reset(&hd_qiov);
507481fb9cfSDenis V. Lunev         qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
508481fb9cfSDenis V. Lunev 
509bcbb3866SEdgar Kaziakhmedov         if (position < 0) {
510bcbb3866SEdgar Kaziakhmedov             if (bs->backing) {
511d08c2a24SEric Blake                 ret = bdrv_co_preadv(bs->backing, sector_num * BDRV_SECTOR_SIZE,
512d08c2a24SEric Blake                                      nbytes, &hd_qiov, 0);
513bcbb3866SEdgar Kaziakhmedov                 if (ret < 0) {
514bcbb3866SEdgar Kaziakhmedov                     break;
515bcbb3866SEdgar Kaziakhmedov                 }
516bcbb3866SEdgar Kaziakhmedov             } else {
517bcbb3866SEdgar Kaziakhmedov                 qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
518bcbb3866SEdgar Kaziakhmedov             }
519bcbb3866SEdgar Kaziakhmedov         } else {
520d08c2a24SEric Blake             ret = bdrv_co_preadv(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
521d08c2a24SEric Blake                                  &hd_qiov, 0);
522481fb9cfSDenis V. Lunev             if (ret < 0) {
523481fb9cfSDenis V. Lunev                 break;
5249d8b88f6SChristoph Hellwig             }
525019d6b8fSAnthony Liguori         }
526019d6b8fSAnthony Liguori 
527481fb9cfSDenis V. Lunev         nb_sectors -= n;
528481fb9cfSDenis V. Lunev         sector_num += n;
529481fb9cfSDenis V. Lunev         bytes_done += nbytes;
530481fb9cfSDenis V. Lunev     }
531481fb9cfSDenis V. Lunev 
532481fb9cfSDenis V. Lunev     qemu_iovec_destroy(&hd_qiov);
5332914caa0SPaolo Bonzini     return ret;
5342914caa0SPaolo Bonzini }
5352914caa0SPaolo Bonzini 
536c54fb435SDenis V. Lunev 
537c54fb435SDenis V. Lunev static int coroutine_fn GRAPH_RDLOCK
parallels_co_pdiscard(BlockDriverState * bs,int64_t offset,int64_t bytes)538c54fb435SDenis V. Lunev parallels_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
539c54fb435SDenis V. Lunev {
540c54fb435SDenis V. Lunev     int ret = 0;
541c54fb435SDenis V. Lunev     uint32_t cluster, count;
542c54fb435SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
543c54fb435SDenis V. Lunev 
544c54fb435SDenis V. Lunev     /*
545c54fb435SDenis V. Lunev      * The image does not support ZERO mark inside the BAT, which means that
546c54fb435SDenis V. Lunev      * stale data could be exposed from the backing file.
547c54fb435SDenis V. Lunev      */
548c54fb435SDenis V. Lunev     if (bs->backing) {
549c54fb435SDenis V. Lunev         return -ENOTSUP;
550c54fb435SDenis V. Lunev     }
551c54fb435SDenis V. Lunev 
552c54fb435SDenis V. Lunev     if (!QEMU_IS_ALIGNED(offset, s->cluster_size)) {
553c54fb435SDenis V. Lunev         return -ENOTSUP;
554c54fb435SDenis V. Lunev     } else if (!QEMU_IS_ALIGNED(bytes, s->cluster_size)) {
555c54fb435SDenis V. Lunev         return -ENOTSUP;
556c54fb435SDenis V. Lunev     }
557c54fb435SDenis V. Lunev 
558c54fb435SDenis V. Lunev     cluster = offset / s->cluster_size;
559c54fb435SDenis V. Lunev     count = bytes / s->cluster_size;
560c54fb435SDenis V. Lunev 
561c54fb435SDenis V. Lunev     qemu_co_mutex_lock(&s->lock);
562c54fb435SDenis V. Lunev     for (; count > 0; cluster++, count--) {
563c54fb435SDenis V. Lunev         int64_t host_off = bat2sect(s, cluster) << BDRV_SECTOR_BITS;
564c54fb435SDenis V. Lunev         if (host_off == 0) {
565c54fb435SDenis V. Lunev             continue;
566c54fb435SDenis V. Lunev         }
567c54fb435SDenis V. Lunev 
568c54fb435SDenis V. Lunev         ret = bdrv_co_pdiscard(bs->file, host_off, s->cluster_size);
569c54fb435SDenis V. Lunev         if (ret < 0) {
570c54fb435SDenis V. Lunev             goto done;
571c54fb435SDenis V. Lunev         }
572c54fb435SDenis V. Lunev 
573c54fb435SDenis V. Lunev         parallels_set_bat_entry(s, cluster, 0);
574c54fb435SDenis V. Lunev         bitmap_clear(s->used_bmap, host_cluster_index(s, host_off), 1);
575c54fb435SDenis V. Lunev     }
576c54fb435SDenis V. Lunev done:
577c54fb435SDenis V. Lunev     qemu_co_mutex_unlock(&s->lock);
578c54fb435SDenis V. Lunev     return ret;
579c54fb435SDenis V. Lunev }
580c54fb435SDenis V. Lunev 
581a98b260aSDenis V. Lunev static int coroutine_fn GRAPH_RDLOCK
parallels_co_pwrite_zeroes(BlockDriverState * bs,int64_t offset,int64_t bytes,BdrvRequestFlags flags)582a98b260aSDenis V. Lunev parallels_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
583a98b260aSDenis V. Lunev                            BdrvRequestFlags flags)
584a98b260aSDenis V. Lunev {
585a98b260aSDenis V. Lunev     /*
586a98b260aSDenis V. Lunev      * The zero flag is missed in the Parallels format specification. We can
587a98b260aSDenis V. Lunev      * resort to discard if we have no backing file (this condition is checked
588a98b260aSDenis V. Lunev      * inside parallels_co_pdiscard().
589a98b260aSDenis V. Lunev      */
590a98b260aSDenis V. Lunev     return parallels_co_pdiscard(bs, offset, bytes);
591a98b260aSDenis V. Lunev }
592a98b260aSDenis V. Lunev 
593a98b260aSDenis V. Lunev 
parallels_check_unclean(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix)59496de69c7SAlexander Ivanov static void parallels_check_unclean(BlockDriverState *bs,
59596de69c7SAlexander Ivanov                                     BdrvCheckResult *res,
59696de69c7SAlexander Ivanov                                     BdrvCheckMode fix)
59796de69c7SAlexander Ivanov {
59896de69c7SAlexander Ivanov     BDRVParallelsState *s = bs->opaque;
59996de69c7SAlexander Ivanov 
60096de69c7SAlexander Ivanov     if (!s->header_unclean) {
60196de69c7SAlexander Ivanov         return;
60296de69c7SAlexander Ivanov     }
60396de69c7SAlexander Ivanov 
60496de69c7SAlexander Ivanov     fprintf(stderr, "%s image was not closed correctly\n",
60596de69c7SAlexander Ivanov             fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
60696de69c7SAlexander Ivanov     res->corruptions++;
60796de69c7SAlexander Ivanov     if (fix & BDRV_FIX_ERRORS) {
60896de69c7SAlexander Ivanov         /* parallels_close will do the job right */
60996de69c7SAlexander Ivanov         res->corruptions_fixed++;
61096de69c7SAlexander Ivanov         s->header_unclean = false;
61196de69c7SAlexander Ivanov     }
61296de69c7SAlexander Ivanov }
61349ad6467SDenis V. Lunev 
6148cd19203SAlexander Ivanov /*
6158cd19203SAlexander Ivanov  * Returns true if data_off is correct, otherwise false. In both cases
6168cd19203SAlexander Ivanov  * correct_offset is set to the proper value.
6178cd19203SAlexander Ivanov  */
parallels_test_data_off(BDRVParallelsState * s,int64_t file_nb_sectors,uint32_t * correct_offset)6188cd19203SAlexander Ivanov static bool parallels_test_data_off(BDRVParallelsState *s,
6198cd19203SAlexander Ivanov                                     int64_t file_nb_sectors,
6208cd19203SAlexander Ivanov                                     uint32_t *correct_offset)
6218cd19203SAlexander Ivanov {
6228cd19203SAlexander Ivanov     uint32_t data_off, min_off;
6238cd19203SAlexander Ivanov     bool old_magic;
6248cd19203SAlexander Ivanov 
6258cd19203SAlexander Ivanov     /*
6268cd19203SAlexander Ivanov      * There are two slightly different image formats: with "WithoutFreeSpace"
6278cd19203SAlexander Ivanov      * or "WithouFreSpacExt" magic words. Call the first one as "old magic".
6288cd19203SAlexander Ivanov      * In such images data_off field can be zero. In this case the offset is
6298cd19203SAlexander Ivanov      * calculated as the end of BAT table plus some padding to ensure sector
6308cd19203SAlexander Ivanov      * size alignment.
6318cd19203SAlexander Ivanov      */
6328cd19203SAlexander Ivanov     old_magic = !memcmp(s->header->magic, HEADER_MAGIC, 16);
6338cd19203SAlexander Ivanov 
6348cd19203SAlexander Ivanov     min_off = DIV_ROUND_UP(bat_entry_off(s->bat_size), BDRV_SECTOR_SIZE);
6358cd19203SAlexander Ivanov     if (!old_magic) {
6368cd19203SAlexander Ivanov         min_off = ROUND_UP(min_off, s->cluster_size / BDRV_SECTOR_SIZE);
6378cd19203SAlexander Ivanov     }
6388cd19203SAlexander Ivanov 
6398cd19203SAlexander Ivanov     if (correct_offset) {
6408cd19203SAlexander Ivanov         *correct_offset = min_off;
6418cd19203SAlexander Ivanov     }
6428cd19203SAlexander Ivanov 
6438cd19203SAlexander Ivanov     data_off = le32_to_cpu(s->header->data_off);
6448cd19203SAlexander Ivanov     if (data_off == 0 && old_magic) {
6458cd19203SAlexander Ivanov         return true;
6468cd19203SAlexander Ivanov     }
6478cd19203SAlexander Ivanov 
6488cd19203SAlexander Ivanov     if (data_off < min_off || data_off > file_nb_sectors) {
6498cd19203SAlexander Ivanov         return false;
6508cd19203SAlexander Ivanov     }
6518cd19203SAlexander Ivanov 
6528cd19203SAlexander Ivanov     if (correct_offset) {
6538cd19203SAlexander Ivanov         *correct_offset = data_off;
6548cd19203SAlexander Ivanov     }
6558cd19203SAlexander Ivanov 
6568cd19203SAlexander Ivanov     return true;
6578cd19203SAlexander Ivanov }
6588cd19203SAlexander Ivanov 
6598cd19203SAlexander Ivanov static int coroutine_fn GRAPH_RDLOCK
parallels_check_data_off(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix)6608cd19203SAlexander Ivanov parallels_check_data_off(BlockDriverState *bs, BdrvCheckResult *res,
6618cd19203SAlexander Ivanov                          BdrvCheckMode fix)
6628cd19203SAlexander Ivanov {
6638cd19203SAlexander Ivanov     BDRVParallelsState *s = bs->opaque;
6648cd19203SAlexander Ivanov     int64_t file_size;
6658cd19203SAlexander Ivanov     uint32_t data_off;
6668cd19203SAlexander Ivanov 
6678cd19203SAlexander Ivanov     file_size = bdrv_co_nb_sectors(bs->file->bs);
6688cd19203SAlexander Ivanov     if (file_size < 0) {
6698cd19203SAlexander Ivanov         res->check_errors++;
6708cd19203SAlexander Ivanov         return file_size;
6718cd19203SAlexander Ivanov     }
6728cd19203SAlexander Ivanov 
6738cd19203SAlexander Ivanov     if (parallels_test_data_off(s, file_size, &data_off)) {
6748cd19203SAlexander Ivanov         return 0;
6758cd19203SAlexander Ivanov     }
6768cd19203SAlexander Ivanov 
6778cd19203SAlexander Ivanov     res->corruptions++;
6788cd19203SAlexander Ivanov     if (fix & BDRV_FIX_ERRORS) {
679e185100fSDenis V. Lunev         int err;
6808cd19203SAlexander Ivanov         s->header->data_off = cpu_to_le32(data_off);
6816f2206b0SDenis V. Lunev         s->data_start = data_off;
682e185100fSDenis V. Lunev 
683e185100fSDenis V. Lunev         parallels_free_used_bitmap(bs);
684e185100fSDenis V. Lunev         err = parallels_fill_used_bitmap(bs);
685e185100fSDenis V. Lunev         if (err == -ENOMEM) {
686e185100fSDenis V. Lunev             res->check_errors++;
687e185100fSDenis V. Lunev             return err;
688e185100fSDenis V. Lunev         }
689e185100fSDenis V. Lunev 
6908cd19203SAlexander Ivanov         res->corruptions_fixed++;
6918cd19203SAlexander Ivanov     }
6928cd19203SAlexander Ivanov 
6938cd19203SAlexander Ivanov     fprintf(stderr, "%s data_off field has incorrect value\n",
6948cd19203SAlexander Ivanov             fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
6958cd19203SAlexander Ivanov 
6968cd19203SAlexander Ivanov     return 0;
6978cd19203SAlexander Ivanov }
6988cd19203SAlexander Ivanov 
699c2b8e315SKevin Wolf static int coroutine_fn GRAPH_RDLOCK
parallels_check_outside_image(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix)7006d416e56SAlexander Ivanov parallels_check_outside_image(BlockDriverState *bs, BdrvCheckResult *res,
7016d416e56SAlexander Ivanov                               BdrvCheckMode fix)
7026d416e56SAlexander Ivanov {
7036d416e56SAlexander Ivanov     BDRVParallelsState *s = bs->opaque;
7046d416e56SAlexander Ivanov     uint32_t i;
7056d416e56SAlexander Ivanov     int64_t off, high_off, size;
7066d416e56SAlexander Ivanov 
7070af02bd1SPaolo Bonzini     size = bdrv_co_getlength(bs->file->bs);
7086d416e56SAlexander Ivanov     if (size < 0) {
7096d416e56SAlexander Ivanov         res->check_errors++;
7106d416e56SAlexander Ivanov         return size;
7116d416e56SAlexander Ivanov     }
7126d416e56SAlexander Ivanov 
7136d416e56SAlexander Ivanov     high_off = 0;
7146d416e56SAlexander Ivanov     for (i = 0; i < s->bat_size; i++) {
7156d416e56SAlexander Ivanov         off = bat2sect(s, i) << BDRV_SECTOR_BITS;
716029136f2SAlexander Ivanov         if (off + s->cluster_size > size) {
7176d416e56SAlexander Ivanov             fprintf(stderr, "%s cluster %u is outside image\n",
7186d416e56SAlexander Ivanov                     fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
7196d416e56SAlexander Ivanov             res->corruptions++;
7206d416e56SAlexander Ivanov             if (fix & BDRV_FIX_ERRORS) {
7216d416e56SAlexander Ivanov                 parallels_set_bat_entry(s, i, 0);
7226d416e56SAlexander Ivanov                 res->corruptions_fixed++;
7236d416e56SAlexander Ivanov             }
7246d416e56SAlexander Ivanov             continue;
7256d416e56SAlexander Ivanov         }
7266d416e56SAlexander Ivanov         if (high_off < off) {
7276d416e56SAlexander Ivanov             high_off = off;
7286d416e56SAlexander Ivanov         }
7296d416e56SAlexander Ivanov     }
7306d416e56SAlexander Ivanov 
7316d416e56SAlexander Ivanov     if (high_off == 0) {
7326d416e56SAlexander Ivanov         res->image_end_offset = s->data_end << BDRV_SECTOR_BITS;
7336d416e56SAlexander Ivanov     } else {
7346d416e56SAlexander Ivanov         res->image_end_offset = high_off + s->cluster_size;
7356d416e56SAlexander Ivanov         s->data_end = res->image_end_offset >> BDRV_SECTOR_BITS;
7366d416e56SAlexander Ivanov     }
7376d416e56SAlexander Ivanov 
7386d416e56SAlexander Ivanov     return 0;
7396d416e56SAlexander Ivanov }
7406d416e56SAlexander Ivanov 
7416d416e56SAlexander Ivanov static int coroutine_fn GRAPH_RDLOCK
parallels_check_leak(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix,bool explicit)74209a21edfSAlexander Ivanov parallels_check_leak(BlockDriverState *bs, BdrvCheckResult *res,
743728e1017SAlexander Ivanov                      BdrvCheckMode fix, bool explicit)
74449ad6467SDenis V. Lunev {
74549ad6467SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
74609a21edfSAlexander Ivanov     int64_t size;
7476d416e56SAlexander Ivanov     int ret;
74849ad6467SDenis V. Lunev 
7497c5f86d5SAlexander Ivanov     size = bdrv_co_getlength(bs->file->bs);
75049ad6467SDenis V. Lunev     if (size < 0) {
75149ad6467SDenis V. Lunev         res->check_errors++;
75249ad6467SDenis V. Lunev         return size;
75349ad6467SDenis V. Lunev     }
75449ad6467SDenis V. Lunev 
75509a21edfSAlexander Ivanov     if (size > res->image_end_offset) {
75609a21edfSAlexander Ivanov         int64_t count;
75709a21edfSAlexander Ivanov         count = DIV_ROUND_UP(size - res->image_end_offset, s->cluster_size);
758728e1017SAlexander Ivanov         if (explicit) {
759728e1017SAlexander Ivanov             fprintf(stderr,
760728e1017SAlexander Ivanov                     "%s space leaked at the end of the image %" PRId64 "\n",
76109a21edfSAlexander Ivanov                     fix & BDRV_FIX_LEAKS ? "Repairing" : "ERROR",
76209a21edfSAlexander Ivanov                     size - res->image_end_offset);
76309a21edfSAlexander Ivanov             res->leaks += count;
764728e1017SAlexander Ivanov         }
76509a21edfSAlexander Ivanov         if (fix & BDRV_FIX_LEAKS) {
76609a21edfSAlexander Ivanov             Error *local_err = NULL;
76709a21edfSAlexander Ivanov 
76809a21edfSAlexander Ivanov             /*
76909a21edfSAlexander Ivanov              * In order to really repair the image, we must shrink it.
77009a21edfSAlexander Ivanov              * That means we have to pass exact=true.
77109a21edfSAlexander Ivanov              */
77209a21edfSAlexander Ivanov             ret = bdrv_co_truncate(bs->file, res->image_end_offset, true,
77309a21edfSAlexander Ivanov                                    PREALLOC_MODE_OFF, 0, &local_err);
77409a21edfSAlexander Ivanov             if (ret < 0) {
77509a21edfSAlexander Ivanov                 error_report_err(local_err);
77609a21edfSAlexander Ivanov                 res->check_errors++;
77709a21edfSAlexander Ivanov                 return ret;
77809a21edfSAlexander Ivanov             }
779728e1017SAlexander Ivanov             if (explicit) {
78009a21edfSAlexander Ivanov                 res->leaks_fixed += count;
78109a21edfSAlexander Ivanov             }
78209a21edfSAlexander Ivanov         }
783728e1017SAlexander Ivanov     }
78409a21edfSAlexander Ivanov 
78509a21edfSAlexander Ivanov     return 0;
78609a21edfSAlexander Ivanov }
78709a21edfSAlexander Ivanov 
7886bb8bc63SAlexander Ivanov static int coroutine_fn GRAPH_RDLOCK
parallels_check_duplicate(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix)7896bb8bc63SAlexander Ivanov parallels_check_duplicate(BlockDriverState *bs, BdrvCheckResult *res,
7906bb8bc63SAlexander Ivanov                           BdrvCheckMode fix)
7916bb8bc63SAlexander Ivanov {
7926bb8bc63SAlexander Ivanov     BDRVParallelsState *s = bs->opaque;
7936bb8bc63SAlexander Ivanov     int64_t host_off, host_sector, guest_sector;
7946bb8bc63SAlexander Ivanov     unsigned long *bitmap;
795a398275eSDenis V. Lunev     uint32_t i, bitmap_size, bat_entry;
7966bb8bc63SAlexander Ivanov     int n, ret = 0;
7976bb8bc63SAlexander Ivanov     uint64_t *buf = NULL;
7986bb8bc63SAlexander Ivanov     bool fixed = false;
7996bb8bc63SAlexander Ivanov 
8006bb8bc63SAlexander Ivanov     /*
8016bb8bc63SAlexander Ivanov      * Create a bitmap of used clusters.
8026bb8bc63SAlexander Ivanov      * If a bit is set, there is a BAT entry pointing to this cluster.
8036bb8bc63SAlexander Ivanov      * Loop through the BAT entries, check bits relevant to an entry offset.
8046bb8bc63SAlexander Ivanov      * If bit is set, this entry is duplicated. Otherwise set the bit.
8056bb8bc63SAlexander Ivanov      *
8066bb8bc63SAlexander Ivanov      * We shouldn't worry about newly allocated clusters outside the image
8076bb8bc63SAlexander Ivanov      * because they are created higher then any existing cluster pointed by
8086bb8bc63SAlexander Ivanov      * a BAT entry.
8096bb8bc63SAlexander Ivanov      */
8106bb8bc63SAlexander Ivanov     bitmap_size = host_cluster_index(s, res->image_end_offset);
8116bb8bc63SAlexander Ivanov     if (bitmap_size == 0) {
8126bb8bc63SAlexander Ivanov         return 0;
8136bb8bc63SAlexander Ivanov     }
8146bb8bc63SAlexander Ivanov     if (res->image_end_offset % s->cluster_size) {
8156bb8bc63SAlexander Ivanov         /* A not aligned image end leads to a bitmap shorter by 1 */
8166bb8bc63SAlexander Ivanov         bitmap_size++;
8176bb8bc63SAlexander Ivanov     }
8186bb8bc63SAlexander Ivanov 
8196bb8bc63SAlexander Ivanov     bitmap = bitmap_new(bitmap_size);
8206bb8bc63SAlexander Ivanov 
8216bb8bc63SAlexander Ivanov     buf = qemu_blockalign(bs, s->cluster_size);
8226bb8bc63SAlexander Ivanov 
8236bb8bc63SAlexander Ivanov     for (i = 0; i < s->bat_size; i++) {
8246bb8bc63SAlexander Ivanov         host_off = bat2sect(s, i) << BDRV_SECTOR_BITS;
8256bb8bc63SAlexander Ivanov         if (host_off == 0) {
8266bb8bc63SAlexander Ivanov             continue;
8276bb8bc63SAlexander Ivanov         }
8286bb8bc63SAlexander Ivanov 
82973194d3fSDenis V. Lunev         ret = mark_used(bs, bitmap, bitmap_size, host_off, 1);
830a398275eSDenis V. Lunev         assert(ret != -E2BIG);
831a398275eSDenis V. Lunev         if (ret == 0) {
8326bb8bc63SAlexander Ivanov             continue;
8336bb8bc63SAlexander Ivanov         }
8346bb8bc63SAlexander Ivanov 
8356bb8bc63SAlexander Ivanov         /* this cluster duplicates another one */
8366bb8bc63SAlexander Ivanov         fprintf(stderr, "%s duplicate offset in BAT entry %u\n",
8376bb8bc63SAlexander Ivanov                 fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
8386bb8bc63SAlexander Ivanov 
8396bb8bc63SAlexander Ivanov         res->corruptions++;
8406bb8bc63SAlexander Ivanov 
8416bb8bc63SAlexander Ivanov         if (!(fix & BDRV_FIX_ERRORS)) {
8426bb8bc63SAlexander Ivanov             continue;
8436bb8bc63SAlexander Ivanov         }
8446bb8bc63SAlexander Ivanov 
8456bb8bc63SAlexander Ivanov         /*
8466bb8bc63SAlexander Ivanov          * Reset the entry and allocate a new cluster
8476bb8bc63SAlexander Ivanov          * for the relevant guest offset. In this way we let
8486bb8bc63SAlexander Ivanov          * the lower layer to place the new cluster properly.
8496bb8bc63SAlexander Ivanov          * Copy the original cluster to the allocated one.
8506bb8bc63SAlexander Ivanov          * But before save the old offset value for repairing
8516bb8bc63SAlexander Ivanov          * if we have an error.
8526bb8bc63SAlexander Ivanov          */
8536bb8bc63SAlexander Ivanov         bat_entry = s->bat_bitmap[i];
8546bb8bc63SAlexander Ivanov         parallels_set_bat_entry(s, i, 0);
8556bb8bc63SAlexander Ivanov 
8566bb8bc63SAlexander Ivanov         ret = bdrv_co_pread(bs->file, host_off, s->cluster_size, buf, 0);
8576bb8bc63SAlexander Ivanov         if (ret < 0) {
8586bb8bc63SAlexander Ivanov             res->check_errors++;
8596bb8bc63SAlexander Ivanov             goto out_repair_bat;
8606bb8bc63SAlexander Ivanov         }
8616bb8bc63SAlexander Ivanov 
8626bb8bc63SAlexander Ivanov         guest_sector = (i * (int64_t)s->cluster_size) >> BDRV_SECTOR_BITS;
8636bb8bc63SAlexander Ivanov         host_sector = allocate_clusters(bs, guest_sector, s->tracks, &n);
8646bb8bc63SAlexander Ivanov         if (host_sector < 0) {
8656bb8bc63SAlexander Ivanov             res->check_errors++;
8666bb8bc63SAlexander Ivanov             goto out_repair_bat;
8676bb8bc63SAlexander Ivanov         }
8686bb8bc63SAlexander Ivanov         host_off = host_sector << BDRV_SECTOR_BITS;
8696bb8bc63SAlexander Ivanov 
8706bb8bc63SAlexander Ivanov         ret = bdrv_co_pwrite(bs->file, host_off, s->cluster_size, buf, 0);
8716bb8bc63SAlexander Ivanov         if (ret < 0) {
8726bb8bc63SAlexander Ivanov             res->check_errors++;
8736bb8bc63SAlexander Ivanov             goto out_repair_bat;
8746bb8bc63SAlexander Ivanov         }
8756bb8bc63SAlexander Ivanov 
8766bb8bc63SAlexander Ivanov         if (host_off + s->cluster_size > res->image_end_offset) {
8776bb8bc63SAlexander Ivanov             res->image_end_offset = host_off + s->cluster_size;
8786bb8bc63SAlexander Ivanov         }
8796bb8bc63SAlexander Ivanov 
8806bb8bc63SAlexander Ivanov         /*
8816bb8bc63SAlexander Ivanov          * In the future allocate_cluster() will reuse holed offsets
8826bb8bc63SAlexander Ivanov          * inside the image. Keep the used clusters bitmap content
8836bb8bc63SAlexander Ivanov          * consistent for the new allocated clusters too.
8846bb8bc63SAlexander Ivanov          *
8856bb8bc63SAlexander Ivanov          * Note, clusters allocated outside the current image are not
886a398275eSDenis V. Lunev          * considered, and the bitmap size doesn't change. This specifically
887a398275eSDenis V. Lunev          * means that -E2BIG is OK.
8886bb8bc63SAlexander Ivanov          */
88973194d3fSDenis V. Lunev         ret = mark_used(bs, bitmap, bitmap_size, host_off, 1);
890a398275eSDenis V. Lunev         if (ret == -EBUSY) {
891a398275eSDenis V. Lunev             res->check_errors++;
892a398275eSDenis V. Lunev             goto out_repair_bat;
8936bb8bc63SAlexander Ivanov         }
8946bb8bc63SAlexander Ivanov 
8956bb8bc63SAlexander Ivanov         fixed = true;
8966bb8bc63SAlexander Ivanov         res->corruptions_fixed++;
8976bb8bc63SAlexander Ivanov 
8986bb8bc63SAlexander Ivanov     }
8996bb8bc63SAlexander Ivanov 
9006bb8bc63SAlexander Ivanov     if (fixed) {
9016bb8bc63SAlexander Ivanov         /*
9026bb8bc63SAlexander Ivanov          * When new clusters are allocated, the file size increases by
9036bb8bc63SAlexander Ivanov          * 128 Mb. We need to truncate the file to the right size. Let
9046bb8bc63SAlexander Ivanov          * the leak fix code make its job without res changing.
9056bb8bc63SAlexander Ivanov          */
9066bb8bc63SAlexander Ivanov         ret = parallels_check_leak(bs, res, fix, false);
9076bb8bc63SAlexander Ivanov     }
9086bb8bc63SAlexander Ivanov 
9096bb8bc63SAlexander Ivanov out_free:
9106bb8bc63SAlexander Ivanov     g_free(buf);
9116bb8bc63SAlexander Ivanov     g_free(bitmap);
9126bb8bc63SAlexander Ivanov     return ret;
9136bb8bc63SAlexander Ivanov /*
9146bb8bc63SAlexander Ivanov  * We can get here only from places where index and old_offset have
9156bb8bc63SAlexander Ivanov  * meaningful values.
9166bb8bc63SAlexander Ivanov  */
9176bb8bc63SAlexander Ivanov out_repair_bat:
9186bb8bc63SAlexander Ivanov     s->bat_bitmap[i] = bat_entry;
9196bb8bc63SAlexander Ivanov     goto out_free;
9206bb8bc63SAlexander Ivanov }
9216bb8bc63SAlexander Ivanov 
parallels_collect_statistics(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix)9227e259e25SAlexander Ivanov static void parallels_collect_statistics(BlockDriverState *bs,
9237e259e25SAlexander Ivanov                                          BdrvCheckResult *res,
9247e259e25SAlexander Ivanov                                          BdrvCheckMode fix)
9257e259e25SAlexander Ivanov {
9267e259e25SAlexander Ivanov     BDRVParallelsState *s = bs->opaque;
9277e259e25SAlexander Ivanov     int64_t off, prev_off;
9287e259e25SAlexander Ivanov     uint32_t i;
9297e259e25SAlexander Ivanov 
9307e259e25SAlexander Ivanov     res->bfi.total_clusters = s->bat_size;
9317e259e25SAlexander Ivanov     res->bfi.compressed_clusters = 0; /* compression is not supported */
9327e259e25SAlexander Ivanov 
9337e259e25SAlexander Ivanov     prev_off = 0;
9347e259e25SAlexander Ivanov     for (i = 0; i < s->bat_size; i++) {
9357e259e25SAlexander Ivanov         off = bat2sect(s, i) << BDRV_SECTOR_BITS;
9367e259e25SAlexander Ivanov         /*
9377e259e25SAlexander Ivanov          * If BDRV_FIX_ERRORS is not set, out-of-image BAT entries were not
9387e259e25SAlexander Ivanov          * fixed. Skip not allocated and out-of-image BAT entries.
9397e259e25SAlexander Ivanov          */
9407e259e25SAlexander Ivanov         if (off == 0 || off + s->cluster_size > res->image_end_offset) {
9417e259e25SAlexander Ivanov             prev_off = 0;
9427e259e25SAlexander Ivanov             continue;
9437e259e25SAlexander Ivanov         }
9447e259e25SAlexander Ivanov 
9457e259e25SAlexander Ivanov         if (prev_off != 0 && (prev_off + s->cluster_size) != off) {
9467e259e25SAlexander Ivanov             res->bfi.fragmented_clusters++;
9477e259e25SAlexander Ivanov         }
9487e259e25SAlexander Ivanov         prev_off = off;
9497e259e25SAlexander Ivanov         res->bfi.allocated_clusters++;
9507e259e25SAlexander Ivanov     }
9517e259e25SAlexander Ivanov }
9527e259e25SAlexander Ivanov 
95309a21edfSAlexander Ivanov static int coroutine_fn GRAPH_RDLOCK
parallels_co_check(BlockDriverState * bs,BdrvCheckResult * res,BdrvCheckMode fix)95409a21edfSAlexander Ivanov parallels_co_check(BlockDriverState *bs, BdrvCheckResult *res,
95509a21edfSAlexander Ivanov                    BdrvCheckMode fix)
95609a21edfSAlexander Ivanov {
95709a21edfSAlexander Ivanov     BDRVParallelsState *s = bs->opaque;
95809a21edfSAlexander Ivanov     int ret;
95909a21edfSAlexander Ivanov 
960c0fc051dSAlexander Ivanov     WITH_QEMU_LOCK_GUARD(&s->lock) {
96196de69c7SAlexander Ivanov         parallels_check_unclean(bs, res, fix);
9626dd6b9f1SDenis V. Lunev 
9638cd19203SAlexander Ivanov         ret = parallels_check_data_off(bs, res, fix);
9648cd19203SAlexander Ivanov         if (ret < 0) {
9658cd19203SAlexander Ivanov             return ret;
9668cd19203SAlexander Ivanov         }
9678cd19203SAlexander Ivanov 
9686d416e56SAlexander Ivanov         ret = parallels_check_outside_image(bs, res, fix);
9696d416e56SAlexander Ivanov         if (ret < 0) {
970c0fc051dSAlexander Ivanov             return ret;
9716d416e56SAlexander Ivanov         }
9726d416e56SAlexander Ivanov 
973728e1017SAlexander Ivanov         ret = parallels_check_leak(bs, res, fix, true);
97409a21edfSAlexander Ivanov         if (ret < 0) {
975c0fc051dSAlexander Ivanov             return ret;
97609a21edfSAlexander Ivanov         }
97709a21edfSAlexander Ivanov 
9786bb8bc63SAlexander Ivanov         ret = parallels_check_duplicate(bs, res, fix);
9796bb8bc63SAlexander Ivanov         if (ret < 0) {
9806bb8bc63SAlexander Ivanov             return ret;
9816bb8bc63SAlexander Ivanov         }
9826bb8bc63SAlexander Ivanov 
9837e259e25SAlexander Ivanov         parallels_collect_statistics(bs, res, fix);
984c0fc051dSAlexander Ivanov     }
98549ad6467SDenis V. Lunev 
9863569cb7bSAlexander Ivanov     ret = bdrv_co_flush(bs);
9873569cb7bSAlexander Ivanov     if (ret < 0) {
9883569cb7bSAlexander Ivanov         res->check_errors++;
9893569cb7bSAlexander Ivanov     }
9903569cb7bSAlexander Ivanov 
9912fd61638SPaolo Bonzini     return ret;
99249ad6467SDenis V. Lunev }
99349ad6467SDenis V. Lunev 
99449ad6467SDenis V. Lunev 
9954db7ba3bSKevin Wolf static int coroutine_fn GRAPH_UNLOCKED
parallels_co_create(BlockdevCreateOptions * opts,Error ** errp)9964db7ba3bSKevin Wolf parallels_co_create(BlockdevCreateOptions* opts, Error **errp)
99774cf6c50SDenis V. Lunev {
9981511b490SKevin Wolf     BlockdevCreateOptionsParallels *parallels_opts;
9991511b490SKevin Wolf     BlockDriverState *bs;
10001511b490SKevin Wolf     BlockBackend *blk;
100174cf6c50SDenis V. Lunev     int64_t total_size, cl_size;
1002369f7de9SDenis V. Lunev     uint32_t bat_entries, bat_sectors;
100374cf6c50SDenis V. Lunev     ParallelsHeader header;
10041511b490SKevin Wolf     uint8_t tmp[BDRV_SECTOR_SIZE];
100574cf6c50SDenis V. Lunev     int ret;
100674cf6c50SDenis V. Lunev 
10071511b490SKevin Wolf     assert(opts->driver == BLOCKDEV_DRIVER_PARALLELS);
10081511b490SKevin Wolf     parallels_opts = &opts->u.parallels;
10091511b490SKevin Wolf 
10101511b490SKevin Wolf     /* Sanity checks */
10111511b490SKevin Wolf     total_size = parallels_opts->size;
10121511b490SKevin Wolf 
10131511b490SKevin Wolf     if (parallels_opts->has_cluster_size) {
10141511b490SKevin Wolf         cl_size = parallels_opts->cluster_size;
10151511b490SKevin Wolf     } else {
10161511b490SKevin Wolf         cl_size = DEFAULT_CLUSTER_SIZE;
10171511b490SKevin Wolf     }
10181511b490SKevin Wolf 
10192332d825SKevin Wolf     /* XXX What is the real limit here? This is an insanely large maximum. */
10202332d825SKevin Wolf     if (cl_size >= INT64_MAX / MAX_PARALLELS_IMAGE_FACTOR) {
10212332d825SKevin Wolf         error_setg(errp, "Cluster size is too large");
10222332d825SKevin Wolf         return -EINVAL;
10232332d825SKevin Wolf     }
1024555a608cSKlim Kireev     if (total_size >= MAX_PARALLELS_IMAGE_FACTOR * cl_size) {
10251511b490SKevin Wolf         error_setg(errp, "Image size is too large for this cluster size");
1026555a608cSKlim Kireev         return -E2BIG;
1027555a608cSKlim Kireev     }
102874cf6c50SDenis V. Lunev 
10291511b490SKevin Wolf     if (!QEMU_IS_ALIGNED(total_size, BDRV_SECTOR_SIZE)) {
10301511b490SKevin Wolf         error_setg(errp, "Image size must be a multiple of 512 bytes");
10311511b490SKevin Wolf         return -EINVAL;
103274cf6c50SDenis V. Lunev     }
103374cf6c50SDenis V. Lunev 
10341511b490SKevin Wolf     if (!QEMU_IS_ALIGNED(cl_size, BDRV_SECTOR_SIZE)) {
10351511b490SKevin Wolf         error_setg(errp, "Cluster size must be a multiple of 512 bytes");
10361511b490SKevin Wolf         return -EINVAL;
10371511b490SKevin Wolf     }
10381511b490SKevin Wolf 
10391511b490SKevin Wolf     /* Create BlockBackend to write to the image */
104048a4e92dSKevin Wolf     bs = bdrv_co_open_blockdev_ref(parallels_opts->file, errp);
10411511b490SKevin Wolf     if (bs == NULL) {
10428942764fSKevin Wolf         return -EIO;
104374cf6c50SDenis V. Lunev     }
10448942764fSKevin Wolf 
104548a4e92dSKevin Wolf     blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
1046a3aeeab5SEric Blake                              errp);
1047a3aeeab5SEric Blake     if (!blk) {
1048a3aeeab5SEric Blake         ret = -EPERM;
10491511b490SKevin Wolf         goto out;
10501511b490SKevin Wolf     }
10511511b490SKevin Wolf     blk_set_allow_write_beyond_eof(blk, true);
10521511b490SKevin Wolf 
10531511b490SKevin Wolf     /* Create image format */
1054369f7de9SDenis V. Lunev     bat_entries = DIV_ROUND_UP(total_size, cl_size);
10552d68e22eSDenis V. Lunev     bat_sectors = DIV_ROUND_UP(bat_entry_off(bat_entries), cl_size);
1056369f7de9SDenis V. Lunev     bat_sectors = (bat_sectors *  cl_size) >> BDRV_SECTOR_BITS;
105774cf6c50SDenis V. Lunev 
105874cf6c50SDenis V. Lunev     memset(&header, 0, sizeof(header));
105974cf6c50SDenis V. Lunev     memcpy(header.magic, HEADER_MAGIC2, sizeof(header.magic));
106074cf6c50SDenis V. Lunev     header.version = cpu_to_le32(HEADER_VERSION);
106174cf6c50SDenis V. Lunev     /* don't care much about geometry, it is not used on image level */
1062908b1c84SKlim Kireev     header.heads = cpu_to_le32(HEADS_NUMBER);
1063908b1c84SKlim Kireev     header.cylinders = cpu_to_le32(total_size / BDRV_SECTOR_SIZE
1064908b1c84SKlim Kireev                                    / HEADS_NUMBER / SEC_IN_CYL);
106574cf6c50SDenis V. Lunev     header.tracks = cpu_to_le32(cl_size >> BDRV_SECTOR_BITS);
1066369f7de9SDenis V. Lunev     header.bat_entries = cpu_to_le32(bat_entries);
106774cf6c50SDenis V. Lunev     header.nb_sectors = cpu_to_le64(DIV_ROUND_UP(total_size, BDRV_SECTOR_SIZE));
1068369f7de9SDenis V. Lunev     header.data_off = cpu_to_le32(bat_sectors);
106974cf6c50SDenis V. Lunev 
107074cf6c50SDenis V. Lunev     /* write all the data */
107174cf6c50SDenis V. Lunev     memset(tmp, 0, sizeof(tmp));
107274cf6c50SDenis V. Lunev     memcpy(tmp, &header, sizeof(header));
107374cf6c50SDenis V. Lunev 
107450688be0SAlberto Faria     ret = blk_co_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
107574cf6c50SDenis V. Lunev     if (ret < 0) {
107674cf6c50SDenis V. Lunev         goto exit;
107774cf6c50SDenis V. Lunev     }
107850688be0SAlberto Faria     ret = blk_co_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
1079983a1600SEric Blake                                (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
108074cf6c50SDenis V. Lunev     if (ret < 0) {
108174cf6c50SDenis V. Lunev         goto exit;
108274cf6c50SDenis V. Lunev     }
108374cf6c50SDenis V. Lunev 
10841511b490SKevin Wolf     ret = 0;
10851511b490SKevin Wolf out:
1086b2ab5f54SKevin Wolf     blk_co_unref(blk);
1087b2ab5f54SKevin Wolf     bdrv_co_unref(bs);
108874cf6c50SDenis V. Lunev     return ret;
108974cf6c50SDenis V. Lunev 
109074cf6c50SDenis V. Lunev exit:
109174cf6c50SDenis V. Lunev     error_setg_errno(errp, -ret, "Failed to create Parallels image");
10921511b490SKevin Wolf     goto out;
10931511b490SKevin Wolf }
10941511b490SKevin Wolf 
10954db7ba3bSKevin Wolf static int coroutine_fn GRAPH_UNLOCKED
parallels_co_create_opts(BlockDriver * drv,const char * filename,QemuOpts * opts,Error ** errp)10964ec8df01SKevin Wolf parallels_co_create_opts(BlockDriver *drv, const char *filename,
10974ec8df01SKevin Wolf                          QemuOpts *opts, Error **errp)
10981511b490SKevin Wolf {
10991511b490SKevin Wolf     BlockdevCreateOptions *create_options = NULL;
11001511b490SKevin Wolf     BlockDriverState *bs = NULL;
110192adf9dbSMarkus Armbruster     QDict *qdict;
11021511b490SKevin Wolf     Visitor *v;
11031511b490SKevin Wolf     int ret;
11041511b490SKevin Wolf 
11051511b490SKevin Wolf     static const QDictRenames opt_renames[] = {
11061511b490SKevin Wolf         { BLOCK_OPT_CLUSTER_SIZE,       "cluster-size" },
11071511b490SKevin Wolf         { NULL, NULL },
11081511b490SKevin Wolf     };
11091511b490SKevin Wolf 
11101511b490SKevin Wolf     /* Parse options and convert legacy syntax */
11111511b490SKevin Wolf     qdict = qemu_opts_to_qdict_filtered(opts, NULL, &parallels_create_opts,
11121511b490SKevin Wolf                                         true);
11131511b490SKevin Wolf 
11141511b490SKevin Wolf     if (!qdict_rename_keys(qdict, opt_renames, errp)) {
11151511b490SKevin Wolf         ret = -EINVAL;
111674cf6c50SDenis V. Lunev         goto done;
111774cf6c50SDenis V. Lunev     }
111874cf6c50SDenis V. Lunev 
11191511b490SKevin Wolf     /* Create and open the file (protocol layer) */
11202475a0d0SEmanuele Giuseppe Esposito     ret = bdrv_co_create_file(filename, opts, errp);
11211511b490SKevin Wolf     if (ret < 0) {
11221511b490SKevin Wolf         goto done;
11231511b490SKevin Wolf     }
11241511b490SKevin Wolf 
112548a4e92dSKevin Wolf     bs = bdrv_co_open(filename, NULL, NULL,
11261511b490SKevin Wolf                       BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
11271511b490SKevin Wolf     if (bs == NULL) {
11281511b490SKevin Wolf         ret = -EIO;
11291511b490SKevin Wolf         goto done;
11301511b490SKevin Wolf     }
11311511b490SKevin Wolf 
11321511b490SKevin Wolf     /* Now get the QAPI type BlockdevCreateOptions */
11331511b490SKevin Wolf     qdict_put_str(qdict, "driver", "parallels");
11341511b490SKevin Wolf     qdict_put_str(qdict, "file", bs->node_name);
11351511b490SKevin Wolf 
1136af91062eSMarkus Armbruster     v = qobject_input_visitor_new_flat_confused(qdict, errp);
1137af91062eSMarkus Armbruster     if (!v) {
11381511b490SKevin Wolf         ret = -EINVAL;
11391511b490SKevin Wolf         goto done;
11401511b490SKevin Wolf     }
11411511b490SKevin Wolf 
1142b11a093cSMarkus Armbruster     visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp);
11431511b490SKevin Wolf     visit_free(v);
1144b11a093cSMarkus Armbruster     if (!create_options) {
11451511b490SKevin Wolf         ret = -EINVAL;
11461511b490SKevin Wolf         goto done;
11471511b490SKevin Wolf     }
11481511b490SKevin Wolf 
11491511b490SKevin Wolf     /* Silently round up sizes */
11501511b490SKevin Wolf     create_options->u.parallels.size =
11511511b490SKevin Wolf         ROUND_UP(create_options->u.parallels.size, BDRV_SECTOR_SIZE);
11521511b490SKevin Wolf     create_options->u.parallels.cluster_size =
11531511b490SKevin Wolf         ROUND_UP(create_options->u.parallels.cluster_size, BDRV_SECTOR_SIZE);
11541511b490SKevin Wolf 
11551511b490SKevin Wolf     /* Create the Parallels image (format layer) */
11561511b490SKevin Wolf     ret = parallels_co_create(create_options, errp);
11571511b490SKevin Wolf     if (ret < 0) {
11581511b490SKevin Wolf         goto done;
11591511b490SKevin Wolf     }
11601511b490SKevin Wolf     ret = 0;
11611511b490SKevin Wolf 
11621511b490SKevin Wolf done:
1163cb3e7f08SMarc-André Lureau     qobject_unref(qdict);
1164b2ab5f54SKevin Wolf     bdrv_co_unref(bs);
11651511b490SKevin Wolf     qapi_free_BlockdevCreateOptions(create_options);
11661511b490SKevin Wolf     return ret;
11671511b490SKevin Wolf }
11681511b490SKevin Wolf 
116923d6bd3bSDenis V. Lunev 
parallels_probe(const uint8_t * buf,int buf_size,const char * filename)117023d6bd3bSDenis V. Lunev static int parallels_probe(const uint8_t *buf, int buf_size,
117123d6bd3bSDenis V. Lunev                            const char *filename)
117223d6bd3bSDenis V. Lunev {
117323d6bd3bSDenis V. Lunev     const ParallelsHeader *ph = (const void *)buf;
117423d6bd3bSDenis V. Lunev 
117523d6bd3bSDenis V. Lunev     if (buf_size < sizeof(ParallelsHeader)) {
117623d6bd3bSDenis V. Lunev         return 0;
117723d6bd3bSDenis V. Lunev     }
117823d6bd3bSDenis V. Lunev 
117923d6bd3bSDenis V. Lunev     if ((!memcmp(ph->magic, HEADER_MAGIC, 16) ||
118023d6bd3bSDenis V. Lunev            !memcmp(ph->magic, HEADER_MAGIC2, 16)) &&
118123d6bd3bSDenis V. Lunev            (le32_to_cpu(ph->version) == HEADER_VERSION)) {
118223d6bd3bSDenis V. Lunev         return 100;
118323d6bd3bSDenis V. Lunev     }
118423d6bd3bSDenis V. Lunev 
118523d6bd3bSDenis V. Lunev     return 0;
118623d6bd3bSDenis V. Lunev }
118723d6bd3bSDenis V. Lunev 
parallels_update_header(BlockDriverState * bs)11881f051dcbSKevin Wolf static int GRAPH_RDLOCK parallels_update_header(BlockDriverState *bs)
11896dd6b9f1SDenis V. Lunev {
11906dd6b9f1SDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
11919a4f4c31SKevin Wolf     unsigned size = MAX(bdrv_opt_mem_align(bs->file->bs),
11929a4f4c31SKevin Wolf                         sizeof(ParallelsHeader));
11936dd6b9f1SDenis V. Lunev 
11946dd6b9f1SDenis V. Lunev     if (size > s->header_size) {
11956dd6b9f1SDenis V. Lunev         size = s->header_size;
11966dd6b9f1SDenis V. Lunev     }
119732cc71deSAlberto Faria     return bdrv_pwrite_sync(bs->file, 0, size, s->header, 0);
11986dd6b9f1SDenis V. Lunev }
11996dd6b9f1SDenis V. Lunev 
120093361b7eSDenis V. Lunev 
parallels_opts_prealloc(BlockDriverState * bs,QDict * options,Error ** errp)120193361b7eSDenis V. Lunev static int parallels_opts_prealloc(BlockDriverState *bs, QDict *options,
120293361b7eSDenis V. Lunev                                    Error **errp)
120393361b7eSDenis V. Lunev {
120493361b7eSDenis V. Lunev     int err;
120593361b7eSDenis V. Lunev     char *buf;
120693361b7eSDenis V. Lunev     int64_t bytes;
120793361b7eSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
120893361b7eSDenis V. Lunev     Error *local_err = NULL;
120993361b7eSDenis V. Lunev     QemuOpts *opts = qemu_opts_create(&parallels_runtime_opts, NULL, 0, errp);
121093361b7eSDenis V. Lunev     if (!opts) {
121193361b7eSDenis V. Lunev         return -ENOMEM;
121293361b7eSDenis V. Lunev     }
121393361b7eSDenis V. Lunev 
121493361b7eSDenis V. Lunev     err = -EINVAL;
121593361b7eSDenis V. Lunev     if (!qemu_opts_absorb_qdict(opts, options, errp)) {
121693361b7eSDenis V. Lunev         goto done;
121793361b7eSDenis V. Lunev     }
121893361b7eSDenis V. Lunev 
121993361b7eSDenis V. Lunev     bytes = qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
122093361b7eSDenis V. Lunev     s->prealloc_size = bytes >> BDRV_SECTOR_BITS;
122193361b7eSDenis V. Lunev     buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
122293361b7eSDenis V. Lunev     /* prealloc_mode can be downgraded later during allocate_clusters */
122393361b7eSDenis V. Lunev     s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf,
122493361b7eSDenis V. Lunev                                        PRL_PREALLOC_MODE_FALLOCATE,
122593361b7eSDenis V. Lunev                                        &local_err);
122693361b7eSDenis V. Lunev     g_free(buf);
122793361b7eSDenis V. Lunev     if (local_err != NULL) {
122893361b7eSDenis V. Lunev         error_propagate(errp, local_err);
122993361b7eSDenis V. Lunev         goto done;
123093361b7eSDenis V. Lunev     }
123193361b7eSDenis V. Lunev     err = 0;
123293361b7eSDenis V. Lunev 
123393361b7eSDenis V. Lunev done:
123493361b7eSDenis V. Lunev     qemu_opts_del(opts);
123593361b7eSDenis V. Lunev     return err;
123693361b7eSDenis V. Lunev }
123793361b7eSDenis V. Lunev 
parallels_open(BlockDriverState * bs,QDict * options,int flags,Error ** errp)123823d6bd3bSDenis V. Lunev static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
123923d6bd3bSDenis V. Lunev                           Error **errp)
124023d6bd3bSDenis V. Lunev {
124123d6bd3bSDenis V. Lunev     BDRVParallelsState *s = bs->opaque;
124223d6bd3bSDenis V. Lunev     ParallelsHeader ph;
124319f5dc15SDenis V. Lunev     int ret, size, i;
1244cfce1091SAlexander Ivanov     int64_t file_nb_sectors, sector;
1245c89d4362SAlexander Ivanov     uint32_t data_start;
12468f5f5326SDenis V. Lunev     bool need_check = false;
124723d6bd3bSDenis V. Lunev 
124893361b7eSDenis V. Lunev     ret = parallels_opts_prealloc(bs, options, errp);
124993361b7eSDenis V. Lunev     if (ret < 0) {
125093361b7eSDenis V. Lunev         return ret;
125193361b7eSDenis V. Lunev     }
125293361b7eSDenis V. Lunev 
125383930780SVladimir Sementsov-Ogievskiy     ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
125483930780SVladimir Sementsov-Ogievskiy     if (ret < 0) {
125583930780SVladimir Sementsov-Ogievskiy         return ret;
12564e4bf5c4SKevin Wolf     }
12574e4bf5c4SKevin Wolf 
1258a4b740dbSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
1259a4b740dbSKevin Wolf 
1260f5e715dbSAlexander Ivanov     file_nb_sectors = bdrv_nb_sectors(bs->file->bs);
1261f5e715dbSAlexander Ivanov     if (file_nb_sectors < 0) {
1262f5e715dbSAlexander Ivanov         return -EINVAL;
1263f5e715dbSAlexander Ivanov     }
1264f5e715dbSAlexander Ivanov 
126532cc71deSAlberto Faria     ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
126623d6bd3bSDenis V. Lunev     if (ret < 0) {
1267e17b9d08SDenis V. Lunev         return ret;
126823d6bd3bSDenis V. Lunev     }
126923d6bd3bSDenis V. Lunev 
127023d6bd3bSDenis V. Lunev     bs->total_sectors = le64_to_cpu(ph.nb_sectors);
127123d6bd3bSDenis V. Lunev 
127223d6bd3bSDenis V. Lunev     if (le32_to_cpu(ph.version) != HEADER_VERSION) {
127323d6bd3bSDenis V. Lunev         goto fail_format;
127423d6bd3bSDenis V. Lunev     }
127523d6bd3bSDenis V. Lunev     if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {
127623d6bd3bSDenis V. Lunev         s->off_multiplier = 1;
127723d6bd3bSDenis V. Lunev         bs->total_sectors = 0xffffffff & bs->total_sectors;
127823d6bd3bSDenis V. Lunev     } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {
127923d6bd3bSDenis V. Lunev         s->off_multiplier = le32_to_cpu(ph.tracks);
128023d6bd3bSDenis V. Lunev     } else {
128123d6bd3bSDenis V. Lunev         goto fail_format;
128223d6bd3bSDenis V. Lunev     }
128323d6bd3bSDenis V. Lunev 
128423d6bd3bSDenis V. Lunev     s->tracks = le32_to_cpu(ph.tracks);
128523d6bd3bSDenis V. Lunev     if (s->tracks == 0) {
128623d6bd3bSDenis V. Lunev         error_setg(errp, "Invalid image: Zero sectors per track");
1287e17b9d08SDenis V. Lunev         return -EINVAL;
128823d6bd3bSDenis V. Lunev     }
128923d6bd3bSDenis V. Lunev     if (s->tracks > INT32_MAX/513) {
129023d6bd3bSDenis V. Lunev         error_setg(errp, "Invalid image: Too big cluster");
1291e17b9d08SDenis V. Lunev         return -EFBIG;
129223d6bd3bSDenis V. Lunev     }
129393361b7eSDenis V. Lunev     s->prealloc_size = MAX(s->tracks, s->prealloc_size);
1294e0b5207fSVladimir Sementsov-Ogievskiy     s->cluster_size = s->tracks << BDRV_SECTOR_BITS;
129523d6bd3bSDenis V. Lunev 
129623d6bd3bSDenis V. Lunev     s->bat_size = le32_to_cpu(ph.bat_entries);
129723d6bd3bSDenis V. Lunev     if (s->bat_size > INT_MAX / sizeof(uint32_t)) {
129823d6bd3bSDenis V. Lunev         error_setg(errp, "Catalog too large");
1299e17b9d08SDenis V. Lunev         return -EFBIG;
130023d6bd3bSDenis V. Lunev     }
130123d6bd3bSDenis V. Lunev 
13022d68e22eSDenis V. Lunev     size = bat_entry_off(s->bat_size);
13039a4f4c31SKevin Wolf     s->header_size = ROUND_UP(size, bdrv_opt_mem_align(bs->file->bs));
13049a4f4c31SKevin Wolf     s->header = qemu_try_blockalign(bs->file->bs, s->header_size);
130523d6bd3bSDenis V. Lunev     if (s->header == NULL) {
1306e17b9d08SDenis V. Lunev         return -ENOMEM;
130723d6bd3bSDenis V. Lunev     }
130823d6bd3bSDenis V. Lunev 
130932cc71deSAlberto Faria     ret = bdrv_pread(bs->file, 0, s->header_size, s->header, 0);
131023d6bd3bSDenis V. Lunev     if (ret < 0) {
131123d6bd3bSDenis V. Lunev         goto fail;
131223d6bd3bSDenis V. Lunev     }
131323d6bd3bSDenis V. Lunev     s->bat_bitmap = (uint32_t *)(s->header + 1);
131423d6bd3bSDenis V. Lunev 
13156dd6b9f1SDenis V. Lunev     if (le32_to_cpu(ph.inuse) == HEADER_INUSE_MAGIC) {
13168f5f5326SDenis V. Lunev         need_check = s->header_unclean = true;
13176dd6b9f1SDenis V. Lunev     }
13186dd6b9f1SDenis V. Lunev 
13198f5f5326SDenis V. Lunev     {
13208f5f5326SDenis V. Lunev         bool ok = parallels_test_data_off(s, file_nb_sectors, &data_start);
13218f5f5326SDenis V. Lunev         need_check = need_check || !ok;
13228f5f5326SDenis V. Lunev     }
13238f5f5326SDenis V. Lunev 
1324c89d4362SAlexander Ivanov     s->data_start = data_start;
1325c89d4362SAlexander Ivanov     s->data_end = s->data_start;
1326c89d4362SAlexander Ivanov     if (s->data_end < (s->header_size >> BDRV_SECTOR_BITS)) {
1327c89d4362SAlexander Ivanov         /*
1328c89d4362SAlexander Ivanov          * There is not enough unused space to fit to block align between BAT
1329c89d4362SAlexander Ivanov          * and actual data. We can't avoid read-modify-write...
1330c89d4362SAlexander Ivanov          */
1331c89d4362SAlexander Ivanov         s->header_size = size;
1332c89d4362SAlexander Ivanov     }
1333c89d4362SAlexander Ivanov 
1334baefd977SVladimir Sementsov-Ogievskiy     if (ph.ext_off) {
1335baefd977SVladimir Sementsov-Ogievskiy         if (flags & BDRV_O_RDWR) {
1336baefd977SVladimir Sementsov-Ogievskiy             /*
1337baefd977SVladimir Sementsov-Ogievskiy              * It's unsafe to open image RW if there is an extension (as we
1338baefd977SVladimir Sementsov-Ogievskiy              * don't support it). But parallels driver in QEMU historically
1339baefd977SVladimir Sementsov-Ogievskiy              * ignores the extension, so print warning and don't care.
1340baefd977SVladimir Sementsov-Ogievskiy              */
1341baefd977SVladimir Sementsov-Ogievskiy             warn_report("Format Extension ignored in RW mode");
1342baefd977SVladimir Sementsov-Ogievskiy         } else {
1343baefd977SVladimir Sementsov-Ogievskiy             ret = parallels_read_format_extension(
1344baefd977SVladimir Sementsov-Ogievskiy                     bs, le64_to_cpu(ph.ext_off) << BDRV_SECTOR_BITS, errp);
1345baefd977SVladimir Sementsov-Ogievskiy             if (ret < 0) {
1346baefd977SVladimir Sementsov-Ogievskiy                 goto fail;
1347baefd977SVladimir Sementsov-Ogievskiy             }
1348baefd977SVladimir Sementsov-Ogievskiy         }
1349baefd977SVladimir Sementsov-Ogievskiy     }
1350baefd977SVladimir Sementsov-Ogievskiy 
13516c7d390bSJeff Cody     if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_INACTIVE)) {
13526dd6b9f1SDenis V. Lunev         s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC);
13536dd6b9f1SDenis V. Lunev         ret = parallels_update_header(bs);
13546dd6b9f1SDenis V. Lunev         if (ret < 0) {
13556dd6b9f1SDenis V. Lunev             goto fail;
13566dd6b9f1SDenis V. Lunev         }
13576dd6b9f1SDenis V. Lunev     }
13586dd6b9f1SDenis V. Lunev 
13598e3b0cbbSMarc-André Lureau     s->bat_dirty_block = 4 * qemu_real_host_page_size();
13600d31c7c2SDenis V. Lunev     s->bat_dirty_bmap =
13610d31c7c2SDenis V. Lunev         bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
13620d31c7c2SDenis V. Lunev 
1363a94750d9SEmanuele Giuseppe Esposito     /* Disable migration until bdrv_activate method is added */
13641d0f37cfSJeff Cody     error_setg(&s->migration_blocker, "The Parallels format used by node '%s' "
13651d0f37cfSJeff Cody                "does not support live migration",
13661d0f37cfSJeff Cody                bdrv_get_device_or_node_name(bs));
13674026f1c4SKevin Wolf 
1368e0ee3a8fSSteve Sistare     ret = migrate_add_blocker_normal(&s->migration_blocker, errp);
1369386f6c07SMarkus Armbruster     if (ret < 0) {
13701d0f37cfSJeff Cody         goto fail;
13711d0f37cfSJeff Cody     }
137223d6bd3bSDenis V. Lunev     qemu_co_mutex_init(&s->lock);
1373cfce1091SAlexander Ivanov 
1374cfce1091SAlexander Ivanov     for (i = 0; i < s->bat_size; i++) {
1375cfce1091SAlexander Ivanov         sector = bat2sect(s, i);
1376cfce1091SAlexander Ivanov         if (sector + s->tracks > s->data_end) {
1377cfce1091SAlexander Ivanov             s->data_end = sector + s->tracks;
1378cfce1091SAlexander Ivanov         }
1379cfce1091SAlexander Ivanov     }
13808f5f5326SDenis V. Lunev     need_check = need_check || s->data_end > file_nb_sectors;
1381cfce1091SAlexander Ivanov 
1382e185100fSDenis V. Lunev     if (!need_check) {
1383e185100fSDenis V. Lunev         ret = parallels_fill_used_bitmap(bs);
1384e185100fSDenis V. Lunev         if (ret == -ENOMEM) {
1385e185100fSDenis V. Lunev             goto fail;
1386e185100fSDenis V. Lunev         }
1387e185100fSDenis V. Lunev         need_check = need_check || ret < 0; /* These are correctable errors */
1388e185100fSDenis V. Lunev     }
1389e185100fSDenis V. Lunev 
1390cfce1091SAlexander Ivanov     /*
1391cfce1091SAlexander Ivanov      * We don't repair the image here if it's opened for checks. Also we don't
1392cfce1091SAlexander Ivanov      * want to change inactive images and can't change readonly images.
1393cfce1091SAlexander Ivanov      */
1394cfce1091SAlexander Ivanov     if ((flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) || !(flags & BDRV_O_RDWR)) {
1395cfce1091SAlexander Ivanov         return 0;
1396cfce1091SAlexander Ivanov     }
1397cfce1091SAlexander Ivanov 
13988f5f5326SDenis V. Lunev     /* Repair the image if corruption was detected. */
13998f5f5326SDenis V. Lunev     if (need_check) {
1400cfce1091SAlexander Ivanov         BdrvCheckResult res;
1401cfce1091SAlexander Ivanov         ret = bdrv_check(bs, &res, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
1402cfce1091SAlexander Ivanov         if (ret < 0) {
1403cfce1091SAlexander Ivanov             error_setg_errno(errp, -ret, "Could not repair corrupted image");
1404c8a7fc51SSteve Sistare             migrate_del_blocker(&s->migration_blocker);
1405cfce1091SAlexander Ivanov             goto fail;
1406cfce1091SAlexander Ivanov         }
1407cfce1091SAlexander Ivanov     }
140823d6bd3bSDenis V. Lunev     return 0;
140923d6bd3bSDenis V. Lunev 
141023d6bd3bSDenis V. Lunev fail_format:
141123d6bd3bSDenis V. Lunev     error_setg(errp, "Image not in Parallels format");
14129c398781SDenis V. Lunev     return -EINVAL;
14139c398781SDenis V. Lunev 
141423d6bd3bSDenis V. Lunev fail:
1415cfce1091SAlexander Ivanov     /*
1416cfce1091SAlexander Ivanov      * "s" object was allocated by g_malloc0 so we can safely
1417cfce1091SAlexander Ivanov      * try to free its fields even they were not allocated.
1418cfce1091SAlexander Ivanov      */
1419e185100fSDenis V. Lunev     parallels_free_used_bitmap(bs);
1420e185100fSDenis V. Lunev 
1421cfce1091SAlexander Ivanov     g_free(s->bat_dirty_bmap);
142223d6bd3bSDenis V. Lunev     qemu_vfree(s->header);
142323d6bd3bSDenis V. Lunev     return ret;
142423d6bd3bSDenis V. Lunev }
142523d6bd3bSDenis V. Lunev 
142623d6bd3bSDenis V. Lunev 
parallels_close(BlockDriverState * bs)1427019d6b8fSAnthony Liguori static void parallels_close(BlockDriverState *bs)
1428019d6b8fSAnthony Liguori {
1429019d6b8fSAnthony Liguori     BDRVParallelsState *s = bs->opaque;
14306dd6b9f1SDenis V. Lunev 
14311f051dcbSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
14321f051dcbSKevin Wolf 
14336c7d390bSJeff Cody     if ((bs->open_flags & BDRV_O_RDWR) && !(bs->open_flags & BDRV_O_INACTIVE)) {
14346dd6b9f1SDenis V. Lunev         s->header->inuse = 0;
14356dd6b9f1SDenis V. Lunev         parallels_update_header(bs);
1436e8d04f92SMax Reitz 
1437e8d04f92SMax Reitz         /* errors are ignored, so we might as well pass exact=true */
1438e8d04f92SMax Reitz         bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
14397b8e4857SKevin Wolf                       PREALLOC_MODE_OFF, 0, NULL);
144019f5dc15SDenis V. Lunev     }
144119f5dc15SDenis V. Lunev 
1442e185100fSDenis V. Lunev     parallels_free_used_bitmap(bs);
1443e185100fSDenis V. Lunev 
14440d31c7c2SDenis V. Lunev     g_free(s->bat_dirty_bmap);
14459eae9ccaSDenis V. Lunev     qemu_vfree(s->header);
14461d0f37cfSJeff Cody 
1447c8a7fc51SSteve Sistare     migrate_del_blocker(&s->migration_blocker);
1448019d6b8fSAnthony Liguori }
1449019d6b8fSAnthony Liguori 
parallels_is_support_dirty_bitmaps(BlockDriverState * bs)145073f3e136SDenis V. Lunev static bool parallels_is_support_dirty_bitmaps(BlockDriverState *bs)
145173f3e136SDenis V. Lunev {
145273f3e136SDenis V. Lunev     return 1;
145373f3e136SDenis V. Lunev }
145473f3e136SDenis V. Lunev 
1455019d6b8fSAnthony Liguori static BlockDriver bdrv_parallels = {
1456019d6b8fSAnthony Liguori     .format_name                = "parallels",
1457019d6b8fSAnthony Liguori     .instance_size              = sizeof(BDRVParallelsState),
1458bb16991fSDenis V. Lunev     .create_opts                = &parallels_create_opts,
1459bb16991fSDenis V. Lunev     .is_format                  = true,
1460bb16991fSDenis V. Lunev     .supports_backing           = true,
1461bb16991fSDenis V. Lunev 
1462bb16991fSDenis V. Lunev     .bdrv_has_zero_init         = bdrv_has_zero_init_1,
146373f3e136SDenis V. Lunev     .bdrv_supports_persistent_dirty_bitmap = parallels_is_support_dirty_bitmaps,
1464bb16991fSDenis V. Lunev 
1465019d6b8fSAnthony Liguori     .bdrv_probe                 = parallels_probe,
14661dec5a70SChristoph Hellwig     .bdrv_open                  = parallels_open,
1467019d6b8fSAnthony Liguori     .bdrv_close                 = parallels_close,
146869dca43dSMax Reitz     .bdrv_child_perm            = bdrv_default_perms,
14698e0cf59dSEric Blake     .bdrv_co_block_status       = parallels_co_block_status,
14700d31c7c2SDenis V. Lunev     .bdrv_co_flush_to_os        = parallels_co_flush_to_os,
1471481fb9cfSDenis V. Lunev     .bdrv_co_readv              = parallels_co_readv,
14725a41e1faSDenis V. Lunev     .bdrv_co_writev             = parallels_co_writev,
14731511b490SKevin Wolf     .bdrv_co_create             = parallels_co_create,
1474efc75e2aSStefan Hajnoczi     .bdrv_co_create_opts        = parallels_co_create_opts,
14752fd61638SPaolo Bonzini     .bdrv_co_check              = parallels_co_check,
1476c54fb435SDenis V. Lunev     .bdrv_co_pdiscard           = parallels_co_pdiscard,
1477a98b260aSDenis V. Lunev     .bdrv_co_pwrite_zeroes      = parallels_co_pwrite_zeroes,
1478019d6b8fSAnthony Liguori };
1479019d6b8fSAnthony Liguori 
bdrv_parallels_init(void)1480019d6b8fSAnthony Liguori static void bdrv_parallels_init(void)
1481019d6b8fSAnthony Liguori {
1482019d6b8fSAnthony Liguori     bdrv_register(&bdrv_parallels);
1483019d6b8fSAnthony Liguori }
1484019d6b8fSAnthony Liguori 
1485019d6b8fSAnthony Liguori block_init(bdrv_parallels_init);
1486