1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Generic associative array implementation. 3 * 4 * See Documentation/core-api/assoc_array.rst for information. 5 * 6 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. 7 * Written by David Howells (dhowells@redhat.com) 8 */ 9 //#define DEBUG 10 #include <linux/rcupdate.h> 11 #include <linux/slab.h> 12 #include <linux/err.h> 13 #include <linux/assoc_array_priv.h> 14 15 /* 16 * Iterate over an associative array. The caller must hold the RCU read lock 17 * or better. 18 */ 19 static int assoc_array_subtree_iterate(const struct assoc_array_ptr *root, 20 const struct assoc_array_ptr *stop, 21 int (*iterator)(const void *leaf, 22 void *iterator_data), 23 void *iterator_data) 24 { 25 const struct assoc_array_shortcut *shortcut; 26 const struct assoc_array_node *node; 27 const struct assoc_array_ptr *cursor, *ptr, *parent; 28 unsigned long has_meta; 29 int slot, ret; 30 31 cursor = root; 32 33 begin_node: 34 if (assoc_array_ptr_is_shortcut(cursor)) { 35 /* Descend through a shortcut */ 36 shortcut = assoc_array_ptr_to_shortcut(cursor); 37 cursor = READ_ONCE(shortcut->next_node); /* Address dependency. */ 38 } 39 40 node = assoc_array_ptr_to_node(cursor); 41 slot = 0; 42 43 /* We perform two passes of each node. 44 * 45 * The first pass does all the leaves in this node. This means we 46 * don't miss any leaves if the node is split up by insertion whilst 47 * we're iterating over the branches rooted here (we may, however, see 48 * some leaves twice). 49 */ 50 has_meta = 0; 51 for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 52 ptr = READ_ONCE(node->slots[slot]); /* Address dependency. */ 53 has_meta |= (unsigned long)ptr; 54 if (ptr && assoc_array_ptr_is_leaf(ptr)) { 55 /* We need a barrier between the read of the pointer, 56 * which is supplied by the above READ_ONCE(). 57 */ 58 /* Invoke the callback */ 59 ret = iterator(assoc_array_ptr_to_leaf(ptr), 60 iterator_data); 61 if (ret) 62 return ret; 63 } 64 } 65 66 /* The second pass attends to all the metadata pointers. If we follow 67 * one of these we may find that we don't come back here, but rather go 68 * back to a replacement node with the leaves in a different layout. 69 * 70 * We are guaranteed to make progress, however, as the slot number for 71 * a particular portion of the key space cannot change - and we 72 * continue at the back pointer + 1. 73 */ 74 if (!(has_meta & ASSOC_ARRAY_PTR_META_TYPE)) 75 goto finished_node; 76 slot = 0; 77 78 continue_node: 79 node = assoc_array_ptr_to_node(cursor); 80 for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 81 ptr = READ_ONCE(node->slots[slot]); /* Address dependency. */ 82 if (assoc_array_ptr_is_meta(ptr)) { 83 cursor = ptr; 84 goto begin_node; 85 } 86 } 87 88 finished_node: 89 /* Move up to the parent (may need to skip back over a shortcut) */ 90 parent = READ_ONCE(node->back_pointer); /* Address dependency. */ 91 slot = node->parent_slot; 92 if (parent == stop) 93 return 0; 94 95 if (assoc_array_ptr_is_shortcut(parent)) { 96 shortcut = assoc_array_ptr_to_shortcut(parent); 97 cursor = parent; 98 parent = READ_ONCE(shortcut->back_pointer); /* Address dependency. */ 99 slot = shortcut->parent_slot; 100 if (parent == stop) 101 return 0; 102 } 103 104 /* Ascend to next slot in parent node */ 105 cursor = parent; 106 slot++; 107 goto continue_node; 108 } 109 110 /** 111 * assoc_array_iterate - Pass all objects in the array to a callback 112 * @array: The array to iterate over. 113 * @iterator: The callback function. 114 * @iterator_data: Private data for the callback function. 115 * 116 * Iterate over all the objects in an associative array. Each one will be 117 * presented to the iterator function. 118 * 119 * If the array is being modified concurrently with the iteration then it is 120 * possible that some objects in the array will be passed to the iterator 121 * callback more than once - though every object should be passed at least 122 * once. If this is undesirable then the caller must lock against modification 123 * for the duration of this function. 124 * 125 * The function will return 0 if no objects were in the array or else it will 126 * return the result of the last iterator function called. Iteration stops 127 * immediately if any call to the iteration function results in a non-zero 128 * return. 129 * 130 * The caller should hold the RCU read lock or better if concurrent 131 * modification is possible. 132 */ 133 int assoc_array_iterate(const struct assoc_array *array, 134 int (*iterator)(const void *object, 135 void *iterator_data), 136 void *iterator_data) 137 { 138 struct assoc_array_ptr *root = READ_ONCE(array->root); /* Address dependency. */ 139 140 if (!root) 141 return 0; 142 return assoc_array_subtree_iterate(root, NULL, iterator, iterator_data); 143 } 144 145 enum assoc_array_walk_status { 146 assoc_array_walk_tree_empty, 147 assoc_array_walk_found_terminal_node, 148 assoc_array_walk_found_wrong_shortcut, 149 }; 150 151 struct assoc_array_walk_result { 152 struct { 153 struct assoc_array_node *node; /* Node in which leaf might be found */ 154 int level; 155 int slot; 156 } terminal_node; 157 struct { 158 struct assoc_array_shortcut *shortcut; 159 int level; 160 int sc_level; 161 unsigned long sc_segments; 162 unsigned long dissimilarity; 163 } wrong_shortcut; 164 }; 165 166 /* 167 * Navigate through the internal tree looking for the closest node to the key. 168 */ 169 static enum assoc_array_walk_status 170 assoc_array_walk(const struct assoc_array *array, 171 const struct assoc_array_ops *ops, 172 const void *index_key, 173 struct assoc_array_walk_result *result) 174 { 175 struct assoc_array_shortcut *shortcut; 176 struct assoc_array_node *node; 177 struct assoc_array_ptr *cursor, *ptr; 178 unsigned long sc_segments, dissimilarity; 179 unsigned long segments; 180 int level, sc_level, next_sc_level; 181 int slot; 182 183 pr_devel("-->%s()\n", __func__); 184 185 cursor = READ_ONCE(array->root); /* Address dependency. */ 186 if (!cursor) 187 return assoc_array_walk_tree_empty; 188 189 level = 0; 190 191 /* Use segments from the key for the new leaf to navigate through the 192 * internal tree, skipping through nodes and shortcuts that are on 193 * route to the destination. Eventually we'll come to a slot that is 194 * either empty or contains a leaf at which point we've found a node in 195 * which the leaf we're looking for might be found or into which it 196 * should be inserted. 197 */ 198 jumped: 199 segments = ops->get_key_chunk(index_key, level); 200 pr_devel("segments[%d]: %lx\n", level, segments); 201 202 if (assoc_array_ptr_is_shortcut(cursor)) 203 goto follow_shortcut; 204 205 consider_node: 206 node = assoc_array_ptr_to_node(cursor); 207 slot = segments >> (level & ASSOC_ARRAY_KEY_CHUNK_MASK); 208 slot &= ASSOC_ARRAY_FAN_MASK; 209 ptr = READ_ONCE(node->slots[slot]); /* Address dependency. */ 210 211 pr_devel("consider slot %x [ix=%d type=%lu]\n", 212 slot, level, (unsigned long)ptr & 3); 213 214 if (!assoc_array_ptr_is_meta(ptr)) { 215 /* The node doesn't have a node/shortcut pointer in the slot 216 * corresponding to the index key that we have to follow. 217 */ 218 result->terminal_node.node = node; 219 result->terminal_node.level = level; 220 result->terminal_node.slot = slot; 221 pr_devel("<--%s() = terminal_node\n", __func__); 222 return assoc_array_walk_found_terminal_node; 223 } 224 225 if (assoc_array_ptr_is_node(ptr)) { 226 /* There is a pointer to a node in the slot corresponding to 227 * this index key segment, so we need to follow it. 228 */ 229 cursor = ptr; 230 level += ASSOC_ARRAY_LEVEL_STEP; 231 if ((level & ASSOC_ARRAY_KEY_CHUNK_MASK) != 0) 232 goto consider_node; 233 goto jumped; 234 } 235 236 /* There is a shortcut in the slot corresponding to the index key 237 * segment. We follow the shortcut if its partial index key matches 238 * this leaf's. Otherwise we need to split the shortcut. 239 */ 240 cursor = ptr; 241 follow_shortcut: 242 shortcut = assoc_array_ptr_to_shortcut(cursor); 243 pr_devel("shortcut to %d\n", shortcut->skip_to_level); 244 sc_level = level + ASSOC_ARRAY_LEVEL_STEP; 245 BUG_ON(sc_level > shortcut->skip_to_level); 246 247 do { 248 /* Check the leaf against the shortcut's index key a word at a 249 * time, trimming the final word (the shortcut stores the index 250 * key completely from the root to the shortcut's target). 251 */ 252 if ((sc_level & ASSOC_ARRAY_KEY_CHUNK_MASK) == 0) 253 segments = ops->get_key_chunk(index_key, sc_level); 254 255 sc_segments = shortcut->index_key[sc_level >> ASSOC_ARRAY_KEY_CHUNK_SHIFT]; 256 dissimilarity = segments ^ sc_segments; 257 258 if (shortcut->skip_to_level < round_down(sc_level, 259 ASSOC_ARRAY_KEY_CHUNK_SIZE) + ASSOC_ARRAY_KEY_CHUNK_SIZE) { 260 /* Trim segments that are beyond the shortcut */ 261 int shift = shortcut->skip_to_level & ASSOC_ARRAY_KEY_CHUNK_MASK; 262 dissimilarity &= ~(ULONG_MAX << shift); 263 next_sc_level = shortcut->skip_to_level; 264 } else { 265 next_sc_level = sc_level + ASSOC_ARRAY_KEY_CHUNK_SIZE; 266 next_sc_level = round_down(next_sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE); 267 } 268 269 if (dissimilarity != 0) { 270 /* This shortcut points elsewhere */ 271 result->wrong_shortcut.shortcut = shortcut; 272 result->wrong_shortcut.level = level; 273 result->wrong_shortcut.sc_level = sc_level; 274 result->wrong_shortcut.sc_segments = sc_segments; 275 result->wrong_shortcut.dissimilarity = dissimilarity; 276 return assoc_array_walk_found_wrong_shortcut; 277 } 278 279 sc_level = next_sc_level; 280 } while (sc_level < shortcut->skip_to_level); 281 282 /* The shortcut matches the leaf's index to this point. */ 283 cursor = READ_ONCE(shortcut->next_node); /* Address dependency. */ 284 if (((level ^ sc_level) & ~ASSOC_ARRAY_KEY_CHUNK_MASK) != 0) { 285 level = sc_level; 286 goto jumped; 287 } else { 288 level = sc_level; 289 goto consider_node; 290 } 291 } 292 293 /** 294 * assoc_array_find - Find an object by index key 295 * @array: The associative array to search. 296 * @ops: The operations to use. 297 * @index_key: The key to the object. 298 * 299 * Find an object in an associative array by walking through the internal tree 300 * to the node that should contain the object and then searching the leaves 301 * there. NULL is returned if the requested object was not found in the array. 302 * 303 * The caller must hold the RCU read lock or better. 304 */ 305 void *assoc_array_find(const struct assoc_array *array, 306 const struct assoc_array_ops *ops, 307 const void *index_key) 308 { 309 struct assoc_array_walk_result result; 310 const struct assoc_array_node *node; 311 const struct assoc_array_ptr *ptr; 312 const void *leaf; 313 int slot; 314 315 if (assoc_array_walk(array, ops, index_key, &result) != 316 assoc_array_walk_found_terminal_node) 317 return NULL; 318 319 node = result.terminal_node.node; 320 321 /* If the target key is available to us, it's has to be pointed to by 322 * the terminal node. 323 */ 324 for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 325 ptr = READ_ONCE(node->slots[slot]); /* Address dependency. */ 326 if (ptr && assoc_array_ptr_is_leaf(ptr)) { 327 /* We need a barrier between the read of the pointer 328 * and dereferencing the pointer - but only if we are 329 * actually going to dereference it. 330 */ 331 leaf = assoc_array_ptr_to_leaf(ptr); 332 if (ops->compare_object(leaf, index_key)) 333 return (void *)leaf; 334 } 335 } 336 337 return NULL; 338 } 339 340 /* 341 * Destructively iterate over an associative array. The caller must prevent 342 * other simultaneous accesses. 343 */ 344 static void assoc_array_destroy_subtree(struct assoc_array_ptr *root, 345 const struct assoc_array_ops *ops) 346 { 347 struct assoc_array_shortcut *shortcut; 348 struct assoc_array_node *node; 349 struct assoc_array_ptr *cursor, *parent = NULL; 350 int slot = -1; 351 352 pr_devel("-->%s()\n", __func__); 353 354 cursor = root; 355 if (!cursor) { 356 pr_devel("empty\n"); 357 return; 358 } 359 360 move_to_meta: 361 if (assoc_array_ptr_is_shortcut(cursor)) { 362 /* Descend through a shortcut */ 363 pr_devel("[%d] shortcut\n", slot); 364 BUG_ON(!assoc_array_ptr_is_shortcut(cursor)); 365 shortcut = assoc_array_ptr_to_shortcut(cursor); 366 BUG_ON(shortcut->back_pointer != parent); 367 BUG_ON(slot != -1 && shortcut->parent_slot != slot); 368 parent = cursor; 369 cursor = shortcut->next_node; 370 slot = -1; 371 BUG_ON(!assoc_array_ptr_is_node(cursor)); 372 } 373 374 pr_devel("[%d] node\n", slot); 375 node = assoc_array_ptr_to_node(cursor); 376 BUG_ON(node->back_pointer != parent); 377 BUG_ON(slot != -1 && node->parent_slot != slot); 378 slot = 0; 379 380 continue_node: 381 pr_devel("Node %p [back=%p]\n", node, node->back_pointer); 382 for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 383 struct assoc_array_ptr *ptr = node->slots[slot]; 384 if (!ptr) 385 continue; 386 if (assoc_array_ptr_is_meta(ptr)) { 387 parent = cursor; 388 cursor = ptr; 389 goto move_to_meta; 390 } 391 392 if (ops) { 393 pr_devel("[%d] free leaf\n", slot); 394 ops->free_object(assoc_array_ptr_to_leaf(ptr)); 395 } 396 } 397 398 parent = node->back_pointer; 399 slot = node->parent_slot; 400 pr_devel("free node\n"); 401 kfree(node); 402 if (!parent) 403 return; /* Done */ 404 405 /* Move back up to the parent (may need to free a shortcut on 406 * the way up) */ 407 if (assoc_array_ptr_is_shortcut(parent)) { 408 shortcut = assoc_array_ptr_to_shortcut(parent); 409 BUG_ON(shortcut->next_node != cursor); 410 cursor = parent; 411 parent = shortcut->back_pointer; 412 slot = shortcut->parent_slot; 413 pr_devel("free shortcut\n"); 414 kfree(shortcut); 415 if (!parent) 416 return; 417 418 BUG_ON(!assoc_array_ptr_is_node(parent)); 419 } 420 421 /* Ascend to next slot in parent node */ 422 pr_devel("ascend to %p[%d]\n", parent, slot); 423 cursor = parent; 424 node = assoc_array_ptr_to_node(cursor); 425 slot++; 426 goto continue_node; 427 } 428 429 /** 430 * assoc_array_destroy - Destroy an associative array 431 * @array: The array to destroy. 432 * @ops: The operations to use. 433 * 434 * Discard all metadata and free all objects in an associative array. The 435 * array will be empty and ready to use again upon completion. This function 436 * cannot fail. 437 * 438 * The caller must prevent all other accesses whilst this takes place as no 439 * attempt is made to adjust pointers gracefully to permit RCU readlock-holding 440 * accesses to continue. On the other hand, no memory allocation is required. 441 */ 442 void assoc_array_destroy(struct assoc_array *array, 443 const struct assoc_array_ops *ops) 444 { 445 assoc_array_destroy_subtree(array->root, ops); 446 array->root = NULL; 447 } 448 449 /* 450 * Handle insertion into an empty tree. 451 */ 452 static bool assoc_array_insert_in_empty_tree(struct assoc_array_edit *edit) 453 { 454 struct assoc_array_node *new_n0; 455 456 pr_devel("-->%s()\n", __func__); 457 458 new_n0 = kzalloc_obj(struct assoc_array_node); 459 if (!new_n0) 460 return false; 461 462 edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); 463 edit->leaf_p = &new_n0->slots[0]; 464 edit->adjust_count_on = new_n0; 465 edit->set[0].ptr = &edit->array->root; 466 edit->set[0].to = assoc_array_node_to_ptr(new_n0); 467 468 pr_devel("<--%s() = ok [no root]\n", __func__); 469 return true; 470 } 471 472 /* 473 * Handle insertion into a terminal node. 474 */ 475 static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit, 476 const struct assoc_array_ops *ops, 477 const void *index_key, 478 struct assoc_array_walk_result *result) 479 { 480 struct assoc_array_shortcut *shortcut, *new_s0; 481 struct assoc_array_node *node, *new_n0, *new_n1, *side; 482 struct assoc_array_ptr *ptr; 483 unsigned long dissimilarity, base_seg, blank; 484 size_t keylen; 485 bool have_meta; 486 int level, diff; 487 int slot, next_slot, free_slot, i, j; 488 489 node = result->terminal_node.node; 490 level = result->terminal_node.level; 491 edit->segment_cache[ASSOC_ARRAY_FAN_OUT] = result->terminal_node.slot; 492 493 pr_devel("-->%s()\n", __func__); 494 495 /* We arrived at a node which doesn't have an onward node or shortcut 496 * pointer that we have to follow. This means that (a) the leaf we 497 * want must go here (either by insertion or replacement) or (b) we 498 * need to split this node and insert in one of the fragments. 499 */ 500 free_slot = -1; 501 502 /* Firstly, we have to check the leaves in this node to see if there's 503 * a matching one we should replace in place. 504 */ 505 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 506 ptr = node->slots[i]; 507 if (!ptr) { 508 free_slot = i; 509 continue; 510 } 511 if (assoc_array_ptr_is_leaf(ptr) && 512 ops->compare_object(assoc_array_ptr_to_leaf(ptr), 513 index_key)) { 514 pr_devel("replace in slot %d\n", i); 515 edit->leaf_p = &node->slots[i]; 516 edit->dead_leaf = node->slots[i]; 517 pr_devel("<--%s() = ok [replace]\n", __func__); 518 return true; 519 } 520 } 521 522 /* If there is a free slot in this node then we can just insert the 523 * leaf here. 524 */ 525 if (free_slot >= 0) { 526 pr_devel("insert in free slot %d\n", free_slot); 527 edit->leaf_p = &node->slots[free_slot]; 528 edit->adjust_count_on = node; 529 pr_devel("<--%s() = ok [insert]\n", __func__); 530 return true; 531 } 532 533 /* The node has no spare slots - so we're either going to have to split 534 * it or insert another node before it. 535 * 536 * Whatever, we're going to need at least two new nodes - so allocate 537 * those now. We may also need a new shortcut, but we deal with that 538 * when we need it. 539 */ 540 new_n0 = kzalloc_obj(struct assoc_array_node); 541 if (!new_n0) 542 return false; 543 edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); 544 new_n1 = kzalloc_obj(struct assoc_array_node); 545 if (!new_n1) 546 return false; 547 edit->new_meta[1] = assoc_array_node_to_ptr(new_n1); 548 549 /* We need to find out how similar the leaves are. */ 550 pr_devel("no spare slots\n"); 551 have_meta = false; 552 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 553 ptr = node->slots[i]; 554 if (assoc_array_ptr_is_meta(ptr)) { 555 edit->segment_cache[i] = 0xff; 556 have_meta = true; 557 continue; 558 } 559 base_seg = ops->get_object_key_chunk( 560 assoc_array_ptr_to_leaf(ptr), level); 561 base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK; 562 edit->segment_cache[i] = base_seg & ASSOC_ARRAY_FAN_MASK; 563 } 564 565 if (have_meta) { 566 pr_devel("have meta\n"); 567 goto split_node; 568 } 569 570 /* The node contains only leaves */ 571 dissimilarity = 0; 572 base_seg = edit->segment_cache[0]; 573 for (i = 1; i < ASSOC_ARRAY_FAN_OUT; i++) 574 dissimilarity |= edit->segment_cache[i] ^ base_seg; 575 576 pr_devel("only leaves; dissimilarity=%lx\n", dissimilarity); 577 578 if ((dissimilarity & ASSOC_ARRAY_FAN_MASK) == 0) { 579 /* The old leaves all cluster in the same slot. We will need 580 * to insert a shortcut if the new node wants to cluster with them. 581 */ 582 if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0) 583 goto all_leaves_cluster_together; 584 585 /* Otherwise all the old leaves cluster in the same slot, but 586 * the new leaf wants to go into a different slot - so we 587 * create a new node (n0) to hold the new leaf and a pointer to 588 * a new node (n1) holding all the old leaves. 589 * 590 * This can be done by falling through to the node splitting 591 * path. 592 */ 593 pr_devel("present leaves cluster but not new leaf\n"); 594 } 595 596 split_node: 597 pr_devel("split node\n"); 598 599 /* We need to split the current node. The node must contain anything 600 * from a single leaf (in the one leaf case, this leaf will cluster 601 * with the new leaf) and the rest meta-pointers, to all leaves, some 602 * of which may cluster. 603 * 604 * It won't contain the case in which all the current leaves plus the 605 * new leaves want to cluster in the same slot. 606 * 607 * We need to expel at least two leaves out of a set consisting of the 608 * leaves in the node and the new leaf. The current meta pointers can 609 * just be copied as they shouldn't cluster with any of the leaves. 610 * 611 * We need a new node (n0) to replace the current one and a new node to 612 * take the expelled nodes (n1). 613 */ 614 edit->set[0].to = assoc_array_node_to_ptr(new_n0); 615 new_n0->back_pointer = node->back_pointer; 616 new_n0->parent_slot = node->parent_slot; 617 new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); 618 new_n1->parent_slot = -1; /* Need to calculate this */ 619 620 do_split_node: 621 pr_devel("do_split_node\n"); 622 623 new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; 624 new_n1->nr_leaves_on_branch = 0; 625 626 /* Begin by finding two matching leaves. There have to be at least two 627 * that match - even if there are meta pointers - because any leaf that 628 * would match a slot with a meta pointer in it must be somewhere 629 * behind that meta pointer and cannot be here. Further, given N 630 * remaining leaf slots, we now have N+1 leaves to go in them. 631 */ 632 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 633 slot = edit->segment_cache[i]; 634 if (slot != 0xff) 635 for (j = i + 1; j < ASSOC_ARRAY_FAN_OUT + 1; j++) 636 if (edit->segment_cache[j] == slot) 637 goto found_slot_for_multiple_occupancy; 638 } 639 found_slot_for_multiple_occupancy: 640 pr_devel("same slot: %x %x [%02x]\n", i, j, slot); 641 BUG_ON(i >= ASSOC_ARRAY_FAN_OUT); 642 BUG_ON(j >= ASSOC_ARRAY_FAN_OUT + 1); 643 BUG_ON(slot >= ASSOC_ARRAY_FAN_OUT); 644 645 new_n1->parent_slot = slot; 646 647 /* Metadata pointers cannot change slot */ 648 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) 649 if (assoc_array_ptr_is_meta(node->slots[i])) 650 new_n0->slots[i] = node->slots[i]; 651 else 652 new_n0->slots[i] = NULL; 653 BUG_ON(new_n0->slots[slot] != NULL); 654 new_n0->slots[slot] = assoc_array_node_to_ptr(new_n1); 655 656 /* Filter the leaf pointers between the new nodes */ 657 free_slot = -1; 658 next_slot = 0; 659 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 660 if (assoc_array_ptr_is_meta(node->slots[i])) 661 continue; 662 if (edit->segment_cache[i] == slot) { 663 new_n1->slots[next_slot++] = node->slots[i]; 664 new_n1->nr_leaves_on_branch++; 665 } else { 666 do { 667 free_slot++; 668 } while (new_n0->slots[free_slot] != NULL); 669 new_n0->slots[free_slot] = node->slots[i]; 670 } 671 } 672 673 pr_devel("filtered: f=%x n=%x\n", free_slot, next_slot); 674 675 if (edit->segment_cache[ASSOC_ARRAY_FAN_OUT] != slot) { 676 do { 677 free_slot++; 678 } while (new_n0->slots[free_slot] != NULL); 679 edit->leaf_p = &new_n0->slots[free_slot]; 680 edit->adjust_count_on = new_n0; 681 } else { 682 edit->leaf_p = &new_n1->slots[next_slot++]; 683 edit->adjust_count_on = new_n1; 684 } 685 686 BUG_ON(next_slot <= 1); 687 688 edit->set_backpointers_to = assoc_array_node_to_ptr(new_n0); 689 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 690 if (edit->segment_cache[i] == 0xff) { 691 ptr = node->slots[i]; 692 BUG_ON(assoc_array_ptr_is_leaf(ptr)); 693 if (assoc_array_ptr_is_node(ptr)) { 694 side = assoc_array_ptr_to_node(ptr); 695 edit->set_backpointers[i] = &side->back_pointer; 696 } else { 697 shortcut = assoc_array_ptr_to_shortcut(ptr); 698 edit->set_backpointers[i] = &shortcut->back_pointer; 699 } 700 } 701 } 702 703 ptr = node->back_pointer; 704 if (!ptr) 705 edit->set[0].ptr = &edit->array->root; 706 else if (assoc_array_ptr_is_node(ptr)) 707 edit->set[0].ptr = &assoc_array_ptr_to_node(ptr)->slots[node->parent_slot]; 708 else 709 edit->set[0].ptr = &assoc_array_ptr_to_shortcut(ptr)->next_node; 710 edit->excised_meta[0] = assoc_array_node_to_ptr(node); 711 pr_devel("<--%s() = ok [split node]\n", __func__); 712 return true; 713 714 all_leaves_cluster_together: 715 /* All the leaves, new and old, want to cluster together in this node 716 * in the same slot, so we have to replace this node with a shortcut to 717 * skip over the identical parts of the key and then place a pair of 718 * nodes, one inside the other, at the end of the shortcut and 719 * distribute the keys between them. 720 * 721 * Firstly we need to work out where the leaves start diverging as a 722 * bit position into their keys so that we know how big the shortcut 723 * needs to be. 724 * 725 * We only need to make a single pass of N of the N+1 leaves because if 726 * any keys differ between themselves at bit X then at least one of 727 * them must also differ with the base key at bit X or before. 728 */ 729 pr_devel("all leaves cluster together\n"); 730 diff = INT_MAX; 731 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 732 int x = ops->diff_objects(assoc_array_ptr_to_leaf(node->slots[i]), 733 index_key); 734 if (x < diff) { 735 BUG_ON(x < 0); 736 diff = x; 737 } 738 } 739 BUG_ON(diff == INT_MAX); 740 BUG_ON(diff < level + ASSOC_ARRAY_LEVEL_STEP); 741 742 keylen = round_up(diff, ASSOC_ARRAY_KEY_CHUNK_SIZE); 743 keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; 744 745 new_s0 = kzalloc_flex(*new_s0, index_key, keylen); 746 if (!new_s0) 747 return false; 748 edit->new_meta[2] = assoc_array_shortcut_to_ptr(new_s0); 749 750 edit->set[0].to = assoc_array_shortcut_to_ptr(new_s0); 751 new_s0->back_pointer = node->back_pointer; 752 new_s0->parent_slot = node->parent_slot; 753 new_s0->next_node = assoc_array_node_to_ptr(new_n0); 754 new_n0->back_pointer = assoc_array_shortcut_to_ptr(new_s0); 755 new_n0->parent_slot = 0; 756 new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); 757 new_n1->parent_slot = -1; /* Need to calculate this */ 758 759 new_s0->skip_to_level = level = diff & ~ASSOC_ARRAY_LEVEL_STEP_MASK; 760 pr_devel("skip_to_level = %d [diff %d]\n", level, diff); 761 BUG_ON(level <= 0); 762 763 for (i = 0; i < keylen; i++) 764 new_s0->index_key[i] = 765 ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE); 766 767 if (level & ASSOC_ARRAY_KEY_CHUNK_MASK) { 768 blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK); 769 pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank); 770 new_s0->index_key[keylen - 1] &= ~blank; 771 } 772 773 /* This now reduces to a node splitting exercise for which we'll need 774 * to regenerate the disparity table. 775 */ 776 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 777 ptr = node->slots[i]; 778 base_seg = ops->get_object_key_chunk(assoc_array_ptr_to_leaf(ptr), 779 level); 780 base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK; 781 edit->segment_cache[i] = base_seg & ASSOC_ARRAY_FAN_MASK; 782 } 783 784 base_seg = ops->get_key_chunk(index_key, level); 785 base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK; 786 edit->segment_cache[ASSOC_ARRAY_FAN_OUT] = base_seg & ASSOC_ARRAY_FAN_MASK; 787 goto do_split_node; 788 } 789 790 /* 791 * Handle insertion into the middle of a shortcut. 792 */ 793 static bool assoc_array_insert_mid_shortcut(struct assoc_array_edit *edit, 794 const struct assoc_array_ops *ops, 795 struct assoc_array_walk_result *result) 796 { 797 struct assoc_array_shortcut *shortcut, *new_s0, *new_s1; 798 struct assoc_array_node *node, *new_n0, *side; 799 unsigned long sc_segments, dissimilarity, blank; 800 size_t keylen; 801 int level, sc_level, diff; 802 int sc_slot; 803 804 shortcut = result->wrong_shortcut.shortcut; 805 level = result->wrong_shortcut.level; 806 sc_level = result->wrong_shortcut.sc_level; 807 sc_segments = result->wrong_shortcut.sc_segments; 808 dissimilarity = result->wrong_shortcut.dissimilarity; 809 810 pr_devel("-->%s(ix=%d dis=%lx scix=%d)\n", 811 __func__, level, dissimilarity, sc_level); 812 813 /* We need to split a shortcut and insert a node between the two 814 * pieces. Zero-length pieces will be dispensed with entirely. 815 * 816 * First of all, we need to find out in which level the first 817 * difference was. 818 */ 819 diff = __ffs(dissimilarity); 820 diff &= ~ASSOC_ARRAY_LEVEL_STEP_MASK; 821 diff += sc_level & ~ASSOC_ARRAY_KEY_CHUNK_MASK; 822 pr_devel("diff=%d\n", diff); 823 824 if (!shortcut->back_pointer) { 825 edit->set[0].ptr = &edit->array->root; 826 } else if (assoc_array_ptr_is_node(shortcut->back_pointer)) { 827 node = assoc_array_ptr_to_node(shortcut->back_pointer); 828 edit->set[0].ptr = &node->slots[shortcut->parent_slot]; 829 } else { 830 BUG(); 831 } 832 833 edit->excised_meta[0] = assoc_array_shortcut_to_ptr(shortcut); 834 835 /* Create a new node now since we're going to need it anyway */ 836 new_n0 = kzalloc_obj(struct assoc_array_node); 837 if (!new_n0) 838 return false; 839 edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); 840 edit->adjust_count_on = new_n0; 841 842 /* Insert a new shortcut before the new node if this segment isn't of 843 * zero length - otherwise we just connect the new node directly to the 844 * parent. 845 */ 846 level += ASSOC_ARRAY_LEVEL_STEP; 847 if (diff > level) { 848 pr_devel("pre-shortcut %d...%d\n", level, diff); 849 keylen = round_up(diff, ASSOC_ARRAY_KEY_CHUNK_SIZE); 850 keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; 851 852 new_s0 = kzalloc_flex(*new_s0, index_key, keylen); 853 if (!new_s0) 854 return false; 855 edit->new_meta[1] = assoc_array_shortcut_to_ptr(new_s0); 856 edit->set[0].to = assoc_array_shortcut_to_ptr(new_s0); 857 new_s0->back_pointer = shortcut->back_pointer; 858 new_s0->parent_slot = shortcut->parent_slot; 859 new_s0->next_node = assoc_array_node_to_ptr(new_n0); 860 new_s0->skip_to_level = diff; 861 862 new_n0->back_pointer = assoc_array_shortcut_to_ptr(new_s0); 863 new_n0->parent_slot = 0; 864 865 memcpy(new_s0->index_key, shortcut->index_key, 866 flex_array_size(new_s0, index_key, keylen)); 867 868 blank = ULONG_MAX << (diff & ASSOC_ARRAY_KEY_CHUNK_MASK); 869 pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, diff, blank); 870 new_s0->index_key[keylen - 1] &= ~blank; 871 } else { 872 pr_devel("no pre-shortcut\n"); 873 edit->set[0].to = assoc_array_node_to_ptr(new_n0); 874 new_n0->back_pointer = shortcut->back_pointer; 875 new_n0->parent_slot = shortcut->parent_slot; 876 } 877 878 side = assoc_array_ptr_to_node(shortcut->next_node); 879 new_n0->nr_leaves_on_branch = side->nr_leaves_on_branch; 880 881 /* We need to know which slot in the new node is going to take a 882 * metadata pointer. 883 */ 884 sc_slot = sc_segments >> (diff & ASSOC_ARRAY_KEY_CHUNK_MASK); 885 sc_slot &= ASSOC_ARRAY_FAN_MASK; 886 887 pr_devel("new slot %lx >> %d -> %d\n", 888 sc_segments, diff & ASSOC_ARRAY_KEY_CHUNK_MASK, sc_slot); 889 890 /* Determine whether we need to follow the new node with a replacement 891 * for the current shortcut. We could in theory reuse the current 892 * shortcut if its parent slot number doesn't change - but that's a 893 * 1-in-16 chance so not worth expending the code upon. 894 */ 895 level = diff + ASSOC_ARRAY_LEVEL_STEP; 896 if (level < shortcut->skip_to_level) { 897 pr_devel("post-shortcut %d...%d\n", level, shortcut->skip_to_level); 898 keylen = round_up(shortcut->skip_to_level, ASSOC_ARRAY_KEY_CHUNK_SIZE); 899 keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; 900 901 new_s1 = kzalloc_flex(*new_s1, index_key, keylen); 902 if (!new_s1) 903 return false; 904 edit->new_meta[2] = assoc_array_shortcut_to_ptr(new_s1); 905 906 new_s1->back_pointer = assoc_array_node_to_ptr(new_n0); 907 new_s1->parent_slot = sc_slot; 908 new_s1->next_node = shortcut->next_node; 909 new_s1->skip_to_level = shortcut->skip_to_level; 910 911 new_n0->slots[sc_slot] = assoc_array_shortcut_to_ptr(new_s1); 912 913 memcpy(new_s1->index_key, shortcut->index_key, 914 flex_array_size(new_s1, index_key, keylen)); 915 916 edit->set[1].ptr = &side->back_pointer; 917 edit->set[1].to = assoc_array_shortcut_to_ptr(new_s1); 918 } else { 919 pr_devel("no post-shortcut\n"); 920 921 /* We don't have to replace the pointed-to node as long as we 922 * use memory barriers to make sure the parent slot number is 923 * changed before the back pointer (the parent slot number is 924 * irrelevant to the old parent shortcut). 925 */ 926 new_n0->slots[sc_slot] = shortcut->next_node; 927 edit->set_parent_slot[0].p = &side->parent_slot; 928 edit->set_parent_slot[0].to = sc_slot; 929 edit->set[1].ptr = &side->back_pointer; 930 edit->set[1].to = assoc_array_node_to_ptr(new_n0); 931 } 932 933 /* Install the new leaf in a spare slot in the new node. */ 934 if (sc_slot == 0) 935 edit->leaf_p = &new_n0->slots[1]; 936 else 937 edit->leaf_p = &new_n0->slots[0]; 938 939 pr_devel("<--%s() = ok [split shortcut]\n", __func__); 940 return true; 941 } 942 943 /** 944 * assoc_array_insert - Script insertion of an object into an associative array 945 * @array: The array to insert into. 946 * @ops: The operations to use. 947 * @index_key: The key to insert at. 948 * @object: The object to insert. 949 * 950 * Precalculate and preallocate a script for the insertion or replacement of an 951 * object in an associative array. This results in an edit script that can 952 * either be applied or cancelled. 953 * 954 * The function returns a pointer to an edit script or -ENOMEM. 955 * 956 * The caller should lock against other modifications and must continue to hold 957 * the lock until assoc_array_apply_edit() has been called. 958 * 959 * Accesses to the tree may take place concurrently with this function, 960 * provided they hold the RCU read lock. 961 */ 962 struct assoc_array_edit *assoc_array_insert(struct assoc_array *array, 963 const struct assoc_array_ops *ops, 964 const void *index_key, 965 void *object) 966 { 967 struct assoc_array_walk_result result; 968 struct assoc_array_edit *edit; 969 970 pr_devel("-->%s()\n", __func__); 971 972 /* The leaf pointer we're given must not have the bottom bit set as we 973 * use those for type-marking the pointer. NULL pointers are also not 974 * allowed as they indicate an empty slot but we have to allow them 975 * here as they can be updated later. 976 */ 977 BUG_ON(assoc_array_ptr_is_meta(object)); 978 979 edit = kzalloc_obj(struct assoc_array_edit); 980 if (!edit) 981 return ERR_PTR(-ENOMEM); 982 edit->array = array; 983 edit->ops = ops; 984 edit->leaf = assoc_array_leaf_to_ptr(object); 985 edit->adjust_count_by = 1; 986 987 switch (assoc_array_walk(array, ops, index_key, &result)) { 988 case assoc_array_walk_tree_empty: 989 /* Allocate a root node if there isn't one yet */ 990 if (!assoc_array_insert_in_empty_tree(edit)) 991 goto enomem; 992 return edit; 993 994 case assoc_array_walk_found_terminal_node: 995 /* We found a node that doesn't have a node/shortcut pointer in 996 * the slot corresponding to the index key that we have to 997 * follow. 998 */ 999 if (!assoc_array_insert_into_terminal_node(edit, ops, index_key, 1000 &result)) 1001 goto enomem; 1002 return edit; 1003 1004 case assoc_array_walk_found_wrong_shortcut: 1005 /* We found a shortcut that didn't match our key in a slot we 1006 * needed to follow. 1007 */ 1008 if (!assoc_array_insert_mid_shortcut(edit, ops, &result)) 1009 goto enomem; 1010 return edit; 1011 } 1012 1013 enomem: 1014 /* Clean up after an out of memory error */ 1015 pr_devel("enomem\n"); 1016 assoc_array_cancel_edit(edit); 1017 return ERR_PTR(-ENOMEM); 1018 } 1019 1020 /** 1021 * assoc_array_insert_set_object - Set the new object pointer in an edit script 1022 * @edit: The edit script to modify. 1023 * @object: The object pointer to set. 1024 * 1025 * Change the object to be inserted in an edit script. The object pointed to 1026 * by the old object is not freed. This must be done prior to applying the 1027 * script. 1028 */ 1029 void assoc_array_insert_set_object(struct assoc_array_edit *edit, void *object) 1030 { 1031 BUG_ON(!object); 1032 edit->leaf = assoc_array_leaf_to_ptr(object); 1033 } 1034 1035 struct assoc_array_delete_collapse_context { 1036 struct assoc_array_node *node; 1037 const void *skip_leaf; 1038 int slot; 1039 }; 1040 1041 /* 1042 * Subtree collapse to node iterator. 1043 */ 1044 static int assoc_array_delete_collapse_iterator(const void *leaf, 1045 void *iterator_data) 1046 { 1047 struct assoc_array_delete_collapse_context *collapse = iterator_data; 1048 1049 if (leaf == collapse->skip_leaf) 1050 return 0; 1051 1052 BUG_ON(collapse->slot >= ASSOC_ARRAY_FAN_OUT); 1053 1054 collapse->node->slots[collapse->slot++] = assoc_array_leaf_to_ptr(leaf); 1055 return 0; 1056 } 1057 1058 /** 1059 * assoc_array_delete - Script deletion of an object from an associative array 1060 * @array: The array to search. 1061 * @ops: The operations to use. 1062 * @index_key: The key to the object. 1063 * 1064 * Precalculate and preallocate a script for the deletion of an object from an 1065 * associative array. This results in an edit script that can either be 1066 * applied or cancelled. 1067 * 1068 * The function returns a pointer to an edit script if the object was found, 1069 * NULL if the object was not found or -ENOMEM. 1070 * 1071 * The caller should lock against other modifications and must continue to hold 1072 * the lock until assoc_array_apply_edit() has been called. 1073 * 1074 * Accesses to the tree may take place concurrently with this function, 1075 * provided they hold the RCU read lock. 1076 */ 1077 struct assoc_array_edit *assoc_array_delete(struct assoc_array *array, 1078 const struct assoc_array_ops *ops, 1079 const void *index_key) 1080 { 1081 struct assoc_array_delete_collapse_context collapse; 1082 struct assoc_array_walk_result result; 1083 struct assoc_array_node *node, *new_n0; 1084 struct assoc_array_edit *edit; 1085 struct assoc_array_ptr *ptr; 1086 bool has_meta; 1087 int slot, i; 1088 1089 pr_devel("-->%s()\n", __func__); 1090 1091 edit = kzalloc_obj(struct assoc_array_edit); 1092 if (!edit) 1093 return ERR_PTR(-ENOMEM); 1094 edit->array = array; 1095 edit->ops = ops; 1096 edit->adjust_count_by = -1; 1097 1098 switch (assoc_array_walk(array, ops, index_key, &result)) { 1099 case assoc_array_walk_found_terminal_node: 1100 /* We found a node that should contain the leaf we've been 1101 * asked to remove - *if* it's in the tree. 1102 */ 1103 pr_devel("terminal_node\n"); 1104 node = result.terminal_node.node; 1105 1106 for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 1107 ptr = node->slots[slot]; 1108 if (ptr && 1109 assoc_array_ptr_is_leaf(ptr) && 1110 ops->compare_object(assoc_array_ptr_to_leaf(ptr), 1111 index_key)) 1112 goto found_leaf; 1113 } 1114 fallthrough; 1115 case assoc_array_walk_tree_empty: 1116 case assoc_array_walk_found_wrong_shortcut: 1117 default: 1118 assoc_array_cancel_edit(edit); 1119 pr_devel("not found\n"); 1120 return NULL; 1121 } 1122 1123 found_leaf: 1124 BUG_ON(array->nr_leaves_on_tree <= 0); 1125 1126 /* In the simplest form of deletion we just clear the slot and release 1127 * the leaf after a suitable interval. 1128 */ 1129 edit->dead_leaf = node->slots[slot]; 1130 edit->set[0].ptr = &node->slots[slot]; 1131 edit->set[0].to = NULL; 1132 edit->adjust_count_on = node; 1133 1134 /* If that concludes erasure of the last leaf, then delete the entire 1135 * internal array. 1136 */ 1137 if (array->nr_leaves_on_tree == 1) { 1138 edit->set[1].ptr = &array->root; 1139 edit->set[1].to = NULL; 1140 edit->adjust_count_on = NULL; 1141 edit->excised_subtree = array->root; 1142 pr_devel("all gone\n"); 1143 return edit; 1144 } 1145 1146 /* However, we'd also like to clear up some metadata blocks if we 1147 * possibly can. 1148 * 1149 * We go for a simple algorithm of: if this node has FAN_OUT or fewer 1150 * leaves in it, then attempt to collapse it - and attempt to 1151 * recursively collapse up the tree. 1152 * 1153 * We could also try and collapse in partially filled subtrees to take 1154 * up space in this node. 1155 */ 1156 if (node->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT + 1) { 1157 struct assoc_array_node *parent, *grandparent; 1158 struct assoc_array_ptr *ptr; 1159 1160 /* First of all, we need to know if this node has metadata so 1161 * that we don't try collapsing if all the leaves are already 1162 * here. 1163 */ 1164 has_meta = false; 1165 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 1166 ptr = node->slots[i]; 1167 if (assoc_array_ptr_is_meta(ptr)) { 1168 has_meta = true; 1169 break; 1170 } 1171 } 1172 1173 pr_devel("leaves: %ld [m=%d]\n", 1174 node->nr_leaves_on_branch - 1, has_meta); 1175 1176 /* Look further up the tree to see if we can collapse this node 1177 * into a more proximal node too. 1178 */ 1179 parent = node; 1180 collapse_up: 1181 pr_devel("collapse subtree: %ld\n", parent->nr_leaves_on_branch); 1182 1183 ptr = parent->back_pointer; 1184 if (!ptr) 1185 goto do_collapse; 1186 if (assoc_array_ptr_is_shortcut(ptr)) { 1187 struct assoc_array_shortcut *s = assoc_array_ptr_to_shortcut(ptr); 1188 ptr = s->back_pointer; 1189 if (!ptr) 1190 goto do_collapse; 1191 } 1192 1193 grandparent = assoc_array_ptr_to_node(ptr); 1194 if (grandparent->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT + 1) { 1195 parent = grandparent; 1196 goto collapse_up; 1197 } 1198 1199 do_collapse: 1200 /* There's no point collapsing if the original node has no meta 1201 * pointers to discard and if we didn't merge into one of that 1202 * node's ancestry. 1203 */ 1204 if (has_meta || parent != node) { 1205 node = parent; 1206 1207 /* Create a new node to collapse into */ 1208 new_n0 = kzalloc_obj(struct assoc_array_node); 1209 if (!new_n0) 1210 goto enomem; 1211 edit->new_meta[0] = assoc_array_node_to_ptr(new_n0); 1212 1213 new_n0->back_pointer = node->back_pointer; 1214 new_n0->parent_slot = node->parent_slot; 1215 new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; 1216 edit->adjust_count_on = new_n0; 1217 1218 collapse.node = new_n0; 1219 collapse.skip_leaf = assoc_array_ptr_to_leaf(edit->dead_leaf); 1220 collapse.slot = 0; 1221 assoc_array_subtree_iterate(assoc_array_node_to_ptr(node), 1222 node->back_pointer, 1223 assoc_array_delete_collapse_iterator, 1224 &collapse); 1225 pr_devel("collapsed %d,%lu\n", collapse.slot, new_n0->nr_leaves_on_branch); 1226 BUG_ON(collapse.slot != new_n0->nr_leaves_on_branch - 1); 1227 1228 if (!node->back_pointer) { 1229 edit->set[1].ptr = &array->root; 1230 } else if (assoc_array_ptr_is_leaf(node->back_pointer)) { 1231 BUG(); 1232 } else if (assoc_array_ptr_is_node(node->back_pointer)) { 1233 struct assoc_array_node *p = 1234 assoc_array_ptr_to_node(node->back_pointer); 1235 edit->set[1].ptr = &p->slots[node->parent_slot]; 1236 } else if (assoc_array_ptr_is_shortcut(node->back_pointer)) { 1237 struct assoc_array_shortcut *s = 1238 assoc_array_ptr_to_shortcut(node->back_pointer); 1239 edit->set[1].ptr = &s->next_node; 1240 } 1241 edit->set[1].to = assoc_array_node_to_ptr(new_n0); 1242 edit->excised_subtree = assoc_array_node_to_ptr(node); 1243 } 1244 } 1245 1246 return edit; 1247 1248 enomem: 1249 /* Clean up after an out of memory error */ 1250 pr_devel("enomem\n"); 1251 assoc_array_cancel_edit(edit); 1252 return ERR_PTR(-ENOMEM); 1253 } 1254 1255 /** 1256 * assoc_array_clear - Script deletion of all objects from an associative array 1257 * @array: The array to clear. 1258 * @ops: The operations to use. 1259 * 1260 * Precalculate and preallocate a script for the deletion of all the objects 1261 * from an associative array. This results in an edit script that can either 1262 * be applied or cancelled. 1263 * 1264 * The function returns a pointer to an edit script if there are objects to be 1265 * deleted, NULL if there are no objects in the array or -ENOMEM. 1266 * 1267 * The caller should lock against other modifications and must continue to hold 1268 * the lock until assoc_array_apply_edit() has been called. 1269 * 1270 * Accesses to the tree may take place concurrently with this function, 1271 * provided they hold the RCU read lock. 1272 */ 1273 struct assoc_array_edit *assoc_array_clear(struct assoc_array *array, 1274 const struct assoc_array_ops *ops) 1275 { 1276 struct assoc_array_edit *edit; 1277 1278 pr_devel("-->%s()\n", __func__); 1279 1280 if (!array->root) 1281 return NULL; 1282 1283 edit = kzalloc_obj(struct assoc_array_edit); 1284 if (!edit) 1285 return ERR_PTR(-ENOMEM); 1286 edit->array = array; 1287 edit->ops = ops; 1288 edit->set[1].ptr = &array->root; 1289 edit->set[1].to = NULL; 1290 edit->excised_subtree = array->root; 1291 edit->ops_for_excised_subtree = ops; 1292 pr_devel("all gone\n"); 1293 return edit; 1294 } 1295 1296 /* 1297 * Handle the deferred destruction after an applied edit. 1298 */ 1299 static void assoc_array_rcu_cleanup(struct rcu_head *head) 1300 { 1301 struct assoc_array_edit *edit = 1302 container_of(head, struct assoc_array_edit, rcu); 1303 int i; 1304 1305 pr_devel("-->%s()\n", __func__); 1306 1307 if (edit->dead_leaf) 1308 edit->ops->free_object(assoc_array_ptr_to_leaf(edit->dead_leaf)); 1309 for (i = 0; i < ARRAY_SIZE(edit->excised_meta); i++) 1310 if (edit->excised_meta[i]) 1311 kfree(assoc_array_ptr_to_node(edit->excised_meta[i])); 1312 1313 if (edit->excised_subtree) { 1314 BUG_ON(assoc_array_ptr_is_leaf(edit->excised_subtree)); 1315 if (assoc_array_ptr_is_node(edit->excised_subtree)) { 1316 struct assoc_array_node *n = 1317 assoc_array_ptr_to_node(edit->excised_subtree); 1318 n->back_pointer = NULL; 1319 } else { 1320 struct assoc_array_shortcut *s = 1321 assoc_array_ptr_to_shortcut(edit->excised_subtree); 1322 s->back_pointer = NULL; 1323 } 1324 assoc_array_destroy_subtree(edit->excised_subtree, 1325 edit->ops_for_excised_subtree); 1326 } 1327 1328 kfree(edit); 1329 } 1330 1331 /** 1332 * assoc_array_apply_edit - Apply an edit script to an associative array 1333 * @edit: The script to apply. 1334 * 1335 * Apply an edit script to an associative array to effect an insertion, 1336 * deletion or clearance. As the edit script includes preallocated memory, 1337 * this is guaranteed not to fail. 1338 * 1339 * The edit script, dead objects and dead metadata will be scheduled for 1340 * destruction after an RCU grace period to permit those doing read-only 1341 * accesses on the array to continue to do so under the RCU read lock whilst 1342 * the edit is taking place. 1343 */ 1344 void assoc_array_apply_edit(struct assoc_array_edit *edit) 1345 { 1346 struct assoc_array_shortcut *shortcut; 1347 struct assoc_array_node *node; 1348 struct assoc_array_ptr *ptr; 1349 int i; 1350 1351 pr_devel("-->%s()\n", __func__); 1352 1353 smp_wmb(); 1354 if (edit->leaf_p) 1355 *edit->leaf_p = edit->leaf; 1356 1357 smp_wmb(); 1358 for (i = 0; i < ARRAY_SIZE(edit->set_parent_slot); i++) 1359 if (edit->set_parent_slot[i].p) 1360 *edit->set_parent_slot[i].p = edit->set_parent_slot[i].to; 1361 1362 smp_wmb(); 1363 for (i = 0; i < ARRAY_SIZE(edit->set_backpointers); i++) 1364 if (edit->set_backpointers[i]) 1365 *edit->set_backpointers[i] = edit->set_backpointers_to; 1366 1367 smp_wmb(); 1368 for (i = 0; i < ARRAY_SIZE(edit->set); i++) 1369 if (edit->set[i].ptr) 1370 *edit->set[i].ptr = edit->set[i].to; 1371 1372 if (edit->array->root == NULL) { 1373 edit->array->nr_leaves_on_tree = 0; 1374 } else if (edit->adjust_count_on) { 1375 node = edit->adjust_count_on; 1376 for (;;) { 1377 node->nr_leaves_on_branch += edit->adjust_count_by; 1378 1379 ptr = node->back_pointer; 1380 if (!ptr) 1381 break; 1382 if (assoc_array_ptr_is_shortcut(ptr)) { 1383 shortcut = assoc_array_ptr_to_shortcut(ptr); 1384 ptr = shortcut->back_pointer; 1385 if (!ptr) 1386 break; 1387 } 1388 BUG_ON(!assoc_array_ptr_is_node(ptr)); 1389 node = assoc_array_ptr_to_node(ptr); 1390 } 1391 1392 edit->array->nr_leaves_on_tree += edit->adjust_count_by; 1393 } 1394 1395 call_rcu(&edit->rcu, assoc_array_rcu_cleanup); 1396 } 1397 1398 /** 1399 * assoc_array_cancel_edit - Discard an edit script. 1400 * @edit: The script to discard. 1401 * 1402 * Free an edit script and all the preallocated data it holds without making 1403 * any changes to the associative array it was intended for. 1404 * 1405 * NOTE! In the case of an insertion script, this does _not_ release the leaf 1406 * that was to be inserted. That is left to the caller. 1407 */ 1408 void assoc_array_cancel_edit(struct assoc_array_edit *edit) 1409 { 1410 struct assoc_array_ptr *ptr; 1411 int i; 1412 1413 pr_devel("-->%s()\n", __func__); 1414 1415 /* Clean up after an out of memory error */ 1416 for (i = 0; i < ARRAY_SIZE(edit->new_meta); i++) { 1417 ptr = edit->new_meta[i]; 1418 if (ptr) { 1419 if (assoc_array_ptr_is_node(ptr)) 1420 kfree(assoc_array_ptr_to_node(ptr)); 1421 else 1422 kfree(assoc_array_ptr_to_shortcut(ptr)); 1423 } 1424 } 1425 kfree(edit); 1426 } 1427 1428 /** 1429 * assoc_array_gc - Garbage collect an associative array. 1430 * @array: The array to clean. 1431 * @ops: The operations to use. 1432 * @iterator: A callback function to pass judgement on each object. 1433 * @iterator_data: Private data for the callback function. 1434 * 1435 * Collect garbage from an associative array and pack down the internal tree to 1436 * save memory. 1437 * 1438 * The iterator function is asked to pass judgement upon each object in the 1439 * array. If it returns false, the object is discard and if it returns true, 1440 * the object is kept. If it returns true, it must increment the object's 1441 * usage count (or whatever it needs to do to retain it) before returning. 1442 * 1443 * This function returns 0 if successful or -ENOMEM if out of memory. In the 1444 * latter case, the array is not changed. 1445 * 1446 * The caller should lock against other modifications and must continue to hold 1447 * the lock until assoc_array_apply_edit() has been called. 1448 * 1449 * Accesses to the tree may take place concurrently with this function, 1450 * provided they hold the RCU read lock. 1451 */ 1452 int assoc_array_gc(struct assoc_array *array, 1453 const struct assoc_array_ops *ops, 1454 bool (*iterator)(void *object, void *iterator_data), 1455 void *iterator_data) 1456 { 1457 struct assoc_array_shortcut *shortcut, *new_s; 1458 struct assoc_array_node *node, *new_n; 1459 struct assoc_array_edit *edit; 1460 struct assoc_array_ptr *cursor, *ptr; 1461 struct assoc_array_ptr *new_root, *new_parent, **new_ptr_pp; 1462 unsigned long nr_leaves_on_tree; 1463 bool retained; 1464 int keylen, slot, nr_free, next_slot, i; 1465 1466 pr_devel("-->%s()\n", __func__); 1467 1468 if (!array->root) 1469 return 0; 1470 1471 edit = kzalloc_obj(struct assoc_array_edit); 1472 if (!edit) 1473 return -ENOMEM; 1474 edit->array = array; 1475 edit->ops = ops; 1476 edit->ops_for_excised_subtree = ops; 1477 edit->set[0].ptr = &array->root; 1478 edit->excised_subtree = array->root; 1479 1480 new_root = new_parent = NULL; 1481 new_ptr_pp = &new_root; 1482 cursor = array->root; 1483 1484 descend: 1485 /* If this point is a shortcut, then we need to duplicate it and 1486 * advance the target cursor. 1487 */ 1488 if (assoc_array_ptr_is_shortcut(cursor)) { 1489 shortcut = assoc_array_ptr_to_shortcut(cursor); 1490 keylen = round_up(shortcut->skip_to_level, ASSOC_ARRAY_KEY_CHUNK_SIZE); 1491 keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT; 1492 new_s = kmalloc_flex(*new_s, index_key, keylen); 1493 if (!new_s) 1494 goto enomem; 1495 pr_devel("dup shortcut %p -> %p\n", shortcut, new_s); 1496 memcpy(new_s, shortcut, struct_size(new_s, index_key, keylen)); 1497 new_s->back_pointer = new_parent; 1498 new_s->parent_slot = shortcut->parent_slot; 1499 *new_ptr_pp = new_parent = assoc_array_shortcut_to_ptr(new_s); 1500 new_ptr_pp = &new_s->next_node; 1501 cursor = shortcut->next_node; 1502 } 1503 1504 /* Duplicate the node at this position */ 1505 node = assoc_array_ptr_to_node(cursor); 1506 new_n = kzalloc_obj(struct assoc_array_node); 1507 if (!new_n) 1508 goto enomem; 1509 pr_devel("dup node %p -> %p\n", node, new_n); 1510 new_n->back_pointer = new_parent; 1511 new_n->parent_slot = node->parent_slot; 1512 *new_ptr_pp = new_parent = assoc_array_node_to_ptr(new_n); 1513 new_ptr_pp = NULL; 1514 slot = 0; 1515 1516 continue_node: 1517 /* Filter across any leaves and gc any subtrees */ 1518 for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 1519 ptr = node->slots[slot]; 1520 if (!ptr) 1521 continue; 1522 1523 if (assoc_array_ptr_is_leaf(ptr)) { 1524 if (iterator(assoc_array_ptr_to_leaf(ptr), 1525 iterator_data)) 1526 /* The iterator will have done any reference 1527 * counting on the object for us. 1528 */ 1529 new_n->slots[slot] = ptr; 1530 continue; 1531 } 1532 1533 new_ptr_pp = &new_n->slots[slot]; 1534 cursor = ptr; 1535 goto descend; 1536 } 1537 1538 retry_compress: 1539 pr_devel("-- compress node %p --\n", new_n); 1540 1541 /* Count up the number of empty slots in this node and work out the 1542 * subtree leaf count. 1543 */ 1544 new_n->nr_leaves_on_branch = 0; 1545 nr_free = 0; 1546 for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 1547 ptr = new_n->slots[slot]; 1548 if (!ptr) 1549 nr_free++; 1550 else if (assoc_array_ptr_is_leaf(ptr)) 1551 new_n->nr_leaves_on_branch++; 1552 } 1553 pr_devel("free=%d, leaves=%lu\n", nr_free, new_n->nr_leaves_on_branch); 1554 1555 /* See what we can fold in */ 1556 retained = false; 1557 next_slot = 0; 1558 for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) { 1559 struct assoc_array_shortcut *s; 1560 struct assoc_array_node *child; 1561 1562 ptr = new_n->slots[slot]; 1563 if (!ptr || assoc_array_ptr_is_leaf(ptr)) 1564 continue; 1565 1566 s = NULL; 1567 if (assoc_array_ptr_is_shortcut(ptr)) { 1568 s = assoc_array_ptr_to_shortcut(ptr); 1569 ptr = s->next_node; 1570 } 1571 1572 child = assoc_array_ptr_to_node(ptr); 1573 new_n->nr_leaves_on_branch += child->nr_leaves_on_branch; 1574 1575 if (child->nr_leaves_on_branch <= nr_free + 1) { 1576 /* Fold the child node into this one */ 1577 pr_devel("[%d] fold node %lu/%d [nx %d]\n", 1578 slot, child->nr_leaves_on_branch, nr_free + 1, 1579 next_slot); 1580 1581 /* We would already have reaped an intervening shortcut 1582 * on the way back up the tree. 1583 */ 1584 BUG_ON(s); 1585 1586 new_n->slots[slot] = NULL; 1587 nr_free++; 1588 if (slot < next_slot) 1589 next_slot = slot; 1590 for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) { 1591 struct assoc_array_ptr *p = child->slots[i]; 1592 if (!p) 1593 continue; 1594 BUG_ON(assoc_array_ptr_is_meta(p)); 1595 while (new_n->slots[next_slot]) 1596 next_slot++; 1597 BUG_ON(next_slot >= ASSOC_ARRAY_FAN_OUT); 1598 new_n->slots[next_slot++] = p; 1599 nr_free--; 1600 } 1601 kfree(child); 1602 } else { 1603 pr_devel("[%d] retain node %lu/%d [nx %d]\n", 1604 slot, child->nr_leaves_on_branch, nr_free + 1, 1605 next_slot); 1606 retained = true; 1607 } 1608 } 1609 1610 if (retained && new_n->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT) { 1611 pr_devel("internal nodes remain despite enough space, retrying\n"); 1612 goto retry_compress; 1613 } 1614 pr_devel("after: %lu\n", new_n->nr_leaves_on_branch); 1615 1616 nr_leaves_on_tree = new_n->nr_leaves_on_branch; 1617 1618 /* Excise this node if it is singly occupied by a shortcut */ 1619 if (nr_free == ASSOC_ARRAY_FAN_OUT - 1) { 1620 for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) 1621 if ((ptr = new_n->slots[slot])) 1622 break; 1623 1624 if (assoc_array_ptr_is_meta(ptr) && 1625 assoc_array_ptr_is_shortcut(ptr)) { 1626 pr_devel("excise node %p with 1 shortcut\n", new_n); 1627 new_s = assoc_array_ptr_to_shortcut(ptr); 1628 new_parent = new_n->back_pointer; 1629 slot = new_n->parent_slot; 1630 kfree(new_n); 1631 if (!new_parent) { 1632 new_s->back_pointer = NULL; 1633 new_s->parent_slot = 0; 1634 new_root = ptr; 1635 goto gc_complete; 1636 } 1637 1638 if (assoc_array_ptr_is_shortcut(new_parent)) { 1639 /* We can discard any preceding shortcut also */ 1640 struct assoc_array_shortcut *s = 1641 assoc_array_ptr_to_shortcut(new_parent); 1642 1643 pr_devel("excise preceding shortcut\n"); 1644 1645 new_parent = new_s->back_pointer = s->back_pointer; 1646 slot = new_s->parent_slot = s->parent_slot; 1647 kfree(s); 1648 if (!new_parent) { 1649 new_s->back_pointer = NULL; 1650 new_s->parent_slot = 0; 1651 new_root = ptr; 1652 goto gc_complete; 1653 } 1654 } 1655 1656 new_s->back_pointer = new_parent; 1657 new_s->parent_slot = slot; 1658 new_n = assoc_array_ptr_to_node(new_parent); 1659 new_n->slots[slot] = ptr; 1660 goto ascend_old_tree; 1661 } 1662 } 1663 1664 /* Excise any shortcuts we might encounter that point to nodes that 1665 * only contain leaves. 1666 */ 1667 ptr = new_n->back_pointer; 1668 if (!ptr) 1669 goto gc_complete; 1670 1671 if (assoc_array_ptr_is_shortcut(ptr)) { 1672 new_s = assoc_array_ptr_to_shortcut(ptr); 1673 new_parent = new_s->back_pointer; 1674 slot = new_s->parent_slot; 1675 1676 if (new_n->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT) { 1677 struct assoc_array_node *n; 1678 1679 pr_devel("excise shortcut\n"); 1680 new_n->back_pointer = new_parent; 1681 new_n->parent_slot = slot; 1682 kfree(new_s); 1683 if (!new_parent) { 1684 new_root = assoc_array_node_to_ptr(new_n); 1685 goto gc_complete; 1686 } 1687 1688 n = assoc_array_ptr_to_node(new_parent); 1689 n->slots[slot] = assoc_array_node_to_ptr(new_n); 1690 } 1691 } else { 1692 new_parent = ptr; 1693 } 1694 new_n = assoc_array_ptr_to_node(new_parent); 1695 1696 ascend_old_tree: 1697 ptr = node->back_pointer; 1698 if (assoc_array_ptr_is_shortcut(ptr)) { 1699 shortcut = assoc_array_ptr_to_shortcut(ptr); 1700 slot = shortcut->parent_slot; 1701 cursor = shortcut->back_pointer; 1702 if (!cursor) 1703 goto gc_complete; 1704 } else { 1705 slot = node->parent_slot; 1706 cursor = ptr; 1707 } 1708 BUG_ON(!cursor); 1709 node = assoc_array_ptr_to_node(cursor); 1710 slot++; 1711 goto continue_node; 1712 1713 gc_complete: 1714 edit->set[0].to = new_root; 1715 assoc_array_apply_edit(edit); 1716 array->nr_leaves_on_tree = nr_leaves_on_tree; 1717 return 0; 1718 1719 enomem: 1720 pr_devel("enomem\n"); 1721 assoc_array_destroy_subtree(new_root, edit->ops); 1722 kfree(edit); 1723 return -ENOMEM; 1724 } 1725