block/parallels: add prealloc-mode and prealloc-size open paramemets
[qemu/ar7.git] / block / parallels.c
blob440938e18ab6da5feda73a22a57488e44b6b875f
1 /*
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
9 * available at
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
28 * THE SOFTWARE.
30 #include "qemu-common.h"
31 #include "block/block_int.h"
32 #include "qemu/module.h"
33 #include "qemu/bitmap.h"
34 #include "qapi/util.h"
36 /**************************************************************/
38 #define HEADER_MAGIC "WithoutFreeSpace"
39 #define HEADER_MAGIC2 "WithouFreSpacExt"
40 #define HEADER_VERSION 2
41 #define HEADER_INUSE_MAGIC (0x746F6E59)
43 #define DEFAULT_CLUSTER_SIZE 1048576 /* 1 MiB */
46 // always little-endian
47 typedef struct ParallelsHeader {
48 char magic[16]; // "WithoutFreeSpace"
49 uint32_t version;
50 uint32_t heads;
51 uint32_t cylinders;
52 uint32_t tracks;
53 uint32_t bat_entries;
54 uint64_t nb_sectors;
55 uint32_t inuse;
56 uint32_t data_off;
57 char padding[12];
58 } QEMU_PACKED ParallelsHeader;
61 typedef enum ParallelsPreallocMode {
62 PRL_PREALLOC_MODE_FALLOCATE = 0,
63 PRL_PREALLOC_MODE_TRUNCATE = 1,
64 PRL_PREALLOC_MODE_MAX = 2,
65 } ParallelsPreallocMode;
67 static const char *prealloc_mode_lookup[] = {
68 "falloc",
69 "truncate",
70 NULL,
74 typedef struct BDRVParallelsState {
75 /** Locking is conservative, the lock protects
76 * - image file extending (truncate, fallocate)
77 * - any access to block allocation table
79 CoMutex lock;
81 ParallelsHeader *header;
82 uint32_t header_size;
83 bool header_unclean;
85 unsigned long *bat_dirty_bmap;
86 unsigned int bat_dirty_block;
88 uint32_t *bat_bitmap;
89 unsigned int bat_size;
91 uint64_t prealloc_size;
92 ParallelsPreallocMode prealloc_mode;
94 unsigned int tracks;
96 unsigned int off_multiplier;
97 } BDRVParallelsState;
100 #define PARALLELS_OPT_PREALLOC_MODE "prealloc-mode"
101 #define PARALLELS_OPT_PREALLOC_SIZE "prealloc-size"
103 static QemuOptsList parallels_runtime_opts = {
104 .name = "parallels",
105 .head = QTAILQ_HEAD_INITIALIZER(parallels_runtime_opts.head),
106 .desc = {
108 .name = PARALLELS_OPT_PREALLOC_SIZE,
109 .type = QEMU_OPT_SIZE,
110 .help = "Preallocation size on image expansion",
111 .def_value_str = "128MiB",
114 .name = PARALLELS_OPT_PREALLOC_MODE,
115 .type = QEMU_OPT_STRING,
116 .help = "Preallocation mode on image expansion "
117 "(allowed values: falloc, truncate)",
118 .def_value_str = "falloc",
120 { /* end of list */ },
125 static int64_t bat2sect(BDRVParallelsState *s, uint32_t idx)
127 return (uint64_t)le32_to_cpu(s->bat_bitmap[idx]) * s->off_multiplier;
130 static uint32_t bat_entry_off(uint32_t idx)
132 return sizeof(ParallelsHeader) + sizeof(uint32_t) * idx;
135 static int64_t seek_to_sector(BDRVParallelsState *s, int64_t sector_num)
137 uint32_t index, offset;
139 index = sector_num / s->tracks;
140 offset = sector_num % s->tracks;
142 /* not allocated */
143 if ((index >= s->bat_size) || (s->bat_bitmap[index] == 0)) {
144 return -1;
146 return bat2sect(s, index) + offset;
149 static int cluster_remainder(BDRVParallelsState *s, int64_t sector_num,
150 int nb_sectors)
152 int ret = s->tracks - sector_num % s->tracks;
153 return MIN(nb_sectors, ret);
156 static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
157 int nb_sectors, int *pnum)
159 int64_t start_off = -2, prev_end_off = -2;
161 *pnum = 0;
162 while (nb_sectors > 0 || start_off == -2) {
163 int64_t offset = seek_to_sector(s, sector_num);
164 int to_end;
166 if (start_off == -2) {
167 start_off = offset;
168 prev_end_off = offset;
169 } else if (offset != prev_end_off) {
170 break;
173 to_end = cluster_remainder(s, sector_num, nb_sectors);
174 nb_sectors -= to_end;
175 sector_num += to_end;
176 *pnum += to_end;
178 if (offset > 0) {
179 prev_end_off += to_end;
182 return start_off;
185 static int64_t allocate_cluster(BlockDriverState *bs, int64_t sector_num)
187 BDRVParallelsState *s = bs->opaque;
188 uint32_t idx, offset;
189 int64_t pos;
190 int ret;
192 idx = sector_num / s->tracks;
193 offset = sector_num % s->tracks;
195 if (idx >= s->bat_size) {
196 return -EINVAL;
198 if (s->bat_bitmap[idx] != 0) {
199 return bat2sect(s, idx) + offset;
202 pos = bdrv_getlength(bs->file) >> BDRV_SECTOR_BITS;
203 if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
204 ret = bdrv_truncate(bs->file, (pos + s->tracks) << BDRV_SECTOR_BITS);
205 } else {
206 ret = bdrv_write_zeroes(bs->file, pos, s->tracks, 0);
208 if (ret < 0) {
209 return ret;
212 s->bat_bitmap[idx] = cpu_to_le32(pos / s->off_multiplier);
214 bitmap_set(s->bat_dirty_bmap, bat_entry_off(idx) / s->bat_dirty_block, 1);
215 return bat2sect(s, idx) + offset;
219 static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
221 BDRVParallelsState *s = bs->opaque;
222 unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
223 unsigned long bit;
225 qemu_co_mutex_lock(&s->lock);
227 bit = find_first_bit(s->bat_dirty_bmap, size);
228 while (bit < size) {
229 uint32_t off = bit * s->bat_dirty_block;
230 uint32_t to_write = s->bat_dirty_block;
231 int ret;
233 if (off + to_write > s->header_size) {
234 to_write = s->header_size - off;
236 ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off, to_write);
237 if (ret < 0) {
238 qemu_co_mutex_unlock(&s->lock);
239 return ret;
241 bit = find_next_bit(s->bat_dirty_bmap, size, bit + 1);
243 bitmap_zero(s->bat_dirty_bmap, size);
245 qemu_co_mutex_unlock(&s->lock);
246 return 0;
250 static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs,
251 int64_t sector_num, int nb_sectors, int *pnum)
253 BDRVParallelsState *s = bs->opaque;
254 int64_t offset;
256 qemu_co_mutex_lock(&s->lock);
257 offset = block_status(s, sector_num, nb_sectors, pnum);
258 qemu_co_mutex_unlock(&s->lock);
260 if (offset < 0) {
261 return 0;
264 return (offset << BDRV_SECTOR_BITS) |
265 BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
268 static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
269 int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
271 BDRVParallelsState *s = bs->opaque;
272 uint64_t bytes_done = 0;
273 QEMUIOVector hd_qiov;
274 int ret = 0;
276 qemu_iovec_init(&hd_qiov, qiov->niov);
278 while (nb_sectors > 0) {
279 int64_t position;
280 int n, nbytes;
282 qemu_co_mutex_lock(&s->lock);
283 position = allocate_cluster(bs, sector_num);
284 qemu_co_mutex_unlock(&s->lock);
285 if (position < 0) {
286 ret = (int)position;
287 break;
290 n = cluster_remainder(s, sector_num, nb_sectors);
291 nbytes = n << BDRV_SECTOR_BITS;
293 qemu_iovec_reset(&hd_qiov);
294 qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
296 ret = bdrv_co_writev(bs->file, position, n, &hd_qiov);
297 if (ret < 0) {
298 break;
301 nb_sectors -= n;
302 sector_num += n;
303 bytes_done += nbytes;
306 qemu_iovec_destroy(&hd_qiov);
307 return ret;
310 static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
311 int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
313 BDRVParallelsState *s = bs->opaque;
314 uint64_t bytes_done = 0;
315 QEMUIOVector hd_qiov;
316 int ret = 0;
318 qemu_iovec_init(&hd_qiov, qiov->niov);
320 while (nb_sectors > 0) {
321 int64_t position;
322 int n, nbytes;
324 qemu_co_mutex_lock(&s->lock);
325 position = block_status(s, sector_num, nb_sectors, &n);
326 qemu_co_mutex_unlock(&s->lock);
328 nbytes = n << BDRV_SECTOR_BITS;
330 if (position < 0) {
331 qemu_iovec_memset(qiov, bytes_done, 0, nbytes);
332 } else {
333 qemu_iovec_reset(&hd_qiov);
334 qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
336 ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
337 if (ret < 0) {
338 break;
342 nb_sectors -= n;
343 sector_num += n;
344 bytes_done += nbytes;
347 qemu_iovec_destroy(&hd_qiov);
348 return ret;
352 static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
353 BdrvCheckMode fix)
355 BDRVParallelsState *s = bs->opaque;
356 int64_t size, prev_off, high_off;
357 int ret;
358 uint32_t i;
359 bool flush_bat = false;
360 int cluster_size = s->tracks << BDRV_SECTOR_BITS;
362 size = bdrv_getlength(bs->file);
363 if (size < 0) {
364 res->check_errors++;
365 return size;
368 if (s->header_unclean) {
369 fprintf(stderr, "%s image was not closed correctly\n",
370 fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
371 res->corruptions++;
372 if (fix & BDRV_FIX_ERRORS) {
373 /* parallels_close will do the job right */
374 res->corruptions_fixed++;
375 s->header_unclean = false;
379 res->bfi.total_clusters = s->bat_size;
380 res->bfi.compressed_clusters = 0; /* compression is not supported */
382 high_off = 0;
383 prev_off = 0;
384 for (i = 0; i < s->bat_size; i++) {
385 int64_t off = bat2sect(s, i) << BDRV_SECTOR_BITS;
386 if (off == 0) {
387 prev_off = 0;
388 continue;
391 /* cluster outside the image */
392 if (off > size) {
393 fprintf(stderr, "%s cluster %u is outside image\n",
394 fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
395 res->corruptions++;
396 if (fix & BDRV_FIX_ERRORS) {
397 prev_off = 0;
398 s->bat_bitmap[i] = 0;
399 res->corruptions_fixed++;
400 flush_bat = true;
401 continue;
405 res->bfi.allocated_clusters++;
406 if (off > high_off) {
407 high_off = off;
410 if (prev_off != 0 && (prev_off + cluster_size) != off) {
411 res->bfi.fragmented_clusters++;
413 prev_off = off;
416 if (flush_bat) {
417 ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
418 if (ret < 0) {
419 res->check_errors++;
420 return ret;
424 res->image_end_offset = high_off + cluster_size;
425 if (size > res->image_end_offset) {
426 int64_t count;
427 count = DIV_ROUND_UP(size - res->image_end_offset, cluster_size);
428 fprintf(stderr, "%s space leaked at the end of the image %" PRId64 "\n",
429 fix & BDRV_FIX_LEAKS ? "Repairing" : "ERROR",
430 size - res->image_end_offset);
431 res->leaks += count;
432 if (fix & BDRV_FIX_LEAKS) {
433 ret = bdrv_truncate(bs->file, res->image_end_offset);
434 if (ret < 0) {
435 res->check_errors++;
436 return ret;
438 res->leaks_fixed += count;
442 return 0;
446 static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
448 int64_t total_size, cl_size;
449 uint8_t tmp[BDRV_SECTOR_SIZE];
450 Error *local_err = NULL;
451 BlockDriverState *file;
452 uint32_t bat_entries, bat_sectors;
453 ParallelsHeader header;
454 int ret;
456 total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
457 BDRV_SECTOR_SIZE);
458 cl_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
459 DEFAULT_CLUSTER_SIZE), BDRV_SECTOR_SIZE);
461 ret = bdrv_create_file(filename, opts, &local_err);
462 if (ret < 0) {
463 error_propagate(errp, local_err);
464 return ret;
467 file = NULL;
468 ret = bdrv_open(&file, filename, NULL, NULL,
469 BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
470 if (ret < 0) {
471 error_propagate(errp, local_err);
472 return ret;
474 ret = bdrv_truncate(file, 0);
475 if (ret < 0) {
476 goto exit;
479 bat_entries = DIV_ROUND_UP(total_size, cl_size);
480 bat_sectors = DIV_ROUND_UP(bat_entry_off(bat_entries), cl_size);
481 bat_sectors = (bat_sectors * cl_size) >> BDRV_SECTOR_BITS;
483 memset(&header, 0, sizeof(header));
484 memcpy(header.magic, HEADER_MAGIC2, sizeof(header.magic));
485 header.version = cpu_to_le32(HEADER_VERSION);
486 /* don't care much about geometry, it is not used on image level */
487 header.heads = cpu_to_le32(16);
488 header.cylinders = cpu_to_le32(total_size / BDRV_SECTOR_SIZE / 16 / 32);
489 header.tracks = cpu_to_le32(cl_size >> BDRV_SECTOR_BITS);
490 header.bat_entries = cpu_to_le32(bat_entries);
491 header.nb_sectors = cpu_to_le64(DIV_ROUND_UP(total_size, BDRV_SECTOR_SIZE));
492 header.data_off = cpu_to_le32(bat_sectors);
494 /* write all the data */
495 memset(tmp, 0, sizeof(tmp));
496 memcpy(tmp, &header, sizeof(header));
498 ret = bdrv_pwrite(file, 0, tmp, BDRV_SECTOR_SIZE);
499 if (ret < 0) {
500 goto exit;
502 ret = bdrv_write_zeroes(file, 1, bat_sectors - 1, 0);
503 if (ret < 0) {
504 goto exit;
506 ret = 0;
508 done:
509 bdrv_unref(file);
510 return ret;
512 exit:
513 error_setg_errno(errp, -ret, "Failed to create Parallels image");
514 goto done;
518 static int parallels_probe(const uint8_t *buf, int buf_size,
519 const char *filename)
521 const ParallelsHeader *ph = (const void *)buf;
523 if (buf_size < sizeof(ParallelsHeader)) {
524 return 0;
527 if ((!memcmp(ph->magic, HEADER_MAGIC, 16) ||
528 !memcmp(ph->magic, HEADER_MAGIC2, 16)) &&
529 (le32_to_cpu(ph->version) == HEADER_VERSION)) {
530 return 100;
533 return 0;
536 static int parallels_update_header(BlockDriverState *bs)
538 BDRVParallelsState *s = bs->opaque;
539 unsigned size = MAX(bdrv_opt_mem_align(bs->file), sizeof(ParallelsHeader));
541 if (size > s->header_size) {
542 size = s->header_size;
544 return bdrv_pwrite_sync(bs->file, 0, s->header, size);
547 static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
548 Error **errp)
550 BDRVParallelsState *s = bs->opaque;
551 ParallelsHeader ph;
552 int ret, size;
553 QemuOpts *opts = NULL;
554 Error *local_err = NULL;
555 char *buf;
557 ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
558 if (ret < 0) {
559 goto fail;
562 bs->total_sectors = le64_to_cpu(ph.nb_sectors);
564 if (le32_to_cpu(ph.version) != HEADER_VERSION) {
565 goto fail_format;
567 if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {
568 s->off_multiplier = 1;
569 bs->total_sectors = 0xffffffff & bs->total_sectors;
570 } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {
571 s->off_multiplier = le32_to_cpu(ph.tracks);
572 } else {
573 goto fail_format;
576 s->tracks = le32_to_cpu(ph.tracks);
577 if (s->tracks == 0) {
578 error_setg(errp, "Invalid image: Zero sectors per track");
579 ret = -EINVAL;
580 goto fail;
582 if (s->tracks > INT32_MAX/513) {
583 error_setg(errp, "Invalid image: Too big cluster");
584 ret = -EFBIG;
585 goto fail;
588 s->bat_size = le32_to_cpu(ph.bat_entries);
589 if (s->bat_size > INT_MAX / sizeof(uint32_t)) {
590 error_setg(errp, "Catalog too large");
591 ret = -EFBIG;
592 goto fail;
595 size = bat_entry_off(s->bat_size);
596 s->header_size = ROUND_UP(size, bdrv_opt_mem_align(bs->file));
597 s->header = qemu_try_blockalign(bs->file, s->header_size);
598 if (s->header == NULL) {
599 ret = -ENOMEM;
600 goto fail;
602 if (le32_to_cpu(ph.data_off) < s->header_size) {
603 /* there is not enough unused space to fit to block align between BAT
604 and actual data. We can't avoid read-modify-write... */
605 s->header_size = size;
608 ret = bdrv_pread(bs->file, 0, s->header, s->header_size);
609 if (ret < 0) {
610 goto fail;
612 s->bat_bitmap = (uint32_t *)(s->header + 1);
614 if (le32_to_cpu(ph.inuse) == HEADER_INUSE_MAGIC) {
615 /* Image was not closed correctly. The check is mandatory */
616 s->header_unclean = true;
617 if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) {
618 error_setg(errp, "parallels: Image was not closed correctly; "
619 "cannot be opened read/write");
620 ret = -EACCES;
621 goto fail;
625 opts = qemu_opts_create(&parallels_runtime_opts, NULL, 0, &local_err);
626 if (local_err != NULL) {
627 goto fail_options;
630 qemu_opts_absorb_qdict(opts, options, &local_err);
631 if (local_err != NULL) {
632 goto fail_options;
635 s->prealloc_size =
636 qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
637 s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
638 buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
639 s->prealloc_mode = qapi_enum_parse(prealloc_mode_lookup, buf,
640 PRL_PREALLOC_MODE_MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
641 g_free(buf);
642 if (local_err != NULL) {
643 goto fail_options;
645 if (!bdrv_has_zero_init(bs->file) ||
646 bdrv_truncate(bs->file, bdrv_getlength(bs->file)) != 0) {
647 s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
650 if (flags & BDRV_O_RDWR) {
651 s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC);
652 ret = parallels_update_header(bs);
653 if (ret < 0) {
654 goto fail;
658 s->bat_dirty_block = 4 * getpagesize();
659 s->bat_dirty_bmap =
660 bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block));
662 qemu_co_mutex_init(&s->lock);
663 return 0;
665 fail_format:
666 error_setg(errp, "Image not in Parallels format");
667 ret = -EINVAL;
668 fail:
669 qemu_vfree(s->header);
670 return ret;
672 fail_options:
673 error_propagate(errp, local_err);
674 ret = -EINVAL;
675 goto fail;
679 static void parallels_close(BlockDriverState *bs)
681 BDRVParallelsState *s = bs->opaque;
683 if (bs->open_flags & BDRV_O_RDWR) {
684 s->header->inuse = 0;
685 parallels_update_header(bs);
688 g_free(s->bat_dirty_bmap);
689 qemu_vfree(s->header);
692 static QemuOptsList parallels_create_opts = {
693 .name = "parallels-create-opts",
694 .head = QTAILQ_HEAD_INITIALIZER(parallels_create_opts.head),
695 .desc = {
697 .name = BLOCK_OPT_SIZE,
698 .type = QEMU_OPT_SIZE,
699 .help = "Virtual disk size",
702 .name = BLOCK_OPT_CLUSTER_SIZE,
703 .type = QEMU_OPT_SIZE,
704 .help = "Parallels image cluster size",
705 .def_value_str = stringify(DEFAULT_CLUSTER_SIZE),
707 { /* end of list */ }
711 static BlockDriver bdrv_parallels = {
712 .format_name = "parallels",
713 .instance_size = sizeof(BDRVParallelsState),
714 .bdrv_probe = parallels_probe,
715 .bdrv_open = parallels_open,
716 .bdrv_close = parallels_close,
717 .bdrv_co_get_block_status = parallels_co_get_block_status,
718 .bdrv_has_zero_init = bdrv_has_zero_init_1,
719 .bdrv_co_flush_to_os = parallels_co_flush_to_os,
720 .bdrv_co_readv = parallels_co_readv,
721 .bdrv_co_writev = parallels_co_writev,
723 .bdrv_create = parallels_create,
724 .bdrv_check = parallels_check,
725 .create_opts = &parallels_create_opts,
728 static void bdrv_parallels_init(void)
730 bdrv_register(&bdrv_parallels);
733 block_init(bdrv_parallels_init);