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 /* 28 * etm_ckpt.c 29 * Description: 30 * Checkpoint the ereport events for persitence across fmd restart. 31 * 32 * Each ereport is stored in a named buffer. Each ereport is uniquely 33 * indentified by a id which is consists of a number of ereport fields. The 34 * name of the buffer is derived from the id. 35 * 36 * All ereport ids are stored in the circular list which is saved in a 37 * separate buffer. 38 */ 39 40 #include <assert.h> 41 #include <stdio.h> 42 #include <pthread.h> 43 #include <strings.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <sys/fm/ldom.h> 47 #include <sys/fm/protocol.h> 48 #include <fm/fmd_api.h> 49 #include <fm/libtopo.h> 50 #include <fm/topo_hc.h> 51 52 #include "etm_etm_proto.h" 53 #include "etm_iosvc.h" 54 #include "etm_ckpt.h" 55 #include "etm_filter.h" 56 57 #define ETM_ATTR_PRIMARY "primary" 58 #define ETM_ATTR_TOD "__tod" 59 #define ETM_LDOM_PRIMARY "primary" 60 61 /* 62 * -------------------------- private variables ------------------------------ 63 */ 64 65 static etm_ckpt_id_list_t *etm_id_lst = NULL; /* list of ereports ids */ 66 67 static pthread_mutex_t etm_id_lst_lock; /* list lock */ 68 69 /* 70 * -------------------------- functions -------------------------------------- 71 */ 72 73 /* 74 * etm_ckpt_str_hash() 75 * Description: 76 * Hash a class name to a number 77 */ 78 static uint_t 79 etm_ckpt_str_hash(char *str) 80 { 81 uint_t hash = 0; /* hash value */ 82 83 if (str == NULL) 84 return (0); 85 86 while (*str != '\0') 87 hash += *str++; 88 89 return (hash); 90 } 91 92 /* 93 * etm_ckpt_id2str() 94 * Description: 95 * Get the string of an ereport id. It is used as the named buffer that 96 * store the ereport. 97 */ 98 static void 99 etm_ckpt_id2str(etm_ckpt_erpt_id_t *id, char *str, size_t size) { 100 (void) snprintf(str, size, "%s_%llx_%d_%x_%d", ETM_CKPT_ERPT_PREFIX, 101 id->ei_ena, id->ei_hash, id->ei_tod1, id->ei_pri); 102 } 103 104 /* 105 * etm_ckpt_erpt2id() 106 * Description: 107 * Get the buffer name and ereport id of a given ereport 108 */ 109 static int 110 etm_ckpt_erpt2id(fmd_hdl_t *hdl, nvlist_t *erpt, etm_ckpt_erpt_id_t *id, 111 char *str, int size) { 112 char *class = NULL; 113 uint64_t *tod; 114 uint_t sz; 115 boolean_t pri = B_FALSE; 116 117 bzero(id, sizeof (etm_ckpt_erpt_id_t)); 118 119 /* ena */ 120 if (nvlist_lookup_uint64(erpt, FM_EREPORT_ENA, &id->ei_ena) != 0) { 121 fmd_hdl_debug(hdl, "Ena not found\n"); 122 return (-1); 123 } 124 125 /* class name */ 126 (void) nvlist_lookup_string(erpt, FM_CLASS, &class); 127 if (class == NULL) { 128 fmd_hdl_debug(hdl, "%s not found\n", FM_CLASS); 129 return (-1); 130 } 131 if (strncmp(class, FM_EREPORT_CLASS, strlen(FM_EREPORT_CLASS)) != 0) { 132 fmd_hdl_debug(hdl, "Only support checkpointing %s\n", 133 FM_EREPORT_CLASS); 134 return (-1); 135 } 136 id->ei_hash = etm_ckpt_str_hash(class); 137 138 /* tod[1]: fractional of a second */ 139 if (nvlist_lookup_uint64_array(erpt, ETM_ATTR_TOD, &tod, &sz) == 0) { 140 if (sz >= 2) { 141 id->ei_tod1 = (uint32_t)tod[1]; 142 } 143 } 144 145 /* primary flag */ 146 if (nvlist_lookup_boolean_value(erpt, ETM_ATTR_PRIMARY, &pri) == 0) { 147 id->ei_pri = pri ? 1 : 0; 148 } 149 150 etm_ckpt_id2str(id, str, size); 151 152 return (0); 153 } 154 155 /* 156 * etm_ckpt_il_equal() 157 * Description: 158 * Test if two ereport ids are equal. 159 */ 160 static boolean_t 161 etm_ckpt_il_equal(etm_ckpt_erpt_id_t *i1, etm_ckpt_erpt_id_t *i2) 162 { 163 return ((i1->ei_ena == i2->ei_ena) && (i1->ei_tod1 == i2->ei_tod1) && 164 (i1->ei_pri == i2->ei_pri) && (i1->ei_hash == i2->ei_hash)); 165 } 166 167 /* 168 * etm_ckpt_il_resize() 169 * Description: 170 * Increase the size of the circular list and pack its entries. 171 */ 172 static void 173 etm_ckpt_il_resize(fmd_hdl_t *hdl, uint_t factor) 174 { 175 etm_ckpt_id_list_t *il1, *il2; /* temp lists */ 176 size_t sz1, sz2; /* sizes of lists */ 177 int i, next; /* temp counters */ 178 etm_ckpt_erpt_id_t *p1, *p2, *s1, *s2; /* temp id pointers */ 179 etm_ckpt_erpt_id_t blank; /* blank ereport id */ 180 181 if (factor == 0) 182 return; 183 184 /* the present queue */ 185 il1 = etm_id_lst; 186 sz1 = sizeof (etm_ckpt_id_list_t) + il1->il_ids_sz; 187 188 /* Create an empty queue with a new size */ 189 sz2 = sizeof (etm_ckpt_id_list_t) + (factor * il1->il_ids_sz); 190 il2 = fmd_hdl_zalloc(hdl, sz2, FMD_SLEEP); 191 il2->il_ver = ETM_CKPT_VERSION; 192 il2->il_max = factor * etm_id_lst->il_max; 193 il2->il_ids_sz = factor * il1->il_ids_sz; 194 195 /* pointers to the two arrays of entries */ 196 bzero(&blank, sizeof (blank)); 197 s1 = (etm_ckpt_erpt_id_t *) 198 ((ptrdiff_t)il1 + sizeof (etm_ckpt_id_list_t)); 199 s2 = (etm_ckpt_erpt_id_t *) 200 ((ptrdiff_t)il2 + sizeof (etm_ckpt_id_list_t)); 201 202 /* copy non-empty ereport ids from list il1 to il2. Toss the blank. */ 203 if (il1->il_head != il1->il_tail) { 204 for (i = il1->il_head; i != il1->il_tail; i = next) { 205 next = (i + 1) % il1->il_max; 206 p1 = s1 + next; 207 if (!etm_ckpt_il_equal(p1, &blank)) { 208 /* copy non-empty entries */ 209 il2->il_tail = (il2->il_tail + 1) % il2->il_max; 210 fmd_hdl_debug(hdl, "Copying entry %d to %d\n", 211 next, il2->il_tail); 212 p2 = s2 + il2->il_tail; 213 *p2 = *p1; 214 il2->il_cnt++; 215 } 216 } 217 } 218 219 if (factor == 1) { 220 /* both lists have the same size, update the present list */ 221 bcopy(il2, il1, sz1); 222 fmd_hdl_free(hdl, il2, sz2); 223 fmd_buf_write(hdl, NULL, ETM_CKPT_IL_BUF, (void *) il1, sz1); 224 } else { 225 /* replace the present list */ 226 etm_id_lst = il2; 227 fmd_hdl_free(hdl, il1, sz1); 228 /* write to new buffer */ 229 fmd_buf_destroy(hdl, NULL, ETM_CKPT_IL_BUF); 230 fmd_buf_create(hdl, NULL, ETM_CKPT_IL_BUF, sz2); 231 fmd_buf_write(hdl, NULL, ETM_CKPT_IL_BUF, (void *) il2, sz2); 232 } 233 } 234 235 /* 236 * etm_ckpt_il_find() 237 * Description: 238 * Find the ereport id in the list. 239 */ 240 /* ARGSUSED */ 241 static int 242 etm_ckpt_il_find(fmd_hdl_t *hdl, etm_ckpt_erpt_id_t *id) 243 { 244 int i, next; /* temp counter */ 245 etm_ckpt_erpt_id_t *p, *s; /* temp erpt id */ 246 247 fmd_hdl_debug(hdl, "etm_ckpt_il_find()\n"); 248 249 /* empty list */ 250 if (etm_id_lst->il_head == etm_id_lst->il_tail) { 251 fmd_hdl_debug(hdl, "find an empty list\n"); 252 return (-1); 253 } 254 s = (etm_ckpt_erpt_id_t *)((ptrdiff_t)etm_id_lst + 255 sizeof (etm_ckpt_id_list_t)); 256 for (i = etm_id_lst->il_head; i != etm_id_lst->il_tail; i = next) { 257 next = (i + 1) % etm_id_lst->il_max; 258 p = s + next; 259 if (etm_ckpt_il_equal(p, id)) 260 return (i); 261 } 262 263 return (-1); 264 } 265 266 /* 267 * etm_ckpt_il_add() 268 * Description: 269 * Add an ereport id in the list. 270 */ 271 static int 272 etm_ckpt_il_add(fmd_hdl_t *hdl, etm_ckpt_erpt_id_t *id) { 273 int next; 274 etm_ckpt_erpt_id_t *p, *s; /* temp id */ 275 276 /* 277 * resize the q if it is full. 278 * If the capacity is less 80%, purge the emtpy entries to make more 279 * room for new entries. Otherwise, double the queue size. 280 */ 281 next = (etm_id_lst->il_tail + 1) % etm_id_lst->il_max; 282 if (next == etm_id_lst->il_head) { 283 if ((etm_id_lst->il_cnt * 1.0 / etm_id_lst->il_max) < 0.8) { 284 etm_ckpt_il_resize(hdl, 1); 285 } else { 286 etm_ckpt_il_resize(hdl, 2); 287 } 288 289 /* test if the list again */ 290 next = (etm_id_lst->il_tail + 1) % etm_id_lst->il_max; 291 if (next == etm_id_lst->il_head) { 292 fmd_hdl_error(hdl, "List is full %d %d\n", 293 etm_id_lst->il_head, etm_id_lst->il_tail); 294 } 295 } 296 297 /* Add the id entry at the head */ 298 s = (etm_ckpt_erpt_id_t *)((ptrdiff_t)etm_id_lst + 299 sizeof (etm_ckpt_id_list_t)); 300 etm_id_lst->il_tail = (etm_id_lst->il_tail + 1) % etm_id_lst->il_max; 301 p = s + etm_id_lst->il_tail; 302 *p = *id; 303 etm_id_lst->il_cnt++; 304 305 return (etm_id_lst->il_tail); 306 } 307 308 /* 309 * etm_ckpt_il_delete() 310 * Description: 311 * Delete an ereport id from the list. 312 */ 313 int 314 etm_ckpt_il_delete(fmd_hdl_t *hdl, etm_ckpt_erpt_id_t *id) { 315 316 int i, next; /* temp counter */ 317 etm_ckpt_erpt_id_t *p, *s; /* temp id pointers */ 318 etm_ckpt_erpt_id_t blank; /* blank id */ 319 320 /* empty list */ 321 if (etm_id_lst->il_tail == etm_id_lst->il_head) { 322 fmd_hdl_debug(hdl, "Empty queue(%d)\n", etm_id_lst->il_head); 323 return (-1); 324 } 325 326 bzero(&blank, sizeof (blank)); 327 s = (etm_ckpt_erpt_id_t *)((ptrdiff_t)etm_id_lst + 328 sizeof (etm_ckpt_id_list_t)); 329 330 /* delete leading empty entries */ 331 for (i = etm_id_lst->il_head; i != etm_id_lst->il_tail; i = next) { 332 next = (i + 1) % etm_id_lst->il_max; 333 p = s + next; 334 if (!etm_ckpt_il_equal(p, &blank)) { 335 break; 336 } 337 etm_id_lst->il_cnt--; 338 etm_id_lst->il_head = next; 339 } 340 341 /* empty queue */ 342 if (etm_id_lst->il_head == etm_id_lst->il_tail) { 343 fmd_hdl_debug(hdl, "Empty queue(%d)\n", etm_id_lst->il_head); 344 return (-1); 345 } 346 347 /* find the entry and clear it */ 348 for (i = etm_id_lst->il_head; i != etm_id_lst->il_tail; i = next) { 349 next = (i + 1) % etm_id_lst->il_max; 350 p = s + next; 351 if (etm_ckpt_il_equal(p, id)) { 352 /* clear the entry */ 353 *p = blank; 354 etm_id_lst->il_cnt--; 355 356 /* remove the entry if it is the last one */ 357 if (i == etm_id_lst->il_head) { 358 etm_id_lst->il_head = next; 359 } 360 return (i); 361 } 362 } 363 364 return (-1); 365 } 366 367 368 /* 369 * etm_ckpt_il_restore() 370 * Description: 371 * Restore the idlist named buffer which is the circular list of the 372 * the ereport ids. 373 */ 374 void 375 etm_ckpt_il_restore(fmd_hdl_t *hdl) 376 { 377 size_t size; /* buffer size */ 378 379 /* get the buffer of the id list */ 380 size = fmd_buf_size(hdl, NULL, ETM_CKPT_IL_BUF); 381 if (size < sizeof (etm_ckpt_id_list_t)) { 382 fmd_hdl_debug(hdl, "Buffer name %s do not exist\n", 383 ETM_CKPT_IL_BUF); 384 return; 385 } 386 etm_id_lst = (etm_ckpt_id_list_t *)fmd_hdl_zalloc(hdl, size, FMD_SLEEP); 387 fmd_buf_read(hdl, NULL, ETM_CKPT_IL_BUF, (void *) etm_id_lst, size); 388 389 /* check version */ 390 if (etm_id_lst->il_ver > ETM_CKPT_VERSION) { 391 392 fmd_hdl_error(hdl, "Unsupport checkpoint version (%#x)\n", 393 etm_id_lst->il_ver); 394 fmd_hdl_free(hdl, (void *) etm_id_lst, size); 395 etm_id_lst = NULL; 396 return; 397 } 398 399 /* check the length */ 400 if (etm_id_lst->il_ids_sz != (size - sizeof (etm_ckpt_id_list_t))) { 401 fmd_hdl_debug(hdl, "Invalid ids buffer size (%d, %d)\n", 402 etm_id_lst->il_ids_sz, size); 403 fmd_hdl_free(hdl, (void *) etm_id_lst, size); 404 etm_id_lst = NULL; 405 return; 406 } 407 } 408 409 /* 410 * etm_ckpt_recover() 411 * Description: 412 * Recover ereports from the checkpointed data and dispatch them to the 413 * ldom queue(s). 414 */ 415 void 416 etm_ckpt_recover(fmd_hdl_t *hdl) 417 { 418 int size; /* buffer size */ 419 int i, next; /* temp counter */ 420 boolean_t dirty = B_FALSE; /* dirty flag */ 421 uint64_t did; /* domain id */ 422 char name[ETM_LINE_LEN]; /* temp str */ 423 char ldom[ETM_LINE_LEN]; /* ldom id */ 424 etm_ckpt_erpt_id_t *p, *s; /* temp ereport id */ 425 etm_ckpt_erpt_id_t blank; /* blank ereport id */ 426 etm_ckpt_erpt_buf_t *ep; /* ereport buffer */ 427 size_t sz; /* size of ep */ 428 char *buf; /* temp buf */ 429 nvlist_t *nvl; /* ereport */ 430 etm_iosvc_t *iosvc; /* iosvc data struct */ 431 432 /* 433 * restore the circular list of ereport ids 434 */ 435 etm_ckpt_il_restore(hdl); 436 if (etm_id_lst == NULL) { 437 fmd_hdl_debug(hdl, "Initialize a new id list\n"); 438 size = sizeof (etm_ckpt_id_list_t) + 439 ETM_CKPT_IL_MIN_SIZE * sizeof (etm_ckpt_erpt_id_t); 440 etm_id_lst = fmd_hdl_zalloc(hdl, size, FMD_SLEEP); 441 etm_id_lst->il_ver = ETM_CKPT_VERSION; 442 etm_id_lst->il_max = ETM_CKPT_IL_MIN_SIZE; 443 etm_id_lst->il_head = 0; 444 etm_id_lst->il_tail = 0; 445 etm_id_lst->il_ids_sz = 446 ETM_CKPT_IL_MIN_SIZE * sizeof (etm_ckpt_erpt_id_t); 447 fmd_buf_destroy(hdl, NULL, ETM_CKPT_IL_BUF); 448 fmd_buf_create(hdl, NULL, ETM_CKPT_IL_BUF, size); 449 fmd_buf_write(hdl, NULL, ETM_CKPT_IL_BUF, (void *) etm_id_lst, 450 size); 451 452 /* commit */ 453 fmd_thr_checkpoint(hdl); 454 455 return; 456 } 457 458 /* Empty list */ 459 if ((etm_id_lst->il_head == etm_id_lst->il_tail) || 460 (etm_id_lst->il_cnt == 0)) { 461 return; 462 } 463 464 /* Visit all the entries in the list */ 465 bzero(&blank, sizeof (blank)); 466 s = (etm_ckpt_erpt_id_t *)((ptrdiff_t)etm_id_lst + 467 sizeof (etm_ckpt_id_list_t)); 468 for (i = etm_id_lst->il_head; i != etm_id_lst->il_tail; i = next) { 469 next = (i + 1) % etm_id_lst->il_max; 470 p = s + next; 471 if (etm_ckpt_il_equal(p, &blank)) { 472 fmd_hdl_debug(hdl, "Skip empty entry %d\n", i); 473 continue; 474 } 475 476 etm_ckpt_id2str(p, name, sizeof (name)); 477 fmd_hdl_debug(hdl, "Restoring entry %s\n", name); 478 if ((sz = fmd_buf_size(hdl, NULL, name)) == 0) { 479 fmd_hdl_error(hdl, "Clear the stale entry %s\n", name); 480 *p = blank; 481 continue; 482 } 483 ep = (etm_ckpt_erpt_buf_t *)fmd_hdl_zalloc(hdl, sz, FMD_SLEEP); 484 fmd_buf_read(hdl, NULL, name, (void *) ep, sz); 485 buf = (char *)((ptrdiff_t)ep + sizeof (etm_ckpt_erpt_buf_t)); 486 nvl = NULL; 487 if (nvlist_unpack(buf, ep->eb_len, &nvl, 0)) { 488 fmd_hdl_debug(hdl, "failed to unpack %s\n", name); 489 fmd_hdl_free(hdl, ep, sz); 490 continue; 491 } 492 fmd_hdl_free(hdl, ep, sz); 493 if (etm_filter_find_ldom_id(hdl, nvl, ldom, ETM_LINE_LEN, 494 &did) || (strcmp(name, ETM_LDOM_PRIMARY) == 0)) { 495 fmd_hdl_debug(hdl, "Discard event %s\n", name); 496 fmd_buf_destroy(hdl, NULL, name); 497 *p = blank; 498 nvlist_free(nvl); 499 dirty = B_TRUE; 500 continue; 501 } 502 503 fmd_hdl_debug(hdl, "Dispatch %s to ldom %s\n", name, ldom); 504 505 /* 506 * Find the queue of the ldom, create it if not exist. 507 * Then insert this event into the queue. 508 */ 509 iosvc = etm_iosvc_lookup(hdl, ldom, DS_INVALID_HDL, B_TRUE); 510 if (iosvc != NULL) { 511 (void) etm_pack_ds_msg(hdl, iosvc, NULL, 0, nvl, SP_MSG, 512 ETM_CKPT_RESTORE); 513 } 514 nvlist_free(nvl); 515 } 516 if (dirty) { 517 /* update the buffer of the queue */ 518 size = sizeof (etm_ckpt_id_list_t) + etm_id_lst->il_ids_sz; 519 fmd_buf_write(hdl, NULL, ETM_CKPT_IL_BUF, (void *) etm_id_lst, 520 size); 521 522 /* commit */ 523 fmd_thr_checkpoint(hdl); 524 } 525 526 } /* etm_ckpt_recover */ 527 528 529 /* 530 * etm_ckpt_add_entry() 531 * Description: 532 * Save an ereport for persistence. 533 */ 534 int 535 etm_ckpt_add_entry(fmd_hdl_t *hdl, nvlist_t *erpt) { 536 etm_ckpt_erpt_id_t id; 537 char name[ETM_LINE_LEN]; 538 int rc; /* gen use */ 539 size_t sz; /* size */ 540 size_t buflen; /* sz of packed erpt */ 541 uint8_t *buf; /* buffer of erpt */ 542 etm_ckpt_erpt_buf_t *hdr; 543 544 /* map ereport to id */ 545 bzero(name, ETM_LINE_LEN); 546 rc = etm_ckpt_erpt2id(hdl, erpt, &id, name, ETM_LINE_LEN); 547 if (rc != 0) { 548 fmd_hdl_debug(hdl, "Invalid ereport\n"); 549 return (rc); 550 } 551 552 /* 553 * check for a duplicate entry in the id list 554 * find the ereport buffer and search for the id 555 */ 556 if (fmd_buf_size(hdl, NULL, name) > 0 && 557 etm_ckpt_il_find(hdl, &id) >= 0) { 558 fmd_hdl_debug(hdl, "Duplicate id %s\n", name); 559 return (-1); 560 } 561 562 /* Create the ereport buffer */ 563 if (nvlist_size(erpt, &buflen, NV_ENCODE_XDR) != 0) { 564 fmd_hdl_debug(hdl, "nvlist_size fails\n"); 565 return (-1); 566 } 567 sz = sizeof (etm_ckpt_erpt_buf_t) + buflen; 568 hdr = (etm_ckpt_erpt_buf_t *)fmd_hdl_zalloc(hdl, sz, FMD_SLEEP); 569 buf = (uint8_t *)((ptrdiff_t)hdr + sizeof (etm_ckpt_erpt_buf_t)); 570 hdr->eb_ver = ETM_CKPT_VERSION; 571 hdr->eb_len = buflen; 572 if (nvlist_pack(erpt, (char **)&buf, &buflen, NV_ENCODE_XDR, 0) != 0) { 573 fmd_hdl_free(hdl, hdr, sz); 574 fmd_hdl_debug(hdl, "unpack fails\n"); 575 return (-1); 576 } 577 fmd_hdl_debug(hdl, "Add ckpt event(%s, %d)\n", name, sz); 578 fmd_buf_create(hdl, NULL, name, sz); 579 fmd_buf_write(hdl, NULL, name, hdr, sz); 580 fmd_hdl_free(hdl, hdr, sz); 581 582 /* Insert the ereport id into the id list */ 583 if (etm_ckpt_il_add(hdl, &id) < 0) { 584 fmd_hdl_debug(hdl, "Insert id %s failed\n", name); 585 fmd_buf_destroy(hdl, NULL, name); 586 return (-1); 587 } 588 589 /* update the buffer of the queue */ 590 sz = sizeof (etm_ckpt_id_list_t) + etm_id_lst->il_ids_sz; 591 fmd_buf_write(hdl, NULL, ETM_CKPT_IL_BUF, (void *) etm_id_lst, sz); 592 593 /* commit */ 594 fmd_thr_checkpoint(hdl); 595 596 return (0); 597 } 598 599 /* 600 * etm_ckpt_delete_entry() 601 * Description: 602 * Delete an ereport id in the list. 603 */ 604 static int 605 etm_ckpt_delete_entry(fmd_hdl_t *hdl, nvlist_t *erpt) { 606 etm_ckpt_erpt_id_t id; 607 char name[ETM_LINE_LEN]; 608 int rc; /* return code */ 609 size_t sz; /* size */ 610 611 /* get id, id name */ 612 bzero(name, ETM_LINE_LEN); 613 if (etm_ckpt_erpt2id(hdl, erpt, &id, name, ETM_LINE_LEN) != 0) { 614 fmd_hdl_debug(hdl, "Invalid ereport\n"); 615 return (-1); 616 } 617 fmd_hdl_debug(hdl, "Delete ckpt event(%s)\n", name); 618 619 /* delete the ereport buffer */ 620 if (fmd_buf_size(hdl, NULL, name) > 0) { 621 fmd_buf_destroy(hdl, NULL, name); 622 } 623 624 rc = etm_ckpt_il_delete(hdl, &id); 625 if (rc < 0) { 626 fmd_hdl_debug(hdl, "Delete id %s failed\n", name); 627 return (rc); 628 } 629 630 /* update the buffer of the queue */ 631 sz = sizeof (etm_ckpt_id_list_t) + etm_id_lst->il_ids_sz; 632 fmd_buf_write(hdl, NULL, ETM_CKPT_IL_BUF, (void *) etm_id_lst, sz); 633 634 /* commit */ 635 fmd_thr_checkpoint(hdl); 636 637 return (rc); 638 } 639 640 int 641 etm_ckpt_add(fmd_hdl_t *hdl, nvlist_t *erpt) { 642 643 int rc; /* return code */ 644 645 (void) pthread_mutex_lock(&etm_id_lst_lock); 646 647 rc = etm_ckpt_add_entry(hdl, erpt); 648 649 (void) pthread_mutex_unlock(&etm_id_lst_lock); 650 651 return (rc >= 0 ? 0 : rc); 652 } 653 654 int 655 etm_ckpt_delete(fmd_hdl_t *hdl, nvlist_t *erpt) { 656 int rc; /* return code */ 657 658 (void) pthread_mutex_lock(&etm_id_lst_lock); 659 660 rc = etm_ckpt_delete_entry(hdl, erpt); 661 662 (void) pthread_mutex_unlock(&etm_id_lst_lock); 663 664 return (rc >= 0 ? 0 : rc); 665 } 666 667 /* ARGSUSED */ 668 void 669 etm_ckpt_init(fmd_hdl_t *hdl) { 670 (void) pthread_mutex_init(&etm_id_lst_lock, NULL); 671 etm_id_lst = NULL; 672 } 673 674 void 675 etm_ckpt_fini(fmd_hdl_t *hdl) { 676 if (etm_id_lst != NULL) { 677 fmd_hdl_free(hdl, etm_id_lst, 678 sizeof (etm_ckpt_id_list_t) + etm_id_lst->il_ids_sz); 679 } 680 (void) pthread_mutex_destroy(&etm_id_lst_lock); 681 } 682