static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
			       tid_t sequence, struct recovery_info *info)
{
	journal_revoke_header_t *header;
	int offset, max;
	int record_len = 4;

	header = (journal_revoke_header_t *) bh->b_data;
	offset = sizeof(journal_revoke_header_t);
	max = be32_to_cpu(header->r_count);

	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
		record_len = 8;

	while (offset < max) {
		unsigned long long blocknr;
		int err;

		if (record_len == 4)
			blocknr = ext2fs_be32_to_cpu(*((__be32 *)(bh->b_data +
								  offset)));
		else
			blocknr = ext2fs_be64_to_cpu(*((__be64 *)(bh->b_data +
								  offset)));
		offset += record_len;
		err = journal_set_revoke(journal, blocknr, sequence);
		if (err)
			return err;
		++info->nr_revokes;
	}
	return 0;
}
Example #2
0
static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
			       tid_t sequence, struct recovery_info *info)
{
	journal_revoke_header_t *header;
	int offset, max;
	int csum_size = 0;
	__u32 rcount;
	int record_len = 4;

	header = (journal_revoke_header_t *) bh->b_data;
	offset = sizeof(journal_revoke_header_t);
	rcount = ext2fs_be32_to_cpu(header->r_count);

	if (!jbd2_revoke_block_csum_verify(journal, header))
		return -EFSBADCRC;

	if (journal_has_csum_v2or3(journal))
		csum_size = sizeof(struct journal_revoke_tail);
	if (rcount > journal->j_blocksize - csum_size)
		return -EINVAL;
	max = rcount;

	if (jfs_has_feature_64bit(journal))
		record_len = 8;

	while (offset + record_len <= max) {
		unsigned long long blocknr;
		int err;

		if (record_len == 4)
			blocknr = ext2fs_be32_to_cpu(* ((__u32 *) (bh->b_data+offset)));
		else
			blocknr = ext2fs_be64_to_cpu(* ((__u64 *) (bh->b_data+offset)));
		offset += record_len;
		err = journal_set_revoke(journal, blocknr, sequence);
		if (err)
			return err;
		++info->nr_revokes;
	}
	return 0;
}
Example #3
0
int qcow2_write_raw_image(int qcow2_fd, int raw_fd,
			      struct ext2_qcow2_hdr *hdr)
{
	struct ext2_qcow2_image img;
	errcode_t ret = 0;
	unsigned int l1_index, l2_index;
	ext2_off64_t offset;
	blk64_t *l1_table, *l2_table = 0;
	void *copy_buf = NULL;
	size_t size;

	if (hdr->crypt_method)
		return -QCOW_ENCRYPTED;

	img.fd = qcow2_fd;
	img.hdr = hdr;
	img.l2_cache = NULL;
	img.l1_table = NULL;
	img.cluster_bits = ext2fs_be32_to_cpu(hdr->cluster_bits);
	img.cluster_size = 1 << img.cluster_bits;
	img.l1_size = ext2fs_be32_to_cpu(hdr->l1_size);
	img.l1_offset = ext2fs_be64_to_cpu(hdr->l1_table_offset);
	img.l2_size = 1 << (img.cluster_bits - 3);
	img.image_size = ext2fs_be64_to_cpu(hdr->size);


	ret = ext2fs_get_memzero(img.cluster_size, &l2_table);
	if (ret)
		goto out;

	ret = ext2fs_get_memzero(1 << img.cluster_bits, &copy_buf);
	if (ret)
		goto out;

	if (ext2fs_llseek(raw_fd, 0, SEEK_SET) < 0) {
		ret = errno;
		goto out;
	}

	ret = qcow2_read_l1_table(&img);
	if (ret)
		goto out;

	l1_table = img.l1_table;
	/* Walk through l1 table */
	for (l1_index = 0; l1_index < img.l1_size; l1_index++) {
		ext2_off64_t off_out;

		offset = ext2fs_be64_to_cpu(l1_table[l1_index]) &
			 ~QCOW_OFLAG_COPIED;

		if ((offset > img.image_size) ||
		    (offset <= 0))
			continue;

		if (offset & QCOW_OFLAG_COMPRESSED) {
			ret = -QCOW_COMPRESSED;
			goto out;
		}

		ret = qcow2_read_l2_table(&img, offset, &l2_table);
		if (ret)
			break;

		/* Walk through l2 table and copy data blocks into raw image */
		for (l2_index = 0; l2_index < img.l2_size; l2_index++) {
			offset = ext2fs_be64_to_cpu(l2_table[l2_index]) &
				 ~QCOW_OFLAG_COPIED;

			if (offset == 0)
				continue;

			off_out = (l1_index * img.l2_size) +
				  l2_index;
			off_out <<= img.cluster_bits;
			ret = qcow2_copy_data(qcow2_fd, raw_fd, offset,
					off_out, copy_buf, img.cluster_size);
			if (ret)
				goto out;
		}
	}

	/* Resize the output image to the filesystem size */
	if (ext2fs_llseek(raw_fd, img.image_size - 1, SEEK_SET) < 0)
		return errno;

	((char *)copy_buf)[0] = 0;
	size = write(raw_fd, copy_buf, 1);
	if (size != 1)
		return errno;

out:
	if (copy_buf)
		ext2fs_free_mem(&copy_buf);
	if (img.l1_table)
		ext2fs_free_mem(&img.l1_table);
	if (l2_table)
		ext2fs_free_mem(&l2_table);
	return ret;
}