Esempio n. 1
0
/**
 * Redo logpack.
 *
 * @fd file descriptor of data device (opened).
 * @logpack logpack header to be redo.
 * @buf logpack data.
 *   (data size: logh->total_io_size * physical_bs)
 *
 * RETURN:
 *  true in success, or false.
 */
bool redo_logpack(
	int fd,
	const struct walb_logpack_header* logh,
	const struct sector_data_array *sect_ary)
{
	int i, n_req;

	ASSERT(logh);
	ASSERT_SECTOR_DATA_ARRAY(sect_ary);
	n_req = logh->n_records;

	for (i = 0; i < n_req; i++) {
		unsigned int idx_lb, n_lb;
		u64 off_lb;
		const struct walb_log_record *rec = &logh->record[i];

		if (test_bit_u32(LOG_RECORD_PADDING, &rec->flags)) {
			continue;
		}
		off_lb = rec->offset;
		idx_lb = addr_lb(sect_ary->sector_size, rec->lsid_local - 1);
		n_lb = rec->io_size;
		if (test_bit_u32(LOG_RECORD_DISCARD, &rec->flags)) {
			/* If the data device supports discard request,
			   you must issue discard requests. */
			/* now editing */
			continue;
		}
		if (!sector_array_pwrite_lb(fd, off_lb, sect_ary, idx_lb, n_lb)) {
			LOGe("write sectors failed.\n");
			return false;
		}
	}
	return true;
}
Esempio n. 2
0
/**
 * Write multiple logical sectors at an offset.
 * Logical block size is 512 bytes.
 *
 * @fd file descriptor of the target storage device.
 * @offset_lb storage offset [logical block].
 * @sect_ary input sector data array.
 * @idx_lb start offset in sect_ary [logical block].
 * @n_lb number of sectors to write [logical block].
 *
 * RETURN:
 *   true in success, or false.
 */
bool sector_array_pwrite_lb(
	int fd, u64 offset_lb,
	const struct sector_data_array *sect_ary,
	unsigned int idx_lb, unsigned int n_lb)
{
	const unsigned int pbs = sect_ary->sector_size;
	unsigned int w_lb = 0;

	ASSERT(fd > 0);
	ASSERT_SECTOR_DATA_ARRAY(sect_ary);
	ASSERT(n_lb > 0);

	while (w_lb < n_lb) {
		unsigned int idx = addr_pb(pbs, idx_lb + w_lb);
		unsigned int off_lb = off_in_pb(pbs, idx_lb + w_lb);
		unsigned int tmp_lb =
			get_min_value(n_lb_in_pb(pbs) - off_lb, n_lb - w_lb);
		if (!sector_write_lb(
				fd, offset_lb + w_lb,
				sect_ary->array[idx],
				off_lb, tmp_lb)) {
			return false;
		}
		w_lb += tmp_lb;
	}
	ASSERT(w_lb == n_lb);
	return true;
}
Esempio n. 3
0
/**
 * Read a logpack data from a stream.
 *
 * @fd file descriptor (opened, seeked)
 * @logh corresponding logpack header.
 * @salt checksum salt.
 * @sect_ary sector data array to be store data.
 *
 * RETURN:
 *   true in success, or false.
 */
bool read_logpack_data(
	int fd,
	const struct walb_logpack_header* logh, u32 salt,
	struct sector_data_array *sect_ary)
{
	unsigned int pbs;
	u32 total_pb;
	int i;
	int n_req;

	ASSERT(fd >= 0);
	ASSERT(logh);
	n_req = logh->n_records;
	ASSERT_SECTOR_DATA_ARRAY(sect_ary);
	pbs = sect_ary->sector_size;
	ASSERT_PBS(pbs);

	if (logh->total_io_size > sect_ary->size) {
		LOGe("sect_ary size is not enough.\n");
		return false;
	}

	total_pb = 0;
	for (i = 0; i < n_req; i++) {
		unsigned int idx_pb, log_lb, log_pb;
		u32 csum;
		const struct walb_log_record *rec = &logh->record[i];

		if (test_bit_u32(LOG_RECORD_DISCARD, &rec->flags)) {
			continue;
		}
		idx_pb = rec->lsid_local - 1;
		log_lb = rec->io_size;
		log_pb = capacity_pb(pbs, log_lb);
		/* Read data of the log record. */
		if (!sector_array_read(fd, sect_ary, idx_pb, log_pb)) {
			LOGe("read log data failed.\n");
			return false;
		}

		if (test_bit_u32(LOG_RECORD_PADDING, &rec->flags)) {
			total_pb += log_pb;
			continue;
		}
		/* Confirm checksum. */
		csum = sector_array_checksum(
			sect_ary,
			idx_pb * pbs,
			log_lb * LOGICAL_BLOCK_SIZE, salt);
		if (csum != rec->checksum) {
			LOGe("log record[%d] checksum is invalid. %08x %08x\n",
				i, csum, rec->checksum);
			return false;
		}
		total_pb += log_pb;
	}
	ASSERT(total_pb == logh->total_io_size);
	return true;
}
Esempio n. 4
0
/**
 * Read multiple sectors data at an offset.
 *
 * RETURN:
 *   true in success, or false.
 */
bool sector_array_pread(
	int fd, u64 offset,
	struct sector_data_array *sect_ary,
	unsigned int start_idx, unsigned int n_sectors)
{
	unsigned int i;

	ASSERT(fd > 0);
	ASSERT_SECTOR_DATA_ARRAY(sect_ary);
	ASSERT(start_idx + n_sectors <= sect_ary->size);

	for (i = 0; i < n_sectors; i++) {
		unsigned int idx = start_idx + i;
		u64 off = offset + i;
		bool ret = sector_read(fd, off,
				get_sector_data_in_array(sect_ary, idx));
		if (!ret) {
			LOGe("read failed.\n");
			return false;
		}
	}
	return true;
}
Esempio n. 5
0
/**
 * Write multiple sectors.
 *
 * @fd file descriptor of the target storage device.
 * @sect_ary sector data array.
 * @start_idx start offset in sect_ary [sectors].
 * @n_sectors number of sectors to write [sectors].
 *
 * RETURN:
 *   true in success, or false.
 */
bool sector_array_write(
	int fd,
	const struct sector_data_array *sect_ary,
	unsigned int start_idx, unsigned int n_sectors)
{
	unsigned int i;

	ASSERT(fd >= 0);
	ASSERT_SECTOR_DATA_ARRAY(sect_ary);
	ASSERT(start_idx + n_sectors <= sect_ary->size);

	for (i = 0; i < n_sectors; i++) {
		unsigned int idx = start_idx + i;
		bool ret = write_data(
			fd,
			(u8 *)sect_ary->array[idx]->data,
			sect_ary->sector_size);
		if (!ret) {
			LOGe("read failed.\n");
			return false;
		}
	}
	return true;
}