1/* 2 * net/tipc/ref.c: TIPC object registry code 3 * 4 * Copyright (c) 1991-2006, Ericsson AB 5 * Copyright (c) 2004-2005, Wind River Systems 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the names of the copyright holders nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * Alternatively, this software may be distributed under the terms of the 21 * GNU General Public License ("GPL") version 2 as published by the Free 22 * Software Foundation. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37#include "core.h" 38#include "ref.h" 39#include "port.h" 40#include "subscr.h" 41#include "name_distr.h" 42#include "name_table.h" 43#include "config.h" 44#include "discover.h" 45#include "bearer.h" 46#include "node.h" 47#include "bcast.h" 48 49 50struct ref_table tipc_ref_table = { NULL }; 51 52static DEFINE_RWLOCK(ref_table_lock); 53 54/** 55 * tipc_ref_table_init - create reference table for objects 56 */ 57 58int tipc_ref_table_init(u32 requested_size, u32 start) 59{ 60 struct reference *table; 61 u32 sz = 1 << 4; 62 u32 index_mask; 63 int i; 64 65 while (sz < requested_size) { 66 sz <<= 1; 67 } 68 table = vmalloc(sz * sizeof(*table)); 69 if (table == NULL) 70 return -ENOMEM; 71 72 write_lock_bh(&ref_table_lock); 73 index_mask = sz - 1; 74 for (i = sz - 1; i >= 0; i--) { 75 table[i].object = NULL; 76 spin_lock_init(&table[i].lock); 77 table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; 78 } 79 tipc_ref_table.entries = table; 80 tipc_ref_table.index_mask = index_mask; 81 tipc_ref_table.first_free = sz - 1; 82 tipc_ref_table.last_free = 1; 83 write_unlock_bh(&ref_table_lock); 84 return TIPC_OK; 85} 86 87/** 88 * tipc_ref_table_stop - destroy reference table for objects 89 */ 90 91void tipc_ref_table_stop(void) 92{ 93 if (!tipc_ref_table.entries) 94 return; 95 96 vfree(tipc_ref_table.entries); 97 tipc_ref_table.entries = NULL; 98} 99 100/** 101 * tipc_ref_acquire - create reference to an object 102 * 103 * Return a unique reference value which can be translated back to the pointer 104 * 'object' at a later time. Also, pass back a pointer to the lock protecting 105 * the object, but without locking it. 106 */ 107 108u32 tipc_ref_acquire(void *object, spinlock_t **lock) 109{ 110 struct reference *entry; 111 u32 index; 112 u32 index_mask; 113 u32 next_plus_upper; 114 u32 reference = 0; 115 116 if (!object) { 117 err("Attempt to acquire reference to non-existent object\n"); 118 return 0; 119 } 120 if (!tipc_ref_table.entries) { 121 err("Reference table not found during acquisition attempt\n"); 122 return 0; 123 } 124 125 write_lock_bh(&ref_table_lock); 126 if (tipc_ref_table.first_free) { 127 index = tipc_ref_table.first_free; 128 entry = &(tipc_ref_table.entries[index]); 129 index_mask = tipc_ref_table.index_mask; 130 /* take lock in case a previous user of entry still holds it */ 131 spin_lock_bh(&entry->lock); 132 next_plus_upper = entry->data.next_plus_upper; 133 tipc_ref_table.first_free = next_plus_upper & index_mask; 134 reference = (next_plus_upper & ~index_mask) + index; 135 entry->data.reference = reference; 136 entry->object = object; 137 if (lock != 0) 138 *lock = &entry->lock; 139 spin_unlock_bh(&entry->lock); 140 } 141 write_unlock_bh(&ref_table_lock); 142 return reference; 143} 144 145/** 146 * tipc_ref_discard - invalidate references to an object 147 * 148 * Disallow future references to an object and free up the entry for re-use. 149 * Note: The entry's spin_lock may still be busy after discard 150 */ 151 152void tipc_ref_discard(u32 ref) 153{ 154 struct reference *entry; 155 u32 index; 156 u32 index_mask; 157 158 if (!ref) { 159 err("Attempt to discard reference 0\n"); 160 return; 161 } 162 if (!tipc_ref_table.entries) { 163 err("Reference table not found during discard attempt\n"); 164 return; 165 } 166 167 write_lock_bh(&ref_table_lock); 168 index_mask = tipc_ref_table.index_mask; 169 index = ref & index_mask; 170 entry = &(tipc_ref_table.entries[index]); 171 172 if (!entry->object) { 173 err("Attempt to discard reference to non-existent object\n"); 174 goto exit; 175 } 176 if (entry->data.reference != ref) { 177 err("Attempt to discard non-existent reference\n"); 178 goto exit; 179 } 180 181 /* mark entry as unused */ 182 entry->object = NULL; 183 if (tipc_ref_table.first_free == 0) 184 tipc_ref_table.first_free = index; 185 else 186 tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper 187 |= index; 188 tipc_ref_table.last_free = index; 189 190 /* increment upper bits of entry to invalidate subsequent references */ 191 entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); 192exit: 193 write_unlock_bh(&ref_table_lock); 194} 195