blob: 520df00e676ae0a831ab7a3d9811ec03581ff35d [file] [log] [blame]
/*
* Copyright (C) 2013-2015 Kay Sievers
* Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
* Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
* Copyright (C) 2013-2015 Linux Foundation
*
* kdbus is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*/
#include <linux/atomic.h>
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/kdev_t.h>
#include <linux/rbtree.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include "bus.h"
#include "domain.h"
#include "endpoint.h"
#include "fs.h"
#include "handle.h"
#include "node.h"
#include "util.h"
/**
* DOC: kdbus nodes
*
* Nodes unify lifetime management across exposed kdbus objects and provide a
* hierarchy. Each kdbus object, that might be exposed to user-space, has a
* kdbus_node object embedded and is linked into the hierarchy. Each node can
* have any number (0-n) of child nodes linked. Each child retains a reference
* to its parent node. For root-nodes, the parent is NULL.
*
* Each node object goes through a bunch of states during it's lifetime:
* * NEW
* * LINKED (can be skipped by NEW->FREED transition)
* * ACTIVE (can be skipped by LINKED->INACTIVE transition)
* * INACTIVE
* * DRAINED
* * FREED
*
* Each node is allocated by the caller and initialized via kdbus_node_init().
* This never fails and sets the object into state NEW. From now on, ref-counts
* on the node manage its lifetime. During init, the ref-count is set to 1. Once
* it drops to 0, the node goes to state FREED and the node->free_cb() callback
* is called to deallocate any memory.
*
* After initializing a node, you usually link it into the hierarchy. You need
* to provide a parent node and a name. The node will be linked as child to the
* parent and a globally unique ID is assigned to the child. The name of the
* child must be unique for all children of this parent. Otherwise, linking the
* child will fail with -EEXIST.
* Note that the child is not marked active, yet. Admittedly, it prevents any
* other node from being linked with the same name (thus, it reserves that
* name), but any child-lookup (via name or unique ID) will never return this
* child unless it has been marked active.
*
* Once successfully linked, you can use kdbus_node_activate() to activate a
* child. This will mark the child active. This state can be skipped by directly
* deactivating the child via kdbus_node_deactivate() (see below).
* By activating a child, you enable any lookups on this child to succeed from
* now on. Furthermore, any code that got its hands on a reference to the node,
* can from now on "acquire" the node.
*
* Active References (or: 'acquiring' and 'releasing' a node)
* Additionally to normal object references, nodes support something we call
* "active references". An active reference can be acquired via
* kdbus_node_acquire() and released via kdbus_node_release(). A caller
* _must_ own a normal object reference whenever calling those functions.
* Unlike object references, acquiring an active reference can fail (by
* returning 'false' from kdbus_node_acquire()). An active reference can
* only be acquired if the node is marked active. If it is not marked
* active, yet, or if it was already deactivated, no more active references
* can be acquired, ever!
* Active references are used to track tasks working on a node. Whenever a
* task enters kernel-space to perform an action on a node, it acquires an
* active reference, performs the action and releases the reference again.
* While holding an active reference, the node is guaranteed to stay active.
* If the node is deactivated in parallel, the node is marked as
* deactivated, then we wait for all active references to be dropped, before
* we finally proceed with any cleanups. That is, if you hold an active
* reference to a node, any resources that are bound to the "active" state
* are guaranteed to stay accessible until you release your reference.
*
* Active-references are very similar to rw-locks, where acquiring a node is
* equal to try-read-lock and releasing to read-unlock. Deactivating a node
* means write-lock and never releasing it again.
* Unlike rw-locks, the 'active reference' concept is more versatile and
* avoids unusual rw-lock usage (never releasing a write-lock..).
*
* It is safe to acquire multiple active-references recursively. But you
* need to check the return value of kdbus_node_acquire() on _each_ call. It
* may stop granting references at _any_ time.
*
* You're free to perform any operations you want while holding an active
* reference, except sleeping for an indefinite period. Sleeping for a fixed
* amount of time is fine, but you usually should not wait on wait-queues
* without a timeout.
* For example, if you wait for I/O to happen, you should gather all data
* and schedule the I/O operation, then release your active reference and
* wait for it to complete. Then try to acquire a new reference. If it
* fails, perform any cleanup (the node is now dead). Otherwise, you can
* finish your operation.
*
* All nodes can be deactivated via kdbus_node_deactivate() at any time. You can
* call this multiple times, even in parallel or on nodes that were never
* linked, and it will just work. The only restriction is, you must not hold an
* active reference when calling kdbus_node_deactivate().
* By deactivating a node, it is immediately marked inactive. Then, we wait for
* all active references to be released (called 'draining' the node). This
* shouldn't take very long as we don't perform long-lasting operations while
* holding an active reference. Note that once the node is marked inactive, no
* new active references can be acquired.
* Once all active references are dropped, the node is considered 'drained'. Now
* kdbus_node_deactivate() is called on each child of the node before we
* continue deactvating our node. That is, once all children are entirely
* deactivated, we call ->release_cb() of our node. ->release_cb() can release
* any resources on that node which are bound to the "active" state of a node.
* When done, we unlink the node from its parent rb-tree, mark it as
* 'released' and return.
* If kdbus_node_deactivate() is called multiple times (even in parallel), all
* but one caller will just wait until the node is fully deactivated. That is,
* one random caller of kdbus_node_deactivate() is selected to call
* ->release_cb() and cleanup the node. Only once all this is done, all other
* callers will return from kdbus_node_deactivate(). That is, it doesn't matter
* whether you're the selected caller or not, it will only return after
* everything is fully done.
*
* When a node is activated, we acquire a normal object reference to the node.
* This reference is dropped after deactivation is fully done (and only iff the
* node really was activated). This allows callers to link+activate a child node
* and then drop all refs. The node will be deactivated together with the
* parent, and then be freed when this reference is dropped.
*
* Currently, nodes provide a bunch of resources that external code can use
* directly. This includes:
*
* * node->waitq: Each node has its own wait-queue that is used to manage
* the 'active' state. When a node is deactivated, we wait on
* this queue until all active refs are dropped. Analogously,
* when you release an active reference on a deactivated
* node, and the active ref-count drops to 0, we wake up a
* single thread on this queue. Furthermore, once the
* ->release_cb() callback finished, we wake up all waiters.
* The node-owner is free to re-use this wait-queue for other
* purposes. As node-management uses this queue only during
* deactivation, it is usually totally fine to re-use the
* queue for other, preferably low-overhead, use-cases.
*
* * node->type: This field defines the type of the owner of this node. It
* must be set during node initialization and must remain
* constant. The node management never looks at this value,
* but external users might use to gain access to the owner
* object of a node.
* It is totally up to the owner of the node to define what
* their type means. Usually it means you can access the
* parent structure via container_of(), as long as you hold an
* active reference to the node.
*
* * node->free_cb: callback after all references are dropped
* node->release_cb: callback during node deactivation
* These fields must be set by the node owner during
* node initialization. They must remain constant. If
* NULL, they're skipped.
*
* * node->mode: filesystem access modes
* node->uid: filesystem owner uid
* node->gid: filesystem owner gid
* These fields must be set by the node owner during node
* initialization. They must remain constant and may be
* accessed by other callers to properly initialize
* filesystem nodes.
*
* * node->id: This is an unsigned 32bit integer allocated by an IDR. It is
* always kept as small as possible during allocation and is
* globally unique across all nodes allocated by this module. 0
* is reserved as "not assigned" and is the default.
* The ID is assigned during kdbus_node_link() and is kept until
* the object is freed. Thus, the ID surpasses the active
* lifetime of a node. As long as you hold an object reference
* to a node (and the node was linked once), the ID is valid and
* unique.
*
* * node->name: name of this node
* node->hash: 31bit hash-value of @name (range [2..INT_MAX-1])
* These values follow the same lifetime rules as node->id.
* They're initialized when the node is linked and then remain
* constant until the last object reference is dropped.
* Unlike the id, the name is only unique across all siblings
* and only until the node is deactivated. Currently, the name
* is even unique if linked but not activated, yet. This might
* change in the future, though. Code should not rely on this.
*
* * node->lock: lock to protect node->children, node->rb, node->parent
* * node->parent: Reference to parent node. This is set during LINK time
* and is dropped during destruction. You must not access
* it unless you hold an active reference to the node or if
* you know the node is dead.
* * node->children: rb-tree of all linked children of this node. You must
* not access this directly, but use one of the iterator
* or lookup helpers.
*/
/*
* Bias values track states of "active references". They're all negative. If a
* node is active, its active-ref-counter is >=0 and tracks all active
* references. Once a node is deactivaed, we subtract NODE_BIAS. This means, the
* counter is now negative but still counts the active references. Once it drops
* to exactly NODE_BIAS, we know all active references were dropped. Exactly one
* thread will change it to NODE_RELEASE now, perform cleanup and then put it
* into NODE_DRAINED. Once drained, all other threads that tried deactivating
* the node will now be woken up (thus, they wait until the node is fully done).
* The initial state during node-setup is NODE_NEW. If a node is directly
* deactivated without having ever been active, it is put into
* NODE_RELEASE_DIRECT instead of NODE_BIAS. This tracks this one-bit state
* across node-deactivation. The task putting it into NODE_RELEASE now knows
* whether the node was active before or not.
*
* Some archs implement atomic_sub(v) with atomic_add(-v), so reserve INT_MIN
* to avoid overflows if multiplied by -1.
*/
#define KDBUS_NODE_BIAS (INT_MIN + 5)
#define KDBUS_NODE_RELEASE_DIRECT (KDBUS_NODE_BIAS - 1)
#define KDBUS_NODE_RELEASE (KDBUS_NODE_BIAS - 2)
#define KDBUS_NODE_DRAINED (KDBUS_NODE_BIAS - 3)
#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4)
/* global unique ID mapping for kdbus nodes */
static DEFINE_IDR(kdbus_node_idr);
static DECLARE_RWSEM(kdbus_node_idr_lock);
/**
* kdbus_node_name_hash() - hash a name
* @name: The string to hash
*
* This computes the hash of @name. It is guaranteed to be in the range
* [2..INT_MAX-1]. The values 1, 2 and INT_MAX are unused as they are reserved
* for the filesystem code.
*
* Return: hash value of the passed string
*/
static unsigned int kdbus_node_name_hash(const char *name)
{
unsigned int hash;
/* reserve hash numbers 0, 1 and >=INT_MAX for magic directories */
hash = kdbus_strhash(name) & INT_MAX;
if (hash < 2)
hash += 2;
if (hash >= INT_MAX)
hash = INT_MAX - 1;
return hash;
}
/**
* kdbus_node_name_compare() - compare a name with a node's name
* @hash: hash of the string to compare the node with
* @name: name to compare the node with
* @node: node to compare the name with
*
* Return: 0 if @name and @hash exactly match the information in @node, or
* an integer less than or greater than zero if @name is found, respectively,
* to be less than or be greater than the string stored in @node.
*/
static int kdbus_node_name_compare(unsigned int hash, const char *name,
const struct kdbus_node *node)
{
if (hash != node->hash)
return hash - node->hash;
return strcmp(name, node->name);
}
/**
* kdbus_node_init() - initialize a kdbus_node
* @node: Pointer to the node to initialize
* @type: The type the node will have (KDBUS_NODE_*)
*
* The caller is responsible of allocating @node and initializating it to zero.
* Once this call returns, you must use the node_ref() and node_unref()
* functions to manage this node.
*/
void kdbus_node_init(struct kdbus_node *node, unsigned int type)
{
atomic_set(&node->refcnt, 1);
mutex_init(&node->lock);
node->id = 0;
node->type = type;
RB_CLEAR_NODE(&node->rb);
node->children = RB_ROOT;
init_waitqueue_head(&node->waitq);
atomic_set(&node->active, KDBUS_NODE_NEW);
}
/**
* kdbus_node_link() - link a node into the nodes system
* @node: Pointer to the node to initialize
* @parent: Pointer to a parent node, may be %NULL
* @name: The name of the node (or NULL if root node)
*
* This links a node into the hierarchy. This must not be called multiple times.
* If @parent is NULL, the node becomes a new root node.
*
* This call will fail if @name is not unique across all its siblings or if no
* ID could be allocated. You must not activate a node if linking failed! It is
* safe to deactivate it, though.
*
* Once you linked a node, you must call kdbus_node_deactivate() before you drop
* the last reference (even if you never activate the node).
*
* Return: 0 on success. negative error otherwise.
*/
int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
const char *name)
{
int ret;
if (WARN_ON(node->type != KDBUS_NODE_DOMAIN && !parent))
return -EINVAL;
if (WARN_ON(parent && !name))
return -EINVAL;
if (name) {
node->name = kstrdup(name, GFP_KERNEL);
if (!node->name)
return -ENOMEM;
node->hash = kdbus_node_name_hash(name);
}
down_write(&kdbus_node_idr_lock);
ret = idr_alloc(&kdbus_node_idr, node, 1, 0, GFP_KERNEL);
if (ret >= 0)
node->id = ret;
up_write(&kdbus_node_idr_lock);
if (ret < 0)
return ret;
ret = 0;
if (parent) {
struct rb_node **n, *prev;
if (!kdbus_node_acquire(parent))
return -ESHUTDOWN;
mutex_lock(&parent->lock);
n = &parent->children.rb_node;
prev = NULL;
while (*n) {
struct kdbus_node *pos;
int result;
pos = kdbus_node_from_rb(*n);
prev = *n;
result = kdbus_node_name_compare(node->hash,
node->name,
pos);
if (result == 0) {
ret = -EEXIST;
goto exit_unlock;
}
if (result < 0)
n = &pos->rb.rb_left;
else
n = &pos->rb.rb_right;
}
/* add new node and rebalance the tree */
rb_link_node(&node->rb, prev, n);
rb_insert_color(&node->rb, &parent->children);
node->parent = kdbus_node_ref(parent);
exit_unlock:
mutex_unlock(&parent->lock);
kdbus_node_release(parent);
}
return ret;
}
/**
* kdbus_node_ref() - Acquire object reference
* @node: node to acquire reference to (or NULL)
*
* This acquires a new reference to @node. You must already own a reference when
* calling this!
* If @node is NULL, this is a no-op.
*
* Return: @node is returned
*/
struct kdbus_node *kdbus_node_ref(struct kdbus_node *node)
{
if (node)
atomic_inc(&node->refcnt);
return node;
}
/**
* kdbus_node_unref() - Drop object reference
* @node: node to drop reference to (or NULL)
*
* This drops an object reference to @node. You must not access the node if you
* no longer own a reference.
* If the ref-count drops to 0, the object will be destroyed (->free_cb will be
* called).
*
* If you linked or activated the node, you must deactivate the node before you
* drop your last reference! If you didn't link or activate the node, you can
* drop any reference you want.
*
* Note that this calls into ->free_cb() and thus _might_ sleep. The ->free_cb()
* callbacks must not acquire any outer locks, though. So you can safely drop
* references while holding locks.
*
* If @node is NULL, this is a no-op.
*
* Return: This always returns NULL
*/
struct kdbus_node *kdbus_node_unref(struct kdbus_node *node)
{
if (node && atomic_dec_and_test(&node->refcnt)) {
struct kdbus_node safe = *node;
WARN_ON(atomic_read(&node->active) != KDBUS_NODE_DRAINED);
WARN_ON(!RB_EMPTY_NODE(&node->rb));
if (node->free_cb)
node->free_cb(node);
down_write(&kdbus_node_idr_lock);
if (safe.id > 0)
idr_remove(&kdbus_node_idr, safe.id);
/* drop caches after last node to not leak memory on unload */
if (idr_is_empty(&kdbus_node_idr)) {
idr_destroy(&kdbus_node_idr);
idr_init(&kdbus_node_idr);
}
up_write(&kdbus_node_idr_lock);
kfree(safe.name);
/*
* kdbusfs relies on the parent to be available even after the
* node was deactivated and unlinked. Therefore, we pin it
* until a node is destroyed.
*/
kdbus_node_unref(safe.parent);
}
return NULL;
}
/**
* kdbus_node_is_active() - test whether a node is active
* @node: node to test
*
* This checks whether @node is active. That means, @node was linked and
* activated by the node owner and hasn't been deactivated, yet. If, and only
* if, a node is active, kdbus_node_acquire() will be able to acquire active
* references.
*
* Note that this function does not give any lifetime guarantees. After this
* call returns, the node might be deactivated immediately. Normally, what you
* want is to acquire a real active reference via kdbus_node_acquire().
*
* Return: true if @node is active, false otherwise
*/
bool kdbus_node_is_active(struct kdbus_node *node)
{
return atomic_read(&node->active) >= 0;
}
/**
* kdbus_node_is_deactivated() - test whether a node was already deactivated
* @node: node to test
*
* This checks whether kdbus_node_deactivate() was called on @node. Note that
* this might be true even if you never deactivated the node directly, but only
* one of its ancestors.
*
* Note that even if this returns 'false', the node might get deactivated
* immediately after the call returns.
*
* Return: true if @node was already deactivated, false if not
*/
bool kdbus_node_is_deactivated(struct kdbus_node *node)
{
int v;
v = atomic_read(&node->active);
return v != KDBUS_NODE_NEW && v < 0;
}
/**
* kdbus_node_activate() - activate a node
* @node: node to activate
*
* This marks @node as active if, and only if, the node wasn't activated nor
* deactivated, yet, and the parent is still active. Any but the first call to
* kdbus_node_activate() is a no-op.
* If you called kdbus_node_deactivate() before, then even the first call to
* kdbus_node_activate() will be a no-op.
*
* This call doesn't give any lifetime guarantees. The node might get
* deactivated immediately after this call returns. Or the parent might already
* be deactivated, which will make this call a no-op.
*
* If this call successfully activated a node, it will take an object reference
* to it. This reference is dropped after the node is deactivated. Therefore,
* the object owner can safely drop their reference to @node iff they know that
* its parent node will get deactivated at some point. Once the parent node is
* deactivated, it will deactivate all its child and thus drop this reference
* again.
*
* Return: True if this call successfully activated the node, otherwise false.
* Note that this might return false, even if the node is still active
* (eg., if you called this a second time).
*/
bool kdbus_node_activate(struct kdbus_node *node)
{
bool res = false;
mutex_lock(&node->lock);
if (atomic_read(&node->active) == KDBUS_NODE_NEW) {
atomic_sub(KDBUS_NODE_NEW, &node->active);
/* activated nodes have ref +1 */
kdbus_node_ref(node);
res = true;
}
mutex_unlock(&node->lock);
return res;
}
/**
* kdbus_node_deactivate() - deactivate a node
* @node: The node to deactivate.
*
* This function recursively deactivates this node and all its children. It
* returns only once all children and the node itself were recursively disabled
* (even if you call this function multiple times in parallel).
*
* It is safe to call this function on _any_ node that was initialized _any_
* number of times.
*
* This call may sleep, as it waits for all active references to be dropped.
*/
void kdbus_node_deactivate(struct kdbus_node *node)
{
struct kdbus_node *pos, *child;
struct rb_node *rb;
int v_pre, v_post;
pos = node;
/*
* To avoid recursion, we perform back-tracking while deactivating
* nodes. For each node we enter, we first mark the active-counter as
* deactivated by adding BIAS. If the node as children, we set the first
* child as current position and start over. If the node has no
* children, we drain the node by waiting for all active refs to be
* dropped and then releasing the node.
*
* After the node is released, we set its parent as current position
* and start over. If the current position was the initial node, we're
* done.
*
* Note that this function can be called in parallel by multiple
* callers. We make sure that each node is only released once, and any
* racing caller will wait until the other thread fully released that
* node.
*/
for (;;) {
/*
* Add BIAS to node->active to mark it as inactive. If it was
* never active before, immediately mark it as RELEASE_INACTIVE
* so we remember this state.
* We cannot remember v_pre as we might iterate into the
* children, overwriting v_pre, before we can release our node.
*/
mutex_lock(&pos->lock);
v_pre = atomic_read(&pos->active);
if (v_pre >= 0)
atomic_add_return(KDBUS_NODE_BIAS, &pos->active);
else if (v_pre == KDBUS_NODE_NEW)
atomic_set(&pos->active, KDBUS_NODE_RELEASE_DIRECT);
mutex_unlock(&pos->lock);
/* wait until all active references were dropped */
wait_event(pos->waitq,
atomic_read(&pos->active) <= KDBUS_NODE_BIAS);
mutex_lock(&pos->lock);
/* recurse into first child if any */
rb = rb_first(&pos->children);
if (rb) {
child = kdbus_node_ref(kdbus_node_from_rb(rb));
mutex_unlock(&pos->lock);
pos = child;
continue;
}
/* mark object as RELEASE */
v_post = atomic_read(&pos->active);
if (v_post == KDBUS_NODE_BIAS ||
v_post == KDBUS_NODE_RELEASE_DIRECT)
atomic_set(&pos->active, KDBUS_NODE_RELEASE);
mutex_unlock(&pos->lock);
/*
* If this is the thread that marked the object as RELEASE, we
* perform the actual release. Otherwise, we wait until the
* release is done and the node is marked as DRAINED.
*/
if (v_post == KDBUS_NODE_BIAS ||
v_post == KDBUS_NODE_RELEASE_DIRECT) {
if (pos->release_cb)
pos->release_cb(pos, v_post == KDBUS_NODE_BIAS);
if (pos->parent) {
mutex_lock(&pos->parent->lock);
if (!RB_EMPTY_NODE(&pos->rb)) {
rb_erase(&pos->rb,
&pos->parent->children);
RB_CLEAR_NODE(&pos->rb);
}
mutex_unlock(&pos->parent->lock);
}
/* mark as DRAINED */
atomic_set(&pos->active, KDBUS_NODE_DRAINED);
wake_up_all(&pos->waitq);
/* drop VFS cache */
kdbus_fs_flush(pos);
/*
* If the node was activated and somone subtracted BIAS
* from it to deactivate it, we, and only us, are
* responsible to release the extra ref-count that was
* taken once in kdbus_node_activate().
* If the node was never activated, no-one ever
* subtracted BIAS, but instead skipped that state and
* immediately went to NODE_RELEASE_DIRECT. In that case
* we must not drop the reference.
*/
if (v_post == KDBUS_NODE_BIAS)
kdbus_node_unref(pos);
} else {
/* wait until object is DRAINED */
wait_event(pos->waitq,
atomic_read(&pos->active) == KDBUS_NODE_DRAINED);
}
/*
* We're done with the current node. Continue on its parent
* again, which will try deactivating its next child, or itself
* if no child is left.
* If we've reached our initial node again, we are done and
* can safely return.
*/
if (pos == node)
break;
child = pos;
pos = pos->parent;
kdbus_node_unref(child);
}
}
/**
* kdbus_node_acquire() - Acquire an active ref on a node
* @node: The node
*
* This acquires an active-reference to @node. This will only succeed if the
* node is active. You must release this active reference via
* kdbus_node_release() again.
*
* See the introduction to "active references" for more details.
*
* Return: %true if @node was non-NULL and active
*/
bool kdbus_node_acquire(struct kdbus_node *node)
{
return node && atomic_inc_unless_negative(&node->active);
}
/**
* kdbus_node_release() - Release an active ref on a node
* @node: The node
*
* This releases an active reference that was previously acquired via
* kdbus_node_acquire(). See kdbus_node_acquire() for details.
*/
void kdbus_node_release(struct kdbus_node *node)
{
if (node && atomic_dec_return(&node->active) == KDBUS_NODE_BIAS)
wake_up(&node->waitq);
}
/**
* kdbus_node_find_child() - Find child by name
* @node: parent node to search through
* @name: name of child node
*
* This searches through all children of @node for a child-node with name @name.
* If not found, or if the child is deactivated, NULL is returned. Otherwise,
* the child is acquired and a new reference is returned.
*
* If you're done with the child, you need to release it and drop your
* reference.
*
* This function does not acquire the parent node. However, if the parent was
* already deactivated, then kdbus_node_deactivate() will, at some point, also
* deactivate the child. Therefore, we can rely on the explicit ordering during
* deactivation.
*
* Return: Reference to acquired child node, or NULL if not found / not active.
*/
struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node,
const char *name)
{
struct kdbus_node *child;
struct rb_node *rb;
unsigned int hash;
int ret;
hash = kdbus_node_name_hash(name);
mutex_lock(&node->lock);
rb = node->children.rb_node;
while (rb) {
child = kdbus_node_from_rb(rb);
ret = kdbus_node_name_compare(hash, name, child);
if (ret < 0)
rb = rb->rb_left;
else if (ret > 0)
rb = rb->rb_right;
else
break;
}
if (rb && kdbus_node_acquire(child))
kdbus_node_ref(child);
else
child = NULL;
mutex_unlock(&node->lock);
return child;
}
static struct kdbus_node *node_find_closest_unlocked(struct kdbus_node *node,
unsigned int hash,
const char *name)
{
struct kdbus_node *n, *pos = NULL;
struct rb_node *rb;
int res;
/*
* Find the closest child with ``node->hash >= hash'', or, if @name is
* valid, ``node->name >= name'' (where '>=' is the lex. order).
*/
rb = node->children.rb_node;
while (rb) {
n = kdbus_node_from_rb(rb);
if (name)
res = kdbus_node_name_compare(hash, name, n);
else
res = hash - n->hash;
if (res <= 0) {
rb = rb->rb_left;
pos = n;
} else { /* ``hash > n->hash'', ``name > n->name'' */
rb = rb->rb_right;
}
}
return pos;
}
/**
* kdbus_node_find_closest() - Find closest child-match
* @node: parent node to search through
* @hash: hash value to find closest match for
*
* Find the closest child of @node with a hash greater than or equal to @hash.
* The closest match is the left-most child of @node with this property. Which
* means, it is the first child with that hash returned by
* kdbus_node_next_child(), if you'd iterate the whole parent node.
*
* Return: Reference to acquired child, or NULL if none found.
*/
struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node,
unsigned int hash)
{
struct kdbus_node *child;
struct rb_node *rb;
mutex_lock(&node->lock);
child = node_find_closest_unlocked(node, hash, NULL);
while (child && !kdbus_node_acquire(child)) {
rb = rb_next(&child->rb);
if (rb)
child = kdbus_node_from_rb(rb);
else
child = NULL;
}
kdbus_node_ref(child);
mutex_unlock(&node->lock);
return child;
}
/**
* kdbus_node_next_child() - Acquire next child
* @node: parent node
* @prev: previous child-node position or NULL
*
* This function returns a reference to the next active child of @node, after
* the passed position @prev. If @prev is NULL, a reference to the first active
* child is returned. If no more active children are found, NULL is returned.
*
* This function acquires the next child it returns. If you're done with the
* returned pointer, you need to release _and_ unref it.
*
* The passed in pointer @prev is not modified by this function, and it does
* *not* have to be active. If @prev was acquired via different means, or if it
* was unlinked from its parent before you pass it in, then this iterator will
* still return the next active child (it will have to search through the
* rb-tree based on the node-name, though).
* However, @prev must not be linked to a different parent than @node!
*
* Return: Reference to next acquired child, or NULL if at the end.
*/
struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node,
struct kdbus_node *prev)
{
struct kdbus_node *pos = NULL;
struct rb_node *rb;
mutex_lock(&node->lock);
if (!prev) {
/*
* New iteration; find first node in rb-tree and try to acquire
* it. If we got it, directly return it as first element.
* Otherwise, the loop below will find the next active node.
*/
rb = rb_first(&node->children);
if (!rb)
goto exit;
pos = kdbus_node_from_rb(rb);
if (kdbus_node_acquire(pos))
goto exit;
} else if (RB_EMPTY_NODE(&prev->rb)) {
/*
* The current iterator is no longer linked to the rb-tree. Use
* its hash value and name to find the next _higher_ node and
* acquire it. If we got it, return it as next element.
* Otherwise, the loop below will find the next active node.
*/
pos = node_find_closest_unlocked(node, prev->hash, prev->name);
if (!pos)
goto exit;
if (kdbus_node_acquire(pos))
goto exit;
} else {
/*
* The current iterator is still linked to the parent. Set it
* as current position and use the loop below to find the next
* active element.
*/
pos = prev;
}
/* @pos was already returned or is inactive; find next active node */
do {
rb = rb_next(&pos->rb);
if (rb)
pos = kdbus_node_from_rb(rb);
else
pos = NULL;
} while (pos && !kdbus_node_acquire(pos));
exit:
/* @pos is NULL or acquired. Take ref if non-NULL and return it */
kdbus_node_ref(pos);
mutex_unlock(&node->lock);
return pos;
}