forked from mirrors/linux
		
	dm cache metadata: switch to using the new cursor api for loading metadata
This change offers a pretty significant performance improvement. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
		
							parent
							
								
									fdd1315aa5
								
							
						
					
					
						commit
						f177940a80
					
				
					 1 changed files with 80 additions and 23 deletions
				
			
		| 
						 | 
					@ -140,6 +140,13 @@ struct dm_cache_metadata {
 | 
				
			||||||
	 * the device.
 | 
						 * the device.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	bool fail_io:1;
 | 
						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);
 | 
							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;
 | 
						int r = 0;
 | 
				
			||||||
	bool dirty;
 | 
					
 | 
				
			||||||
	__le64 value;
 | 
						__le64 mapping;
 | 
				
			||||||
	__le32 hint_value = 0;
 | 
						__le32 hint = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__le64 *mapping_value_le;
 | 
				
			||||||
 | 
						__le32 *hint_value_le;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dm_oblock_t oblock;
 | 
						dm_oblock_t oblock;
 | 
				
			||||||
	unsigned flags;
 | 
						unsigned flags;
 | 
				
			||||||
	struct thunk *thunk = context;
 | 
					 | 
				
			||||||
	struct dm_cache_metadata *cmd = thunk->cmd;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(&value, leaf, sizeof(value));
 | 
						dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
 | 
				
			||||||
	unpack_value(value, &oblock, &flags);
 | 
						memcpy(&mapping, mapping_value_le, sizeof(mapping));
 | 
				
			||||||
 | 
						unpack_value(mapping, &oblock, &flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (flags & M_VALID) {
 | 
						if (flags & M_VALID) {
 | 
				
			||||||
		if (thunk->hints_valid) {
 | 
							if (hints_valid) {
 | 
				
			||||||
			r = dm_array_get_value(&cmd->hint_info, cmd->hint_root,
 | 
								dm_array_cursor_get_value(hint_cursor, (void **) &hint_value_le);
 | 
				
			||||||
					       cblock, &hint_value);
 | 
								memcpy(&hint, hint_value_le, sizeof(hint));
 | 
				
			||||||
			if (r && r != -ENODATA)
 | 
					 | 
				
			||||||
				return r;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dirty = thunk->respect_dirty_flags ? (flags & M_DIRTY) : true;
 | 
							r = fn(context, oblock, to_cblock(cb), flags & M_DIRTY,
 | 
				
			||||||
		r = thunk->fn(thunk->context, oblock, to_cblock(cblock),
 | 
							       le32_to_cpu(hint), hints_valid);
 | 
				
			||||||
			      dirty, le32_to_cpu(hint_value), thunk->hints_valid);
 | 
							if (r)
 | 
				
			||||||
 | 
								DMERR("policy couldn't load cblock");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return r;
 | 
						return r;
 | 
				
			||||||
| 
						 | 
					@ -1205,16 +1218,60 @@ static int __load_mappings(struct dm_cache_metadata *cmd,
 | 
				
			||||||
			   struct dm_cache_policy *policy,
 | 
								   struct dm_cache_policy *policy,
 | 
				
			||||||
			   load_mapping_fn fn, void *context)
 | 
								   load_mapping_fn fn, void *context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct thunk thunk;
 | 
						int r;
 | 
				
			||||||
 | 
						uint64_t cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	thunk.fn = fn;
 | 
						bool hints_valid = hints_array_available(cmd, policy);
 | 
				
			||||||
	thunk.context = context;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	thunk.cmd = cmd;
 | 
						if (from_cblock(cmd->cache_blocks) == 0)
 | 
				
			||||||
	thunk.respect_dirty_flags = cmd->clean_when_opened;
 | 
							/* Nothing to do */
 | 
				
			||||||
	thunk.hints_valid = hints_array_available(cmd, policy);
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk);
 | 
						r = dm_array_cursor_begin(&cmd->info, cmd->root, &cmd->mapping_cursor);
 | 
				
			||||||
 | 
						if (r)
 | 
				
			||||||
 | 
							return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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,
 | 
					int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue