9
9
#include "dm-transaction-manager.h"
10
10
11
11
#include <linux/export.h>
12
+ #include <linux/device-mapper.h>
13
+
14
+ #define DM_MSG_PREFIX "btree"
12
15
13
16
/*
14
17
* Removing an entry from a btree
@@ -79,30 +82,43 @@ static void node_shift(struct btree_node *n, int shift)
79
82
}
80
83
}
81
84
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 )
83
86
{
84
87
uint32_t nr_left = le32_to_cpu (left -> header .nr_entries );
85
88
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
+ }
87
93
88
94
if (shift < 0 ) {
89
95
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
+
91
102
memcpy (key_ptr (left , nr_left ),
92
103
key_ptr (right , 0 ),
93
104
shift * sizeof (__le64 ));
94
105
memcpy (value_ptr (left , nr_left ),
95
106
value_ptr (right , 0 ),
96
107
shift * value_size );
97
108
} 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
+
99
114
memcpy (key_ptr (right , 0 ),
100
115
key_ptr (left , nr_left - shift ),
101
116
shift * sizeof (__le64 ));
102
117
memcpy (value_ptr (right , 0 ),
103
118
value_ptr (left , nr_left - shift ),
104
119
shift * value_size );
105
120
}
121
+ return 0 ;
106
122
}
107
123
108
124
/*
@@ -170,35 +186,54 @@ static void exit_child(struct dm_btree_info *info, struct child *c)
170
186
dm_tm_unlock (info -> tm , c -> block );
171
187
}
172
188
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 )
174
190
{
191
+ int r ;
175
192
uint32_t nr_left = le32_to_cpu (left -> header .nr_entries );
176
193
uint32_t nr_right = le32_to_cpu (right -> header .nr_entries );
177
194
uint32_t max_entries = le32_to_cpu (left -> header .max_entries );
178
195
uint32_t r_max_entries = le32_to_cpu (right -> header .max_entries );
179
196
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
+ }
183
211
184
212
if (!count )
185
- return ;
213
+ return 0 ;
186
214
187
215
if (count > 0 ) {
188
216
node_shift (right , count );
189
- node_copy (left , right , count );
217
+ r = node_copy (left , right , count );
218
+ if (r )
219
+ return r ;
190
220
} else {
191
- node_copy (left , right , count );
221
+ r = node_copy (left , right , count );
222
+ if (r )
223
+ return r ;
192
224
node_shift (right , count );
193
225
}
194
226
195
227
left -> header .nr_entries = cpu_to_le32 (nr_left - count );
196
228
right -> header .nr_entries = cpu_to_le32 (nr_right + count );
229
+
230
+ return 0 ;
197
231
}
198
232
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 )
201
235
{
236
+ int ret ;
202
237
struct btree_node * left = l -> n ;
203
238
struct btree_node * right = r -> n ;
204
239
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,
229
264
* Rebalance.
230
265
*/
231
266
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 ;
233
270
* key_ptr (parent , r -> index ) = right -> keys [0 ];
234
271
}
272
+ return 0 ;
235
273
}
236
274
237
275
static 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,
253
291
return r ;
254
292
}
255
293
256
- __rebalance2 (info , parent , & left , & right );
294
+ r = __rebalance2 (info , parent , & left , & right );
257
295
258
296
exit_child (info , & left );
259
297
exit_child (info , & right );
260
298
261
- return 0 ;
299
+ return r ;
262
300
}
263
301
264
302
/*
265
303
* We dump as many entries from center as possible into left, then the rest
266
304
* in right, then rebalance2. This wastes some cpu, but I want something
267
305
* simple atm.
268
306
*/
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 )
273
311
{
274
312
uint32_t max_entries = le32_to_cpu (left -> header .max_entries );
275
313
unsigned shift = min (max_entries - nr_left , nr_center );
276
314
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
+
278
320
node_copy (left , center , - shift );
279
321
left -> header .nr_entries = cpu_to_le32 (nr_left + shift );
280
322
281
323
if (shift != nr_center ) {
282
324
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
+
284
331
node_shift (right , shift );
285
332
node_copy (center , right , shift );
286
333
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
291
338
r -> index -- ;
292
339
293
340
dm_tm_dec (info -> tm , dm_block_location (c -> block ));
294
- __rebalance2 (info , parent , l , r );
341
+ return __rebalance2 (info , parent , l , r );
295
342
}
296
343
297
344
/*
298
345
* Redistributes entries among 3 sibling nodes.
299
346
*/
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 )
304
351
{
305
- int s ;
352
+ int s , ret ;
306
353
uint32_t max_entries = le32_to_cpu (left -> header .max_entries );
307
354
unsigned total = nr_left + nr_center + nr_right ;
308
355
unsigned target_right = total / 3 ;
@@ -317,35 +364,55 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
317
364
318
365
if (s < 0 && nr_center < - s ) {
319
366
/* 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
+
321
371
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 ;
326
375
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
+ }
328
382
383
+ ret = shift (center , right , target_right - nr_right );
384
+ if (ret )
385
+ return ret ;
329
386
} else {
330
387
s = target_right - nr_right ;
331
388
if (s > 0 && nr_center < s ) {
332
389
/* not enough in central node */
333
- shift (center , right , nr_center );
390
+ ret = shift (center , right , nr_center );
391
+ if (ret )
392
+ return ret ;
334
393
s -= nr_center ;
335
- shift (left , right , s );
394
+ ret = shift (left , right , s );
395
+ if (ret )
396
+ return ret ;
336
397
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
+ }
339
403
340
- shift (left , center , nr_left - target_left );
404
+ ret = shift (left , center , nr_left - target_left );
405
+ if (ret )
406
+ return ret ;
341
407
}
342
408
343
409
* key_ptr (parent , c -> index ) = center -> keys [0 ];
344
410
* key_ptr (parent , r -> index ) = right -> keys [0 ];
411
+ return 0 ;
345
412
}
346
413
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 )
349
416
{
350
417
struct btree_node * left = l -> n ;
351
418
struct btree_node * center = c -> n ;
@@ -357,15 +424,19 @@ static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
357
424
358
425
unsigned threshold = merge_threshold (left ) * 4 + 1 ;
359
426
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
+ }
362
437
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 );
369
440
}
370
441
371
442
static 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,
395
466
return r ;
396
467
}
397
468
398
- __rebalance3 (info , parent , & left , & center , & right );
469
+ r = __rebalance3 (info , parent , & left , & center , & right );
399
470
400
471
exit_child (info , & left );
401
472
exit_child (info , & center );
402
473
exit_child (info , & right );
403
474
404
- return 0 ;
475
+ return r ;
405
476
}
406
477
407
478
static int rebalance_children (struct shadow_spine * s ,
0 commit comments