Beispiel #1
0
static int
vhd_journal_write_header(vhd_journal_t *j, vhd_journal_header_t *header)
{
	int err;
	size_t size;
	vhd_journal_header_t h;

	memcpy(&h, header, sizeof(vhd_journal_header_t));

	err = vhd_journal_validate_header(j, &h);
	if (err)
		return err;

	vhd_journal_header_out(&h);
	size = sizeof(vhd_journal_header_t);

	err  = vhd_journal_seek(j, 0, SEEK_SET);
	if (err)
		return err;

	err = vhd_journal_write(j, &h, size);
	if (err)
		return err;

	return 0;
}
Beispiel #2
0
static int
vhd_journal_validate_header(vhd_journal_t *j, vhd_journal_header_t *header)
{
	int err;
	off64_t eof;

	if (memcmp(header->cookie,
		   VHD_JOURNAL_HEADER_COOKIE, sizeof(header->cookie)))
		return -EINVAL;

	err = vhd_journal_seek(j, j->header.journal_eof, SEEK_SET);
	if (err)
		return err;

	eof = vhd_journal_position(j);
	if (eof == (off64_t)-1)
		return -errno;

	if (j->header.journal_data_offset > j->header.journal_eof)
		return -EINVAL;

	if (j->header.journal_metadata_offset > j->header.journal_eof)
		return -EINVAL;

	return 0;
}
Beispiel #3
0
static int
vhd_journal_update(vhd_journal_t *j, off_t offset,
		   char *buf, size_t size, uint32_t type)
{
	int err;
	off_t eof;
	uint64_t *off, off_bak;
	uint32_t *entries;
	vhd_journal_entry_t entry;

	entry.type     = type;
	entry.size     = size;
	entry.offset   = offset;
	entry.cookie   = VHD_JOURNAL_ENTRY_COOKIE;
	entry.checksum = vhd_journal_checksum_entry(&entry, buf, size);

	err = vhd_journal_seek(j, j->header.journal_eof, SEEK_SET);
	if (err)
		return err;

	err = vhd_journal_write_entry(j, &entry);
	if (err)
		goto fail;

	err = vhd_journal_write(j, buf, size);
	if (err)
		goto fail;

	if (type == VHD_JOURNAL_ENTRY_TYPE_DATA) {
		off     = &j->header.journal_data_offset;
		entries = &j->header.journal_data_entries;
	} else {
		off     = &j->header.journal_metadata_offset;
		entries = &j->header.journal_metadata_entries;
	}

	off_bak = *off;
	if (!(*entries)++)
		*off = j->header.journal_eof;
	j->header.journal_eof += (size + sizeof(vhd_journal_entry_t));

	err = vhd_journal_write_header(j, &j->header);
	if (err) {
		if (!--(*entries))
			*off = off_bak;
		j->header.journal_eof -= (size + sizeof(vhd_journal_entry_t));
		goto fail;
	}

	return 0;

fail:
	if (!j->is_block)
		vhd_journal_truncate(j, j->header.journal_eof);
	return err;
}
Beispiel #4
0
static int
vhd_journal_read_journal_header(vhd_journal_t *j, vhd_journal_header_t *header)
{
	int err;
	size_t size;

	size = sizeof(vhd_journal_header_t);
	err  = vhd_journal_seek(j, 0, SEEK_SET);
	if (err)
		return err;

	err  = vhd_journal_read(j, header, size);
	if (err)
		return err;

	vhd_journal_header_in(header);

	return vhd_journal_validate_header(j, header);
}
Beispiel #5
0
static int
vhd_journal_restore_metadata(vhd_journal_t *j)
{
	off64_t off;
	char **locators;
	vhd_footer_t copy;
	vhd_context_t *vhd;
	int i, locs, hlocs, err;

	vhd      = &j->vhd;
	locs     = 0;
	hlocs    = 0;
	locators = NULL;

	err = vhd_journal_seek(j, sizeof(vhd_journal_header_t), SEEK_SET);
	if (err)
		return err;

	err  = vhd_journal_read_footer(j, &vhd->footer);
	if (err)
		return err;

	if (!vhd_type_dynamic(vhd))
		goto restore;

	err  = vhd_journal_read_footer_copy(j, &copy);
	if (err)
		return err;

	err  = vhd_journal_read_header(j, &vhd->header);
	if (err)
		return err;

	for (hlocs = 0, i = 0; i < vhd_parent_locator_count(vhd); i++) {
		if (vhd_validate_platform_code(vhd->header.loc[i].code))
			return err;

		if (vhd->header.loc[i].code != PLAT_CODE_NONE)
			hlocs++;
	}

	if (hlocs) {
		err  = vhd_journal_read_locators(j, &locators, &locs);
		if (err)
			return err;

		if (hlocs != locs) {
			err = -EINVAL;
			goto out;
		}
	}

	err  = vhd_journal_read_bat(j, &vhd->bat);
	if (err)
		goto out;

	if (vhd_has_batmap(vhd)) {
		err  = vhd_journal_read_batmap(j, &vhd->batmap);
		if (err)
			goto out;
	}

restore:
	off  = vhd_journal_position(j);
	if (off == (off64_t)-1)
		return -errno;

	if (j->header.journal_data_offset != off)
		return -EINVAL;

	err  = vhd_journal_restore_footer(j, &vhd->footer);
	if (err)
		goto out;

	if (!vhd_type_dynamic(vhd))
		goto out;

	err  = vhd_journal_restore_footer_copy(j, &copy);
	if (err)
		goto out;

	err  = vhd_journal_restore_header(j, &vhd->header);
	if (err)
		goto out;

	if (locs) {
		err = vhd_journal_restore_locators(j, locators, locs);
		if (err)
			goto out;
	}

	err  = vhd_journal_restore_bat(j, &vhd->bat);
	if (err)
		goto out;

	if (vhd_has_batmap(vhd)) {
		err  = vhd_journal_restore_batmap(j, &vhd->batmap);
		if (err)
			goto out;
	}

	err = 0;

out:
	if (locators) {
		for (i = 0; i < locs; i++)
			free(locators[i]);
		free(locators);
	}

	if (!err && !vhd->is_block)
		err = ftruncate(vhd->fd,
			  j->header.vhd_footer_offset +
			  sizeof(vhd_footer_t));

	return err;
}
Beispiel #6
0
static int
vhd_journal_read_locators(vhd_journal_t *j, char ***locators, int *locs)
{
	int err, n, _locs;
	char **_locators;
	void *buf;
	off_t pos;
	vhd_journal_entry_t entry;

	_locs     = 0;
	*locs     = 0;
	*locators = NULL;

	n = sizeof(j->vhd.header.loc) / sizeof(vhd_parent_locator_t);
	_locators = calloc(n, sizeof(char *));
	if (!_locators)
		return -ENOMEM;

	for (;;) {
		buf = NULL;

		pos = vhd_journal_position(j);
		err = vhd_journal_read_entry(j, &entry);
		if (err)
			goto fail;

		if (entry.type != VHD_JOURNAL_ENTRY_TYPE_LOCATOR) {
			err = vhd_journal_seek(j, pos, SEEK_SET);
			if (err)
				goto fail;
			break;
		}

		if (_locs >= n) {
			err = -EINVAL;
			goto fail;
		}

		err = posix_memalign(&buf, VHD_SECTOR_SIZE, entry.size);
		if (err) {
			err = -err;
			buf = NULL;
			goto fail;
		}

		err = vhd_journal_read(j, buf, entry.size);
		if (err)
			goto fail;

		_locators[_locs++] = buf;
		err                = 0;
	}


	*locs     = _locs;
	*locators = _locators;

	return 0;

fail:
	if (_locators) {
		for (n = 0; n < _locs; n++)
			free(_locators[n]);
		free(_locators);
	}
	return err;
}
Beispiel #7
0
/*
 * revert indicates the transaction failed
 * and we should revert any changes via the undo log
 */
int
vhd_journal_revert(vhd_journal_t *j)
{
	int i, err;
	char *file;
	void *buf;
	vhd_context_t *vhd;
	vhd_journal_entry_t entry;

	err  = 0;
	vhd  = &j->vhd;
	buf  = NULL;

	file = strdup(vhd->file);
	if (!file)
		return -ENOMEM;

	vhd_close(&j->vhd);
	j->vhd.fd = open(file, O_RDWR | O_DIRECT | O_LARGEFILE);
	if (j->vhd.fd == -1) {
		free(file);
		return -errno;
	}

	err = vhd_test_file_fixed(file, &vhd->is_block);
	if (err) {
		free(file);
		return err;
	}

	err  = vhd_journal_restore_metadata(j);
	if (err) {
		free(file);
		return err;
	}

	close(vhd->fd);
	free(vhd->bat.bat);
	free(vhd->batmap.map);

	err = vhd_open(vhd, file, VHD_OPEN_RDWR);
	free(file);
	if (err)
		return err;

	err = vhd_journal_seek(j, j->header.journal_data_offset, SEEK_SET);
	if (err)
		return err;

	for (i = 0; i < j->header.journal_data_entries; i++) {
		err = vhd_journal_read_entry(j, &entry);
		if (err)
			goto end;

		err = posix_memalign(&buf, VHD_SECTOR_SIZE, entry.size);
		if (err) {
			err = -err;
			buf = NULL;
			goto end;
		}

		err = vhd_journal_read(j, buf, entry.size);
		if (err)
			goto end;

		err = vhd_journal_validate_entry_data(&entry, buf);
		if (err)
			goto end;

		err = vhd_seek(vhd, entry.offset, SEEK_SET);
		if (err)
			goto end;

		err = vhd_write(vhd, buf, entry.size);
		if (err)
			goto end;

		err = 0;

	end:
		free(buf);
		buf = NULL;
		if (err)
			break;
	}

	if (err)
		return err;

	if (!vhd->is_block) {
		err = ftruncate(vhd->fd, j->header.vhd_footer_offset +
				sizeof(vhd_footer_t));
		if (err)
			return -errno;
	}

	return vhd_journal_sync(j);
}