99#include "dm-transaction-manager.h"
1010
1111#include <linux/export.h>
12+ #include <linux/device-mapper.h>
13+
14+ #define DM_MSG_PREFIX "btree"
1215
1316/*
1417 * Removing an entry from a btree
@@ -79,30 +82,43 @@ static void node_shift(struct btree_node *n, int shift)
7982 }
8083}
8184
82- static void node_copy (struct btree_node * left , struct btree_node * right , int shift )
85+ static int node_copy (struct btree_node * left , struct btree_node * right , int shift )
8386{
8487 uint32_t nr_left = le32_to_cpu (left -> header .nr_entries );
8588 uint32_t value_size = le32_to_cpu (left -> header .value_size );
86- BUG_ON (value_size != le32_to_cpu (right -> header .value_size ));
89+ if (value_size != le32_to_cpu (right -> header .value_size )) {
90+ DMERR ("mismatched value size" );
91+ return - EILSEQ ;
92+ }
8793
8894 if (shift < 0 ) {
8995 shift = - shift ;
90- BUG_ON (nr_left + shift > le32_to_cpu (left -> header .max_entries ));
96+
97+ if (nr_left + shift > le32_to_cpu (left -> header .max_entries )) {
98+ DMERR ("bad shift" );
99+ return - EINVAL ;
100+ }
101+
91102 memcpy (key_ptr (left , nr_left ),
92103 key_ptr (right , 0 ),
93104 shift * sizeof (__le64 ));
94105 memcpy (value_ptr (left , nr_left ),
95106 value_ptr (right , 0 ),
96107 shift * value_size );
97108 } else {
98- BUG_ON (shift > le32_to_cpu (right -> header .max_entries ));
109+ if (shift > le32_to_cpu (right -> header .max_entries )) {
110+ DMERR ("bad shift" );
111+ return - EINVAL ;
112+ }
113+
99114 memcpy (key_ptr (right , 0 ),
100115 key_ptr (left , nr_left - shift ),
101116 shift * sizeof (__le64 ));
102117 memcpy (value_ptr (right , 0 ),
103118 value_ptr (left , nr_left - shift ),
104119 shift * value_size );
105120 }
121+ return 0 ;
106122}
107123
108124/*
@@ -170,35 +186,54 @@ static void exit_child(struct dm_btree_info *info, struct child *c)
170186 dm_tm_unlock (info -> tm , c -> block );
171187}
172188
173- static void shift (struct btree_node * left , struct btree_node * right , int count )
189+ static int shift (struct btree_node * left , struct btree_node * right , int count )
174190{
191+ int r ;
175192 uint32_t nr_left = le32_to_cpu (left -> header .nr_entries );
176193 uint32_t nr_right = le32_to_cpu (right -> header .nr_entries );
177194 uint32_t max_entries = le32_to_cpu (left -> header .max_entries );
178195 uint32_t r_max_entries = le32_to_cpu (right -> header .max_entries );
179196
180- BUG_ON (max_entries != r_max_entries );
181- BUG_ON (nr_left - count > max_entries );
182- BUG_ON (nr_right + count > max_entries );
197+ if (max_entries != r_max_entries ) {
198+ DMERR ("node max_entries mismatch" );
199+ return - EILSEQ ;
200+ }
201+
202+ if (nr_left - count > max_entries ) {
203+ DMERR ("node shift out of bounds" );
204+ return - EINVAL ;
205+ }
206+
207+ if (nr_right + count > max_entries ) {
208+ DMERR ("node shift out of bounds" );
209+ return - EINVAL ;
210+ }
183211
184212 if (!count )
185- return ;
213+ return 0 ;
186214
187215 if (count > 0 ) {
188216 node_shift (right , count );
189- node_copy (left , right , count );
217+ r = node_copy (left , right , count );
218+ if (r )
219+ return r ;
190220 } else {
191- node_copy (left , right , count );
221+ r = node_copy (left , right , count );
222+ if (r )
223+ return r ;
192224 node_shift (right , count );
193225 }
194226
195227 left -> header .nr_entries = cpu_to_le32 (nr_left - count );
196228 right -> header .nr_entries = cpu_to_le32 (nr_right + count );
229+
230+ return 0 ;
197231}
198232
199- static void __rebalance2 (struct dm_btree_info * info , struct btree_node * parent ,
200- struct child * l , struct child * r )
233+ static int __rebalance2 (struct dm_btree_info * info , struct btree_node * parent ,
234+ struct child * l , struct child * r )
201235{
236+ int ret ;
202237 struct btree_node * left = l -> n ;
203238 struct btree_node * right = r -> n ;
204239 uint32_t nr_left = le32_to_cpu (left -> header .nr_entries );
@@ -229,9 +264,12 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
229264 * Rebalance.
230265 */
231266 unsigned target_left = (nr_left + nr_right ) / 2 ;
232- shift (left , right , nr_left - target_left );
267+ ret = shift (left , right , nr_left - target_left );
268+ if (ret )
269+ return ret ;
233270 * key_ptr (parent , r -> index ) = right -> keys [0 ];
234271 }
272+ return 0 ;
235273}
236274
237275static int rebalance2 (struct shadow_spine * s , struct dm_btree_info * info ,
@@ -253,34 +291,43 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
253291 return r ;
254292 }
255293
256- __rebalance2 (info , parent , & left , & right );
294+ r = __rebalance2 (info , parent , & left , & right );
257295
258296 exit_child (info , & left );
259297 exit_child (info , & right );
260298
261- return 0 ;
299+ return r ;
262300}
263301
264302/*
265303 * We dump as many entries from center as possible into left, then the rest
266304 * in right, then rebalance2. This wastes some cpu, but I want something
267305 * simple atm.
268306 */
269- static void delete_center_node (struct dm_btree_info * info , struct btree_node * parent ,
270- struct child * l , struct child * c , struct child * r ,
271- struct btree_node * left , struct btree_node * center , struct btree_node * right ,
272- uint32_t nr_left , uint32_t nr_center , uint32_t nr_right )
307+ static int delete_center_node (struct dm_btree_info * info , struct btree_node * parent ,
308+ struct child * l , struct child * c , struct child * r ,
309+ struct btree_node * left , struct btree_node * center , struct btree_node * right ,
310+ uint32_t nr_left , uint32_t nr_center , uint32_t nr_right )
273311{
274312 uint32_t max_entries = le32_to_cpu (left -> header .max_entries );
275313 unsigned shift = min (max_entries - nr_left , nr_center );
276314
277- BUG_ON (nr_left + shift > max_entries );
315+ if (nr_left + shift > max_entries ) {
316+ DMERR ("node shift out of bounds" );
317+ return - EINVAL ;
318+ }
319+
278320 node_copy (left , center , - shift );
279321 left -> header .nr_entries = cpu_to_le32 (nr_left + shift );
280322
281323 if (shift != nr_center ) {
282324 shift = nr_center - shift ;
283- BUG_ON ((nr_right + shift ) > max_entries );
325+
326+ if ((nr_right + shift ) > max_entries ) {
327+ DMERR ("node shift out of bounds" );
328+ return - EINVAL ;
329+ }
330+
284331 node_shift (right , shift );
285332 node_copy (center , right , shift );
286333 right -> header .nr_entries = cpu_to_le32 (nr_right + shift );
@@ -291,18 +338,18 @@ static void delete_center_node(struct dm_btree_info *info, struct btree_node *pa
291338 r -> index -- ;
292339
293340 dm_tm_dec (info -> tm , dm_block_location (c -> block ));
294- __rebalance2 (info , parent , l , r );
341+ return __rebalance2 (info , parent , l , r );
295342}
296343
297344/*
298345 * Redistributes entries among 3 sibling nodes.
299346 */
300- static void redistribute3 (struct dm_btree_info * info , struct btree_node * parent ,
301- struct child * l , struct child * c , struct child * r ,
302- struct btree_node * left , struct btree_node * center , struct btree_node * right ,
303- uint32_t nr_left , uint32_t nr_center , uint32_t nr_right )
347+ static int redistribute3 (struct dm_btree_info * info , struct btree_node * parent ,
348+ struct child * l , struct child * c , struct child * r ,
349+ struct btree_node * left , struct btree_node * center , struct btree_node * right ,
350+ uint32_t nr_left , uint32_t nr_center , uint32_t nr_right )
304351{
305- int s ;
352+ int s , ret ;
306353 uint32_t max_entries = le32_to_cpu (left -> header .max_entries );
307354 unsigned total = nr_left + nr_center + nr_right ;
308355 unsigned target_right = total / 3 ;
@@ -317,35 +364,55 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
317364
318365 if (s < 0 && nr_center < - s ) {
319366 /* not enough in central node */
320- shift (left , center , - nr_center );
367+ ret = shift (left , center , - nr_center );
368+ if (ret )
369+ return ret ;
370+
321371 s += nr_center ;
322- shift (left , right , s );
323- nr_right += s ;
324- } else
325- shift (left , center , s );
372+ ret = shift (left , right , s );
373+ if (ret )
374+ return ret ;
326375
327- shift (center , right , target_right - nr_right );
376+ nr_right += s ;
377+ } else {
378+ ret = shift (left , center , s );
379+ if (ret )
380+ return ret ;
381+ }
328382
383+ ret = shift (center , right , target_right - nr_right );
384+ if (ret )
385+ return ret ;
329386 } else {
330387 s = target_right - nr_right ;
331388 if (s > 0 && nr_center < s ) {
332389 /* not enough in central node */
333- shift (center , right , nr_center );
390+ ret = shift (center , right , nr_center );
391+ if (ret )
392+ return ret ;
334393 s -= nr_center ;
335- shift (left , right , s );
394+ ret = shift (left , right , s );
395+ if (ret )
396+ return ret ;
336397 nr_left -= s ;
337- } else
338- shift (center , right , s );
398+ } else {
399+ ret = shift (center , right , s );
400+ if (ret )
401+ return ret ;
402+ }
339403
340- shift (left , center , nr_left - target_left );
404+ ret = shift (left , center , nr_left - target_left );
405+ if (ret )
406+ return ret ;
341407 }
342408
343409 * key_ptr (parent , c -> index ) = center -> keys [0 ];
344410 * key_ptr (parent , r -> index ) = right -> keys [0 ];
411+ return 0 ;
345412}
346413
347- static void __rebalance3 (struct dm_btree_info * info , struct btree_node * parent ,
348- struct child * l , struct child * c , struct child * r )
414+ static int __rebalance3 (struct dm_btree_info * info , struct btree_node * parent ,
415+ struct child * l , struct child * c , struct child * r )
349416{
350417 struct btree_node * left = l -> n ;
351418 struct btree_node * center = c -> n ;
@@ -357,15 +424,19 @@ static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
357424
358425 unsigned threshold = merge_threshold (left ) * 4 + 1 ;
359426
360- BUG_ON (left -> header .max_entries != center -> header .max_entries );
361- BUG_ON (center -> header .max_entries != right -> header .max_entries );
427+ if ((left -> header .max_entries != center -> header .max_entries ) ||
428+ (center -> header .max_entries != right -> header .max_entries )) {
429+ DMERR ("bad btree metadata, max_entries differ" );
430+ return - EILSEQ ;
431+ }
432+
433+ if ((nr_left + nr_center + nr_right ) < threshold ) {
434+ return delete_center_node (info , parent , l , c , r , left , center , right ,
435+ nr_left , nr_center , nr_right );
436+ }
362437
363- if ((nr_left + nr_center + nr_right ) < threshold )
364- delete_center_node (info , parent , l , c , r , left , center , right ,
365- nr_left , nr_center , nr_right );
366- else
367- redistribute3 (info , parent , l , c , r , left , center , right ,
368- nr_left , nr_center , nr_right );
438+ return redistribute3 (info , parent , l , c , r , left , center , right ,
439+ nr_left , nr_center , nr_right );
369440}
370441
371442static int rebalance3 (struct shadow_spine * s , struct dm_btree_info * info ,
@@ -395,13 +466,13 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
395466 return r ;
396467 }
397468
398- __rebalance3 (info , parent , & left , & center , & right );
469+ r = __rebalance3 (info , parent , & left , & center , & right );
399470
400471 exit_child (info , & left );
401472 exit_child (info , & center );
402473 exit_child (info , & right );
403474
404- return 0 ;
475+ return r ;
405476}
406477
407478static int rebalance_children (struct shadow_spine * s ,
0 commit comments