2 * Block driver for Parallels disk image format
4 * Copyright (c) 2007 Alex Beregszaszi
5 * Copyright (c) 2015 Denis V. Lunev <den@openvz.org>
7 * This code was originally based on comparing different disk images created
8 * by Parallels. Currently it is based on opened OpenVZ sources
10 * http://git.openvz.org/?p=ploop;a=summary
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 #include "qemu-common.h"
31 #include "block/block_int.h"
32 #include "qemu/module.h"
34 /**************************************************************/
36 #define HEADER_MAGIC "WithoutFreeSpace"
37 #define HEADER_MAGIC2 "WithouFreSpacExt"
38 #define HEADER_VERSION 2
40 #define DEFAULT_CLUSTER_SIZE 1048576 /* 1 MiB */
43 // always little-endian
44 typedef struct ParallelsHeader
{
45 char magic
[16]; // "WithoutFreeSpace"
55 } QEMU_PACKED ParallelsHeader
;
57 typedef struct BDRVParallelsState
{
58 /** Locking is conservative, the lock protects
59 * - image file extending (truncate, fallocate)
60 * - any access to block allocation table
65 unsigned int bat_size
;
69 unsigned int off_multiplier
;
74 static int parallels_probe(const uint8_t *buf
, int buf_size
, const char *filename
)
76 const ParallelsHeader
*ph
= (const void *)buf
;
78 if (buf_size
< sizeof(ParallelsHeader
))
81 if ((!memcmp(ph
->magic
, HEADER_MAGIC
, 16) ||
82 !memcmp(ph
->magic
, HEADER_MAGIC2
, 16)) &&
83 (le32_to_cpu(ph
->version
) == HEADER_VERSION
))
89 static int parallels_open(BlockDriverState
*bs
, QDict
*options
, int flags
,
92 BDRVParallelsState
*s
= bs
->opaque
;
97 ret
= bdrv_pread(bs
->file
, 0, &ph
, sizeof(ph
));
102 bs
->total_sectors
= le64_to_cpu(ph
.nb_sectors
);
104 if (le32_to_cpu(ph
.version
) != HEADER_VERSION
) {
107 if (!memcmp(ph
.magic
, HEADER_MAGIC
, 16)) {
108 s
->off_multiplier
= 1;
109 bs
->total_sectors
= 0xffffffff & bs
->total_sectors
;
110 } else if (!memcmp(ph
.magic
, HEADER_MAGIC2
, 16)) {
111 s
->off_multiplier
= le32_to_cpu(ph
.tracks
);
116 s
->tracks
= le32_to_cpu(ph
.tracks
);
117 if (s
->tracks
== 0) {
118 error_setg(errp
, "Invalid image: Zero sectors per track");
122 if (s
->tracks
> INT32_MAX
/513) {
123 error_setg(errp
, "Invalid image: Too big cluster");
128 s
->bat_size
= le32_to_cpu(ph
.bat_entries
);
129 if (s
->bat_size
> INT_MAX
/ sizeof(uint32_t)) {
130 error_setg(errp
, "Catalog too large");
134 s
->bat_bitmap
= g_try_new(uint32_t, s
->bat_size
);
135 if (s
->bat_size
&& s
->bat_bitmap
== NULL
) {
140 ret
= bdrv_pread(bs
->file
, sizeof(ParallelsHeader
),
141 s
->bat_bitmap
, s
->bat_size
* sizeof(uint32_t));
146 for (i
= 0; i
< s
->bat_size
; i
++) {
147 le32_to_cpus(&s
->bat_bitmap
[i
]);
150 s
->has_truncate
= bdrv_has_zero_init(bs
->file
) &&
151 bdrv_truncate(bs
->file
, bdrv_getlength(bs
->file
)) == 0;
153 qemu_co_mutex_init(&s
->lock
);
157 error_setg(errp
, "Image not in Parallels format");
160 g_free(s
->bat_bitmap
);
165 static int64_t bat2sect(BDRVParallelsState
*s
, uint32_t idx
)
167 return (uint64_t)s
->bat_bitmap
[idx
] * s
->off_multiplier
;
170 static int64_t seek_to_sector(BDRVParallelsState
*s
, int64_t sector_num
)
172 uint32_t index
, offset
;
174 index
= sector_num
/ s
->tracks
;
175 offset
= sector_num
% s
->tracks
;
178 if ((index
>= s
->bat_size
) || (s
->bat_bitmap
[index
] == 0)) {
181 return bat2sect(s
, index
) + offset
;
184 static int cluster_remainder(BDRVParallelsState
*s
, int64_t sector_num
,
187 int ret
= s
->tracks
- sector_num
% s
->tracks
;
188 return MIN(nb_sectors
, ret
);
191 static int64_t allocate_cluster(BlockDriverState
*bs
, int64_t sector_num
)
193 BDRVParallelsState
*s
= bs
->opaque
;
194 uint32_t idx
, offset
, tmp
;
198 idx
= sector_num
/ s
->tracks
;
199 offset
= sector_num
% s
->tracks
;
201 if (idx
>= s
->bat_size
) {
204 if (s
->bat_bitmap
[idx
] != 0) {
205 return bat2sect(s
, idx
) + offset
;
208 pos
= bdrv_getlength(bs
->file
) >> BDRV_SECTOR_BITS
;
209 if (s
->has_truncate
) {
210 ret
= bdrv_truncate(bs
->file
, (pos
+ s
->tracks
) << BDRV_SECTOR_BITS
);
212 ret
= bdrv_write_zeroes(bs
->file
, pos
, s
->tracks
, 0);
218 s
->bat_bitmap
[idx
] = pos
/ s
->off_multiplier
;
220 tmp
= cpu_to_le32(s
->bat_bitmap
[idx
]);
222 ret
= bdrv_pwrite(bs
->file
,
223 sizeof(ParallelsHeader
) + idx
* sizeof(tmp
), &tmp
, sizeof(tmp
));
225 s
->bat_bitmap
[idx
] = 0;
228 return bat2sect(s
, idx
) + offset
;
231 static int64_t coroutine_fn
parallels_co_get_block_status(BlockDriverState
*bs
,
232 int64_t sector_num
, int nb_sectors
, int *pnum
)
234 BDRVParallelsState
*s
= bs
->opaque
;
237 qemu_co_mutex_lock(&s
->lock
);
238 offset
= seek_to_sector(s
, sector_num
);
239 qemu_co_mutex_unlock(&s
->lock
);
241 *pnum
= cluster_remainder(s
, sector_num
, nb_sectors
);
247 return (offset
<< BDRV_SECTOR_BITS
) |
248 BDRV_BLOCK_DATA
| BDRV_BLOCK_OFFSET_VALID
;
251 static coroutine_fn
int parallels_co_writev(BlockDriverState
*bs
,
252 int64_t sector_num
, int nb_sectors
, QEMUIOVector
*qiov
)
254 BDRVParallelsState
*s
= bs
->opaque
;
255 uint64_t bytes_done
= 0;
256 QEMUIOVector hd_qiov
;
259 qemu_iovec_init(&hd_qiov
, qiov
->niov
);
261 while (nb_sectors
> 0) {
265 qemu_co_mutex_lock(&s
->lock
);
266 position
= allocate_cluster(bs
, sector_num
);
267 qemu_co_mutex_unlock(&s
->lock
);
273 n
= cluster_remainder(s
, sector_num
, nb_sectors
);
274 nbytes
= n
<< BDRV_SECTOR_BITS
;
276 qemu_iovec_reset(&hd_qiov
);
277 qemu_iovec_concat(&hd_qiov
, qiov
, bytes_done
, nbytes
);
279 ret
= bdrv_co_writev(bs
->file
, position
, n
, &hd_qiov
);
286 bytes_done
+= nbytes
;
289 qemu_iovec_destroy(&hd_qiov
);
293 static coroutine_fn
int parallels_co_readv(BlockDriverState
*bs
,
294 int64_t sector_num
, int nb_sectors
, QEMUIOVector
*qiov
)
296 BDRVParallelsState
*s
= bs
->opaque
;
297 uint64_t bytes_done
= 0;
298 QEMUIOVector hd_qiov
;
301 qemu_iovec_init(&hd_qiov
, qiov
->niov
);
303 while (nb_sectors
> 0) {
307 qemu_co_mutex_lock(&s
->lock
);
308 position
= seek_to_sector(s
, sector_num
);
309 qemu_co_mutex_unlock(&s
->lock
);
311 n
= cluster_remainder(s
, sector_num
, nb_sectors
);
312 nbytes
= n
<< BDRV_SECTOR_BITS
;
315 qemu_iovec_memset(qiov
, bytes_done
, 0, nbytes
);
317 qemu_iovec_reset(&hd_qiov
);
318 qemu_iovec_concat(&hd_qiov
, qiov
, bytes_done
, nbytes
);
320 ret
= bdrv_co_readv(bs
->file
, position
, n
, &hd_qiov
);
328 bytes_done
+= nbytes
;
331 qemu_iovec_destroy(&hd_qiov
);
335 static int parallels_create(const char *filename
, QemuOpts
*opts
, Error
**errp
)
337 int64_t total_size
, cl_size
;
338 uint8_t tmp
[BDRV_SECTOR_SIZE
];
339 Error
*local_err
= NULL
;
340 BlockDriverState
*file
;
341 uint32_t bat_entries
, bat_sectors
;
342 ParallelsHeader header
;
345 total_size
= ROUND_UP(qemu_opt_get_size_del(opts
, BLOCK_OPT_SIZE
, 0),
347 cl_size
= ROUND_UP(qemu_opt_get_size_del(opts
, BLOCK_OPT_CLUSTER_SIZE
,
348 DEFAULT_CLUSTER_SIZE
), BDRV_SECTOR_SIZE
);
350 ret
= bdrv_create_file(filename
, opts
, &local_err
);
352 error_propagate(errp
, local_err
);
357 ret
= bdrv_open(&file
, filename
, NULL
, NULL
,
358 BDRV_O_RDWR
| BDRV_O_PROTOCOL
, NULL
, &local_err
);
360 error_propagate(errp
, local_err
);
363 ret
= bdrv_truncate(file
, 0);
368 bat_entries
= DIV_ROUND_UP(total_size
, cl_size
);
369 bat_sectors
= DIV_ROUND_UP(bat_entries
* sizeof(uint32_t) +
370 sizeof(ParallelsHeader
), cl_size
);
371 bat_sectors
= (bat_sectors
* cl_size
) >> BDRV_SECTOR_BITS
;
373 memset(&header
, 0, sizeof(header
));
374 memcpy(header
.magic
, HEADER_MAGIC2
, sizeof(header
.magic
));
375 header
.version
= cpu_to_le32(HEADER_VERSION
);
376 /* don't care much about geometry, it is not used on image level */
377 header
.heads
= cpu_to_le32(16);
378 header
.cylinders
= cpu_to_le32(total_size
/ BDRV_SECTOR_SIZE
/ 16 / 32);
379 header
.tracks
= cpu_to_le32(cl_size
>> BDRV_SECTOR_BITS
);
380 header
.bat_entries
= cpu_to_le32(bat_entries
);
381 header
.nb_sectors
= cpu_to_le64(DIV_ROUND_UP(total_size
, BDRV_SECTOR_SIZE
));
382 header
.data_off
= cpu_to_le32(bat_sectors
);
384 /* write all the data */
385 memset(tmp
, 0, sizeof(tmp
));
386 memcpy(tmp
, &header
, sizeof(header
));
388 ret
= bdrv_pwrite(file
, 0, tmp
, BDRV_SECTOR_SIZE
);
392 ret
= bdrv_write_zeroes(file
, 1, bat_sectors
- 1, 0);
403 error_setg_errno(errp
, -ret
, "Failed to create Parallels image");
407 static void parallels_close(BlockDriverState
*bs
)
409 BDRVParallelsState
*s
= bs
->opaque
;
410 g_free(s
->bat_bitmap
);
413 static QemuOptsList parallels_create_opts
= {
414 .name
= "parallels-create-opts",
415 .head
= QTAILQ_HEAD_INITIALIZER(parallels_create_opts
.head
),
418 .name
= BLOCK_OPT_SIZE
,
419 .type
= QEMU_OPT_SIZE
,
420 .help
= "Virtual disk size",
423 .name
= BLOCK_OPT_CLUSTER_SIZE
,
424 .type
= QEMU_OPT_SIZE
,
425 .help
= "Parallels image cluster size",
426 .def_value_str
= stringify(DEFAULT_CLUSTER_SIZE
),
428 { /* end of list */ }
432 static BlockDriver bdrv_parallels
= {
433 .format_name
= "parallels",
434 .instance_size
= sizeof(BDRVParallelsState
),
435 .bdrv_probe
= parallels_probe
,
436 .bdrv_open
= parallels_open
,
437 .bdrv_close
= parallels_close
,
438 .bdrv_co_get_block_status
= parallels_co_get_block_status
,
439 .bdrv_has_zero_init
= bdrv_has_zero_init_1
,
440 .bdrv_co_readv
= parallels_co_readv
,
441 .bdrv_co_writev
= parallels_co_writev
,
443 .bdrv_create
= parallels_create
,
444 .create_opts
= ¶llels_create_opts
,
447 static void bdrv_parallels_init(void)
449 bdrv_register(&bdrv_parallels
);
452 block_init(bdrv_parallels_init
);