Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f177940a authored by Joe Thornber's avatar Joe Thornber Committed by Mike Snitzer
Browse files

dm cache metadata: switch to using the new cursor api for loading metadata



This change offers a pretty significant performance improvement.

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent fdd1315a
Loading
Loading
Loading
Loading
+80 −23
Original line number Diff line number Diff line
@@ -140,6 +140,13 @@ struct dm_cache_metadata {
	 * the device.
	 */
	bool fail_io:1;

	/*
	 * These structures are used when loading metadata.  They're too
	 * big to put on the stack.
	 */
	struct dm_array_cursor mapping_cursor;
	struct dm_array_cursor hint_cursor;
};

/*-------------------------------------------------------------------
@@ -1171,31 +1178,37 @@ static bool hints_array_available(struct dm_cache_metadata *cmd,
		hints_array_initialized(cmd);
}

static int __load_mapping(void *context, uint64_t cblock, void *leaf)
static int __load_mapping(struct dm_cache_metadata *cmd,
			  uint64_t cb, bool hints_valid,
			  struct dm_array_cursor *mapping_cursor,
			  struct dm_array_cursor *hint_cursor,
			  load_mapping_fn fn, void *context)
{
	int r = 0;
	bool dirty;
	__le64 value;
	__le32 hint_value = 0;

	__le64 mapping;
	__le32 hint = 0;

	__le64 *mapping_value_le;
	__le32 *hint_value_le;

	dm_oblock_t oblock;
	unsigned flags;
	struct thunk *thunk = context;
	struct dm_cache_metadata *cmd = thunk->cmd;

	memcpy(&value, leaf, sizeof(value));
	unpack_value(value, &oblock, &flags);
	dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
	memcpy(&mapping, mapping_value_le, sizeof(mapping));
	unpack_value(mapping, &oblock, &flags);

	if (flags & M_VALID) {
		if (thunk->hints_valid) {
			r = dm_array_get_value(&cmd->hint_info, cmd->hint_root,
					       cblock, &hint_value);
			if (r && r != -ENODATA)
				return r;
		if (hints_valid) {
			dm_array_cursor_get_value(hint_cursor, (void **) &hint_value_le);
			memcpy(&hint, hint_value_le, sizeof(hint));
		}

		dirty = thunk->respect_dirty_flags ? (flags & M_DIRTY) : true;
		r = thunk->fn(thunk->context, oblock, to_cblock(cblock),
			      dirty, le32_to_cpu(hint_value), thunk->hints_valid);
		r = fn(context, oblock, to_cblock(cb), flags & M_DIRTY,
		       le32_to_cpu(hint), hints_valid);
		if (r)
			DMERR("policy couldn't load cblock");
	}

	return r;
@@ -1205,16 +1218,60 @@ static int __load_mappings(struct dm_cache_metadata *cmd,
			   struct dm_cache_policy *policy,
			   load_mapping_fn fn, void *context)
{
	struct thunk thunk;
	int r;
	uint64_t cb;

	thunk.fn = fn;
	thunk.context = context;
	bool hints_valid = hints_array_available(cmd, policy);

	thunk.cmd = cmd;
	thunk.respect_dirty_flags = cmd->clean_when_opened;
	thunk.hints_valid = hints_array_available(cmd, policy);
	if (from_cblock(cmd->cache_blocks) == 0)
		/* Nothing to do */
		return 0;

	r = dm_array_cursor_begin(&cmd->info, cmd->root, &cmd->mapping_cursor);
	if (r)
		return r;

	return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk);
	if (hints_valid) {
		r = dm_array_cursor_begin(&cmd->hint_info, cmd->hint_root, &cmd->hint_cursor);
		if (r) {
			dm_array_cursor_end(&cmd->mapping_cursor);
			return r;
		}
	}

	for (cb = 0; ; cb++) {
		r = __load_mapping(cmd, cb, hints_valid,
				   &cmd->mapping_cursor, &cmd->hint_cursor,
				   fn, context);
		if (r)
			goto out;

		/*
		 * We need to break out before we move the cursors.
		 */
		if (cb >= (from_cblock(cmd->cache_blocks) - 1))
			break;

		r = dm_array_cursor_next(&cmd->mapping_cursor);
		if (r) {
			DMERR("dm_array_cursor_next for mapping failed");
			goto out;
		}

		if (hints_valid) {
			r = dm_array_cursor_next(&cmd->hint_cursor);
			if (r) {
				DMERR("dm_array_cursor_next for hint failed");
				goto out;
			}
		}
	}
out:
	dm_array_cursor_end(&cmd->mapping_cursor);
	if (hints_valid)
		dm_array_cursor_end(&cmd->hint_cursor);

	return r;
}

int dm_cache_load_mappings(struct dm_cache_metadata *cmd,