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