int b1_handle_acquire(B1Peer *peer, B1Handle **handlep, uint64_t handle_id) { B1Handle *handle; CRBNode **slot, *p; int r; assert(peer); assert(handlep); if (handle_id == BUS1_HANDLE_INVALID) { *handlep = NULL; return 0; } slot = c_rbtree_find_slot(&peer->handles, handles_compare, &handle_id, &p); if (slot) { r = b1_handle_new(peer, &handle); if (r < 0) return r; handle->ref_kernel = (CRef)C_REF_INIT; handle->live = true; handle->id = handle_id; c_rbtree_add(&peer->handles, p, slot, &handle->rb); } else { handle = c_container_of(p, B1Handle, rb); if (handle->live) { c_ref_inc(&handle->ref_kernel); /* reusing existing handle, drop redundant reference from kernel */ r = bus1_peer_handle_release(handle->holder->peer, handle->id); if (r < 0) return r; } else { handle->ref_kernel = (CRef)C_REF_INIT; handle->live = true; } c_ref_inc(&handle->ref); } *handlep = handle; return 0; }
/** * b1_node_destroy() - destroy node * @node: node to destroy, or NULL * * Destroy the node in the kernel, regardless of any handles held by other * peers. If any peers still hold handles, they will receive node destruction * notifications for this node. * * If NULL is passed, this is a no-op. * * Return: 0 on success, and a negative error code on failure. */ _c_public_ int b1_node_destroy(B1Node *node) { struct bus1_cmd_nodes_destroy nodes_destroy = { .ptr_nodes = (uintptr_t)&node->id, .n_nodes = 1, }; if (!node) return 0; return bus1_peer_nodes_destroy(node->owner->peer, &nodes_destroy); } /** * b1_handle_ref() - acquire reference * @handle: handle to acquire reference to, or NULL * * Acquire a new reference to a handle. The caller must already own a reference * themself. * * If NULL is passed, this is a no-op. * * Return: @handle is returned. */ _c_public_ B1Handle *b1_handle_ref(B1Handle *handle) { B1Handle *new_handle; int r; if (handle) { if (!handle->live) { r = b1_handle_transfer(handle, handle->holder, &new_handle); assert(r >= 0); assert(new_handle == handle); } else { c_ref_inc(&handle->ref_kernel); c_ref_inc(&handle->ref); } } return handle; }
/** * b1_peer_ref() - acquire reference * @peer: peer to acquire reference to, or NULL * * Return: @peer is returned. */ _c_public_ B1Peer *b1_peer_ref(B1Peer *peer) { if (peer) c_ref_inc(&peer->ref); return peer; }