@@ -140,6 +140,13 @@ struct dm_cache_metadata {
140140 * the device.
141141 */
142142 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 ;
143150};
144151
145152/*-------------------------------------------------------------------
@@ -1171,31 +1178,37 @@ static bool hints_array_available(struct dm_cache_metadata *cmd,
11711178 hints_array_initialized (cmd );
11721179}
11731180
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 )
11751186{
11761187 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+
11801195 dm_oblock_t oblock ;
11811196 unsigned flags ;
1182- struct thunk * thunk = context ;
1183- struct dm_cache_metadata * cmd = thunk -> cmd ;
11841197
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 );
11871201
11881202 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 ));
11941206 }
11951207
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" );
11991212 }
12001213
12011214 return r ;
@@ -1205,16 +1218,60 @@ static int __load_mappings(struct dm_cache_metadata *cmd,
12051218 struct dm_cache_policy * policy ,
12061219 load_mapping_fn fn , void * context )
12071220{
1208- struct thunk thunk ;
1221+ int r ;
1222+ uint64_t cb ;
12091223
1210- thunk .fn = fn ;
1211- thunk .context = context ;
1224+ bool hints_valid = hints_array_available (cmd , policy );
12121225
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 ;
12161229
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 ;
12181275}
12191276
12201277int dm_cache_load_mappings (struct dm_cache_metadata * cmd ,
0 commit comments