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( 73 ) 74 { 75 /* 76 * allocate global cache memory. 77 */ 78 imc = (cache_t *)calloc(sizeof (cache_t), 1); 79 if (imc == NULL || 80 obj_tab_init(imc) != 0 || 81 dd_matrix_init(imc) != 0) { 82 cache_destroy(); 83 return (1); /* no memory */ 84 } 85 86 /* 87 * initialize global cache rwlock. 88 */ 89 (void) rwlock_init(&imc->l, NULL, NULL); 90 91 /* 92 * inintialize global cache functions. 93 */ 94 imc->get_hval = obj_hval; 95 imc->get_uid = get_obj_uid; 96 imc->set_uid = set_obj_uid; 97 imc->timestamp = get_timestamp; 98 imc->add_hook = add_object; 99 imc->replace_hook = replace_object; 100 imc->cmp = obj_cmp; 101 imc->clone = assoc_clone; 102 imc->ddd = update_ddd; 103 #ifdef DEBUG 104 imc->dump = obj_dump; 105 #endif 106 107 return (0); 108 } 109 110 /* 111 * **************************************************************************** 112 * cache_destroy: 113 * destroy the cache data. 114 * 115 * **************************************************************************** 116 */ 117 void 118 cache_destroy( 119 ) 120 { 121 /* do nothing */ 122 } 123 124 /* 125 * **************************************************************************** 126 * cache_lock: 127 * grab the lock on the cache data. 128 * 129 * mode - the read/write mode of the lock. 130 * return - error code. 131 * 132 * **************************************************************************** 133 */ 134 int 135 cache_lock( 136 int mode 137 ) 138 { 139 int ret = 0; 140 141 switch (mode) { 142 case CACHE_WRITE: 143 ret = rw_wrlock(&imc->l); 144 #ifdef DEBUG 145 if (verbose_lock) { 146 printf("cache locked for writing.\n"); 147 } 148 #endif 149 break; 150 case CACHE_READ: 151 ret = rw_rdlock(&imc->l); 152 #ifdef DEBUG 153 if (verbose_lock) { 154 printf("cache locked for reading.\n"); 155 } 156 #endif 157 break; 158 case CACHE_TRY_READ: 159 ret = rw_tryrdlock(&imc->l); 160 #ifdef DEBUG 161 if (verbose_lock) { 162 if (ret == 0) { 163 printf("cache locked for reading.\n"); 164 } else { 165 printf("cache locked for reading failed.\n"); 166 } 167 } 168 #endif 169 break; 170 default: 171 break; 172 } 173 174 return (ret); 175 } 176 177 /* 178 * **************************************************************************** 179 * cache_unlock: 180 * release the lock on the cache data. 181 * if the cache was locked for writing, a synchronization between 182 * the cache and persistent data store needs to be performed. 183 * 184 * mode - the read/write mode which the cache data was locked for. 185 * ec - 0: commit the cache update; otherwise retreat it. 186 * return - error code. 187 * 188 * **************************************************************************** 189 */ 190 int 191 cache_unlock( 192 int mode, 193 int ec 194 ) 195 { 196 if (mode != CACHE_NO_ACTION) { 197 /* sync between cache and data store */ 198 if (mode == CACHE_WRITE) { 199 if (sys_q) { 200 ec = data_sync(ec); 201 } 202 203 /* rest the cache update flag */ 204 RESET_CACHE_UPDATED(); 205 } 206 207 ASSERT(!IS_CACHE_UPDATED()); 208 209 /* unlock it */ 210 (void) rw_unlock(&imc->l); 211 #ifdef DEBUG 212 if (verbose_lock) { 213 printf("cache unlocked.\n"); 214 } 215 #endif 216 } 217 218 return (ec); 219 } 220 221 /* 222 * **************************************************************************** 223 * cache_lock_read: 224 * grab the read lock on the cache. 225 * 226 * return - error code. 227 * 228 * **************************************************************************** 229 */ 230 int 231 cache_lock_read( 232 ) 233 { 234 return (cache_lock(CACHE_READ)); 235 } 236 237 /* 238 * **************************************************************************** 239 * cache_lock_write: 240 * grab the write lock on the cache. 241 * 242 * return - error code. 243 * 244 * **************************************************************************** 245 */ 246 int 247 cache_lock_write( 248 ) 249 { 250 return (cache_lock(CACHE_WRITE)); 251 } 252 253 /* 254 * **************************************************************************** 255 * cache_unlock_sync: 256 * synchronize the cache with persistent data store and 257 * release the lock. 258 * 259 * ec - 0: commit the cache update; otherwise retreat it. 260 * return - error code. 261 * 262 * **************************************************************************** 263 */ 264 int 265 cache_unlock_sync( 266 int ec 267 ) 268 { 269 return (cache_unlock(CACHE_WRITE, ec)); 270 } 271 272 /* 273 * **************************************************************************** 274 * cache_unlock_nosync: 275 * release the lock, no need to sync the data between cache and 276 * data store. 277 * if the cache has been updated, do not call this function, call 278 * cache_unlock_sync() with non-zero error code to indicate the 279 * sync action. 280 * 281 * return - error code. 282 * 283 * **************************************************************************** 284 */ 285 int 286 cache_unlock_nosync( 287 ) 288 { 289 return (cache_unlock(CACHE_READ, 0)); 290 } 291 292 /* 293 * **************************************************************************** 294 * cache_get_htab: 295 * get the hash table for individual type of object. 296 * 297 * type - the object type. 298 * return - the hash table. 299 * 300 * **************************************************************************** 301 */ 302 htab_t * 303 cache_get_htab( 304 isns_type_t type 305 ) 306 { 307 if (type > 0 && type < MAX_OBJ_TYPE) { 308 return (imc->t[type]); 309 } 310 311 return (NULL); 312 } 313 314 /* 315 * **************************************************************************** 316 * cache_get_matrix: 317 * get the membership matrix for a discovery domain or a 318 * discovery domain set. 319 * 320 * type - the discovery domain or discovery domain set object type. 321 * return - the matrix. 322 * 323 * **************************************************************************** 324 */ 325 matrix_t * 326 cache_get_matrix( 327 isns_type_t type 328 ) 329 { 330 matrix_t *x = NULL; 331 332 switch (type) { 333 case OBJ_DD: 334 x = imc->x[0]; 335 break; 336 case OBJ_DDS: 337 x = imc->x[1]; 338 break; 339 default: 340 break; 341 } 342 343 return (x); 344 } 345 346 /* 347 * **************************************************************************** 348 * cache_lookup: 349 * invoke the hash table lookup for looking up a specific object and 350 * perform the callback function on the object. 351 * 352 * lcp - the object lookup control data. 353 * uid_p - the pointer of object UID for returning. 354 * callback - the callback function for the object. 355 * return - error code. 356 * 357 * **************************************************************************** 358 */ 359 int 360 cache_lookup( 361 lookup_ctrl_t *lcp, 362 uint32_t *uid_p, 363 int (*callback)(void *, void *) 364 ) 365 { 366 return (htab_lookup(imc->t[lcp->type], 367 lcp, 368 (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0, 369 uid_p, 370 callback, 371 0)); 372 } 373 374 /* 375 * **************************************************************************** 376 * cache_lookup: 377 * invoke the hash table lookup for looking up a specific object, 378 * the callback function is going to change the key of the object. 379 * 380 * lcp - the object lookup control data. 381 * uid_p - the pointer of object UID for returning. 382 * callback - the callback function for the object. 383 * return - error code. 384 * 385 * **************************************************************************** 386 */ 387 int 388 cache_rekey( 389 lookup_ctrl_t *lcp, 390 uint32_t *uid_p, 391 int (*callback)(void *, void *) 392 ) 393 { 394 return (htab_lookup(imc->t[lcp->type], 395 lcp, 396 (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0, 397 uid_p, 398 callback, 399 1)); 400 } 401 402 /* 403 * **************************************************************************** 404 * cache_add: 405 * invoke hash table add to add an object. 406 * 407 * obj - the object being added. 408 * flag - 0: a real object; 409 * otherwise an association object for discovery domain membership. 410 * uid_p - the pointer of object UID for returning. 411 * update_p - the pointer of flag (update object or newly register) 412 * for returning. 413 * return - error code. 414 * 415 * **************************************************************************** 416 */ 417 int 418 cache_add( 419 isns_obj_t *obj, 420 int flag, 421 uint32_t *uid_p, 422 int *update_p 423 ) 424 { 425 return (htab_add(imc->t[obj->type], obj, flag, uid_p, update_p)); 426 } 427 428 /* 429 * **************************************************************************** 430 * cache_remove: 431 * invoke hash table remove to remove an object. 432 * 433 * lcp - the lookup control data for the object being removed. 434 * flag - 0: a real object; 435 * otherwise an association object for discovery domain membership. 436 * return - the removed object. 437 * 438 * **************************************************************************** 439 */ 440 isns_obj_t * 441 cache_remove( 442 lookup_ctrl_t *lcp, 443 int flag 444 ) 445 { 446 return (htab_remove(imc->t[lcp->type], 447 lcp, 448 (lcp->op[0] == OP_INTEGER) ? lcp->data[0].ui : 0, 449 flag)); 450 } 451 452 /* 453 * **************************************************************************** 454 * cache_dump_htab: 455 * dump the hash table for debugging purpose. 456 * 457 * type - the object type. 458 * 459 * **************************************************************************** 460 */ 461 #ifdef DEBUG 462 void 463 cache_dump_htab( 464 isns_type_t type 465 ) 466 { 467 (void) htab_dump(imc->t[type]); 468 } 469 #endif 470