163a93856SMark Peek /*-
2*3eeb7511SMark Peek * Copyright (c) 2018 VMware, Inc.
363a93856SMark Peek *
48c302b2eSMark Peek * SPDX-License-Identifier: (BSD-2-Clause OR GPL-2.0)
563a93856SMark Peek */
663a93856SMark Peek
763a93856SMark Peek /* Implementation of the VMCI Hashtable. */
863a93856SMark Peek
963a93856SMark Peek #include <sys/cdefs.h>
1063a93856SMark Peek #include "vmci.h"
1163a93856SMark Peek #include "vmci_driver.h"
1263a93856SMark Peek #include "vmci_hashtable.h"
1363a93856SMark Peek #include "vmci_kernel_defs.h"
1463a93856SMark Peek #include "vmci_utils.h"
1563a93856SMark Peek
1663a93856SMark Peek #define LGPFX "vmci_hashtable: "
1763a93856SMark Peek
1863a93856SMark Peek #define VMCI_HASHTABLE_HASH(_h, _sz) \
1963a93856SMark Peek vmci_hash_id(VMCI_HANDLE_TO_RESOURCE_ID(_h), (_sz))
2063a93856SMark Peek
2163a93856SMark Peek static int hashtable_unlink_entry(struct vmci_hashtable *table,
2263a93856SMark Peek struct vmci_hash_entry *entry);
2363a93856SMark Peek static bool vmci_hashtable_entry_exists_locked(struct vmci_hashtable *table,
2463a93856SMark Peek struct vmci_handle handle);
2563a93856SMark Peek
2663a93856SMark Peek /*
2763a93856SMark Peek *------------------------------------------------------------------------------
2863a93856SMark Peek *
2963a93856SMark Peek * vmci_hashtable_create --
3063a93856SMark Peek *
3163a93856SMark Peek * Creates a hashtable.
3263a93856SMark Peek *
3363a93856SMark Peek * Result:
3463a93856SMark Peek * None.
3563a93856SMark Peek *
3663a93856SMark Peek * Side effects:
3763a93856SMark Peek * None.
3863a93856SMark Peek *
3963a93856SMark Peek *------------------------------------------------------------------------------
4063a93856SMark Peek */
4163a93856SMark Peek
4263a93856SMark Peek struct vmci_hashtable *
vmci_hashtable_create(int size)4363a93856SMark Peek vmci_hashtable_create(int size)
4463a93856SMark Peek {
4563a93856SMark Peek struct vmci_hashtable *table;
4663a93856SMark Peek
4763a93856SMark Peek table = vmci_alloc_kernel_mem(sizeof(*table),
4863a93856SMark Peek VMCI_MEMORY_NORMAL);
4963a93856SMark Peek if (table == NULL)
5063a93856SMark Peek return (NULL);
5163a93856SMark Peek memset(table, 0, sizeof(*table));
5263a93856SMark Peek
5363a93856SMark Peek table->entries = vmci_alloc_kernel_mem(sizeof(*table->entries) * size,
5463a93856SMark Peek VMCI_MEMORY_NORMAL);
5563a93856SMark Peek if (table->entries == NULL) {
5663a93856SMark Peek vmci_free_kernel_mem(table, sizeof(*table));
5763a93856SMark Peek return (NULL);
5863a93856SMark Peek }
5963a93856SMark Peek memset(table->entries, 0, sizeof(*table->entries) * size);
6063a93856SMark Peek table->size = size;
6163a93856SMark Peek if (vmci_init_lock(&table->lock, "VMCI Hashtable lock") <
6263a93856SMark Peek VMCI_SUCCESS) {
6363a93856SMark Peek vmci_free_kernel_mem(table->entries, sizeof(*table->entries) * size);
6463a93856SMark Peek vmci_free_kernel_mem(table, sizeof(*table));
6563a93856SMark Peek return (NULL);
6663a93856SMark Peek }
6763a93856SMark Peek
6863a93856SMark Peek return (table);
6963a93856SMark Peek }
7063a93856SMark Peek
7163a93856SMark Peek /*
7263a93856SMark Peek *------------------------------------------------------------------------------
7363a93856SMark Peek *
7463a93856SMark Peek * vmci_hashtable_destroy --
7563a93856SMark Peek *
7663a93856SMark Peek * This function should be called at module exit time. We rely on the
7763a93856SMark Peek * module ref count to insure that no one is accessing any hash table
7863a93856SMark Peek * entries at this point in time. Hence we should be able to just remove
7963a93856SMark Peek * all entries from the hash table.
8063a93856SMark Peek *
8163a93856SMark Peek * Result:
8263a93856SMark Peek * None.
8363a93856SMark Peek *
8463a93856SMark Peek * Side effects:
8563a93856SMark Peek * None.
8663a93856SMark Peek *
8763a93856SMark Peek *------------------------------------------------------------------------------
8863a93856SMark Peek */
8963a93856SMark Peek
9063a93856SMark Peek void
vmci_hashtable_destroy(struct vmci_hashtable * table)9163a93856SMark Peek vmci_hashtable_destroy(struct vmci_hashtable *table)
9263a93856SMark Peek {
9363a93856SMark Peek
9463a93856SMark Peek ASSERT(table);
9563a93856SMark Peek
9663a93856SMark Peek vmci_grab_lock_bh(&table->lock);
9763a93856SMark Peek vmci_free_kernel_mem(table->entries, sizeof(*table->entries) *
9863a93856SMark Peek table->size);
9963a93856SMark Peek table->entries = NULL;
10063a93856SMark Peek vmci_release_lock_bh(&table->lock);
10163a93856SMark Peek vmci_cleanup_lock(&table->lock);
10263a93856SMark Peek vmci_free_kernel_mem(table, sizeof(*table));
10363a93856SMark Peek }
10463a93856SMark Peek
10563a93856SMark Peek /*
10663a93856SMark Peek *------------------------------------------------------------------------------
10763a93856SMark Peek *
10863a93856SMark Peek * vmci_hashtable_init_entry --
10963a93856SMark Peek *
11063a93856SMark Peek * Initializes a hash entry.
11163a93856SMark Peek *
11263a93856SMark Peek * Result:
11363a93856SMark Peek * None.
11463a93856SMark Peek *
11563a93856SMark Peek * Side effects:
11663a93856SMark Peek * None.
11763a93856SMark Peek *
11863a93856SMark Peek *------------------------------------------------------------------------------
11963a93856SMark Peek */
12063a93856SMark Peek void
vmci_hashtable_init_entry(struct vmci_hash_entry * entry,struct vmci_handle handle)12163a93856SMark Peek vmci_hashtable_init_entry(struct vmci_hash_entry *entry,
12263a93856SMark Peek struct vmci_handle handle)
12363a93856SMark Peek {
12463a93856SMark Peek
12563a93856SMark Peek ASSERT(entry);
12663a93856SMark Peek entry->handle = handle;
12763a93856SMark Peek entry->ref_count = 0;
12863a93856SMark Peek }
12963a93856SMark Peek
13063a93856SMark Peek /*
13163a93856SMark Peek *------------------------------------------------------------------------------
13263a93856SMark Peek *
13363a93856SMark Peek * vmci_hashtable_add_entry --
13463a93856SMark Peek *
13563a93856SMark Peek * Adds an entry to the hashtable.
13663a93856SMark Peek *
13763a93856SMark Peek * Result:
13863a93856SMark Peek * None.
13963a93856SMark Peek *
14063a93856SMark Peek * Side effects:
14163a93856SMark Peek * None.
14263a93856SMark Peek *
14363a93856SMark Peek *------------------------------------------------------------------------------
14463a93856SMark Peek */
14563a93856SMark Peek
14663a93856SMark Peek int
vmci_hashtable_add_entry(struct vmci_hashtable * table,struct vmci_hash_entry * entry)14763a93856SMark Peek vmci_hashtable_add_entry(struct vmci_hashtable *table,
14863a93856SMark Peek struct vmci_hash_entry *entry)
14963a93856SMark Peek {
15063a93856SMark Peek int idx;
15163a93856SMark Peek
15263a93856SMark Peek ASSERT(entry);
15363a93856SMark Peek ASSERT(table);
15463a93856SMark Peek
15563a93856SMark Peek vmci_grab_lock_bh(&table->lock);
15663a93856SMark Peek
15763a93856SMark Peek if (vmci_hashtable_entry_exists_locked(table, entry->handle)) {
15863a93856SMark Peek VMCI_LOG_DEBUG(LGPFX"Entry (handle=0x%x:0x%x) already "
15963a93856SMark Peek "exists.\n", entry->handle.context,
16063a93856SMark Peek entry->handle.resource);
16163a93856SMark Peek vmci_release_lock_bh(&table->lock);
16263a93856SMark Peek return (VMCI_ERROR_DUPLICATE_ENTRY);
16363a93856SMark Peek }
16463a93856SMark Peek
16563a93856SMark Peek idx = VMCI_HASHTABLE_HASH(entry->handle, table->size);
16663a93856SMark Peek ASSERT(idx < table->size);
16763a93856SMark Peek
16863a93856SMark Peek /* New entry is added to top/front of hash bucket. */
16963a93856SMark Peek entry->ref_count++;
17063a93856SMark Peek entry->next = table->entries[idx];
17163a93856SMark Peek table->entries[idx] = entry;
17263a93856SMark Peek vmci_release_lock_bh(&table->lock);
17363a93856SMark Peek
17463a93856SMark Peek return (VMCI_SUCCESS);
17563a93856SMark Peek }
17663a93856SMark Peek
17763a93856SMark Peek /*
17863a93856SMark Peek *------------------------------------------------------------------------------
17963a93856SMark Peek *
18063a93856SMark Peek * vmci_hashtable_remove_entry --
18163a93856SMark Peek *
18263a93856SMark Peek * Removes an entry from the hashtable.
18363a93856SMark Peek *
18463a93856SMark Peek * Result:
18563a93856SMark Peek * None.
18663a93856SMark Peek *
18763a93856SMark Peek * Side effects:
18863a93856SMark Peek * None.
18963a93856SMark Peek *
19063a93856SMark Peek *------------------------------------------------------------------------------
19163a93856SMark Peek */
19263a93856SMark Peek
19363a93856SMark Peek int
vmci_hashtable_remove_entry(struct vmci_hashtable * table,struct vmci_hash_entry * entry)19463a93856SMark Peek vmci_hashtable_remove_entry(struct vmci_hashtable *table,
19563a93856SMark Peek struct vmci_hash_entry *entry)
19663a93856SMark Peek {
19763a93856SMark Peek int result;
19863a93856SMark Peek
19963a93856SMark Peek ASSERT(table);
20063a93856SMark Peek ASSERT(entry);
20163a93856SMark Peek
20263a93856SMark Peek vmci_grab_lock_bh(&table->lock);
20363a93856SMark Peek
20463a93856SMark Peek /* First unlink the entry. */
20563a93856SMark Peek result = hashtable_unlink_entry(table, entry);
20663a93856SMark Peek if (result != VMCI_SUCCESS) {
20763a93856SMark Peek /* We failed to find the entry. */
20863a93856SMark Peek goto done;
20963a93856SMark Peek }
21063a93856SMark Peek
21163a93856SMark Peek /* Decrement refcount and check if this is last reference. */
21263a93856SMark Peek entry->ref_count--;
21363a93856SMark Peek if (entry->ref_count == 0) {
21463a93856SMark Peek result = VMCI_SUCCESS_ENTRY_DEAD;
21563a93856SMark Peek goto done;
21663a93856SMark Peek }
21763a93856SMark Peek
21863a93856SMark Peek done:
21963a93856SMark Peek vmci_release_lock_bh(&table->lock);
22063a93856SMark Peek
22163a93856SMark Peek return (result);
22263a93856SMark Peek }
22363a93856SMark Peek
22463a93856SMark Peek /*
22563a93856SMark Peek *------------------------------------------------------------------------------
22663a93856SMark Peek *
22763a93856SMark Peek * vmci_hashtable_get_entry_locked --
22863a93856SMark Peek *
22963a93856SMark Peek * Looks up an entry in the hash table, that is already locked.
23063a93856SMark Peek *
23163a93856SMark Peek * Result:
23263a93856SMark Peek * If the element is found, a pointer to the element is returned.
23363a93856SMark Peek * Otherwise NULL is returned.
23463a93856SMark Peek *
23563a93856SMark Peek * Side effects:
23663a93856SMark Peek * The reference count of the returned element is increased.
23763a93856SMark Peek *
23863a93856SMark Peek *------------------------------------------------------------------------------
23963a93856SMark Peek */
24063a93856SMark Peek
24163a93856SMark Peek static struct vmci_hash_entry *
vmci_hashtable_get_entry_locked(struct vmci_hashtable * table,struct vmci_handle handle)24263a93856SMark Peek vmci_hashtable_get_entry_locked(struct vmci_hashtable *table,
24363a93856SMark Peek struct vmci_handle handle)
24463a93856SMark Peek {
24563a93856SMark Peek struct vmci_hash_entry *cur = NULL;
24663a93856SMark Peek int idx;
24763a93856SMark Peek
24863a93856SMark Peek ASSERT(!VMCI_HANDLE_EQUAL(handle, VMCI_INVALID_HANDLE));
24963a93856SMark Peek ASSERT(table);
25063a93856SMark Peek
25163a93856SMark Peek idx = VMCI_HASHTABLE_HASH(handle, table->size);
25263a93856SMark Peek
25363a93856SMark Peek cur = table->entries[idx];
25463a93856SMark Peek while (true) {
25563a93856SMark Peek if (cur == NULL)
25663a93856SMark Peek break;
25763a93856SMark Peek
25863a93856SMark Peek if (VMCI_HANDLE_TO_RESOURCE_ID(cur->handle) ==
25963a93856SMark Peek VMCI_HANDLE_TO_RESOURCE_ID(handle)) {
26063a93856SMark Peek if ((VMCI_HANDLE_TO_CONTEXT_ID(cur->handle) ==
26163a93856SMark Peek VMCI_HANDLE_TO_CONTEXT_ID(handle)) ||
26263a93856SMark Peek (VMCI_INVALID_ID == VMCI_HANDLE_TO_CONTEXT_ID(cur->handle))) {
26363a93856SMark Peek cur->ref_count++;
26463a93856SMark Peek break;
26563a93856SMark Peek }
26663a93856SMark Peek }
26763a93856SMark Peek cur = cur->next;
26863a93856SMark Peek }
26963a93856SMark Peek
27063a93856SMark Peek return (cur);
27163a93856SMark Peek }
27263a93856SMark Peek
27363a93856SMark Peek /*
27463a93856SMark Peek *------------------------------------------------------------------------------
27563a93856SMark Peek *
27663a93856SMark Peek * vmci_hashtable_get_entry --
27763a93856SMark Peek *
27863a93856SMark Peek * Gets an entry from the hashtable.
27963a93856SMark Peek *
28063a93856SMark Peek * Result:
28163a93856SMark Peek * None.
28263a93856SMark Peek *
28363a93856SMark Peek * Side effects:
28463a93856SMark Peek * None.
28563a93856SMark Peek *
28663a93856SMark Peek *------------------------------------------------------------------------------
28763a93856SMark Peek */
28863a93856SMark Peek
28963a93856SMark Peek struct vmci_hash_entry *
vmci_hashtable_get_entry(struct vmci_hashtable * table,struct vmci_handle handle)29063a93856SMark Peek vmci_hashtable_get_entry(struct vmci_hashtable *table,
29163a93856SMark Peek struct vmci_handle handle)
29263a93856SMark Peek {
29363a93856SMark Peek struct vmci_hash_entry *entry;
29463a93856SMark Peek
29563a93856SMark Peek if (VMCI_HANDLE_EQUAL(handle, VMCI_INVALID_HANDLE))
29663a93856SMark Peek return (NULL);
29763a93856SMark Peek
29863a93856SMark Peek ASSERT(table);
29963a93856SMark Peek
30063a93856SMark Peek vmci_grab_lock_bh(&table->lock);
30163a93856SMark Peek entry = vmci_hashtable_get_entry_locked(table, handle);
30263a93856SMark Peek vmci_release_lock_bh(&table->lock);
30363a93856SMark Peek
30463a93856SMark Peek return (entry);
30563a93856SMark Peek }
30663a93856SMark Peek
30763a93856SMark Peek /*
30863a93856SMark Peek *------------------------------------------------------------------------------
30963a93856SMark Peek *
31063a93856SMark Peek * vmci_hashtable_hold_entry --
31163a93856SMark Peek *
31263a93856SMark Peek * Hold the given entry. This will increment the entry's reference count.
31363a93856SMark Peek * This is like a GetEntry() but without having to lookup the entry by
31463a93856SMark Peek * handle.
31563a93856SMark Peek *
31663a93856SMark Peek * Result:
31763a93856SMark Peek * None.
31863a93856SMark Peek *
31963a93856SMark Peek * Side effects:
32063a93856SMark Peek * None.
32163a93856SMark Peek *
32263a93856SMark Peek *------------------------------------------------------------------------------
32363a93856SMark Peek */
32463a93856SMark Peek
32563a93856SMark Peek void
vmci_hashtable_hold_entry(struct vmci_hashtable * table,struct vmci_hash_entry * entry)32663a93856SMark Peek vmci_hashtable_hold_entry(struct vmci_hashtable *table,
32763a93856SMark Peek struct vmci_hash_entry *entry)
32863a93856SMark Peek {
32963a93856SMark Peek
33063a93856SMark Peek ASSERT(table);
33163a93856SMark Peek ASSERT(entry);
33263a93856SMark Peek
33363a93856SMark Peek vmci_grab_lock_bh(&table->lock);
33463a93856SMark Peek entry->ref_count++;
33563a93856SMark Peek vmci_release_lock_bh(&table->lock);
33663a93856SMark Peek }
33763a93856SMark Peek
33863a93856SMark Peek /*
33963a93856SMark Peek *------------------------------------------------------------------------------
34063a93856SMark Peek *
34163a93856SMark Peek * vmci_hashtable_release_entry_locked --
34263a93856SMark Peek *
34363a93856SMark Peek * Releases an element previously obtained with
34463a93856SMark Peek * vmci_hashtable_get_entry_locked.
34563a93856SMark Peek *
34663a93856SMark Peek * Result:
34763a93856SMark Peek * If the entry is removed from the hash table, VMCI_SUCCESS_ENTRY_DEAD
34863a93856SMark Peek * is returned. Otherwise, VMCI_SUCCESS is returned.
34963a93856SMark Peek *
35063a93856SMark Peek * Side effects:
35163a93856SMark Peek * The reference count of the entry is decreased and the entry is removed
35263a93856SMark Peek * from the hash table on 0.
35363a93856SMark Peek *
35463a93856SMark Peek *------------------------------------------------------------------------------
35563a93856SMark Peek */
35663a93856SMark Peek
35763a93856SMark Peek static int
vmci_hashtable_release_entry_locked(struct vmci_hashtable * table,struct vmci_hash_entry * entry)35863a93856SMark Peek vmci_hashtable_release_entry_locked(struct vmci_hashtable *table,
35963a93856SMark Peek struct vmci_hash_entry *entry)
36063a93856SMark Peek {
36163a93856SMark Peek int result = VMCI_SUCCESS;
36263a93856SMark Peek
36363a93856SMark Peek ASSERT(table);
36463a93856SMark Peek ASSERT(entry);
36563a93856SMark Peek
36663a93856SMark Peek entry->ref_count--;
36763a93856SMark Peek /* Check if this is last reference and report if so. */
36863a93856SMark Peek if (entry->ref_count == 0) {
36963a93856SMark Peek /*
37063a93856SMark Peek * Remove entry from hash table if not already removed. This
37163a93856SMark Peek * could have happened already because VMCIHashTable_RemoveEntry
37263a93856SMark Peek * was called to unlink it. We ignore if it is not found.
37363a93856SMark Peek * Datagram handles will often have RemoveEntry called, whereas
37463a93856SMark Peek * SharedMemory regions rely on ReleaseEntry to unlink the entry
37563a93856SMark Peek * , since the creator does not call RemoveEntry when it
37663a93856SMark Peek * detaches.
37763a93856SMark Peek */
37863a93856SMark Peek
37963a93856SMark Peek hashtable_unlink_entry(table, entry);
38063a93856SMark Peek result = VMCI_SUCCESS_ENTRY_DEAD;
38163a93856SMark Peek }
38263a93856SMark Peek
38363a93856SMark Peek return (result);
38463a93856SMark Peek }
38563a93856SMark Peek
38663a93856SMark Peek /*
38763a93856SMark Peek *------------------------------------------------------------------------------
38863a93856SMark Peek *
38963a93856SMark Peek * vmci_hashtable_release_entry --
39063a93856SMark Peek *
39163a93856SMark Peek * Releases an entry from the hashtable.
39263a93856SMark Peek *
39363a93856SMark Peek * Result:
39463a93856SMark Peek * None.
39563a93856SMark Peek *
39663a93856SMark Peek * Side effects:
39763a93856SMark Peek * None.
39863a93856SMark Peek *
39963a93856SMark Peek *------------------------------------------------------------------------------
40063a93856SMark Peek */
40163a93856SMark Peek
40263a93856SMark Peek int
vmci_hashtable_release_entry(struct vmci_hashtable * table,struct vmci_hash_entry * entry)40363a93856SMark Peek vmci_hashtable_release_entry(struct vmci_hashtable *table,
40463a93856SMark Peek struct vmci_hash_entry *entry)
40563a93856SMark Peek {
40663a93856SMark Peek int result;
40763a93856SMark Peek
40863a93856SMark Peek ASSERT(table);
40963a93856SMark Peek vmci_grab_lock_bh(&table->lock);
41063a93856SMark Peek result = vmci_hashtable_release_entry_locked(table, entry);
41163a93856SMark Peek vmci_release_lock_bh(&table->lock);
41263a93856SMark Peek
41363a93856SMark Peek return (result);
41463a93856SMark Peek }
41563a93856SMark Peek
41663a93856SMark Peek /*
41763a93856SMark Peek *------------------------------------------------------------------------------
41863a93856SMark Peek *
41963a93856SMark Peek * vmci_hashtable_entry_exists --
42063a93856SMark Peek *
42163a93856SMark Peek * Returns whether an entry exists in the hashtable
42263a93856SMark Peek *
42363a93856SMark Peek * Result:
42463a93856SMark Peek * true if handle already in hashtable. false otherwise.
42563a93856SMark Peek *
42663a93856SMark Peek * Side effects:
42763a93856SMark Peek * None.
42863a93856SMark Peek *
42963a93856SMark Peek *------------------------------------------------------------------------------
43063a93856SMark Peek */
43163a93856SMark Peek
43263a93856SMark Peek bool
vmci_hashtable_entry_exists(struct vmci_hashtable * table,struct vmci_handle handle)43363a93856SMark Peek vmci_hashtable_entry_exists(struct vmci_hashtable *table,
43463a93856SMark Peek struct vmci_handle handle)
43563a93856SMark Peek {
43663a93856SMark Peek bool exists;
43763a93856SMark Peek
43863a93856SMark Peek ASSERT(table);
43963a93856SMark Peek
44063a93856SMark Peek vmci_grab_lock_bh(&table->lock);
44163a93856SMark Peek exists = vmci_hashtable_entry_exists_locked(table, handle);
44263a93856SMark Peek vmci_release_lock_bh(&table->lock);
44363a93856SMark Peek
44463a93856SMark Peek return (exists);
44563a93856SMark Peek }
44663a93856SMark Peek
44763a93856SMark Peek /*
44863a93856SMark Peek *------------------------------------------------------------------------------
44963a93856SMark Peek *
45063a93856SMark Peek * vmci_hashtable_entry_exists_locked --
45163a93856SMark Peek *
45263a93856SMark Peek * Unlocked version of vmci_hashtable_entry_exists.
45363a93856SMark Peek *
45463a93856SMark Peek * Result:
45563a93856SMark Peek * true if handle already in hashtable. false otherwise.
45663a93856SMark Peek *
45763a93856SMark Peek * Side effects:
45863a93856SMark Peek * None.
45963a93856SMark Peek *
46063a93856SMark Peek *------------------------------------------------------------------------------
46163a93856SMark Peek */
46263a93856SMark Peek
46363a93856SMark Peek static bool
vmci_hashtable_entry_exists_locked(struct vmci_hashtable * table,struct vmci_handle handle)46463a93856SMark Peek vmci_hashtable_entry_exists_locked(struct vmci_hashtable *table,
46563a93856SMark Peek struct vmci_handle handle)
46663a93856SMark Peek
46763a93856SMark Peek {
46863a93856SMark Peek struct vmci_hash_entry *entry;
46963a93856SMark Peek int idx;
47063a93856SMark Peek
47163a93856SMark Peek ASSERT(table);
47263a93856SMark Peek
47363a93856SMark Peek idx = VMCI_HASHTABLE_HASH(handle, table->size);
47463a93856SMark Peek
47563a93856SMark Peek entry = table->entries[idx];
47663a93856SMark Peek while (entry) {
47763a93856SMark Peek if (VMCI_HANDLE_TO_RESOURCE_ID(entry->handle) ==
47863a93856SMark Peek VMCI_HANDLE_TO_RESOURCE_ID(handle))
47963a93856SMark Peek if ((VMCI_HANDLE_TO_CONTEXT_ID(entry->handle) ==
48063a93856SMark Peek VMCI_HANDLE_TO_CONTEXT_ID(handle)) ||
48163a93856SMark Peek (VMCI_INVALID_ID == VMCI_HANDLE_TO_CONTEXT_ID(handle)) ||
48263a93856SMark Peek (VMCI_INVALID_ID == VMCI_HANDLE_TO_CONTEXT_ID(entry->handle)))
48363a93856SMark Peek return (true);
48463a93856SMark Peek entry = entry->next;
48563a93856SMark Peek }
48663a93856SMark Peek
48763a93856SMark Peek return (false);
48863a93856SMark Peek }
48963a93856SMark Peek
49063a93856SMark Peek /*
49163a93856SMark Peek *------------------------------------------------------------------------------
49263a93856SMark Peek *
49363a93856SMark Peek * hashtable_unlink_entry --
49463a93856SMark Peek *
49563a93856SMark Peek * Assumes caller holds table lock.
49663a93856SMark Peek *
49763a93856SMark Peek * Result:
49863a93856SMark Peek * None.
49963a93856SMark Peek *
50063a93856SMark Peek * Side effects:
50163a93856SMark Peek * None.
50263a93856SMark Peek *
50363a93856SMark Peek *------------------------------------------------------------------------------
50463a93856SMark Peek */
50563a93856SMark Peek
50663a93856SMark Peek static int
hashtable_unlink_entry(struct vmci_hashtable * table,struct vmci_hash_entry * entry)50763a93856SMark Peek hashtable_unlink_entry(struct vmci_hashtable *table,
50863a93856SMark Peek struct vmci_hash_entry *entry)
50963a93856SMark Peek {
51063a93856SMark Peek int result;
51163a93856SMark Peek struct vmci_hash_entry *prev, *cur;
51263a93856SMark Peek int idx;
51363a93856SMark Peek
51463a93856SMark Peek idx = VMCI_HASHTABLE_HASH(entry->handle, table->size);
51563a93856SMark Peek
51663a93856SMark Peek prev = NULL;
51763a93856SMark Peek cur = table->entries[idx];
51863a93856SMark Peek while (true) {
51963a93856SMark Peek if (cur == NULL) {
52063a93856SMark Peek result = VMCI_ERROR_NOT_FOUND;
52163a93856SMark Peek break;
52263a93856SMark Peek }
52363a93856SMark Peek if (VMCI_HANDLE_EQUAL(cur->handle, entry->handle)) {
52463a93856SMark Peek ASSERT(cur == entry);
52563a93856SMark Peek
52663a93856SMark Peek /* Remove entry and break. */
52763a93856SMark Peek if (prev)
52863a93856SMark Peek prev->next = cur->next;
52963a93856SMark Peek else
53063a93856SMark Peek table->entries[idx] = cur->next;
53163a93856SMark Peek cur->next = NULL;
53263a93856SMark Peek result = VMCI_SUCCESS;
53363a93856SMark Peek break;
53463a93856SMark Peek }
53563a93856SMark Peek prev = cur;
53663a93856SMark Peek cur = cur->next;
53763a93856SMark Peek }
53863a93856SMark Peek return (result);
53963a93856SMark Peek }
54063a93856SMark Peek
54163a93856SMark Peek /*
54263a93856SMark Peek *------------------------------------------------------------------------------
54363a93856SMark Peek *
54463a93856SMark Peek * vmci_hashtable_sync --
54563a93856SMark Peek *
54663a93856SMark Peek * Use this as a synchronization point when setting globals, for example,
54763a93856SMark Peek * during device shutdown.
54863a93856SMark Peek *
54963a93856SMark Peek * Results:
55063a93856SMark Peek * None.
55163a93856SMark Peek *
55263a93856SMark Peek * Side effects:
55363a93856SMark Peek * None.
55463a93856SMark Peek *
55563a93856SMark Peek *------------------------------------------------------------------------------
55663a93856SMark Peek */
55763a93856SMark Peek
55863a93856SMark Peek void
vmci_hashtable_sync(struct vmci_hashtable * table)55963a93856SMark Peek vmci_hashtable_sync(struct vmci_hashtable *table)
56063a93856SMark Peek {
56163a93856SMark Peek
56263a93856SMark Peek ASSERT(table);
56363a93856SMark Peek vmci_grab_lock_bh(&table->lock);
56463a93856SMark Peek vmci_release_lock_bh(&table->lock);
56563a93856SMark Peek }
566