1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include "hfs_btree.h"
17
18
19
20#define FULL (HFS_SECTOR_SIZE - sizeof(struct NodeDescriptor))
21#define NO_SPACE (HFS_SECTOR_SIZE+1)
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43static void bdelete_nonempty(struct hfs_brec *brec, struct hfs_belem *belem)
44{
45 int i, rec, nrecs, tomove;
46 hfs_u16 size;
47 hfs_u8 *start;
48 struct hfs_bnode *bnode = belem->bnr.bn;
49
50 rec = belem->record;
51 nrecs = bnode->ndNRecs;
52 size = bnode_rsize(bnode, rec);
53 tomove = bnode_offset(bnode, nrecs+1) - bnode_offset(bnode, rec+1);
54
55
56 for (i = rec+1; i <= nrecs; ++i) {
57 hfs_put_hs(bnode_offset(bnode,i+1) - size, RECTBL(bnode,i));
58 }
59
60
61 start = bnode_key(bnode, rec);
62 memmove(start, start + size, tomove);
63
64
65 --bnode->ndNRecs;
66}
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90static int del_root(struct hfs_bnode_ref *root)
91{
92 struct hfs_btree *tree = root->bn->tree;
93 struct hfs_bnode_ref child;
94 hfs_u32 node;
95
96 if (root->bn->ndNRecs > 1) {
97 return 0;
98 } else if (root->bn->ndNRecs == 0) {
99
100 tree->bthRoot = 0;
101 tree->root = NULL;
102 tree->bthRoot = 0;
103 tree->bthFNode = 0;
104 tree->bthLNode = 0;
105 --tree->bthDepth;
106 tree->dirt = 1;
107 if (tree->bthDepth) {
108 hfs_warn("hfs_bdelete: empty tree with bthDepth=%d\n",
109 tree->bthDepth);
110 goto bail;
111 }
112 return hfs_bnode_free(root);
113 } else if (root->bn->ndType == ndIndxNode) {
114
115 node = hfs_get_hl(bkey_record(bnode_datastart(root->bn)));
116
117 child = hfs_bnode_find(tree, node, HFS_LOCK_READ);
118 if (!child.bn) {
119 hfs_warn("hfs_bdelete: can't read child node.\n");
120 goto bail;
121 }
122
123 child.bn->sticky = HFS_STICKY;
124 if (child.bn->next) {
125 child.bn->next->prev = child.bn->prev;
126 }
127 if (child.bn->prev) {
128 child.bn->prev->next = child.bn->next;
129 }
130 if (bhash(tree, child.bn->node) == child.bn) {
131 bhash(tree, child.bn->node) = child.bn->next;
132 }
133 child.bn->next = NULL;
134 child.bn->prev = NULL;
135
136 tree->bthRoot = child.bn->node;
137 tree->root = child.bn;
138
139
140
141 if (child.bn->ndType == ndLeafNode) {
142 tree->bthFNode = node;
143 tree->bthLNode = node;
144 }
145 hfs_bnode_relse(&child);
146
147 tree->bthRoot = node;
148 --tree->bthDepth;
149 tree->dirt = 1;
150 if (!tree->bthDepth) {
151 hfs_warn("hfs_bdelete: non-empty tree with "
152 "bthDepth == 0\n");
153 goto bail;
154 }
155 return hfs_bnode_free(root);
156 }
157 hfs_bnode_relse(root);
158 return 0;
159
160bail:
161 hfs_bnode_relse(root);
162 return -EIO;
163}
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203static void delete_empty_bnode(hfs_u32 left_node, struct hfs_bnode_ref *left,
204 struct hfs_bnode_ref *center,
205 hfs_u32 right_node, struct hfs_bnode_ref *right)
206{
207 struct hfs_bnode *bnode = center->bn;
208
209 if (left_node) {
210 left->bn->ndFLink = right_node;
211 } else if (bnode->ndType == ndLeafNode) {
212 bnode->tree->bthFNode = right_node;
213 bnode->tree->dirt = 1;
214 }
215
216 if (right_node) {
217 right->bn->ndBLink = left_node;
218 } else if (bnode->ndType == ndLeafNode) {
219 bnode->tree->bthLNode = left_node;
220 bnode->tree->dirt = 1;
221 }
222}
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245static void balance(struct hfs_bnode *left, struct hfs_bnode *right)
246{
247 int index, left_free, right_free, half;
248
249 left_free = bnode_freespace(left);
250 right_free = bnode_freespace(right);
251 half = (left_free + right_free)/2;
252
253 if (left_free < right_free) {
254
255 index = left->ndNRecs + 1;
256 while (right_free >= half) {
257 --index;
258 right_free -= bnode_rsize(left,index)+sizeof(hfs_u16);
259 }
260 if (index < left->ndNRecs) {
261#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
262 hfs_warn("shifting %d of %d recs right to balance: ",
263 left->ndNRecs - index, left->ndNRecs);
264#endif
265 hfs_bnode_shift_right(left, right, index+1);
266#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
267 hfs_warn("%d,%d\n", left->ndNRecs, right->ndNRecs);
268#endif
269 }
270 } else {
271
272 index = 0;
273 while (left_free >= half) {
274 ++index;
275 left_free -= bnode_rsize(right,index)+sizeof(hfs_u16);
276 }
277 if (index > 1) {
278#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
279 hfs_warn("shifting %d of %d recs left to balance: ",
280 index-1, right->ndNRecs);
281#endif
282 hfs_bnode_shift_left(left, right, index-1);
283#if defined(DEBUG_ALL) || defined(DEBUG_BALANCE)
284 hfs_warn("%d,%d\n", left->ndNRecs, right->ndNRecs);
285#endif
286 }
287 }
288}
289
290
291
292
293
294
295static int bdelete(struct hfs_brec *brec)
296{
297 struct hfs_btree *tree = brec->tree;
298 struct hfs_belem *belem = brec->bottom;
299 struct hfs_belem *parent = (belem-1);
300 struct hfs_bnode *bnode;
301 hfs_u32 left_node, right_node;
302 struct hfs_bnode_ref left, right;
303 int left_space, right_space, min_space;
304 int fix_right_key;
305 int fix_key;
306
307 while ((belem > brec->top) &&
308 (belem->flags & (HFS_BPATH_UNDERFLOW | HFS_BPATH_FIRST))) {
309 bnode = belem->bnr.bn;
310 fix_key = belem->flags & HFS_BPATH_FIRST;
311 fix_right_key = 0;
312
313 bdelete_nonempty(brec, belem);
314
315 if (bnode->node == tree->root->node) {
316 del_root(&belem->bnr);
317 --brec->bottom;
318 goto done;
319 }
320
321
322 left_node = bnode->ndBLink;
323 right_node = bnode->ndFLink;
324 if ((left_node && hfs_bnode_in_brec(left_node, brec)) ||
325 (right_node && hfs_bnode_in_brec(right_node, brec)) ||
326 (left_node == right_node)) {
327 hfs_warn("hfs_bdelete: corrupt btree\n");
328 hfs_brec_relse(brec, NULL);
329 return -EIO;
330 }
331
332
333 if (left_node) {
334 hfs_bnode_lock(&belem->bnr, HFS_LOCK_RESRV);
335 left = hfs_bnode_find(tree,left_node,HFS_LOCK_WRITE);
336 if (!left.bn) {
337 hfs_warn("hfs_bdelete: unable to read left "
338 "neighbor.\n");
339 hfs_brec_relse(brec, NULL);
340 return -EIO;
341 }
342 hfs_bnode_lock(&belem->bnr, HFS_LOCK_WRITE);
343 if (parent->record != 1) {
344 left_space = bnode_freespace(left.bn);
345 } else {
346 left_space = NO_SPACE;
347 }
348 } else {
349 left.bn = NULL;
350 left_space = NO_SPACE;
351 }
352
353
354 if (right_node) {
355 right = hfs_bnode_find(tree,right_node,HFS_LOCK_WRITE);
356 if (!right.bn) {
357 hfs_warn("hfs_bdelete: unable to read right "
358 "neighbor.\n");
359 hfs_bnode_relse(&left);
360 hfs_brec_relse(brec, NULL);
361 return -EIO;
362 }
363 if (parent->record < parent->bnr.bn->ndNRecs) {
364 right_space = bnode_freespace(right.bn);
365 } else {
366 right_space = NO_SPACE;
367 }
368 } else {
369 right.bn = NULL;
370 right_space = NO_SPACE;
371 }
372
373 if (left_space < right_space) {
374 min_space = left_space;
375 } else {
376 min_space = right_space;
377 }
378
379 if (min_space == NO_SPACE) {
380 hfs_warn("hfs_bdelete: no siblings?\n");
381 hfs_brec_relse(brec, NULL);
382 return -EIO;
383 }
384
385 if (bnode->ndNRecs == 0) {
386 delete_empty_bnode(left_node, &left, &belem->bnr,
387 right_node, &right);
388 } else if (min_space + bnode_freespace(bnode) >= FULL) {
389 if ((right_space == NO_SPACE) ||
390 ((right_space == min_space) &&
391 (left_space != NO_SPACE))) {
392 hfs_bnode_shift_left(left.bn, bnode,
393 bnode->ndNRecs);
394 } else {
395 hfs_bnode_shift_right(bnode, right.bn, 1);
396 fix_right_key = 1;
397 }
398 delete_empty_bnode(left_node, &left, &belem->bnr,
399 right_node, &right);
400 } else if (min_space == right_space) {
401 balance(bnode, right.bn);
402 fix_right_key = 1;
403 } else {
404 balance(left.bn, bnode);
405 fix_key = 1;
406 }
407
408 if (fix_right_key) {
409 hfs_bnode_update_key(brec, belem, right.bn, 1);
410 }
411
412 hfs_bnode_relse(&left);
413 hfs_bnode_relse(&right);
414
415 if (bnode->ndNRecs) {
416 if (fix_key) {
417 hfs_bnode_update_key(brec, belem, bnode, 0);
418 }
419 goto done;
420 }
421
422 hfs_bnode_free(&belem->bnr);
423 --brec->bottom;
424 belem = parent;
425 --parent;
426 }
427
428 if (belem < brec->top) {
429 hfs_warn("hfs_bdelete: Missing parent.\n");
430 hfs_brec_relse(brec, NULL);
431 return -EIO;
432 }
433
434 bdelete_nonempty(brec, belem);
435
436done:
437 hfs_brec_relse(brec, NULL);
438 return 0;
439}
440
441
442
443
444
445
446
447
448int hfs_bdelete(struct hfs_btree *tree, const struct hfs_bkey *key)
449{
450 struct hfs_belem *belem;
451 struct hfs_bnode *bnode;
452 struct hfs_brec brec;
453 int retval;
454
455 if (!tree || (tree->magic != HFS_BTREE_MAGIC) || !key) {
456 hfs_warn("hfs_bdelete: invalid arguments.\n");
457 return -EINVAL;
458 }
459
460 retval = hfs_bfind(&brec, tree, key, HFS_BFIND_DELETE);
461 if (!retval) {
462 belem = brec.bottom;
463 bnode = belem->bnr.bn;
464
465 belem->flags = 0;
466 if ((bnode->ndNRecs * sizeof(hfs_u16) + bnode_end(bnode) -
467 bnode_rsize(bnode, belem->record)) < FULL/2) {
468 belem->flags |= HFS_BPATH_UNDERFLOW;
469 }
470 if (belem->record == 1) {
471 belem->flags |= HFS_BPATH_FIRST;
472 }
473
474 if (!belem->flags) {
475 hfs_brec_lock(&brec, brec.bottom);
476 } else {
477 hfs_brec_lock(&brec, NULL);
478 }
479
480 retval = bdelete(&brec);
481 if (!retval) {
482 --brec.tree->bthNRecs;
483 brec.tree->dirt = 1;
484 }
485 hfs_brec_relse(&brec, NULL);
486 }
487 return retval;
488}
489