コード例 #1
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;
}
コード例 #2
0
/**
 * Read logpack data.
 * Padding area will be also read.
 *
 * @fd file descriptor of log device.
 * @super super sector.
 * @logh logpack header.
 * @salt checksum salt.
 * @sect_ary sector array.
 *
 * RETURN:
 *   index of invalid record found at first.
 *   logh->n_records if the whole logpack is valid.
 */
unsigned int read_logpack_data_from_wldev(
	int fd,
	const struct walb_super_sector* super,
	const struct walb_logpack_header* logh, u32 salt,
	struct sector_data_array *sect_ary)
{
	const int lbs = super->logical_bs;
	const int pbs = super->physical_bs;
	int i;
	int total_pb;

	ASSERT(lbs == LOGICAL_BLOCK_SIZE);
	ASSERT_PBS(pbs);

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

	total_pb = 0;
	for (i = 0; i < logh->n_records; i++) {
		u64 log_off;
		u32 log_lb, log_pb;

		if (test_bit_u32(LOG_RECORD_DISCARD, &logh->record[i].flags)) {
			continue;
		}
		log_lb = logh->record[i].io_size;
		log_pb = capacity_pb(pbs, log_lb);
		log_off = get_offset_of_lsid_2
			(super, logh->record[i].lsid);
		LOGd_("lsid: %"PRIu64" log_off: %"PRIu64"\n",
			logh->record[i].lsid,
			log_off);

		/* Read data for the log record. */
		if (!sector_array_pread(
				fd, log_off, sect_ary,
				total_pb, log_pb)) {
			LOGe("read sectors failed.\n");
			return i;
		}

		if (test_bit_u32(LOG_RECORD_PADDING, &logh->record[i].flags)) {
			total_pb += log_pb;
			continue;
		}
		/* Confirm checksum */
		u32 csum = sector_array_checksum(
			sect_ary, total_pb * pbs,
			log_lb * lbs, salt);
		if (csum != logh->record[i].checksum) {
			LOGe("log header checksum is invalid. %08x %08x\n",
				csum, logh->record[i].checksum);
			return i;
		}
		total_pb += log_pb;
	}
	ASSERT(i == logh->n_records);
	return logh->n_records;
}
コード例 #3
0
ファイル: logpack.c プロジェクト: herumi/walb
/**
 * Add a bio to a logpack header.
 * Almost the same as walb_logpack_header_add_req().
 * Do not validate checksum.
 *
 * REQ_DISCARD is supported.
 *
 * @lhead log pack header.
 *   lhead->logpack_lsid must be set correctly.
 *   lhead->sector_type must be set correctly.
 * @logpack_lsid lsid of the log pack.
 * @bio bio to add. must be write and its size >= 0.
 *	size == 0 is permitted with flush requests only.
 * @pbs physical block size.
 * @ring_buffer_size ring buffer size [physical block]
 *
 * RETURN:
 *   true in success, or false (you must create new logpack for the bio).
 */
bool walb_logpack_header_add_bio(
	struct walb_logpack_header *lhead,
	const struct bio *bio,
	unsigned int pbs, u64 ring_buffer_size)
{
	u64 logpack_lsid;
	u64 bio_lsid;
	unsigned int bio_lb, bio_pb;
	u64 padding_pb;
	unsigned int max_n_rec;
	int idx;
	bool is_discard;
	UNUSED const char no_more_bio_msg[] = "no more bio can not be added.\n";

	ASSERT(lhead);
	ASSERT(lhead->sector_type == SECTOR_TYPE_LOGPACK);
	ASSERT(bio);
	ASSERT_PBS(pbs);
	ASSERT(bio->bi_rw & REQ_WRITE);
	ASSERT(ring_buffer_size > 0);

	logpack_lsid = lhead->logpack_lsid;
	max_n_rec = max_n_log_record_in_sector(pbs);
	idx = lhead->n_records;

	ASSERT(lhead->n_records <= max_n_rec);
	if (lhead->n_records == max_n_rec) {
		LOG_(no_more_bio_msg);
		return false;
	}

	bio_lsid = logpack_lsid + 1 + lhead->total_io_size;
	bio_lb = bio_sectors(bio);
	if (bio_lb == 0) {
		/* Only flush requests can have zero-size. */
		ASSERT(bio->bi_rw & REQ_FLUSH);
		/* Currently a zero-flush must be alone. */
		ASSERT(idx == 0);
		return true;
	}
	ASSERT(0 < bio_lb);
	bio_pb = capacity_pb(pbs, bio_lb);
	is_discard = ((bio->bi_rw & REQ_DISCARD) != 0);
	if (!is_discard)
		ASSERT(bio_lb <= WALB_MAX_NORMAL_IO_SECTORS);

	/* Padding check. */
	{
		u64 rem;
		div64_u64_rem(bio_lsid, ring_buffer_size, &rem);
		padding_pb = ring_buffer_size - rem;
	}
	if (!is_discard && padding_pb < bio_pb) {
		/* Log of this request will cross the end of ring buffer.
		   So padding is required. */
		u64 cap_lb;

		if (lhead->total_io_size + padding_pb
			> MAX_TOTAL_IO_SIZE_IN_LOGPACK_HEADER) {
			LOG_(no_more_bio_msg);
			return false;
		}

		/* Fill the padding record contents. */
		set_bit_u32(LOG_RECORD_PADDING, &lhead->record[idx].flags);
		set_bit_u32(LOG_RECORD_EXIST, &lhead->record[idx].flags);
		lhead->record[idx].lsid = bio_lsid;
		ASSERT(bio_lsid - logpack_lsid <= UINT16_MAX);
		lhead->record[idx].lsid_local = (u16)(bio_lsid - logpack_lsid);
		lhead->record[idx].offset = 0;
		cap_lb = capacity_lb(pbs, padding_pb);
		ASSERT(cap_lb <= UINT16_MAX);
		lhead->record[idx].io_size = (u16)cap_lb;
		lhead->n_padding++;
		lhead->n_records++;
		lhead->total_io_size += padding_pb;

		bio_lsid += padding_pb;
		idx++;
		ASSERT(bio_lsid == logpack_lsid + 1 + lhead->total_io_size);

		if (lhead->n_records == max_n_rec) {
			/* The last record is padding. */
			LOG_(no_more_bio_msg);
			return false;
		}
	}

	if (!is_discard &&
		lhead->total_io_size + bio_pb
		> MAX_TOTAL_IO_SIZE_IN_LOGPACK_HEADER) {
		LOG_(no_more_bio_msg);
		return false;
	}

	/* Fill the log record contents. */
	set_bit_u32(LOG_RECORD_EXIST, &lhead->record[idx].flags);
	clear_bit_u32(LOG_RECORD_PADDING, &lhead->record[idx].flags);
	lhead->record[idx].lsid = bio_lsid;
	lhead->record[idx].lsid_local = (u16)(bio_lsid - logpack_lsid);
	lhead->record[idx].offset = (u64)bio->bi_iter.bi_sector;
	lhead->record[idx].io_size = (u32)bio_lb;
	lhead->n_records++;
	if (is_discard) {
		set_bit_u32(LOG_RECORD_DISCARD, &lhead->record[idx].flags);
		/* lhead->total_io_size will not be added. */
	} else {
		clear_bit_u32(LOG_RECORD_DISCARD, &lhead->record[idx].flags);
		lhead->total_io_size += bio_pb;
	}
	return true;
}