Beispiel #1
0
static int
vhd_read_data(vhd_context_t *vhd, uint64_t sec, int count, int hex)
{
	void *buf;
	uint64_t cur;
	int err, max, secs;

	if (vhd_sectors_to_bytes(sec + count) > vhd->footer.curr_size)
		return -ERANGE;

	max = MIN(vhd_sectors_to_bytes(count), VHD_BLOCK_SIZE);
	err = posix_memalign(&buf, VHD_SECTOR_SIZE, max);
	if (err)
		return -err;

	cur = sec;
	while (count) {
		int gcc;

		secs = MIN((max >> VHD_SECTOR_SHIFT), count);
		err  = vhd_io_read(vhd, buf, cur, secs);
		if (err)
			break;

		gcc = write(STDOUT_FILENO, buf, vhd_sectors_to_bytes(secs));
		if (gcc)
			;

		cur   += secs;
		count -= secs;
	}

	free(buf);
	return err;
}
Beispiel #2
0
static int
vhd_print_logical_to_physical(vhd_context_t *vhd,
			      uint64_t sector, int count, int hex)
{
	int i;
	uint32_t blk, lsec;
	uint64_t cur, offset;

	if (vhd_sectors_to_bytes(sector + count) > vhd->footer.curr_size) {
		fprintf(stderr, "sector %s past end of file\n",
			conv(hex, sector + count));
			return -ERANGE;
	}

	for (i = 0; i < count; i++) {
		cur    = sector + i;
		blk    = cur / vhd->spb;
		lsec   = cur % vhd->spb;
		offset = vhd->bat.bat[blk];

		if (offset != DD_BLK_UNUSED) {
			offset += lsec + 1;
			offset  = vhd_sectors_to_bytes(offset);
		}

		printf("logical sector %s: ", conv(hex, cur));
		printf("block number: %s, ", conv(hex, blk));
		printf("sector offset: %s, ", conv(hex, lsec));
		printf("file offset: %s\n", (offset == DD_BLK_UNUSED ?
			"not allocated" : conv(hex, offset)));
	}

	return 0;
}
Beispiel #3
0
static int
vhd_index_schedule_meta_read(vhd_index_t *index, uint32_t blk)
{
	int err;
	off64_t offset;
	vhd_index_block_t *block;
	vhd_index_request_t *req;

	ASSERT(index->bat.table[blk] != DD_BLK_UNUSED);

	block = vhd_index_get_block(index, blk);
	if (!block) {
		err = vhd_index_install_block(index, &block, blk);
		if (err)
			return err;
	}

	offset         = vhd_sectors_to_bytes(index->bat.table[blk]);

	req            = &block->req;
	req->index     = index;
	req->treq.sec  = blk * index->vhdi.spb;
	req->treq.secs = block->table_size >> VHD_SECTOR_SHIFT;

	td_prep_read(&req->tiocb, index->vhdi.fd,
		     (char *)block->vhdi_block.table, block->table_size,
		     offset, vhd_index_complete_meta_read, req);
	td_queue_tiocb(index->driver, &req->tiocb);

	td_flag_set(block->state, VHD_INDEX_BLOCK_READ_PENDING);

	return 0;
}
Beispiel #4
0
static int
vhd_journal_read_batmap_map(vhd_journal_t *j, vhd_batmap_t *batmap)
{
	int err;
	vhd_journal_entry_t entry;
	void *map;

	err  = vhd_journal_read_entry(j, &entry);
	if (err)
		return err;

	if (entry.type != VHD_JOURNAL_ENTRY_TYPE_BATMAP_M)
		return -EINVAL;

	if (entry.size != vhd_sectors_to_bytes(batmap->header.batmap_size))
		return -EINVAL;

	if (entry.offset != batmap->header.batmap_offset)
		return -EINVAL;

	err = posix_memalign(&map, VHD_SECTOR_SIZE, entry.size);
	if (err)
		return -err;

	batmap->map = map;

	err = vhd_journal_read(j, batmap->map, entry.size);
	if (err) {
		free(batmap->map);
		batmap->map = NULL;
		return err;
	}

	return 0;
}
Beispiel #5
0
static int
vhd_index_schedule_data_read(vhd_index_t *index, td_request_t treq)
{
	int i, err;
	size_t size;
	off64_t offset;
	uint32_t blk, sec;
	vhd_index_block_t *block;
	vhd_index_request_t *req;
	vhd_index_file_ref_t *file;

	blk   = treq.sec / index->vhdi.spb;
	sec   = treq.sec % index->vhdi.spb;
	block = vhd_index_get_block(index, blk);

	ASSERT(block && vhd_index_block_valid(block));
	for (i = 0; i < treq.secs; i++) {
		ASSERT(block->vhdi_block.table[sec + i].file_id != 0);
		ASSERT(block->vhdi_block.table[sec + i].offset != DD_BLK_UNUSED);
	}

	req = vhd_index_allocate_request(index);
	if (!req)
		return -EBUSY;

	err = vhd_index_get_file(index,
				 block->vhdi_block.table[sec].file_id, &file);
	if (err) {
		vhd_index_free_request(index, req);
		return err;
	}

	size       = vhd_sectors_to_bytes(treq.secs);
	offset     = vhd_sectors_to_bytes(block->vhdi_block.table[sec].offset);

	req->file  = file;
	req->treq  = treq;
	req->index = index;
	req->off   = offset;

	td_prep_read(&req->tiocb, file->fd, treq.buf, size, offset,
		     vhd_index_complete_data_read, req);
	td_queue_tiocb(index->driver, &req->tiocb);

	return 0;
}
Beispiel #6
0
static int
vhd_test_bitmap(vhd_context_t *vhd, uint64_t sector, int count, int hex)
{
	char *buf;
	uint64_t cur;
	int i, err, bit;
	uint32_t blk, bm_blk, sec;

	if (vhd_sectors_to_bytes(sector + count) > vhd->footer.curr_size) {
		printf("sector %s past end of file\n", conv(hex, sector));
		return -ERANGE;
	}

	bm_blk = -1;
	buf    = NULL;

	for (i = 0; i < count; i++) {
		cur = sector + i;
		blk = cur / vhd->spb;
		sec = cur % vhd->spb;

		if (blk != bm_blk) {
			bm_blk = blk;
			free(buf);
			buf = NULL;

			if (vhd->bat.bat[blk] != DD_BLK_UNUSED) {
				err = vhd_read_bitmap(vhd, blk, &buf);
				if (err)
					goto out;
			}
		}

		if (vhd->bat.bat[blk] == DD_BLK_UNUSED)
			bit = 0;
		else
			bit = vhd_bitmap_test(vhd, buf, sec);

		printf("block %s: ", conv(hex, blk));
		printf("sec: %s: %d\n", conv(hex, sec), bit);
	}

	err = 0;
 out:
	free(buf);
	return err;
}
Beispiel #7
0
static int
vhd_print_batmap(vhd_context_t *vhd)
{
	int err, gcc;
	size_t size;

	err = vhd_get_batmap(vhd);
	if (err) {
		printf("failed to read batmap: %d\n", err);
		return err;
	}

	size = vhd_sectors_to_bytes(vhd->batmap.header.batmap_size);
	gcc = write(STDOUT_FILENO, vhd->batmap.map, size);
	if (gcc)
		;

	return 0;
}
Beispiel #8
0
static int
vhd_print_bat(vhd_context_t *vhd, uint64_t block, int count, int hex)
{
	int i;
	uint64_t cur, offset;

	if (check_block_range(vhd, block + count, hex))
		return -ERANGE;

	for (i = 0; i < count && i < vhd->bat.entries; i++) {
		cur    = block + i;
		offset = vhd->bat.bat[cur];

		printf("block: %s: ", conv(hex, cur));
		printf("offset: %s\n",
		       (offset == DD_BLK_UNUSED ? "not allocated" :
			conv(hex, vhd_sectors_to_bytes(offset))));
	}

	return 0;
}
Beispiel #9
0
static int
vhd_journal_add_batmap(vhd_journal_t *j)
{
	int err;
	off64_t off;
	size_t size;
	vhd_context_t *vhd;
	vhd_batmap_t batmap;

	vhd  = &j->vhd;

	err  = vhd_batmap_header_offset(vhd, &off);
	if (err)
		return err;

	err  = vhd_read_batmap(vhd, &batmap);
	if (err)
		return err;

	size = vhd_bytes_padded(sizeof(struct dd_batmap_hdr));

	vhd_batmap_header_out(&batmap);
	err  = vhd_journal_update(j, off, (char *)&batmap.header, size,
				  VHD_JOURNAL_ENTRY_TYPE_BATMAP_H);
	if (err)
		goto out;

	vhd_batmap_header_in(&batmap);
	off  = batmap.header.batmap_offset;
	size = vhd_sectors_to_bytes(batmap.header.batmap_size);

	err  = vhd_journal_update(j, off, batmap.map, size,
				  VHD_JOURNAL_ENTRY_TYPE_BATMAP_M);

out:
	free(batmap.map);
	return err;
}
Beispiel #10
0
static int
vhd_print_bitmap(vhd_context_t *vhd, uint64_t block, int count, int hex)
{
	char *buf;
	int i, err;
	uint64_t cur;
	ssize_t n;

	if (check_block_range(vhd, block + count, hex))
		return -ERANGE;

	for (i = 0; i < count; i++) {
		cur = block + i;

		if (vhd->bat.bat[cur] == DD_BLK_UNUSED) {
			printf("block %s not allocated\n", conv(hex, cur));
			continue;
		}

		err = vhd_read_bitmap(vhd, cur, &buf);
		if (err)
			goto out;

		n = write(STDOUT_FILENO, buf, vhd_sectors_to_bytes(vhd->bm_secs));
		if (n < 0) {
			err = -errno;
			goto out;
		}

		free(buf);
	}

	err = 0;
out:
	return err;
}
Beispiel #11
0
static void
vhd_index_queue_read(td_driver_t *driver, td_request_t treq)
{
	vhd_index_t *index;

	index = (vhd_index_t *)driver->data;

	while (treq.secs) {
		int err;
		td_request_t clone;

		err   = 0;
		clone = treq;

		switch (vhd_index_read_cache(index, clone.sec)) {
		case -EINVAL:
			err = -EINVAL;
			goto fail;

		case VHD_INDEX_BAT_CLEAR:
			clone.secs = MIN(clone.secs, index->vhdi.spb - (clone.sec % index->vhdi.spb));
			td_forward_request(clone);
			break;

		case VHD_INDEX_BIT_CLEAR:
			clone.secs = vhd_index_read_cache_span(index, clone.sec, clone.secs, 0);
			td_forward_request(clone);
			break;

		case VHD_INDEX_BIT_SET:
			clone.secs = vhd_index_read_cache_span(index, clone.sec, clone.secs, 1);
			err = vhd_index_schedule_data_read(index, clone);
			if (err)
				goto fail;
			break;

		case VHD_INDEX_CACHE_MISS:
			err = vhd_index_schedule_meta_read(index, clone.sec / index->vhdi.spb);
			if (err)
				goto fail;

			clone.secs = MIN(clone.secs, index->vhdi.spb - (clone.sec % index->vhdi.spb));
			vhd_index_queue_request(index, clone);
			break;

		case VHD_INDEX_META_READ_PENDING:
			clone.secs = MIN(clone.secs, index->vhdi.spb - (clone.sec % index->vhdi.spb));
			err = vhd_index_queue_request(index, clone);
			if (err)
				goto fail;
			break;
		}

		treq.sec  += clone.secs;
		treq.secs -= clone.secs;
		treq.buf  += vhd_sectors_to_bytes(clone.secs);
		continue;

	fail:
		clone.secs = treq.secs;
		td_complete_request(clone, err);
		break;
	}
}
Beispiel #12
0
int
vhd_journal_add_block(vhd_journal_t *j, uint32_t block, char mode)
{
	int err;
	char *buf;
	off64_t off;
	size_t size;
	uint64_t blk;
	vhd_context_t *vhd;

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

	if (!vhd_type_dynamic(vhd))
		return -EINVAL;

	err = vhd_get_bat(vhd);
	if (err)
		return err;

	if (block >= vhd->bat.entries)
		return -ERANGE;

	blk = vhd->bat.bat[block];
	if (blk == DD_BLK_UNUSED)
		return 0;

	off = vhd_sectors_to_bytes(blk);

	if (mode & VHD_JOURNAL_METADATA) {
		size = vhd_sectors_to_bytes(vhd->bm_secs);

		err  = vhd_read_bitmap(vhd, block, &buf);
		if (err)
			return err;

		err  = vhd_journal_update(j, off, buf, size,
					  VHD_JOURNAL_ENTRY_TYPE_DATA);

		free(buf);

		if (err)
			return err;
	}

	if (mode & VHD_JOURNAL_DATA) {
		off += vhd_sectors_to_bytes(vhd->bm_secs);
		size = vhd_sectors_to_bytes(vhd->spb);

		err  = vhd_read_block(vhd, block, &buf);
		if (err)
			return err;

		err  = vhd_journal_update(j, off, buf, size,
					  VHD_JOURNAL_ENTRY_TYPE_DATA);
		free(buf);

		if (err)
			return err;
	}

	return vhd_journal_sync(j);
}