1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "isns_server.h" 32 #include "isns_cache.h" 33 #include "isns_msgq.h" 34 #include "isns_obj.h" 35 #include "isns_htab.h" 36 37 /* 38 * external variables 39 */ 40 extern msg_queue_t *sys_q; 41 42 #ifdef DEBUG 43 extern int verbose_lock; 44 #endif 45 46 /* 47 * global data 48 */ 49 int cache_flag = 0; 50 51 /* 52 * local variables 53 */ 54 static cache_t *imc; 55 56 /* 57 * local functions. 58 */ 59 60 /* 61 * **************************************************************************** 62 * cache_init: 63 * create the cache data initially, including to invoke individual 64 * functions for creating the hash tables for object storage and 65 * discovery domain membership matrix. 66 * 67 * return - 0: no error; 1: otherwise. 68 * 69 * **************************************************************************** 70 */ 71 int 72 cache_init(void) 73 { 74 /* 75 * allocate global cache memory. 76 */ 77 imc = (cache_t *)calloc(sizeof (cache_t), 1); 78 if (imc == NULL || 79 obj_tab_init(imc) != 0 || 80 dd_matrix_init(imc) != 0) { 81 cache_destroy(); 82 return (1); /* no memory */ 83 } 84 85 /* 86 * initialize global cache rwlock. 87 */ 88 (void) rwlock_init(&imc->l, USYNC_PROCESS, NULL); 89 90 /* 91 * inintialize global cache functions. 92 */ 93 imc->get_hval = obj_hval; 94 imc->get_uid = get_obj_uid; 95 imc->set_uid = set_obj_uid; 96 imc->timestamp = get_timestamp; 97 imc->add_hook = add_object; 98 imc->replace_hook = replace_object; 99 imc->cmp = obj_cmp; 100 imc->clone = assoc_clone; 101 imc->ddd = update_ddd; 102 #ifdef DEBUG 103 imc->dump = obj_dump; 104 #endif 105 106 return (0); 107 } 108 109 /* 110 * **************************************************************************** 111 * cache_destroy: 112 * destroy the cache data. 113 * 114 * **************************************************************************** 115 */ 116 void 117 cache_destroy(void) 118 { 119 /* do nothing */ 120 } 121 122 /* 123 * **************************************************************************** 124 * cache_lock: 125 * grab the lock on the cache data. 126 * 127 * mode - the read/write mode of the lock. 128 * return - error code. 129 * 130 * **************************************************************************** 131 */ 132 int 133 cache_lock(int mode) 134 { 135 int ret = 0; 136 137 switch (mode) { 138 case CACHE_WRITE: 139 ret = rw_wrlock(&imc->l); 140 #ifdef DEBUG 141 if (verbose_lock) { 142 printf("cache locked for writing.\n"); 143 } 144 #endif 145 break; 146 case CACHE_READ: 147 ret = rw_rdlock(&imc->l); 148 #ifdef DEBUG 149 if (verbose_lock) { 150 printf("cache locked for reading.\n"); 151 } 152 #endif 153 break; 154 case CACHE_TRY_READ: 155 ret = rw_tryrdlock(&imc->l); 156 #ifdef DEBUG 157 if (verbose_lock) { 158 if (ret == 0) { 159 printf("cache locked for reading.\n"); 160 } else { 161 printf("cache locked for reading failed.\n"); 162 } 163 } 164 #endif 165 break; 166 default: 167 break; 168 } 169 170 return (ret); 171 } 172 173 /* 174 * **************************************************************************** 175 * cache_unlock: 176 * release the lock on the cache data. 177 * if the cache was locked for writing, a synchronization between 178 * the cache and persistent data store needs to be performed. 179 * 180 * mode - the read/write mode which the cache data was locked for. 181 * ec - 0: commit the cache update; otherwise retreat it. 182 * return - error code. 183 * 184 * **************************************************************************** 185 */ 186 int 187 cache_unlock(int mode, int ec) 188 { 189 if (mode != CACHE_NO_ACTION) { 190 /* sync between cache and data store */ 191 if (mode == CACHE_WRITE) { 192 if (sys_q) { 193 ec = data_sync(ec); 194 } 195 196 /* rest the cache update flag */ 197 RESET_CACHE_UPDATED(); 198 } 199 200 ASSERT(!IS_CACHE_UPDATED()); 201 202 /* unlock it */ 203 (void) rw_unlock(&imc->l); 204 #ifdef DEBUG 205 if (verbose_lock) { 206 printf("cache unlocked.\n"); 207 } 208 #endif 209 } 210 211 return (ec); 212 } 213 214 /* 215 * **************************************************************************** 216 * cache_lock_read: 217 * grab the read lock on the cache. 218 * 219 * return - error code. 220 * 221 * **************************************************************************** 222 */ 223 int 224 cache_lock_read(void) 225 { 226 return (cache_lock(CACHE_READ)); 227 } 228 229 /* 230 * **************************************************************************** 231 * cache_lock_write: 232 * grab the write lock on the cache. 233 * 234 * return - error code. 235 * 236 * **************************************************************************** 237 */ 238 int 239 cache_lock_write(void) 240 { 241 return (cache_lock(CACHE_WRITE)); 242 } 243 244 /* 245 * **************************************************************************** 246 * cache_unlock_sync: 247 * synchronize the cache with persistent data store and 248 * release the lock. 249 * 250 * ec - 0: commit the cache update; otherwise retreat it. 251 * return - error code. 252 * 253 * **************************************************************************** 254 */ 255 int 256 cache_unlock_sync(int ec) 257 { 258 return (cache_unlock(CACHE_WRITE, ec)); 259 } 260 261 /* 262 * **************************************************************************** 263 * cache_unlock_nosync: 264 * release the lock, no need to sync the data between cache and 265 * data store. 266 * if the cache has been updated, do not call this function, call 267 * cache_unlock_sync() with non-zero error code to indicate the 268 * sync action. 269 * 270 * return - error code. 271 * 272 * **************************************************************************** 273 */ 274 int 275 cache_unlock_nosync(void) 276 { 277 return (cache_unlock(CACHE_READ, 0)); 278 } 279 280 /* 281 * **************************************************************************** 282 * cache_get_htab: 283 * get the hash table for individual type of object. 284 * 285 * type - the object type. 286 * return - the hash table. 287 * 288 * **************************************************************************** 289 */ 290 htab_t * 291 cache_get_htab(isns_type_t type) 292 { 293 if (type > 0 && type < MAX_OBJ_TYPE) { 294 return (imc->t[type]); 295 } 296 297 return (NULL); 298 } 299 300 /* 301 * **************************************************************************** 302 * cache_get_matrix: 303 * get the membership matrix for a discovery domain or a 304 * discovery domain set. 305 * 306 * type - the discovery domain or discovery domain set object type. 307 * return - the matrix. 308 * 309 * **************************************************************************** 310 */ 311 matrix_t * 312 cache_get_matrix(isns_type_t type) 313 { 314 matrix_t *x = NULL; 315 316 switch (type) { 317 case OBJ_DD: 318 x = imc->x[0]; 319 break; 320 case OBJ_DDS: 321 x = imc->x[1]; 322 break; 323 default: 324 break; 325 } 326 327 return (x); 328 } 329 330 /* 331 * **************************************************************************** 332 * cache_lookup: 333 * invoke the hash table lookup for looking up a specific object and 334 * perform the callback function on the object. 335 * 336 * lcp - the object lookup control data. 337 * uid_p - the pointer of object UID for returning. 338 * callback - the callback function for the object. 339 * return - error code. 340 * 341 * **************************************************************************** 342 */ 343 int 344 cache_lookup(lookup_ctrl_t *lcp, uint32_t *uid_p, 345 int (*callback)(void *, void *)) 346 { 347 return (htab_lookup(imc->t[lcp->type], 348 lcp, 349 (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0, 350 uid_p, 351 callback, 352 0)); 353 } 354 355 /* 356 * **************************************************************************** 357 * cache_lookup: 358 * invoke the hash table lookup for looking up a specific object, 359 * the callback function is going to change the key of the object. 360 * 361 * lcp - the object lookup control data. 362 * uid_p - the pointer of object UID for returning. 363 * callback - the callback function for the object. 364 * return - error code. 365 * 366 * **************************************************************************** 367 */ 368 int 369 cache_rekey(lookup_ctrl_t *lcp, uint32_t *uid_p, 370 int (*callback)(void *, void *)) 371 { 372 return (htab_lookup(imc->t[lcp->type], 373 lcp, 374 (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0, 375 uid_p, 376 callback, 377 1)); 378 } 379 380 /* 381 * **************************************************************************** 382 * cache_add: 383 * invoke hash table add to add an object. 384 * 385 * obj - the object being added. 386 * flag - 0: a real object; 387 * otherwise an association object for discovery domain membership. 388 * uid_p - the pointer of object UID for returning. 389 * update_p - the pointer of flag (update object or newly register) 390 * for returning. 391 * return - error code. 392 * 393 * **************************************************************************** 394 */ 395 int 396 cache_add(isns_obj_t *obj, int flag, uint32_t *uid_p, int *update_p) 397 { 398 return (htab_add(imc->t[obj->type], obj, flag, uid_p, update_p)); 399 } 400 401 /* 402 * **************************************************************************** 403 * cache_remove: 404 * invoke hash table remove to remove an object. 405 * 406 * lcp - the lookup control data for the object being removed. 407 * flag - 0: a real object; 408 * otherwise an association object for discovery domain membership. 409 * return - the removed object. 410 * 411 * **************************************************************************** 412 */ 413 isns_obj_t * 414 cache_remove(lookup_ctrl_t *lcp, int flag) 415 { 416 return (htab_remove(imc->t[lcp->type], 417 lcp, 418 (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0, 419 flag)); 420 } 421 422 /* 423 * **************************************************************************** 424 * cache_dump_htab: 425 * dump the hash table for debugging purpose. 426 * 427 * type - the object type. 428 * 429 * **************************************************************************** 430 */ 431 #ifdef DEBUG 432 void 433 cache_dump_htab(isns_type_t type) 434 { 435 (void) htab_dump(imc->t[type]); 436 } 437 #endif 438