parallels: Image repairing in parallels_open()
Repair an image at opening if the image is unclean or out-of-image corruption was detected. Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com> Reviewed-by: Denis V. Lunev <den@openvz.org> Signed-off-by: Denis V. Lunev <den@openvz.org>
This commit is contained in:
parent
6bb8bc6367
commit
cfce1091d5
@ -951,7 +951,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
BDRVParallelsState *s = bs->opaque;
|
||||
ParallelsHeader ph;
|
||||
int ret, size, i;
|
||||
int64_t file_nb_sectors;
|
||||
int64_t file_nb_sectors, sector;
|
||||
QemuOpts *opts = NULL;
|
||||
Error *local_err = NULL;
|
||||
char *buf;
|
||||
@ -1024,11 +1024,6 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
*/
|
||||
s->header_size = size;
|
||||
}
|
||||
if (s->data_end > file_nb_sectors) {
|
||||
error_setg(errp, "Invalid image: incorrect data_off field");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_pread(bs->file, 0, s->header_size, s->header, 0);
|
||||
if (ret < 0) {
|
||||
@ -1036,33 +1031,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
s->bat_bitmap = (uint32_t *)(s->header + 1);
|
||||
|
||||
for (i = 0; i < s->bat_size; i++) {
|
||||
int64_t off = bat2sect(s, i);
|
||||
if (off >= file_nb_sectors) {
|
||||
if (flags & BDRV_O_CHECK) {
|
||||
continue;
|
||||
}
|
||||
error_setg(errp, "parallels: Offset %" PRIi64 " in BAT[%d] entry "
|
||||
"is larger than file size (%" PRIi64 ")",
|
||||
off << BDRV_SECTOR_BITS, i,
|
||||
file_nb_sectors << BDRV_SECTOR_BITS);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (off >= s->data_end) {
|
||||
s->data_end = off + s->tracks;
|
||||
}
|
||||
}
|
||||
|
||||
if (le32_to_cpu(ph.inuse) == HEADER_INUSE_MAGIC) {
|
||||
/* Image was not closed correctly. The check is mandatory */
|
||||
s->header_unclean = true;
|
||||
if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) {
|
||||
error_setg(errp, "parallels: Image was not closed correctly; "
|
||||
"cannot be opened read/write");
|
||||
ret = -EACCES;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
opts = qemu_opts_create(¶llels_runtime_opts, NULL, 0, errp);
|
||||
@ -1123,10 +1093,40 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
bdrv_get_device_or_node_name(bs));
|
||||
ret = migrate_add_blocker(s->migration_blocker, errp);
|
||||
if (ret < 0) {
|
||||
error_free(s->migration_blocker);
|
||||
error_setg(errp, "Migration blocker error");
|
||||
goto fail;
|
||||
}
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
|
||||
for (i = 0; i < s->bat_size; i++) {
|
||||
sector = bat2sect(s, i);
|
||||
if (sector + s->tracks > s->data_end) {
|
||||
s->data_end = sector + s->tracks;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't repair the image here if it's opened for checks. Also we don't
|
||||
* want to change inactive images and can't change readonly images.
|
||||
*/
|
||||
if ((flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) || !(flags & BDRV_O_RDWR)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Repair the image if it's dirty or
|
||||
* out-of-image corruption was detected.
|
||||
*/
|
||||
if (s->data_end > file_nb_sectors || s->header_unclean) {
|
||||
BdrvCheckResult res;
|
||||
ret = bdrv_check(bs, &res, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not repair corrupted image");
|
||||
migrate_del_blocker(s->migration_blocker);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_format:
|
||||
@ -1134,6 +1134,12 @@ fail_format:
|
||||
fail_options:
|
||||
ret = -EINVAL;
|
||||
fail:
|
||||
/*
|
||||
* "s" object was allocated by g_malloc0 so we can safely
|
||||
* try to free its fields even they were not allocated.
|
||||
*/
|
||||
error_free(s->migration_blocker);
|
||||
g_free(s->bat_dirty_bmap);
|
||||
qemu_vfree(s->header);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user