@@ -140,6 +140,13 @@ struct dm_cache_metadata {
140
140
* the device.
141
141
*/
142
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
1178
hints_array_initialized (cmd );
1172
1179
}
1173
1180
1174
- static int __load_mapping (void * context , uint64_t cblock , void * leaf )
1181
+ static 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
1187
int r = 0 ;
1177
- bool dirty ;
1178
- __le64 value ;
1179
- __le32 hint_value = 0 ;
1188
+
1189
+ __le64 mapping ;
1190
+ __le32 hint = 0 ;
1191
+
1192
+ __le64 * mapping_value_le ;
1193
+ __le32 * hint_value_le ;
1194
+
1180
1195
dm_oblock_t oblock ;
1181
1196
unsigned flags ;
1182
- struct thunk * thunk = context ;
1183
- struct dm_cache_metadata * cmd = thunk -> cmd ;
1184
1197
1185
- memcpy (& value , leaf , sizeof (value ));
1186
- unpack_value (value , & oblock , & flags );
1198
+ dm_array_cursor_get_value (mapping_cursor , (void * * ) & mapping_value_le );
1199
+ memcpy (& mapping , mapping_value_le , sizeof (mapping ));
1200
+ unpack_value (mapping , & oblock , & flags );
1187
1201
1188
1202
if (flags & M_VALID ) {
1189
- if (thunk -> hints_valid ) {
1190
- r = dm_array_get_value (& cmd -> hint_info , cmd -> hint_root ,
1191
- cblock , & hint_value );
1192
- if (r && r != - ENODATA )
1193
- return r ;
1203
+ if (hints_valid ) {
1204
+ dm_array_cursor_get_value (hint_cursor , (void * * ) & hint_value_le );
1205
+ memcpy (& hint , hint_value_le , sizeof (hint ));
1194
1206
}
1195
1207
1196
- dirty = thunk -> respect_dirty_flags ? (flags & M_DIRTY ) : true;
1197
- r = thunk -> fn (thunk -> context , oblock , to_cblock (cblock ),
1198
- dirty , le32_to_cpu (hint_value ), thunk -> hints_valid );
1208
+ r = fn (context , oblock , to_cblock (cb ), flags & M_DIRTY ,
1209
+ le32_to_cpu (hint ), hints_valid );
1210
+ if (r )
1211
+ DMERR ("policy couldn't load cblock" );
1199
1212
}
1200
1213
1201
1214
return r ;
@@ -1205,16 +1218,60 @@ static int __load_mappings(struct dm_cache_metadata *cmd,
1205
1218
struct dm_cache_policy * policy ,
1206
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 ;
1211
- thunk .context = context ;
1224
+ bool hints_valid = hints_array_available (cmd , policy );
1212
1225
1213
- thunk . cmd = cmd ;
1214
- thunk . respect_dirty_flags = cmd -> clean_when_opened ;
1215
- thunk . hints_valid = hints_array_available ( cmd , policy ) ;
1226
+ if ( from_cblock ( cmd -> cache_blocks ) == 0 )
1227
+ /* Nothing to do */
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
+ }
1269
+ out :
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
1220
1277
int dm_cache_load_mappings (struct dm_cache_metadata * cmd ,
0 commit comments