static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) { struct rb_node *left = node->rb_left; struct rb_node *parent = rb_parent(node); if((node->rb_left = left->rb_right)) { rb_set_parent(left->rb_right, node); } left->rb_right = node; rb_set_parent(left, parent); if(parent) { if(node == parent->rb_right) { parent->rb_right = left; } else { parent->rb_left = left; } } else { root->rb_node = left; } rb_set_parent(node, left); }
static void rb_rotate_right(struct rb_node* x, struct rb_root* root) { struct rb_node *y = x->left, *px = rb_parent(x); x->left = y->right; rb_set_parent(y, px); if (y->right) rb_set_parent(y->right, x); if (px) { if (x == px->left) px->left = y; else px->right = y; } else root->node = y; y->right = x; rb_set_parent(x, y); }
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) { struct rb_node *left = node->rb_left; struct rb_node *parent = rb_parent(node); node->rb_left = left->rb_right; if (node->rb_left) rb_set_parent(left->rb_right, node); left->rb_right = node; rb_set_parent(left, parent); if (parent) { if (node == parent->rb_right) parent->rb_right = left; else parent->rb_left = left; } else root->rb_node = left; rb_set_parent(node, left); }
static void rb_rotate_right(char *node, char **tree) { char *p = node; char *q = rbtree_get_left(node); /* can't be NULL */ char *parent = rb_get_parent(p); if (!rb_is_root(p)) { if (rbtree_get_left(parent) == p) rb_set_left(q, parent); else rb_set_right(q, parent); } else *tree = q; rb_set_parent(parent, q); rb_set_parent(q, p); rb_set_left(rbtree_get_right(q), p); if (rbtree_get_left(p)) rb_set_parent(p, rbtree_get_left(p)); rb_set_right(p, q); }
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) { struct rb_node *right = node->rb_right; struct rb_node *parent = rb_parent(node); if ((node->rb_right = right->rb_left)) rb_set_parent(right->rb_left, node); right->rb_left = node; rb_set_parent(right, parent); if (parent) { if (node == parent->rb_left) parent->rb_left = right; else parent->rb_right = right; } else root->rb_node = right; rb_set_parent(node, right); }
static void __rb_rotate_right(LPRB_NODE node, LPRB_ROOT root) { LPRB_NODE left = node->rb_left; LPRB_NODE parent = rb_parent(node); if ((node->rb_left = left->rb_right)) rb_set_parent(left->rb_right, node); left->rb_right = node; rb_set_parent(left, parent); if (parent) { if (node == parent->rb_right) parent->rb_right = left; else parent->rb_left = left; } else root->rb_node = left; rb_set_parent(node, left); }
void rb_replace_node(struct rb_node *victim, struct rb_node *new_node, struct rb_root *root) { struct rb_node *parent = rb_parent(victim); /* Set the surrounding nodes to point to the replacement */ if (parent) { if (victim == parent->rb_left) parent->rb_left = new_node; else parent->rb_right = new_node; } else { root->rb_node = new_node; } if (victim->rb_left) rb_set_parent(victim->rb_left, new_node); if (victim->rb_right) rb_set_parent(victim->rb_right, new_node); /* Copy the pointers/colour from the victim to the replacement */ *new_node = *victim; }
void rb_erase(LPRB_NODE node, LPRB_ROOT root) { LPRB_NODE child, parent; int color; if (!node->rb_left) child = node->rb_right; else if (!node->rb_right) child = node->rb_left; else { LPRB_NODE old = node, left; node = node->rb_right; while ((left = node->rb_left) != NULL) node = left; if (rb_parent(old)) { if (rb_parent(old)->rb_left == old) rb_parent(old)->rb_left = node; else rb_parent(old)->rb_right = node; } else root->rb_node = node; child = node->rb_right; parent = rb_parent(node); color = rb_color(node); if (parent == old) { parent = node; } else { if (child) rb_set_parent(child, parent); parent->rb_left = child; node->rb_right = old->rb_right; rb_set_parent(old->rb_right, node); } node->rb_parent_color = old->rb_parent_color; node->rb_left = old->rb_left; rb_set_parent(old->rb_left, node); goto color; } parent = rb_parent(node); color = rb_color(node); if (child) rb_set_parent(child, parent); if (parent) { if (parent->rb_left == node) parent->rb_left = child; else parent->rb_right = child; } else root->rb_node = child; color: if (color == RB_BLACK) __rb_erase_color(child, parent, root); }
void rb_erase(struct rb_node *node, struct rb_root *root) { struct rb_node *child, *parent; int color; if (!node->rb_left) child = node->rb_right; else if (!node->rb_right) child = node->rb_left; else { struct rb_node *old = node, *left; node = node->rb_right; while ((left = node->rb_left) != NULL) node = left; child = node->rb_right; parent = rb_parent(node); color = rb_color(node); if (child) rb_set_parent(child, parent); if (parent == old) { parent->rb_right = child; parent = node; } else parent->rb_left = child; node->rb_parent_color = old->rb_parent_color; node->rb_right = old->rb_right; node->rb_left = old->rb_left; if (rb_parent(old)) { if (rb_parent(old)->rb_left == old) rb_parent(old)->rb_left = node; else rb_parent(old)->rb_right = node; } else root->rb_node = node; rb_set_parent(old->rb_left, node); if (old->rb_right) rb_set_parent(old->rb_right, node); goto color; } parent = rb_parent(node); color = rb_color(node); if (child) rb_set_parent(child, parent); if (parent) { if (parent->rb_left == node) parent->rb_left = child; else parent->rb_right = child; } else root->rb_node = child; color: if (color == RB_BLACK) __rb_erase_color(child, parent, root); }
void rb_erase(struct rb_node *node, struct rb_root *root) { struct rb_node *child, *parent; int color; struct mytype *mytype; mytype = container_of(node, struct mytype, node); if (!node->rb_left) child = node->rb_right; else if (!node->rb_right) child = node->rb_left; else { struct rb_node *old = node, *left; node = node->rb_right; while ((left = node->rb_left) != NULL) node = left; if (rb_parent(old)) { if (rb_parent(old)->rb_left == old) rb_parent(old)->rb_left = node; else rb_parent(old)->rb_right = node; } else root->rb_node = node; child = node->rb_right; parent = rb_parent(node); color = rb_color(node); if (parent == old) { parent = node; } else { if (child) rb_set_parent(child, parent); parent->rb_left = child; node->rb_right = old->rb_right; rb_set_parent(old->rb_right, node); } node->rb_parent_color = old->rb_parent_color; node->rb_left = old->rb_left; rb_set_parent(old->rb_left, node); goto color; } parent = rb_parent(node); color = rb_color(node); if (child) rb_set_parent(child, parent); if (parent) { if (parent->rb_left == node) parent->rb_left = child; else parent->rb_right = child; } else root->rb_node = child; color: if (color == RB_BLACK) { pr_debug("delete value = %02d, ", mytype->keyvalue); __rb_erase_color(child, parent, root); } else { pr_debug("delete value = %02d, 对应情况X。\n", mytype->keyvalue); } }
static void rbtree_remove(char *node, char **tree) { char *parent = rb_get_parent(node); char *left = rbtree_get_left(node); char *right = rbtree_get_right(node); char *next; int color; if (!left) next = right; else if (!right) next = left; else next = rbtree_first(right); if (parent) rb_set_child(next, parent, rbtree_get_left(parent) == node); else *tree = next; if (left && right) { color = rb_get_color(next); rb_set_color(rb_get_color(node), next); rb_set_left(left, next); rb_set_parent(next, left); if (next != right) { parent = rb_get_parent(next); rb_set_parent(rb_get_parent(node), next); node = rbtree_get_right(next); rb_set_left(node, parent); rb_set_right(right, next); rb_set_parent(next, right); } else { rb_set_parent(parent, next); parent = next; node = rbtree_get_right(next); } } else { color = rb_get_color(node); node = next; } /* * 'node' is now the sole successor's child and 'parent' its * new parent (since the successor can have been moved). */ if (node) rb_set_parent(parent, node); /* * The 'easy' cases. */ if (color == RB_RED) return; if (node && rb_is_red(node)) { rb_set_color(RB_BLACK, node); return; } do { if (node == *tree) break; if (node == rbtree_get_left(parent)) { char *sibling = rbtree_get_right(parent); if (rb_is_red(sibling)) { rb_set_color(RB_BLACK, sibling); rb_set_color(RB_RED, parent); rb_rotate_left(parent, tree); sibling = rbtree_get_right(parent); } if ((!rbtree_get_left(sibling) || rb_is_black(rbtree_get_left(sibling))) && (!rbtree_get_right(sibling) || rb_is_black(rbtree_get_right(sibling)))) { rb_set_color(RB_RED, sibling); node = parent; parent = rb_get_parent(parent); continue; } if (!rbtree_get_right(sibling) || rb_is_black(rbtree_get_right(sibling))) { rb_set_color(RB_BLACK, rbtree_get_left(sibling)); rb_set_color(RB_RED, sibling); rb_rotate_right(sibling, tree); sibling = rbtree_get_right(parent); } rb_set_color(rb_get_color(parent), sibling); rb_set_color(RB_BLACK, parent); rb_set_color(RB_BLACK, rbtree_get_right(sibling)); rb_rotate_left(parent, tree); node = *tree; break; } else { char *sibling = rbtree_get_left(parent); if (rb_is_red(sibling)) { rb_set_color(RB_BLACK, sibling); rb_set_color(RB_RED, parent); rb_rotate_right(parent, tree); sibling = rbtree_get_left(parent); } if ((!rbtree_get_left(sibling) || rb_is_black(rbtree_get_left(sibling))) && (!rbtree_get_right(sibling) || rb_is_black(rbtree_get_right(sibling)))) { rb_set_color(RB_RED, sibling); node = parent; parent = rb_get_parent(parent); continue; } if (!rbtree_get_left(sibling) || rb_is_black(rbtree_get_left(sibling))) { rb_set_color(RB_BLACK, rbtree_get_right(sibling)); rb_set_color(RB_RED, sibling); rb_rotate_left(sibling, tree); sibling = rbtree_get_left(parent); } rb_set_color(rb_get_color(parent), sibling); rb_set_color(RB_BLACK, parent); rb_set_color(RB_BLACK, rbtree_get_left(sibling)); rb_rotate_right(parent, tree); node = *tree; break; } } while (rb_is_black(node)); if (node) rb_set_color(RB_BLACK, node); }
static char *rbtree_insert(char *node, char **tree) { char *key, *parent; int is_left; key = rb_do_lookup(node, *tree, &parent, &is_left); if (key) return key; rb_set_left(NULL, node); rb_set_right(NULL, node); rb_set_color(RB_RED, node); rb_set_parent(parent, node); if (parent) { rb_set_child(node, parent, is_left); } else { *tree = node; } /* * Fixup the modified tree by recoloring nodes and performing * rotations (2 at most) hence the red-black tree properties are * preserved. */ while ((parent = rb_get_parent(node)) && rb_is_red(parent)) { char *grandpa = rb_get_parent(parent); if (parent == rbtree_get_left(grandpa)) { char *uncle = rbtree_get_right(grandpa); if (uncle && rb_is_red(uncle)) { rb_set_color(RB_BLACK, parent); rb_set_color(RB_BLACK, uncle); rb_set_color(RB_RED, grandpa); node = grandpa; } else { if (node == rbtree_get_right(parent)) { rb_rotate_left(parent, tree); node = parent; parent = rb_get_parent(node); } rb_set_color(RB_BLACK, parent); rb_set_color(RB_RED, grandpa); rb_rotate_right(grandpa, tree); } } else { char *uncle = rbtree_get_left(grandpa); if (uncle && rb_is_red(uncle)) { rb_set_color(RB_BLACK, parent); rb_set_color(RB_BLACK, uncle); rb_set_color(RB_RED, grandpa); node = grandpa; } else { if (node == rbtree_get_left(parent)) { rb_rotate_right(parent, tree); node = parent; parent = rb_get_parent(node); } rb_set_color(RB_BLACK, parent); rb_set_color(RB_RED, grandpa); rb_rotate_left(grandpa, tree); } } } rb_set_color(RB_BLACK, *tree); return NULL; }
void rb_delete(struct rb_node* node, struct rb_root* root) { int color; struct rb_node *parent, *child = NULL; if (node->left && node->right) { struct rb_node* old = node; struct rb_node* old_parent = rb_parent(node); node = node->right; while (node->left) node = node->left; if (old_parent) { if (old == old_parent->left) old_parent->left = node; else old_parent->right = node; } else root->node = node; child = node->right; parent = rb_parent(node); color = rb_color(node); if (parent == old) parent = node; else { if (child) rb_set_parent(child, parent); parent->left = child; node->right = old->right; rb_set_parent(old->right, node); } node->parent_color = old->parent_color; node->left = old->left; rb_set_parent(old->left, node); goto rebalance; } if (!node->left) child = node->right; else child = node->left; parent = rb_parent(node); color = rb_color(node); if (child) rb_set_parent(child, parent); if (parent) { if (node == parent->left) parent->left = child; else parent->right = child; } else root->node = child; rebalance: if (color == RB_BLACK) rb_delete_rebalance(child, parent, root); }
static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *latest_node) { struct jffs2_tmp_dnode_info *tn; struct rb_root tn_list; struct rb_node *rb, *repl_rb; struct jffs2_full_dirent *fd_list; struct jffs2_full_dnode *fn, *first_fn = NULL; uint32_t crc; uint32_t latest_mctime, mctime_ver; size_t retlen; int ret; dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); /* Grab all nodes relevant to this ino */ ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); if (ret) { JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); return ret; } f->dents = fd_list; rb = rb_first(&tn_list); while (rb) { cond_resched(); tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); fn = tn->fn; ret = 1; dbg_readinode("consider node ver %u, phys offset " "%#08x(%d), range %u-%u.\n", tn->version, ref_offset(fn->raw), ref_flags(fn->raw), fn->ofs, fn->ofs + fn->size); if (fn->size) { ret = jffs2_add_older_frag_to_fragtree(c, f, tn); /* TODO: the error code isn't checked, check it */ jffs2_dbg_fragtree_paranoia_check_nolock(f); BUG_ON(ret < 0); if (!first_fn && ret == 0) first_fn = fn; } else if (!first_fn) { first_fn = fn; f->metadata = fn; ret = 0; /* Prevent freeing the metadata update node */ } else jffs2_mark_node_obsolete(c, fn->raw); BUG_ON(rb->rb_left); if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) { /* We were then left-hand child of our parent. We need * to move our own right-hand child into our place. */ repl_rb = rb->rb_right; if (repl_rb) rb_set_parent(repl_rb, rb_parent(rb)); } else repl_rb = NULL; rb = rb_next(rb); /* Remove the spent tn from the tree; don't bother rebalancing * but put our right-hand child in our own place. */ if (rb_parent(&tn->rb)) { if (rb_parent(&tn->rb)->rb_left == &tn->rb) rb_parent(&tn->rb)->rb_left = repl_rb; else if (rb_parent(&tn->rb)->rb_right == &tn->rb) rb_parent(&tn->rb)->rb_right = repl_rb; else BUG(); } else if (tn->rb.rb_right) rb_set_parent(tn->rb.rb_right, NULL); jffs2_free_tmp_dnode_info(tn); if (ret) { dbg_readinode("delete dnode %u-%u.\n", fn->ofs, fn->ofs + fn->size); jffs2_free_full_dnode(fn); } } jffs2_dbg_fragtree_paranoia_check_nolock(f); BUG_ON(first_fn && ref_obsolete(first_fn->raw)); fn = first_fn; if (unlikely(!first_fn)) { /* No data nodes for this inode. */ if (f->inocache->ino != 1) { JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); if (!fd_list) { if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); return -EIO; } JFFS2_NOTICE("but it has children so we fake some modes for it\n"); } latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); latest_node->version = cpu_to_je32(0); latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); latest_node->isize = cpu_to_je32(0); latest_node->gid = cpu_to_je16(0); latest_node->uid = cpu_to_je16(0); if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); return 0; } ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); if (ret || retlen != sizeof(*latest_node)) { JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", ret, retlen, sizeof(*latest_node)); /* FIXME: If this fails, there seems to be a memory leak. Find it. */ up(&f->sem); jffs2_do_clear_inode(c, f); return ret?ret:-EIO; } crc = crc32(0, latest_node, sizeof(*latest_node)-8); if (crc != je32_to_cpu(latest_node->node_crc)) { JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { case S_IFDIR: if (mctime_ver > je32_to_cpu(latest_node->version)) { /* The times in the latest_node are actually older than mctime in the latest dirent. Cheat. */ latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); } break; case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); break; case S_IFLNK: /* Hack to work around broken isize in old symlink code. Remove this when dwmw2 comes to his senses and stops symlinks from being an entirely gratuitous special case. */ if (!je32_to_cpu(latest_node->isize)) latest_node->isize = latest_node->dsize; if (f->inocache->state != INO_STATE_CHECKING) { /* Symlink's inode data is the target path. Read it and * keep in RAM to facilitate quick follow symlink * operation. */ f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); if (!f->target) { JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); up(&f->sem); jffs2_do_clear_inode(c, f); return -ENOMEM; } ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; kfree(f->target); f->target = NULL; up(&f->sem); jffs2_do_clear_inode(c, f); return -ret; } f->target[je32_to_cpu(latest_node->csize)] = '\0'; dbg_readinode("symlink's target '%s' cached\n", f->target); } /* fall through... */ case S_IFBLK: case S_IFCHR: /* Certain inode types should have only one data node, and it's kept as the metadata node */ if (f->metadata) { JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", f->inocache->ino, jemode_to_cpu(latest_node->mode)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } if (!frag_first(&f->fragtree)) { JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", f->inocache->ino, jemode_to_cpu(latest_node->mode)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } /* ASSERT: f->fraglist != NULL */ if (frag_next(frag_first(&f->fragtree))) { JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", f->inocache->ino, jemode_to_cpu(latest_node->mode)); /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } /* OK. We're happy */ f->metadata = frag_first(&f->fragtree)->node; jffs2_free_node_frag(frag_first(&f->fragtree)); f->fragtree = RB_ROOT; break; } if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); return 0; }
/* * 删除结点 * * 参数说明: * tree 红黑树的根结点 * node 删除的结点 */ void rbtree_delete(RBRoot *root, Node *node) { Node *child, *parent; int color; // tree // / \ // dnode // / \ // left right // / \ // replace right // 被删除节点的"左右孩子都不为空"的情况。 if ( (node->left!=NULL) && (node->right!=NULL) ) { // 被删节点的后继节点。(称为"取代节点") // 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。 Node *replace = node; // 获取后继节点 replace = replace->right; while (replace->left != NULL) replace = replace->left; // "node节点"不是根节点(只有根节点不存在父节点) if (rb_parent(node)) { if (rb_parent(node)->left == node) rb_parent(node)->left = replace; else rb_parent(node)->right = replace; } else // "node节点"是根节点,更新根节点。 root->node = replace; // child是"取代节点"的右孩子,也是需要"调整的节点"。 // "取代节点"肯定不存在左孩子!因为它是一个后继节点。 child = replace->right; parent = rb_parent(replace); // 保存"取代节点"的颜色 color = rb_color(replace); // "被删除节点"是"它的后继节点的父节点" if (parent == node) { parent = replace; } else { // child不为空 if (child) rb_set_parent(child, parent); parent->left = child; replace->right = node->right; rb_set_parent(node->right, replace); } replace->parent = node->parent; replace->color = node->color; replace->left = node->left; node->left->parent = replace; if (color == BLACK) rbtree_delete_fixup(root, child, parent); free(node); return ; } if (node->left !=NULL) child = node->left; else child = node->right; parent = node->parent; // 保存"取代节点"的颜色 color = node->color; if (child) child->parent = parent; // "node节点"不是根节点 if (parent) { if (parent->left == node) parent->left = child; else parent->right = child; } else root->node = child; if (color == BLACK) rbtree_delete_fixup(root, child, parent); free(node); }