dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fm / modules / sun4v / etm / etm_ckpt.c
blob36edbd8332493790b43688b1808a0c67dbf37dc6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * etm_ckpt.c
29 * Description:
30 * Checkpoint the ereport events for persitence across fmd restart.
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.
36 * All ereport ids are stored in the circular list which is saved in a
37 * separate buffer.
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>
52 #include "etm_etm_proto.h"
53 #include "etm_iosvc.h"
54 #include "etm_ckpt.h"
55 #include "etm_filter.h"
57 #define ETM_ATTR_PRIMARY "primary"
58 #define ETM_ATTR_TOD "__tod"
59 #define ETM_LDOM_PRIMARY "primary"
62 * -------------------------- private variables ------------------------------
65 static etm_ckpt_id_list_t *etm_id_lst = NULL; /* list of ereports ids */
67 static pthread_mutex_t etm_id_lst_lock; /* list lock */
70 * -------------------------- functions --------------------------------------
74 * etm_ckpt_str_hash()
75 * Description:
76 * Hash a class name to a number
78 static uint_t
79 etm_ckpt_str_hash(char *str)
81 uint_t hash = 0; /* hash value */
83 if (str == NULL)
84 return (0);
86 while (*str != '\0')
87 hash += *str++;
89 return (hash);
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.
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);
105 * etm_ckpt_erpt2id()
106 * Description:
107 * Get the buffer name and ereport id of a given ereport
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;
117 bzero(id, sizeof (etm_ckpt_erpt_id_t));
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);
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);
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);
136 id->ei_hash = etm_ckpt_str_hash(class);
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];
145 /* primary flag */
146 if (nvlist_lookup_boolean_value(erpt, ETM_ATTR_PRIMARY, &pri) == 0) {
147 id->ei_pri = pri ? 1 : 0;
150 etm_ckpt_id2str(id, str, size);
152 return (0);
156 * etm_ckpt_il_equal()
157 * Description:
158 * Test if two ereport ids are equal.
160 static boolean_t
161 etm_ckpt_il_equal(etm_ckpt_erpt_id_t *i1, etm_ckpt_erpt_id_t *i2)
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));
168 * etm_ckpt_il_resize()
169 * Description:
170 * Increase the size of the circular list and pack its entries.
172 static void
173 etm_ckpt_il_resize(fmd_hdl_t *hdl, uint_t factor)
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 */
181 if (factor == 0)
182 return;
184 /* the present queue */
185 il1 = etm_id_lst;
186 sz1 = sizeof (etm_ckpt_id_list_t) + il1->il_ids_sz;
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;
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));
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++;
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);
236 * etm_ckpt_il_find()
237 * Description:
238 * Find the ereport id in the list.
240 /* ARGSUSED */
241 static int
242 etm_ckpt_il_find(fmd_hdl_t *hdl, etm_ckpt_erpt_id_t *id)
244 int i, next; /* temp counter */
245 etm_ckpt_erpt_id_t *p, *s; /* temp erpt id */
247 fmd_hdl_debug(hdl, "etm_ckpt_il_find()\n");
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);
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);
263 return (-1);
267 * etm_ckpt_il_add()
268 * Description:
269 * Add an ereport id in the list.
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 */
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.
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);
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);
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++;
305 return (etm_id_lst->il_tail);
309 * etm_ckpt_il_delete()
310 * Description:
311 * Delete an ereport id from the list.
314 etm_ckpt_il_delete(fmd_hdl_t *hdl, etm_ckpt_erpt_id_t *id) {
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 */
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);
326 bzero(&blank, sizeof (blank));
327 s = (etm_ckpt_erpt_id_t *)((ptrdiff_t)etm_id_lst +
328 sizeof (etm_ckpt_id_list_t));
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;
337 etm_id_lst->il_cnt--;
338 etm_id_lst->il_head = next;
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);
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--;
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;
360 return (i);
364 return (-1);
369 * etm_ckpt_il_restore()
370 * Description:
371 * Restore the idlist named buffer which is the circular list of the
372 * the ereport ids.
374 void
375 etm_ckpt_il_restore(fmd_hdl_t *hdl)
377 size_t size; /* buffer size */
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;
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);
389 /* check version */
390 if (etm_id_lst->il_ver > ETM_CKPT_VERSION) {
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;
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;
410 * etm_ckpt_recover()
411 * Description:
412 * Recover ereports from the checkpointed data and dispatch them to the
413 * ldom queue(s).
415 void
416 etm_ckpt_recover(fmd_hdl_t *hdl)
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 */
433 * restore the circular list of ereport ids
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);
452 /* commit */
453 fmd_thr_checkpoint(hdl);
455 return;
458 /* Empty list */
459 if ((etm_id_lst->il_head == etm_id_lst->il_tail) ||
460 (etm_id_lst->il_cnt == 0)) {
461 return;
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;
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;
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;
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;
503 fmd_hdl_debug(hdl, "Dispatch %s to ldom %s\n", name, ldom);
506 * Find the queue of the ldom, create it if not exist.
507 * Then insert this event into the queue.
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);
514 nvlist_free(nvl);
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);
522 /* commit */
523 fmd_thr_checkpoint(hdl);
526 } /* etm_ckpt_recover */
530 * etm_ckpt_add_entry()
531 * Description:
532 * Save an ereport for persistence.
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;
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);
553 * check for a duplicate entry in the id list
554 * find the ereport buffer and search for the id
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);
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);
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);
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);
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);
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);
593 /* commit */
594 fmd_thr_checkpoint(hdl);
596 return (0);
600 * etm_ckpt_delete_entry()
601 * Description:
602 * Delete an ereport id in the list.
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 */
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);
617 fmd_hdl_debug(hdl, "Delete ckpt event(%s)\n", name);
619 /* delete the ereport buffer */
620 if (fmd_buf_size(hdl, NULL, name) > 0) {
621 fmd_buf_destroy(hdl, NULL, name);
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);
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);
634 /* commit */
635 fmd_thr_checkpoint(hdl);
637 return (rc);
641 etm_ckpt_add(fmd_hdl_t *hdl, nvlist_t *erpt) {
643 int rc; /* return code */
645 (void) pthread_mutex_lock(&etm_id_lst_lock);
647 rc = etm_ckpt_add_entry(hdl, erpt);
649 (void) pthread_mutex_unlock(&etm_id_lst_lock);
651 return (rc >= 0 ? 0 : rc);
655 etm_ckpt_delete(fmd_hdl_t *hdl, nvlist_t *erpt) {
656 int rc; /* return code */
658 (void) pthread_mutex_lock(&etm_id_lst_lock);
660 rc = etm_ckpt_delete_entry(hdl, erpt);
662 (void) pthread_mutex_unlock(&etm_id_lst_lock);
664 return (rc >= 0 ? 0 : rc);
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;
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);
680 (void) pthread_mutex_destroy(&etm_id_lst_lock);