@@ -994,3 +994,165 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
994994 return walk_node (info , root , fn , context );
995995}
996996EXPORT_SYMBOL_GPL (dm_btree_walk );
997+
998+ /*----------------------------------------------------------------*/
999+
1000+ static void prefetch_values (struct dm_btree_cursor * c )
1001+ {
1002+ unsigned i , nr ;
1003+ __le64 value_le ;
1004+ struct cursor_node * n = c -> nodes + c -> depth - 1 ;
1005+ struct btree_node * bn = dm_block_data (n -> b );
1006+ struct dm_block_manager * bm = dm_tm_get_bm (c -> info -> tm );
1007+
1008+ BUG_ON (c -> info -> value_type .size != sizeof (value_le ));
1009+
1010+ nr = le32_to_cpu (bn -> header .nr_entries );
1011+ for (i = 0 ; i < nr ; i ++ ) {
1012+ memcpy (& value_le , value_ptr (bn , i ), sizeof (value_le ));
1013+ dm_bm_prefetch (bm , le64_to_cpu (value_le ));
1014+ }
1015+ }
1016+
1017+ static bool leaf_node (struct dm_btree_cursor * c )
1018+ {
1019+ struct cursor_node * n = c -> nodes + c -> depth - 1 ;
1020+ struct btree_node * bn = dm_block_data (n -> b );
1021+
1022+ return le32_to_cpu (bn -> header .flags ) & LEAF_NODE ;
1023+ }
1024+
1025+ static int push_node (struct dm_btree_cursor * c , dm_block_t b )
1026+ {
1027+ int r ;
1028+ struct cursor_node * n = c -> nodes + c -> depth ;
1029+
1030+ if (c -> depth >= DM_BTREE_CURSOR_MAX_DEPTH - 1 ) {
1031+ DMERR ("couldn't push cursor node, stack depth too high" );
1032+ return - EINVAL ;
1033+ }
1034+
1035+ r = bn_read_lock (c -> info , b , & n -> b );
1036+ if (r )
1037+ return r ;
1038+
1039+ n -> index = 0 ;
1040+ c -> depth ++ ;
1041+
1042+ if (c -> prefetch_leaves || !leaf_node (c ))
1043+ prefetch_values (c );
1044+
1045+ return 0 ;
1046+ }
1047+
1048+ static void pop_node (struct dm_btree_cursor * c )
1049+ {
1050+ c -> depth -- ;
1051+ unlock_block (c -> info , c -> nodes [c -> depth ].b );
1052+ }
1053+
1054+ static int inc_or_backtrack (struct dm_btree_cursor * c )
1055+ {
1056+ struct cursor_node * n ;
1057+ struct btree_node * bn ;
1058+
1059+ for (;;) {
1060+ if (!c -> depth )
1061+ return - ENODATA ;
1062+
1063+ n = c -> nodes + c -> depth - 1 ;
1064+ bn = dm_block_data (n -> b );
1065+
1066+ n -> index ++ ;
1067+ if (n -> index < le32_to_cpu (bn -> header .nr_entries ))
1068+ break ;
1069+
1070+ pop_node (c );
1071+ }
1072+
1073+ return 0 ;
1074+ }
1075+
1076+ static int find_leaf (struct dm_btree_cursor * c )
1077+ {
1078+ int r = 0 ;
1079+ struct cursor_node * n ;
1080+ struct btree_node * bn ;
1081+ __le64 value_le ;
1082+
1083+ for (;;) {
1084+ n = c -> nodes + c -> depth - 1 ;
1085+ bn = dm_block_data (n -> b );
1086+
1087+ if (le32_to_cpu (bn -> header .flags ) & LEAF_NODE )
1088+ break ;
1089+
1090+ memcpy (& value_le , value_ptr (bn , n -> index ), sizeof (value_le ));
1091+ r = push_node (c , le64_to_cpu (value_le ));
1092+ if (r ) {
1093+ DMERR ("push_node failed" );
1094+ break ;
1095+ }
1096+ }
1097+
1098+ if (!r && (le32_to_cpu (bn -> header .nr_entries ) == 0 ))
1099+ return - ENODATA ;
1100+
1101+ return r ;
1102+ }
1103+
1104+ int dm_btree_cursor_begin (struct dm_btree_info * info , dm_block_t root ,
1105+ bool prefetch_leaves , struct dm_btree_cursor * c )
1106+ {
1107+ int r ;
1108+
1109+ c -> info = info ;
1110+ c -> root = root ;
1111+ c -> depth = 0 ;
1112+ c -> prefetch_leaves = prefetch_leaves ;
1113+
1114+ r = push_node (c , root );
1115+ if (r )
1116+ return r ;
1117+
1118+ return find_leaf (c );
1119+ }
1120+ EXPORT_SYMBOL_GPL (dm_btree_cursor_begin );
1121+
1122+ void dm_btree_cursor_end (struct dm_btree_cursor * c )
1123+ {
1124+ while (c -> depth )
1125+ pop_node (c );
1126+ }
1127+ EXPORT_SYMBOL_GPL (dm_btree_cursor_end );
1128+
1129+ int dm_btree_cursor_next (struct dm_btree_cursor * c )
1130+ {
1131+ int r = inc_or_backtrack (c );
1132+ if (!r ) {
1133+ r = find_leaf (c );
1134+ if (r )
1135+ DMERR ("find_leaf failed" );
1136+ }
1137+
1138+ return r ;
1139+ }
1140+ EXPORT_SYMBOL_GPL (dm_btree_cursor_next );
1141+
1142+ int dm_btree_cursor_get_value (struct dm_btree_cursor * c , uint64_t * key , void * value_le )
1143+ {
1144+ if (c -> depth ) {
1145+ struct cursor_node * n = c -> nodes + c -> depth - 1 ;
1146+ struct btree_node * bn = dm_block_data (n -> b );
1147+
1148+ if (le32_to_cpu (bn -> header .flags ) & INTERNAL_NODE )
1149+ return - EINVAL ;
1150+
1151+ * key = le64_to_cpu (* key_ptr (bn , n -> index ));
1152+ memcpy (value_le , value_ptr (bn , n -> index ), c -> info -> value_type .size );
1153+ return 0 ;
1154+
1155+ } else
1156+ return - ENODATA ;
1157+ }
1158+ EXPORT_SYMBOL_GPL (dm_btree_cursor_get_value );
0 commit comments