void rb_insert(struct rb_tree *t, struct rb_node *n, struct rb_callbacks *cb) { /* insert node into the correct location in the tree, then link it in to recolor the tree */ struct rb_node *parent = t->root; while (parent) { if (cb->cmp(n, parent) < 0) { if (!parent->left) { parent->left = n; break; } parent = parent->left; } else { if (!parent->right) { parent->right = n; break; } parent = parent->right; } } n->parent = parent; rb_link(t, n, cb); }
static struct fs_entry *vfs_lookup(struct fs_entry *dir, const char *name, bool create, int *rc) { struct fs_node *node = dir->node; struct rb_node **plink = &dir->children.root; struct rb_node *parent = 0; if (!node->ops->lookup) { *rc = -ENOTSUP; return 0; } const bool enabled = spin_lock_irqsave(&dir->lock); while (*plink) { struct fs_entry *entry = TREE_ENTRY(*plink, struct fs_entry, link); const int cmp = strcmp(entry->name, name); if (!cmp) { *rc = 0; vfs_entry_get(entry); spin_unlock_irqrestore(&dir->lock, enabled); return entry; } parent = *plink; if (cmp < 0) plink = &parent->right; else plink = &parent->left; } struct fs_entry *entry = vfs_entry_create(name); if (!entry) { spin_unlock_irqrestore(&dir->lock, enabled); *rc = -ENOMEM; return 0; } rb_link(&entry->link, parent, plink); rb_insert(&entry->link, &dir->children); entry->parent = vfs_entry_get(dir); entry->cached = true; spin_unlock_irqrestore(&dir->lock, enabled); *rc = node->ops->lookup(node, entry); if (*rc && !create) { vfs_entry_put(entry); return 0; } return entry; }