summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-cache-metadata.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2016-09-20 06:16:00 -0400
committerMike Snitzer <snitzer@redhat.com>2016-09-22 11:15:05 -0400
commitf177940a80917044f0ea6fd18ea1bfbdff012050 (patch)
treefc1a276c90fcb1b77eb302fa35808616d127e7a2 /drivers/md/dm-cache-metadata.c
parentfdd1315aa5f022fe6574efdc2d9535f75a0ee255 (diff)
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>
Diffstat (limited to 'drivers/md/dm-cache-metadata.c')
-rw-r--r--drivers/md/dm-cache-metadata.c103
1 files changed, 80 insertions, 23 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index a60f10a0ee0a..695577812cf6 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -140,6 +140,13 @@ struct dm_cache_metadata {
140 * the device. 140 * the device.
141 */ 141 */
142 bool fail_io:1; 142 bool fail_io:1;
143
144 /*
145 * These structures are used when loading metadata. They're too
146 * big to put on the stack.
147 */
148 struct dm_array_cursor mapping_cursor;
149 struct dm_array_cursor hint_cursor;
143}; 150};
144 151
145/*------------------------------------------------------------------- 152/*-------------------------------------------------------------------
@@ -1171,31 +1178,37 @@ static bool hints_array_available(struct dm_cache_metadata *cmd,
1171 hints_array_initialized(cmd); 1178 hints_array_initialized(cmd);
1172} 1179}
1173 1180
1174static int __load_mapping(void *context, uint64_t cblock, void *leaf) 1181static int __load_mapping(struct dm_cache_metadata *cmd,
1182 uint64_t cb, bool hints_valid,
1183 struct dm_array_cursor *mapping_cursor,
1184 struct dm_array_cursor *hint_cursor,
1185 load_mapping_fn fn, void *context)
1175{ 1186{
1176 int r = 0; 1187 int r = 0;
1177 bool dirty; 1188
1178 __le64 value; 1189 __le64 mapping;
1179 __le32 hint_value = 0; 1190 __le32 hint = 0;
1191
1192 __le64 *mapping_value_le;
1193 __le32 *hint_value_le;
1194
1180 dm_oblock_t oblock; 1195 dm_oblock_t oblock;
1181 unsigned flags; 1196 unsigned flags;
1182 struct thunk *thunk = context;
1183 struct dm_cache_metadata *cmd = thunk->cmd;
1184 1197
1185 memcpy(&value, leaf, sizeof(value)); 1198 dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
1186 unpack_value(value, &oblock, &flags); 1199 memcpy(&mapping, mapping_value_le, sizeof(mapping));
1200 unpack_value(mapping, &oblock, &flags);
1187 1201
1188 if (flags & M_VALID) { 1202 if (flags & M_VALID) {
1189 if (thunk->hints_valid) { 1203 if (hints_valid) {
1190 r = dm_array_get_value(&cmd->hint_info, cmd->hint_root, 1204 dm_array_cursor_get_value(hint_cursor, (void **) &hint_value_le);
1191 cblock, &hint_value); 1205 memcpy(&hint, hint_value_le, sizeof(hint));
1192 if (r && r != -ENODATA)
1193 return r;
1194 } 1206 }
1195 1207
1196 dirty = thunk->respect_dirty_flags ? (flags & M_DIRTY) : true; 1208 r = fn(context, oblock, to_cblock(cb), flags & M_DIRTY,
1197 r = thunk->fn(thunk->context, oblock, to_cblock(cblock), 1209 le32_to_cpu(hint), hints_valid);
1198 dirty, le32_to_cpu(hint_value), thunk->hints_valid); 1210 if (r)
1211 DMERR("policy couldn't load cblock");
1199 } 1212 }
1200 1213
1201 return r; 1214 return r;
@@ -1205,16 +1218,60 @@ static int __load_mappings(struct dm_cache_metadata *cmd,
1205 struct dm_cache_policy *policy, 1218 struct dm_cache_policy *policy,
1206 load_mapping_fn fn, void *context) 1219 load_mapping_fn fn, void *context)
1207{ 1220{
1208 struct thunk thunk; 1221 int r;
1222 uint64_t cb;
1209 1223
1210 thunk.fn = fn; 1224 bool hints_valid = hints_array_available(cmd, policy);
1211 thunk.context = context;
1212 1225
1213 thunk.cmd = cmd; 1226 if (from_cblock(cmd->cache_blocks) == 0)
1214 thunk.respect_dirty_flags = cmd->clean_when_opened; 1227 /* Nothing to do */
1215 thunk.hints_valid = hints_array_available(cmd, policy); 1228 return 0;
1216 1229
1217 return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk); 1230 r = dm_array_cursor_begin(&cmd->info, cmd->root, &cmd->mapping_cursor);
1231 if (r)
1232 return r;
1233
1234 if (hints_valid) {
1235 r = dm_array_cursor_begin(&cmd->hint_info, cmd->hint_root, &cmd->hint_cursor);
1236 if (r) {
1237 dm_array_cursor_end(&cmd->mapping_cursor);
1238 return r;
1239 }
1240 }
1241
1242 for (cb = 0; ; cb++) {
1243 r = __load_mapping(cmd, cb, hints_valid,
1244 &cmd->mapping_cursor, &cmd->hint_cursor,
1245 fn, context);
1246 if (r)
1247 goto out;
1248
1249 /*
1250 * We need to break out before we move the cursors.
1251 */
1252 if (cb >= (from_cblock(cmd->cache_blocks) - 1))
1253 break;
1254
1255 r = dm_array_cursor_next(&cmd->mapping_cursor);
1256 if (r) {
1257 DMERR("dm_array_cursor_next for mapping failed");
1258 goto out;
1259 }
1260
1261 if (hints_valid) {
1262 r = dm_array_cursor_next(&cmd->hint_cursor);
1263 if (r) {
1264 DMERR("dm_array_cursor_next for hint failed");
1265 goto out;
1266 }
1267 }
1268 }
1269out:
1270 dm_array_cursor_end(&cmd->mapping_cursor);
1271 if (hints_valid)
1272 dm_array_cursor_end(&cmd->hint_cursor);
1273
1274 return r;
1218} 1275}
1219 1276
1220int dm_cache_load_mappings(struct dm_cache_metadata *cmd, 1277int dm_cache_load_mappings(struct dm_cache_metadata *cmd,