10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55255Sstephh * Common Development and Distribution License (the "License").
65255Sstephh * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
211193Smws
220Sstevel@tonic-gate /*
23*11416SStephen.Hanson@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/fm/protocol.h>
280Sstevel@tonic-gate #include <uuid/uuid.h>
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <dirent.h>
310Sstevel@tonic-gate #include <limits.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <alloca.h>
346228Sstephh #include <stddef.h>
356869Seschrock #include <fm/libtopo.h>
360Sstevel@tonic-gate
370Sstevel@tonic-gate #include <fmd_alloc.h>
380Sstevel@tonic-gate #include <fmd_string.h>
390Sstevel@tonic-gate #include <fmd_error.h>
400Sstevel@tonic-gate #include <fmd_subr.h>
410Sstevel@tonic-gate #include <fmd_protocol.h>
420Sstevel@tonic-gate #include <fmd_event.h>
430Sstevel@tonic-gate #include <fmd_conf.h>
440Sstevel@tonic-gate #include <fmd_fmri.h>
450Sstevel@tonic-gate #include <fmd_dispq.h>
461193Smws #include <fmd_case.h>
471193Smws #include <fmd_module.h>
480Sstevel@tonic-gate #include <fmd_asru.h>
490Sstevel@tonic-gate
500Sstevel@tonic-gate #include <fmd.h>
510Sstevel@tonic-gate
520Sstevel@tonic-gate static const char *const _fmd_asru_events[] = {
531193Smws FMD_RSRC_CLASS "asru.ok", /* UNUSABLE=0 FAULTED=0 */
541193Smws FMD_RSRC_CLASS "asru.degraded", /* UNUSABLE=0 FAULTED=1 */
551193Smws FMD_RSRC_CLASS "asru.unknown", /* UNUSABLE=1 FAULTED=0 */
561193Smws FMD_RSRC_CLASS "asru.faulted" /* UNUSABLE=1 FAULTED=1 */
570Sstevel@tonic-gate };
580Sstevel@tonic-gate
590Sstevel@tonic-gate static const char *const _fmd_asru_snames[] = {
600Sstevel@tonic-gate "uf", "uF", "Uf", "UF" /* same order as above */
610Sstevel@tonic-gate };
620Sstevel@tonic-gate
635255Sstephh volatile uint32_t fmd_asru_fake_not_present = 0;
645255Sstephh
656869Seschrock static uint_t
fmd_asru_strhash(fmd_asru_hash_t * ahp,const char * val)666869Seschrock fmd_asru_strhash(fmd_asru_hash_t *ahp, const char *val)
676869Seschrock {
686869Seschrock return (topo_fmri_strhash(ahp->ah_topo->ft_hdl, val) % ahp->ah_hashlen);
696869Seschrock }
706869Seschrock
716869Seschrock static boolean_t
fmd_asru_strcmp(fmd_asru_hash_t * ahp,const char * a,const char * b)726869Seschrock fmd_asru_strcmp(fmd_asru_hash_t *ahp, const char *a, const char *b)
736869Seschrock {
746869Seschrock return (topo_fmri_strcmp(ahp->ah_topo->ft_hdl, a, b));
756869Seschrock }
766869Seschrock
770Sstevel@tonic-gate static fmd_asru_t *
fmd_asru_create(fmd_asru_hash_t * ahp,const char * uuid,const char * name,nvlist_t * fmri)780Sstevel@tonic-gate fmd_asru_create(fmd_asru_hash_t *ahp, const char *uuid,
790Sstevel@tonic-gate const char *name, nvlist_t *fmri)
800Sstevel@tonic-gate {
816228Sstephh fmd_asru_t *ap = fmd_zalloc(sizeof (fmd_asru_t), FMD_SLEEP);
820Sstevel@tonic-gate char *s;
830Sstevel@tonic-gate
840Sstevel@tonic-gate (void) pthread_mutex_init(&ap->asru_lock, NULL);
850Sstevel@tonic-gate (void) pthread_cond_init(&ap->asru_cv, NULL);
860Sstevel@tonic-gate
870Sstevel@tonic-gate ap->asru_name = fmd_strdup(name, FMD_SLEEP);
886228Sstephh if (fmri)
896228Sstephh (void) nvlist_xdup(fmri, &ap->asru_fmri, &fmd.d_nva);
900Sstevel@tonic-gate ap->asru_root = fmd_strdup(ahp->ah_dirpath, FMD_SLEEP);
910Sstevel@tonic-gate ap->asru_uuid = fmd_strdup(uuid, FMD_SLEEP);
920Sstevel@tonic-gate ap->asru_uuidlen = ap->asru_uuid ? strlen(ap->asru_uuid) : 0;
930Sstevel@tonic-gate ap->asru_refs = 1;
940Sstevel@tonic-gate
956228Sstephh if (fmri && nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &s) == 0 &&
960Sstevel@tonic-gate strcmp(s, FM_FMRI_SCHEME_FMD) == 0)
970Sstevel@tonic-gate ap->asru_flags |= FMD_ASRU_INTERNAL;
980Sstevel@tonic-gate
990Sstevel@tonic-gate return (ap);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate static void
fmd_asru_destroy(fmd_asru_t * ap)1030Sstevel@tonic-gate fmd_asru_destroy(fmd_asru_t *ap)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ap->asru_lock));
1060Sstevel@tonic-gate ASSERT(ap->asru_refs == 0);
1070Sstevel@tonic-gate
1081552Smws nvlist_free(ap->asru_event);
1090Sstevel@tonic-gate fmd_strfree(ap->asru_name);
1100Sstevel@tonic-gate nvlist_free(ap->asru_fmri);
1110Sstevel@tonic-gate fmd_strfree(ap->asru_root);
1120Sstevel@tonic-gate fmd_free(ap->asru_uuid, ap->asru_uuidlen + 1);
1130Sstevel@tonic-gate fmd_free(ap, sizeof (fmd_asru_t));
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate static void
fmd_asru_hash_insert(fmd_asru_hash_t * ahp,fmd_asru_t * ap)1170Sstevel@tonic-gate fmd_asru_hash_insert(fmd_asru_hash_t *ahp, fmd_asru_t *ap)
1180Sstevel@tonic-gate {
1196869Seschrock uint_t h = fmd_asru_strhash(ahp, ap->asru_name);
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&ahp->ah_lock));
1220Sstevel@tonic-gate ap->asru_next = ahp->ah_hash[h];
1230Sstevel@tonic-gate ahp->ah_hash[h] = ap;
1240Sstevel@tonic-gate ahp->ah_count++;
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate static fmd_asru_t *
fmd_asru_hold(fmd_asru_t * ap)1280Sstevel@tonic-gate fmd_asru_hold(fmd_asru_t *ap)
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate (void) pthread_mutex_lock(&ap->asru_lock);
1310Sstevel@tonic-gate ap->asru_refs++;
1320Sstevel@tonic-gate ASSERT(ap->asru_refs != 0);
1330Sstevel@tonic-gate (void) pthread_mutex_unlock(&ap->asru_lock);
1340Sstevel@tonic-gate return (ap);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate /*
1380Sstevel@tonic-gate * Lookup an asru in the hash by name and place a hold on it. If the asru is
1390Sstevel@tonic-gate * not found, no entry is created and NULL is returned. This internal function
1400Sstevel@tonic-gate * is for callers who have the ah_lock held and is used by lookup_name below.
1410Sstevel@tonic-gate */
1420Sstevel@tonic-gate fmd_asru_t *
fmd_asru_hash_lookup(fmd_asru_hash_t * ahp,const char * name)1430Sstevel@tonic-gate fmd_asru_hash_lookup(fmd_asru_hash_t *ahp, const char *name)
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate fmd_asru_t *ap;
1460Sstevel@tonic-gate uint_t h;
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate ASSERT(RW_LOCK_HELD(&ahp->ah_lock));
1496869Seschrock h = fmd_asru_strhash(ahp, name);
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate for (ap = ahp->ah_hash[h]; ap != NULL; ap = ap->asru_next) {
1526869Seschrock if (fmd_asru_strcmp(ahp, ap->asru_name, name))
1530Sstevel@tonic-gate break;
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate if (ap != NULL)
1570Sstevel@tonic-gate (void) fmd_asru_hold(ap);
1580Sstevel@tonic-gate else
1590Sstevel@tonic-gate (void) fmd_set_errno(EFMD_ASRU_NOENT);
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate return (ap);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1649120SStephen.Hanson@Sun.COM #define HC_ONLY_FALSE 0
1659120SStephen.Hanson@Sun.COM #define HC_ONLY_TRUE 1
1669120SStephen.Hanson@Sun.COM
1676228Sstephh static int
fmd_asru_replacement_state(nvlist_t * event,int hc_only)1689120SStephen.Hanson@Sun.COM fmd_asru_replacement_state(nvlist_t *event, int hc_only)
1696228Sstephh {
1706228Sstephh int ps = -1;
1716228Sstephh nvlist_t *asru, *fru, *rsrc;
1729120SStephen.Hanson@Sun.COM char *s;
1736228Sstephh
1746228Sstephh /*
1756228Sstephh * Check if there is evidence that this object is no longer present.
1766228Sstephh * In general fmd_fmri_present() should be supported on resources and/or
1776228Sstephh * frus, as those are the things that are physically present or not
1786228Sstephh * present - an asru can be spread over a number of frus some of which
1796228Sstephh * are present and some not, so fmd_fmri_present() is not generally
1806228Sstephh * meaningful. However retain a check for asru first for compatibility.
1816228Sstephh * If we have checked all three and we still get -1 then nothing knows
1826228Sstephh * whether it's present or not, so err on the safe side and treat it
1836228Sstephh * as still present.
1849120SStephen.Hanson@Sun.COM *
1859120SStephen.Hanson@Sun.COM * Note that if hc_only is set, then we only check status using fmris
1869120SStephen.Hanson@Sun.COM * that are in hc-scheme.
1876228Sstephh */
1886228Sstephh if (fmd_asru_fake_not_present)
1897275Sstephh return (fmd_asru_fake_not_present);
1909120SStephen.Hanson@Sun.COM if (nvlist_lookup_nvlist(event, FM_FAULT_ASRU, &asru) == 0 &&
1919120SStephen.Hanson@Sun.COM (hc_only == HC_ONLY_FALSE || (nvlist_lookup_string(asru,
1929120SStephen.Hanson@Sun.COM FM_FMRI_SCHEME, &s) == 0 && strcmp(s, FM_FMRI_SCHEME_HC) == 0)))
1937275Sstephh ps = fmd_fmri_replaced(asru);
1949120SStephen.Hanson@Sun.COM if (ps == -1 || ps == FMD_OBJ_STATE_UNKNOWN) {
1957275Sstephh if (nvlist_lookup_nvlist(event, FM_FAULT_RESOURCE,
1969120SStephen.Hanson@Sun.COM &rsrc) == 0 && (hc_only == HC_ONLY_FALSE ||
1979120SStephen.Hanson@Sun.COM (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &s) == 0 &&
1989120SStephen.Hanson@Sun.COM strcmp(s, FM_FMRI_SCHEME_HC) == 0))) {
1999120SStephen.Hanson@Sun.COM if (ps == -1) {
2009120SStephen.Hanson@Sun.COM ps = fmd_fmri_replaced(rsrc);
2019120SStephen.Hanson@Sun.COM } else {
2029120SStephen.Hanson@Sun.COM /* see if we can improve on UNKNOWN */
2039120SStephen.Hanson@Sun.COM int ps2 = fmd_fmri_replaced(rsrc);
2049120SStephen.Hanson@Sun.COM if (ps2 == FMD_OBJ_STATE_STILL_PRESENT ||
2059120SStephen.Hanson@Sun.COM ps2 == FMD_OBJ_STATE_REPLACED)
2069120SStephen.Hanson@Sun.COM ps = ps2;
2079120SStephen.Hanson@Sun.COM }
2087275Sstephh }
2097275Sstephh }
2109120SStephen.Hanson@Sun.COM if (ps == -1 || ps == FMD_OBJ_STATE_UNKNOWN) {
2119120SStephen.Hanson@Sun.COM if (nvlist_lookup_nvlist(event, FM_FAULT_FRU, &fru) == 0 &&
2129120SStephen.Hanson@Sun.COM (hc_only == HC_ONLY_FALSE || (nvlist_lookup_string(fru,
2139120SStephen.Hanson@Sun.COM FM_FMRI_SCHEME, &s) == 0 &&
2149120SStephen.Hanson@Sun.COM strcmp(s, FM_FMRI_SCHEME_HC) == 0))) {
2159120SStephen.Hanson@Sun.COM if (ps == -1) {
2169120SStephen.Hanson@Sun.COM ps = fmd_fmri_replaced(fru);
2179120SStephen.Hanson@Sun.COM } else {
2189120SStephen.Hanson@Sun.COM /* see if we can improve on UNKNOWN */
2199120SStephen.Hanson@Sun.COM int ps2 = fmd_fmri_replaced(fru);
2209120SStephen.Hanson@Sun.COM if (ps2 == FMD_OBJ_STATE_STILL_PRESENT ||
2219120SStephen.Hanson@Sun.COM ps2 == FMD_OBJ_STATE_REPLACED)
2229120SStephen.Hanson@Sun.COM ps = ps2;
2239120SStephen.Hanson@Sun.COM }
2247275Sstephh }
2257275Sstephh }
2266228Sstephh if (ps == -1)
2277275Sstephh ps = FMD_OBJ_STATE_UNKNOWN;
2286228Sstephh return (ps);
2296228Sstephh }
2306228Sstephh
2316228Sstephh static void
fmd_asru_asru_hash_insert(fmd_asru_hash_t * ahp,fmd_asru_link_t * alp,char * name)2326228Sstephh fmd_asru_asru_hash_insert(fmd_asru_hash_t *ahp, fmd_asru_link_t *alp,
2336228Sstephh char *name)
2346228Sstephh {
2356869Seschrock uint_t h = fmd_asru_strhash(ahp, name);
2366228Sstephh
2376228Sstephh ASSERT(RW_WRITE_HELD(&ahp->ah_lock));
2386228Sstephh alp->al_asru_next = ahp->ah_asru_hash[h];
2396228Sstephh ahp->ah_asru_hash[h] = alp;
2406228Sstephh ahp->ah_al_count++;
2416228Sstephh }
2426228Sstephh
2436228Sstephh static void
fmd_asru_case_hash_insert(fmd_asru_hash_t * ahp,fmd_asru_link_t * alp,char * name)2446228Sstephh fmd_asru_case_hash_insert(fmd_asru_hash_t *ahp, fmd_asru_link_t *alp,
2456228Sstephh char *name)
2466228Sstephh {
2476869Seschrock uint_t h = fmd_asru_strhash(ahp, name);
2486228Sstephh
2496228Sstephh ASSERT(RW_WRITE_HELD(&ahp->ah_lock));
2506228Sstephh alp->al_case_next = ahp->ah_case_hash[h];
2516228Sstephh ahp->ah_case_hash[h] = alp;
2526228Sstephh }
2536228Sstephh
2546228Sstephh static void
fmd_asru_fru_hash_insert(fmd_asru_hash_t * ahp,fmd_asru_link_t * alp,char * name)2556228Sstephh fmd_asru_fru_hash_insert(fmd_asru_hash_t *ahp, fmd_asru_link_t *alp, char *name)
2566228Sstephh {
2576869Seschrock uint_t h = fmd_asru_strhash(ahp, name);
2586228Sstephh
2596228Sstephh ASSERT(RW_WRITE_HELD(&ahp->ah_lock));
2606228Sstephh alp->al_fru_next = ahp->ah_fru_hash[h];
2616228Sstephh ahp->ah_fru_hash[h] = alp;
2626228Sstephh }
2636228Sstephh
2646228Sstephh static void
fmd_asru_label_hash_insert(fmd_asru_hash_t * ahp,fmd_asru_link_t * alp,char * name)2656228Sstephh fmd_asru_label_hash_insert(fmd_asru_hash_t *ahp, fmd_asru_link_t *alp,
2666228Sstephh char *name)
2676228Sstephh {
2686869Seschrock uint_t h = fmd_asru_strhash(ahp, name);
2696228Sstephh
2706228Sstephh ASSERT(RW_WRITE_HELD(&ahp->ah_lock));
2716228Sstephh alp->al_label_next = ahp->ah_label_hash[h];
2726228Sstephh ahp->ah_label_hash[h] = alp;
2736228Sstephh }
2746228Sstephh
2756228Sstephh static void
fmd_asru_rsrc_hash_insert(fmd_asru_hash_t * ahp,fmd_asru_link_t * alp,char * name)2766228Sstephh fmd_asru_rsrc_hash_insert(fmd_asru_hash_t *ahp, fmd_asru_link_t *alp,
2776228Sstephh char *name)
2786228Sstephh {
2796869Seschrock uint_t h = fmd_asru_strhash(ahp, name);
2806228Sstephh
2816228Sstephh ASSERT(RW_WRITE_HELD(&ahp->ah_lock));
2826228Sstephh alp->al_rsrc_next = ahp->ah_rsrc_hash[h];
2836228Sstephh ahp->ah_rsrc_hash[h] = alp;
2846228Sstephh }
2856228Sstephh
2866228Sstephh static void
fmd_asru_al_destroy(fmd_asru_link_t * alp)2876228Sstephh fmd_asru_al_destroy(fmd_asru_link_t *alp)
2886228Sstephh {
2896228Sstephh ASSERT(alp->al_refs == 0);
2906228Sstephh ASSERT(MUTEX_HELD(&alp->al_asru->asru_lock));
2916228Sstephh
2926228Sstephh if (alp->al_log != NULL)
2936228Sstephh fmd_log_rele(alp->al_log);
2946228Sstephh
2956228Sstephh fmd_free(alp->al_uuid, alp->al_uuidlen + 1);
2966228Sstephh nvlist_free(alp->al_event);
2976228Sstephh fmd_strfree(alp->al_rsrc_name);
2986228Sstephh fmd_strfree(alp->al_case_uuid);
2996228Sstephh fmd_strfree(alp->al_fru_name);
3006228Sstephh fmd_strfree(alp->al_asru_name);
3016228Sstephh fmd_strfree(alp->al_label);
3026228Sstephh nvlist_free(alp->al_asru_fmri);
3036228Sstephh fmd_free(alp, sizeof (fmd_asru_link_t));
3046228Sstephh }
3056228Sstephh
3066228Sstephh static fmd_asru_link_t *
fmd_asru_al_hold(fmd_asru_link_t * alp)3076228Sstephh fmd_asru_al_hold(fmd_asru_link_t *alp)
3086228Sstephh {
3096228Sstephh fmd_asru_t *ap = alp->al_asru;
3106228Sstephh
3116228Sstephh (void) pthread_mutex_lock(&ap->asru_lock);
3126228Sstephh ap->asru_refs++;
3136228Sstephh alp->al_refs++;
3146228Sstephh ASSERT(alp->al_refs != 0);
3156228Sstephh (void) pthread_mutex_unlock(&ap->asru_lock);
3166228Sstephh return (alp);
3176228Sstephh }
3186228Sstephh
3196228Sstephh static void fmd_asru_destroy(fmd_asru_t *ap);
3206228Sstephh
3216228Sstephh /*ARGSUSED*/
3226228Sstephh static void
fmd_asru_al_hash_release(fmd_asru_hash_t * ahp,fmd_asru_link_t * alp)3236228Sstephh fmd_asru_al_hash_release(fmd_asru_hash_t *ahp, fmd_asru_link_t *alp)
3246228Sstephh {
3256228Sstephh fmd_asru_t *ap = alp->al_asru;
3266228Sstephh
3276228Sstephh (void) pthread_mutex_lock(&ap->asru_lock);
3286228Sstephh ASSERT(alp->al_refs != 0);
3296228Sstephh if (--alp->al_refs == 0)
3306228Sstephh fmd_asru_al_destroy(alp);
3316228Sstephh ASSERT(ap->asru_refs != 0);
3326228Sstephh if (--ap->asru_refs == 0)
3336228Sstephh fmd_asru_destroy(ap);
3346228Sstephh else
3356228Sstephh (void) pthread_mutex_unlock(&ap->asru_lock);
3366228Sstephh }
3376228Sstephh
3386228Sstephh static int
fmd_asru_get_namestr(nvlist_t * nvl,char ** name,ssize_t * namelen)3396228Sstephh fmd_asru_get_namestr(nvlist_t *nvl, char **name, ssize_t *namelen)
3406228Sstephh {
3416228Sstephh if ((*namelen = fmd_fmri_nvl2str(nvl, NULL, 0)) == -1)
3426228Sstephh return (EFMD_ASRU_FMRI);
3436228Sstephh *name = fmd_alloc(*namelen + 1, FMD_SLEEP);
3446228Sstephh if (fmd_fmri_nvl2str(nvl, *name, *namelen + 1) == -1) {
3456228Sstephh if (*name != NULL)
3466228Sstephh fmd_free(*name, *namelen + 1);
3476228Sstephh return (EFMD_ASRU_FMRI);
3486228Sstephh }
3496228Sstephh return (0);
3506228Sstephh }
3516228Sstephh
3526228Sstephh static fmd_asru_link_t *
fmd_asru_al_create(fmd_asru_hash_t * ahp,nvlist_t * nvl,fmd_case_t * cp,const char * al_uuid)3536228Sstephh fmd_asru_al_create(fmd_asru_hash_t *ahp, nvlist_t *nvl, fmd_case_t *cp,
3546228Sstephh const char *al_uuid)
3556228Sstephh {
3566228Sstephh nvlist_t *asru = NULL, *fru, *rsrc;
3576228Sstephh int got_rsrc = 0, got_asru = 0, got_fru = 0;
3586228Sstephh ssize_t fru_namelen, rsrc_namelen, asru_namelen;
3596228Sstephh char *asru_name, *rsrc_name, *fru_name, *name, *label;
3606228Sstephh fmd_asru_link_t *alp;
3616228Sstephh fmd_asru_t *ap;
3626228Sstephh boolean_t msg;
3636228Sstephh fmd_case_impl_t *cip = (fmd_case_impl_t *)cp;
3646228Sstephh
3656228Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &asru) == 0 &&
3666228Sstephh fmd_asru_get_namestr(asru, &asru_name, &asru_namelen) == 0)
3676228Sstephh got_asru = 1;
3686228Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &fru) == 0 &&
3696228Sstephh fmd_asru_get_namestr(fru, &fru_name, &fru_namelen) == 0)
3706228Sstephh got_fru = 1;
3716228Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0 &&
3726228Sstephh fmd_asru_get_namestr(rsrc, &rsrc_name, &rsrc_namelen) == 0)
3736228Sstephh got_rsrc = 1;
3746228Sstephh if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION, &label) != 0)
3756228Sstephh label = "";
3766228Sstephh
3776228Sstephh /*
3786228Sstephh * Grab the rwlock as a writer; Then create and insert the asru with
3796228Sstephh * ahp->ah_lock held and hash it in. We'll then drop the rwlock and
3806228Sstephh * proceed to initializing the asru.
3816228Sstephh */
3826228Sstephh (void) pthread_rwlock_wrlock(&ahp->ah_lock);
3836228Sstephh
3846228Sstephh /*
3856228Sstephh * Create and initialise the per-fault "link" structure.
3866228Sstephh */
3876228Sstephh alp = fmd_zalloc(sizeof (fmd_asru_link_t), FMD_SLEEP);
3886228Sstephh if (got_asru)
3896228Sstephh (void) nvlist_xdup(asru, &alp->al_asru_fmri, &fmd.d_nva);
3906228Sstephh alp->al_uuid = fmd_strdup(al_uuid, FMD_SLEEP);
3916228Sstephh alp->al_uuidlen = strlen(alp->al_uuid);
3926228Sstephh alp->al_refs = 1;
3936228Sstephh
3946228Sstephh /*
3956228Sstephh * If this is the first fault for this asru, then create the per-asru
3966228Sstephh * structure and link into the hash.
3976228Sstephh */
3986228Sstephh name = got_asru ? asru_name : "";
3996228Sstephh if ((ap = fmd_asru_hash_lookup(ahp, name)) == NULL) {
4006228Sstephh ap = fmd_asru_create(ahp, al_uuid, name, got_asru ? asru :
4016228Sstephh NULL);
4026228Sstephh fmd_asru_hash_insert(ahp, ap);
4036228Sstephh } else
4046228Sstephh nvlist_free(ap->asru_event);
4056228Sstephh (void) nvlist_xdup(nvl, &ap->asru_event, &fmd.d_nva);
4066228Sstephh
4076228Sstephh /*
4086228Sstephh * Put the link structure on the list associated with the per-asru
4096228Sstephh * structure. Then put the link structure on the various hashes.
4106228Sstephh */
4116228Sstephh fmd_list_append(&ap->asru_list, (fmd_list_t *)alp);
4126228Sstephh alp->al_asru = ap;
4136228Sstephh alp->al_asru_name = got_asru ? asru_name : fmd_strdup("", FMD_SLEEP);
4146228Sstephh fmd_asru_asru_hash_insert(ahp, alp, alp->al_asru_name);
4156228Sstephh alp->al_fru_name = got_fru ? fru_name : fmd_strdup("", FMD_SLEEP);
4166228Sstephh fmd_asru_fru_hash_insert(ahp, alp, alp->al_fru_name);
4176228Sstephh alp->al_rsrc_name = got_rsrc ? rsrc_name : fmd_strdup("", FMD_SLEEP);
4186228Sstephh fmd_asru_rsrc_hash_insert(ahp, alp, alp->al_rsrc_name);
4196228Sstephh alp->al_label = fmd_strdup(label, FMD_SLEEP);
4206228Sstephh fmd_asru_label_hash_insert(ahp, alp, label);
4216228Sstephh alp->al_case_uuid = fmd_strdup(cip->ci_uuid, FMD_SLEEP);
4226228Sstephh fmd_asru_case_hash_insert(ahp, alp, cip->ci_uuid);
4236228Sstephh (void) pthread_mutex_lock(&ap->asru_lock);
4246228Sstephh (void) pthread_rwlock_unlock(&ahp->ah_lock);
4256228Sstephh
4266228Sstephh ap->asru_case = alp->al_case = cp;
4276228Sstephh if (nvlist_lookup_boolean_value(nvl, FM_SUSPECT_MESSAGE, &msg) == 0 &&
4286228Sstephh msg == B_FALSE)
4296228Sstephh ap->asru_flags |= FMD_ASRU_INVISIBLE;
4306228Sstephh (void) nvlist_xdup(nvl, &alp->al_event, &fmd.d_nva);
4316228Sstephh ap->asru_flags |= FMD_ASRU_VALID;
4326228Sstephh (void) pthread_cond_broadcast(&ap->asru_cv);
4336228Sstephh (void) pthread_mutex_unlock(&ap->asru_lock);
4346228Sstephh return (alp);
4356228Sstephh }
4366228Sstephh
4370Sstevel@tonic-gate static void
fmd_asru_hash_recreate(fmd_log_t * lp,fmd_event_t * ep,fmd_asru_hash_t * ahp)4380Sstevel@tonic-gate fmd_asru_hash_recreate(fmd_log_t *lp, fmd_event_t *ep, fmd_asru_hash_t *ahp)
4390Sstevel@tonic-gate {
4401193Smws nvlist_t *nvl = FMD_EVENT_NVL(ep);
4417275Sstephh boolean_t faulty = FMD_B_FALSE, unusable = FMD_B_FALSE;
4427275Sstephh int ps;
4437275Sstephh boolean_t repaired = FMD_B_FALSE, replaced = FMD_B_FALSE;
44410656SStephen.Hanson@Sun.COM boolean_t acquitted = FMD_B_FALSE, resolved = FMD_B_FALSE;
4456228Sstephh nvlist_t *flt, *flt_copy, *asru;
4461193Smws char *case_uuid = NULL, *case_code = NULL;
4470Sstevel@tonic-gate fmd_asru_t *ap;
4486228Sstephh fmd_asru_link_t *alp;
4496228Sstephh fmd_case_t *cp;
4505255Sstephh int64_t *diag_time;
4519120SStephen.Hanson@Sun.COM nvlist_t *de_fmri, *de_fmri_dup;
4525255Sstephh uint_t nelem;
4537197Sstephh topo_hdl_t *thp;
4547197Sstephh char *class;
4557197Sstephh nvlist_t *rsrc;
4567197Sstephh int err;
45710928SStephen.Hanson@Sun.COM boolean_t injected;
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate /*
4606228Sstephh * Extract the most recent values of 'faulty' from the event log.
4610Sstevel@tonic-gate */
4627275Sstephh if (nvlist_lookup_boolean_value(nvl, FM_RSRC_ASRU_FAULTY,
4637275Sstephh &faulty) != 0) {
4640Sstevel@tonic-gate fmd_error(EFMD_ASRU_EVENT, "failed to reload asru %s: "
4650Sstevel@tonic-gate "invalid event log record\n", lp->log_name);
4660Sstevel@tonic-gate ahp->ah_error = EFMD_ASRU_EVENT;
4670Sstevel@tonic-gate return;
4680Sstevel@tonic-gate }
4696228Sstephh if (nvlist_lookup_nvlist(nvl, FM_RSRC_ASRU_EVENT, &flt) != 0) {
4706228Sstephh fmd_error(EFMD_ASRU_EVENT, "failed to reload asru %s: "
4716228Sstephh "invalid event log record\n", lp->log_name);
4726228Sstephh ahp->ah_error = EFMD_ASRU_EVENT;
4736228Sstephh return;
4746228Sstephh }
4756228Sstephh (void) nvlist_lookup_string(nvl, FM_RSRC_ASRU_UUID, &case_uuid);
4766228Sstephh (void) nvlist_lookup_string(nvl, FM_RSRC_ASRU_CODE, &case_code);
4777275Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_RSRC_ASRU_UNUSABLE,
4787275Sstephh &unusable);
4797275Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_RSRC_ASRU_REPAIRED,
4807275Sstephh &repaired);
4817275Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_RSRC_ASRU_REPLACED,
4827275Sstephh &replaced);
4837275Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_RSRC_ASRU_ACQUITTED,
4847275Sstephh &acquitted);
48510656SStephen.Hanson@Sun.COM (void) nvlist_lookup_boolean_value(nvl, FM_RSRC_ASRU_RESOLVED,
48610656SStephen.Hanson@Sun.COM &resolved);
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate /*
48910656SStephen.Hanson@Sun.COM * Attempt to recreate the case in CLOSED, REPAIRED or RESOLVED state
49010656SStephen.Hanson@Sun.COM * (depending on whether the faulty/resolved bits are set).
4916228Sstephh * If the case is already present, fmd_case_recreate() will return it.
4926228Sstephh * If not, we'll create a new orphaned case. Either way, we use the
4936228Sstephh * ASRU event to insert a suspect into the partially-restored case.
4945255Sstephh */
4956228Sstephh fmd_module_lock(fmd.d_rmod);
4967275Sstephh cp = fmd_case_recreate(fmd.d_rmod, NULL, faulty ? FMD_CASE_CLOSED :
49710656SStephen.Hanson@Sun.COM resolved ? FMD_CASE_RESOLVED : FMD_CASE_REPAIRED, case_uuid,
49810656SStephen.Hanson@Sun.COM case_code);
4996228Sstephh fmd_case_hold(cp);
5006228Sstephh fmd_module_unlock(fmd.d_rmod);
50110928SStephen.Hanson@Sun.COM if (nvlist_lookup_boolean_value(nvl, FM_SUSPECT_INJECTED,
50210928SStephen.Hanson@Sun.COM &injected) == 0 && injected)
50310928SStephen.Hanson@Sun.COM fmd_case_set_injected(cp);
5046228Sstephh if (nvlist_lookup_int64_array(nvl, FM_SUSPECT_DIAG_TIME, &diag_time,
5056228Sstephh &nelem) == 0 && nelem >= 2)
5066228Sstephh fmd_case_settime(cp, diag_time[0], diag_time[1]);
5076228Sstephh else
5086228Sstephh fmd_case_settime(cp, lp->log_stat.st_ctime, 0);
5099120SStephen.Hanson@Sun.COM if (nvlist_lookup_nvlist(nvl, FM_SUSPECT_DE, &de_fmri) == 0) {
5109120SStephen.Hanson@Sun.COM (void) nvlist_xdup(de_fmri, &de_fmri_dup, &fmd.d_nva);
5119120SStephen.Hanson@Sun.COM fmd_case_set_de_fmri(cp, de_fmri_dup);
5129120SStephen.Hanson@Sun.COM }
5136228Sstephh (void) nvlist_xdup(flt, &flt_copy, &fmd.d_nva);
5147197Sstephh
5157197Sstephh /*
5167197Sstephh * For faults with a resource, re-evaluate the asru from the resource.
5177197Sstephh */
5187197Sstephh thp = fmd_fmri_topo_hold(TOPO_VERSION);
5197197Sstephh if (nvlist_lookup_string(flt_copy, FM_CLASS, &class) == 0 &&
5207197Sstephh strncmp(class, "fault", 5) == 0 &&
5217197Sstephh nvlist_lookup_nvlist(flt_copy, FM_FAULT_RESOURCE, &rsrc) == 0 &&
522*11416SStephen.Hanson@Sun.COM rsrc != NULL &&
523*11416SStephen.Hanson@Sun.COM (fmd_fmri_replaced(rsrc) != FMD_OBJ_STATE_REPLACED) &&
524*11416SStephen.Hanson@Sun.COM topo_fmri_asru(thp, rsrc, &asru, &err) == 0) {
5257197Sstephh (void) nvlist_remove(flt_copy, FM_FAULT_ASRU, DATA_TYPE_NVLIST);
5267197Sstephh (void) nvlist_add_nvlist(flt_copy, FM_FAULT_ASRU, asru);
5277197Sstephh nvlist_free(asru);
5287197Sstephh }
5297197Sstephh fmd_fmri_topo_rele(thp);
5307197Sstephh
5317197Sstephh (void) nvlist_xdup(flt_copy, &flt, &fmd.d_nva);
5327197Sstephh
5336228Sstephh fmd_case_recreate_suspect(cp, flt_copy);
5346228Sstephh
5356228Sstephh /*
5366228Sstephh * Now create the resource cache entries.
5376228Sstephh */
5386228Sstephh alp = fmd_asru_al_create(ahp, flt, cp, fmd_strbasename(lp->log_name));
5396228Sstephh ap = alp->al_asru;
5405255Sstephh
5415255Sstephh /*
5427275Sstephh * Check to see if the resource is still present in the system.
5430Sstevel@tonic-gate */
5449120SStephen.Hanson@Sun.COM ps = fmd_asru_replacement_state(flt, HC_ONLY_FALSE);
5457532SSean.Ye@Sun.COM if (ps == FMD_OBJ_STATE_REPLACED) {
5467532SSean.Ye@Sun.COM replaced = FMD_B_TRUE;
5477532SSean.Ye@Sun.COM } else if (ps == FMD_OBJ_STATE_STILL_PRESENT ||
5487532SSean.Ye@Sun.COM ps == FMD_OBJ_STATE_UNKNOWN) {
5497275Sstephh ap->asru_flags |= FMD_ASRU_PRESENT;
5507532SSean.Ye@Sun.COM if (nvlist_lookup_nvlist(alp->al_event, FM_FAULT_ASRU,
5517532SSean.Ye@Sun.COM &asru) == 0) {
5527532SSean.Ye@Sun.COM int us;
5537532SSean.Ye@Sun.COM
5547532SSean.Ye@Sun.COM switch (fmd_fmri_service_state(asru)) {
5557532SSean.Ye@Sun.COM case FMD_SERVICE_STATE_UNUSABLE:
5567532SSean.Ye@Sun.COM unusable = FMD_B_TRUE;
5577532SSean.Ye@Sun.COM break;
5587532SSean.Ye@Sun.COM case FMD_SERVICE_STATE_OK:
5598245SStephen.Hanson@Sun.COM case FMD_SERVICE_STATE_ISOLATE_PENDING:
5607532SSean.Ye@Sun.COM case FMD_SERVICE_STATE_DEGRADED:
5617532SSean.Ye@Sun.COM unusable = FMD_B_FALSE;
5627532SSean.Ye@Sun.COM break;
5637532SSean.Ye@Sun.COM case FMD_SERVICE_STATE_UNKNOWN:
5647532SSean.Ye@Sun.COM case -1:
5657532SSean.Ye@Sun.COM /* not supported by scheme */
5667532SSean.Ye@Sun.COM us = fmd_fmri_unusable(asru);
5677532SSean.Ye@Sun.COM if (us > 0)
5687532SSean.Ye@Sun.COM unusable = FMD_B_TRUE;
5697532SSean.Ye@Sun.COM else if (us == 0)
5707532SSean.Ye@Sun.COM unusable = FMD_B_FALSE;
5717532SSean.Ye@Sun.COM break;
5727532SSean.Ye@Sun.COM }
5737532SSean.Ye@Sun.COM }
5747532SSean.Ye@Sun.COM }
5750Sstevel@tonic-gate
5767197Sstephh nvlist_free(flt);
5777197Sstephh
5786228Sstephh ap->asru_flags |= FMD_ASRU_RECREATED;
5797275Sstephh if (faulty) {
5806228Sstephh alp->al_flags |= FMD_ASRU_FAULTY;
5816228Sstephh ap->asru_flags |= FMD_ASRU_FAULTY;
5820Sstevel@tonic-gate }
5837275Sstephh if (unusable) {
5846228Sstephh alp->al_flags |= FMD_ASRU_UNUSABLE;
5856228Sstephh ap->asru_flags |= FMD_ASRU_UNUSABLE;
5860Sstevel@tonic-gate }
5877275Sstephh if (replaced)
5887275Sstephh alp->al_reason = FMD_ASRU_REPLACED;
5897275Sstephh else if (repaired)
5907275Sstephh alp->al_reason = FMD_ASRU_REPAIRED;
5917275Sstephh else if (acquitted)
5927275Sstephh alp->al_reason = FMD_ASRU_ACQUITTED;
59310656SStephen.Hanson@Sun.COM else
59410656SStephen.Hanson@Sun.COM alp->al_reason = FMD_ASRU_REMOVED;
5950Sstevel@tonic-gate
5966228Sstephh TRACE((FMD_DBG_ASRU, "asru %s recreated as %p (%s)", alp->al_uuid,
5970Sstevel@tonic-gate (void *)ap, _fmd_asru_snames[ap->asru_flags & FMD_ASRU_STATE]));
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate static void
fmd_asru_hash_discard(fmd_asru_hash_t * ahp,const char * uuid,int err)6010Sstevel@tonic-gate fmd_asru_hash_discard(fmd_asru_hash_t *ahp, const char *uuid, int err)
6020Sstevel@tonic-gate {
6030Sstevel@tonic-gate char src[PATH_MAX], dst[PATH_MAX];
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate (void) snprintf(src, PATH_MAX, "%s/%s", ahp->ah_dirpath, uuid);
6060Sstevel@tonic-gate (void) snprintf(dst, PATH_MAX, "%s/%s-", ahp->ah_dirpath, uuid);
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate if (err != 0)
6090Sstevel@tonic-gate err = rename(src, dst);
6100Sstevel@tonic-gate else
6110Sstevel@tonic-gate err = unlink(src);
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate if (err != 0 && errno != ENOENT)
6140Sstevel@tonic-gate fmd_error(EFMD_ASRU_EVENT, "failed to rename log %s", src);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate * Open a saved log file and restore it into the ASRU hash. If we can't even
6190Sstevel@tonic-gate * open the log, rename the log file to <uuid>- to indicate it is corrupt. If
6200Sstevel@tonic-gate * fmd_log_replay() fails, we either delete the file (if it has reached the
6210Sstevel@tonic-gate * upper limit on cache age) or rename it for debugging if it was corrupted.
6220Sstevel@tonic-gate */
6230Sstevel@tonic-gate static void
fmd_asru_hash_logopen(fmd_asru_hash_t * ahp,const char * uuid)6240Sstevel@tonic-gate fmd_asru_hash_logopen(fmd_asru_hash_t *ahp, const char *uuid)
6250Sstevel@tonic-gate {
6260Sstevel@tonic-gate fmd_log_t *lp = fmd_log_tryopen(ahp->ah_dirpath, uuid, FMD_LOG_ASRU);
6270Sstevel@tonic-gate uint_t n;
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate if (lp == NULL) {
6300Sstevel@tonic-gate fmd_asru_hash_discard(ahp, uuid, errno);
6310Sstevel@tonic-gate return;
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate ahp->ah_error = 0;
6356228Sstephh n = ahp->ah_al_count;
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate fmd_log_replay(lp, (fmd_log_f *)fmd_asru_hash_recreate, ahp);
6380Sstevel@tonic-gate fmd_log_rele(lp);
6390Sstevel@tonic-gate
6406228Sstephh if (ahp->ah_al_count == n)
6410Sstevel@tonic-gate fmd_asru_hash_discard(ahp, uuid, ahp->ah_error);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate void
fmd_asru_hash_refresh(fmd_asru_hash_t * ahp)6450Sstevel@tonic-gate fmd_asru_hash_refresh(fmd_asru_hash_t *ahp)
6460Sstevel@tonic-gate {
647871Scasper struct dirent *dp;
6480Sstevel@tonic-gate DIR *dirp;
6490Sstevel@tonic-gate int zero;
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate if ((dirp = opendir(ahp->ah_dirpath)) == NULL) {
6520Sstevel@tonic-gate fmd_error(EFMD_ASRU_NODIR,
6530Sstevel@tonic-gate "failed to open asru cache directory %s", ahp->ah_dirpath);
6540Sstevel@tonic-gate return;
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate (void) fmd_conf_getprop(fmd.d_conf, "rsrc.zero", &zero);
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&ahp->ah_lock);
6600Sstevel@tonic-gate
661871Scasper while ((dp = readdir(dirp)) != NULL) {
6620Sstevel@tonic-gate if (dp->d_name[0] == '.')
6630Sstevel@tonic-gate continue; /* skip "." and ".." */
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate if (zero)
6660Sstevel@tonic-gate fmd_asru_hash_discard(ahp, dp->d_name, 0);
6670Sstevel@tonic-gate else if (!fmd_strmatch(dp->d_name, "*-"))
6680Sstevel@tonic-gate fmd_asru_hash_logopen(ahp, dp->d_name);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate (void) pthread_rwlock_unlock(&ahp->ah_lock);
6720Sstevel@tonic-gate (void) closedir(dirp);
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate
6751552Smws /*
6761552Smws * If the resource is present and faulty but not unusable, replay the fault
6771552Smws * event that caused it be marked faulty. This will cause the agent
6781552Smws * subscribing to this fault class to again disable the resource.
6791552Smws */
6801552Smws /*ARGSUSED*/
6811552Smws static void
fmd_asru_hash_replay_asru(fmd_asru_t * ap,void * data)6821552Smws fmd_asru_hash_replay_asru(fmd_asru_t *ap, void *data)
6831552Smws {
6841552Smws fmd_event_t *e;
6851552Smws nvlist_t *nvl;
6861552Smws char *class;
6871552Smws
6881552Smws if (ap->asru_event != NULL && (ap->asru_flags & (FMD_ASRU_STATE |
6891552Smws FMD_ASRU_PRESENT)) == (FMD_ASRU_FAULTY | FMD_ASRU_PRESENT)) {
6901552Smws
6911552Smws fmd_dprintf(FMD_DBG_ASRU,
6921552Smws "replaying fault event for %s", ap->asru_name);
6931552Smws
6941552Smws (void) nvlist_xdup(ap->asru_event, &nvl, &fmd.d_nva);
6951552Smws (void) nvlist_lookup_string(nvl, FM_CLASS, &class);
6961552Smws
6971552Smws (void) nvlist_add_string(nvl, FMD_EVN_UUID,
6981552Smws ((fmd_case_impl_t *)ap->asru_case)->ci_uuid);
6991552Smws
7001552Smws e = fmd_event_create(FMD_EVT_PROTOCOL, FMD_HRT_NOW, nvl, class);
7011552Smws fmd_dispq_dispatch(fmd.d_disp, e, class);
7021552Smws }
7031552Smws }
7041552Smws
7051552Smws void
fmd_asru_hash_replay(fmd_asru_hash_t * ahp)7061552Smws fmd_asru_hash_replay(fmd_asru_hash_t *ahp)
7071552Smws {
7081552Smws fmd_asru_hash_apply(ahp, fmd_asru_hash_replay_asru, NULL);
7091552Smws }
7101552Smws
7116228Sstephh /*
7126228Sstephh * Check if the resource is still present. If not, and if the rsrc.age time
7136228Sstephh * has expired, then do an implicit repair on the resource.
7146228Sstephh */
7157275Sstephh /*ARGSUSED*/
7166228Sstephh static void
fmd_asru_repair_if_aged(fmd_asru_link_t * alp,void * arg)7177275Sstephh fmd_asru_repair_if_aged(fmd_asru_link_t *alp, void *arg)
7186228Sstephh {
7196228Sstephh struct timeval tv;
7206228Sstephh fmd_log_t *lp;
7216228Sstephh hrtime_t hrt;
7227275Sstephh int ps;
7237275Sstephh int err;
7249120SStephen.Hanson@Sun.COM fmd_asru_rep_arg_t fara;
7256228Sstephh
72610656SStephen.Hanson@Sun.COM if (!(alp->al_flags & FMD_ASRU_FAULTY))
72710656SStephen.Hanson@Sun.COM return;
72810656SStephen.Hanson@Sun.COM
7299120SStephen.Hanson@Sun.COM /*
7309120SStephen.Hanson@Sun.COM * Checking for aged resources only happens on the diagnosing side
7319120SStephen.Hanson@Sun.COM * not on a proxy.
7329120SStephen.Hanson@Sun.COM */
7339120SStephen.Hanson@Sun.COM if (alp->al_flags & FMD_ASRU_PROXY)
7349120SStephen.Hanson@Sun.COM return;
7359120SStephen.Hanson@Sun.COM
7369120SStephen.Hanson@Sun.COM ps = fmd_asru_replacement_state(alp->al_event, HC_ONLY_FALSE);
7377275Sstephh if (ps == FMD_OBJ_STATE_REPLACED) {
7389120SStephen.Hanson@Sun.COM fara.fara_reason = FMD_ASRU_REPLACED;
7399120SStephen.Hanson@Sun.COM fara.fara_bywhat = FARA_ALL;
7409120SStephen.Hanson@Sun.COM fara.fara_rval = &err;
7419120SStephen.Hanson@Sun.COM fmd_asru_repaired(alp, &fara);
7427275Sstephh } else if (ps == FMD_OBJ_STATE_NOT_PRESENT) {
7437275Sstephh fmd_time_gettimeofday(&tv);
7447275Sstephh lp = fmd_log_open(alp->al_asru->asru_root, alp->al_uuid,
7457275Sstephh FMD_LOG_ASRU);
74611202SStephen.Hanson@Sun.COM if (lp == NULL)
74711202SStephen.Hanson@Sun.COM return;
7487275Sstephh hrt = (hrtime_t)(tv.tv_sec - lp->log_stat.st_mtime);
7497275Sstephh fmd_log_rele(lp);
7509120SStephen.Hanson@Sun.COM if (hrt * NANOSEC >= fmd.d_asrus->ah_lifetime) {
7519120SStephen.Hanson@Sun.COM fara.fara_reason = FMD_ASRU_REMOVED;
7529120SStephen.Hanson@Sun.COM fara.fara_bywhat = FARA_ALL;
7539120SStephen.Hanson@Sun.COM fara.fara_rval = &err;
7549120SStephen.Hanson@Sun.COM fmd_asru_repaired(alp, &fara);
7559120SStephen.Hanson@Sun.COM }
7567275Sstephh }
7576228Sstephh }
7586228Sstephh
75910656SStephen.Hanson@Sun.COM /*ARGSUSED*/
76010656SStephen.Hanson@Sun.COM void
fmd_asru_check_if_aged(fmd_asru_link_t * alp,void * arg)76110656SStephen.Hanson@Sun.COM fmd_asru_check_if_aged(fmd_asru_link_t *alp, void *arg)
76210656SStephen.Hanson@Sun.COM {
76310656SStephen.Hanson@Sun.COM struct timeval tv;
76410656SStephen.Hanson@Sun.COM fmd_log_t *lp;
76510656SStephen.Hanson@Sun.COM hrtime_t hrt;
76610656SStephen.Hanson@Sun.COM
76710656SStephen.Hanson@Sun.COM /*
76810656SStephen.Hanson@Sun.COM * Case must be in resolved state for this to be called. So modified
76910656SStephen.Hanson@Sun.COM * time on resource cache entry should be the time the resolve occurred.
77010656SStephen.Hanson@Sun.COM * Return 0 if not yet hit rsrc.aged.
77110656SStephen.Hanson@Sun.COM */
77210656SStephen.Hanson@Sun.COM fmd_time_gettimeofday(&tv);
77310656SStephen.Hanson@Sun.COM lp = fmd_log_open(alp->al_asru->asru_root, alp->al_uuid, FMD_LOG_ASRU);
77410656SStephen.Hanson@Sun.COM if (lp == NULL)
77510656SStephen.Hanson@Sun.COM return;
77610656SStephen.Hanson@Sun.COM hrt = (hrtime_t)(tv.tv_sec - lp->log_stat.st_mtime);
77710656SStephen.Hanson@Sun.COM fmd_log_rele(lp);
77810656SStephen.Hanson@Sun.COM if (hrt * NANOSEC < fmd.d_asrus->ah_lifetime)
77910656SStephen.Hanson@Sun.COM *(int *)arg = 0;
78010656SStephen.Hanson@Sun.COM }
78110656SStephen.Hanson@Sun.COM
78210656SStephen.Hanson@Sun.COM /*ARGSUSED*/
78310656SStephen.Hanson@Sun.COM void
fmd_asru_most_recent(fmd_asru_link_t * alp,void * arg)78410656SStephen.Hanson@Sun.COM fmd_asru_most_recent(fmd_asru_link_t *alp, void *arg)
78510656SStephen.Hanson@Sun.COM {
78610656SStephen.Hanson@Sun.COM fmd_log_t *lp;
78710656SStephen.Hanson@Sun.COM uint64_t hrt;
78810656SStephen.Hanson@Sun.COM
78910656SStephen.Hanson@Sun.COM /*
79010656SStephen.Hanson@Sun.COM * Find most recent modified time of a set of resource cache entries.
79110656SStephen.Hanson@Sun.COM */
79210656SStephen.Hanson@Sun.COM lp = fmd_log_open(alp->al_asru->asru_root, alp->al_uuid, FMD_LOG_ASRU);
79310656SStephen.Hanson@Sun.COM if (lp == NULL)
79410656SStephen.Hanson@Sun.COM return;
79510656SStephen.Hanson@Sun.COM hrt = lp->log_stat.st_mtime;
79610656SStephen.Hanson@Sun.COM fmd_log_rele(lp);
79710656SStephen.Hanson@Sun.COM if (*(uint64_t *)arg < hrt)
79810656SStephen.Hanson@Sun.COM *(uint64_t *)arg = hrt;
79910656SStephen.Hanson@Sun.COM }
80010656SStephen.Hanson@Sun.COM
8016228Sstephh void
fmd_asru_clear_aged_rsrcs()8026228Sstephh fmd_asru_clear_aged_rsrcs()
8036228Sstephh {
80410656SStephen.Hanson@Sun.COM int check_if_aged = 1;
8057275Sstephh fmd_asru_al_hash_apply(fmd.d_asrus, fmd_asru_repair_if_aged, NULL);
80610656SStephen.Hanson@Sun.COM fmd_case_hash_apply(fmd.d_cases, fmd_case_discard_resolved,
80710656SStephen.Hanson@Sun.COM &check_if_aged);
8086228Sstephh }
8096228Sstephh
8100Sstevel@tonic-gate fmd_asru_hash_t *
fmd_asru_hash_create(const char * root,const char * dir)8110Sstevel@tonic-gate fmd_asru_hash_create(const char *root, const char *dir)
8120Sstevel@tonic-gate {
8130Sstevel@tonic-gate fmd_asru_hash_t *ahp;
8140Sstevel@tonic-gate char path[PATH_MAX];
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate ahp = fmd_alloc(sizeof (fmd_asru_hash_t), FMD_SLEEP);
8170Sstevel@tonic-gate (void) pthread_rwlock_init(&ahp->ah_lock, NULL);
8180Sstevel@tonic-gate ahp->ah_hashlen = fmd.d_str_buckets;
8190Sstevel@tonic-gate ahp->ah_hash = fmd_zalloc(sizeof (void *) * ahp->ah_hashlen, FMD_SLEEP);
8206228Sstephh ahp->ah_asru_hash = fmd_zalloc(sizeof (void *) * ahp->ah_hashlen,
8216228Sstephh FMD_SLEEP);
8226228Sstephh ahp->ah_case_hash = fmd_zalloc(sizeof (void *) * ahp->ah_hashlen,
8236228Sstephh FMD_SLEEP);
8246228Sstephh ahp->ah_fru_hash = fmd_zalloc(sizeof (void *) * ahp->ah_hashlen,
8256228Sstephh FMD_SLEEP);
8266228Sstephh ahp->ah_label_hash = fmd_zalloc(sizeof (void *) * ahp->ah_hashlen,
8276228Sstephh FMD_SLEEP);
8286228Sstephh ahp->ah_rsrc_hash = fmd_zalloc(sizeof (void *) * ahp->ah_hashlen,
8296228Sstephh FMD_SLEEP);
8300Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s/%s", root, dir);
8310Sstevel@tonic-gate ahp->ah_dirpath = fmd_strdup(path, FMD_SLEEP);
8320Sstevel@tonic-gate (void) fmd_conf_getprop(fmd.d_conf, "rsrc.age", &ahp->ah_lifetime);
8335255Sstephh (void) fmd_conf_getprop(fmd.d_conf, "fakenotpresent",
8345255Sstephh (uint32_t *)&fmd_asru_fake_not_present);
8356228Sstephh ahp->ah_al_count = 0;
8360Sstevel@tonic-gate ahp->ah_count = 0;
8370Sstevel@tonic-gate ahp->ah_error = 0;
8386869Seschrock ahp->ah_topo = fmd_topo_hold();
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate return (ahp);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate void
fmd_asru_hash_destroy(fmd_asru_hash_t * ahp)8440Sstevel@tonic-gate fmd_asru_hash_destroy(fmd_asru_hash_t *ahp)
8450Sstevel@tonic-gate {
8466228Sstephh fmd_asru_link_t *alp, *np;
8470Sstevel@tonic-gate uint_t i;
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate for (i = 0; i < ahp->ah_hashlen; i++) {
8506228Sstephh for (alp = ahp->ah_case_hash[i]; alp != NULL; alp = np) {
8516228Sstephh np = alp->al_case_next;
8526228Sstephh alp->al_case_next = NULL;
8536228Sstephh fmd_case_rele(alp->al_case);
8546228Sstephh alp->al_case = NULL;
8556228Sstephh fmd_asru_al_hash_release(ahp, alp);
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate fmd_strfree(ahp->ah_dirpath);
8600Sstevel@tonic-gate fmd_free(ahp->ah_hash, sizeof (void *) * ahp->ah_hashlen);
8616228Sstephh fmd_free(ahp->ah_asru_hash, sizeof (void *) * ahp->ah_hashlen);
8626228Sstephh fmd_free(ahp->ah_case_hash, sizeof (void *) * ahp->ah_hashlen);
8636228Sstephh fmd_free(ahp->ah_fru_hash, sizeof (void *) * ahp->ah_hashlen);
8646228Sstephh fmd_free(ahp->ah_label_hash, sizeof (void *) * ahp->ah_hashlen);
8656228Sstephh fmd_free(ahp->ah_rsrc_hash, sizeof (void *) * ahp->ah_hashlen);
8666869Seschrock fmd_topo_rele(ahp->ah_topo);
8670Sstevel@tonic-gate fmd_free(ahp, sizeof (fmd_asru_hash_t));
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate /*
8710Sstevel@tonic-gate * Take a snapshot of the ASRU database by placing an additional hold on each
8720Sstevel@tonic-gate * member in an auxiliary array, and then call 'func' for each ASRU.
8730Sstevel@tonic-gate */
8740Sstevel@tonic-gate void
fmd_asru_hash_apply(fmd_asru_hash_t * ahp,void (* func)(fmd_asru_t *,void *),void * arg)8750Sstevel@tonic-gate fmd_asru_hash_apply(fmd_asru_hash_t *ahp,
8760Sstevel@tonic-gate void (*func)(fmd_asru_t *, void *), void *arg)
8770Sstevel@tonic-gate {
8780Sstevel@tonic-gate fmd_asru_t *ap, **aps, **app;
8790Sstevel@tonic-gate uint_t apc, i;
8800Sstevel@tonic-gate
8810Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&ahp->ah_lock);
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate aps = app = fmd_alloc(ahp->ah_count * sizeof (fmd_asru_t *), FMD_SLEEP);
8840Sstevel@tonic-gate apc = ahp->ah_count;
8850Sstevel@tonic-gate
8860Sstevel@tonic-gate for (i = 0; i < ahp->ah_hashlen; i++) {
8870Sstevel@tonic-gate for (ap = ahp->ah_hash[i]; ap != NULL; ap = ap->asru_next)
8880Sstevel@tonic-gate *app++ = fmd_asru_hold(ap);
8890Sstevel@tonic-gate }
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate ASSERT(app == aps + apc);
8920Sstevel@tonic-gate (void) pthread_rwlock_unlock(&ahp->ah_lock);
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate for (i = 0; i < apc; i++) {
8956228Sstephh if (aps[i]->asru_fmri != NULL)
8966228Sstephh func(aps[i], arg);
8970Sstevel@tonic-gate fmd_asru_hash_release(ahp, aps[i]);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate fmd_free(aps, apc * sizeof (fmd_asru_t *));
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9036228Sstephh void
fmd_asru_al_hash_apply(fmd_asru_hash_t * ahp,void (* func)(fmd_asru_link_t *,void *),void * arg)9046228Sstephh fmd_asru_al_hash_apply(fmd_asru_hash_t *ahp,
9056228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg)
9066228Sstephh {
9076228Sstephh fmd_asru_link_t *alp, **alps, **alpp;
9086228Sstephh uint_t alpc, i;
9096228Sstephh
9106228Sstephh (void) pthread_rwlock_rdlock(&ahp->ah_lock);
9116228Sstephh
9126228Sstephh alps = alpp = fmd_alloc(ahp->ah_al_count * sizeof (fmd_asru_link_t *),
9136228Sstephh FMD_SLEEP);
9146228Sstephh alpc = ahp->ah_al_count;
9156228Sstephh
9166228Sstephh for (i = 0; i < ahp->ah_hashlen; i++) {
9176228Sstephh for (alp = ahp->ah_case_hash[i]; alp != NULL;
9186228Sstephh alp = alp->al_case_next)
9196228Sstephh *alpp++ = fmd_asru_al_hold(alp);
9206228Sstephh }
9216228Sstephh
9226228Sstephh ASSERT(alpp == alps + alpc);
9236228Sstephh (void) pthread_rwlock_unlock(&ahp->ah_lock);
9246228Sstephh
9256228Sstephh for (i = 0; i < alpc; i++) {
9266228Sstephh func(alps[i], arg);
9276228Sstephh fmd_asru_al_hash_release(ahp, alps[i]);
9286228Sstephh }
9296228Sstephh
9306228Sstephh fmd_free(alps, alpc * sizeof (fmd_asru_link_t *));
9316228Sstephh }
9326228Sstephh
9336228Sstephh static void
fmd_asru_do_hash_apply(fmd_asru_hash_t * ahp,const char * name,void (* func)(fmd_asru_link_t *,void *),void * arg,fmd_asru_link_t ** hash,size_t match_offset,size_t next_offset)9349728SEric.Schrock@Sun.COM fmd_asru_do_hash_apply(fmd_asru_hash_t *ahp, const char *name,
9356228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg,
9366228Sstephh fmd_asru_link_t **hash, size_t match_offset, size_t next_offset)
9376228Sstephh {
9386228Sstephh fmd_asru_link_t *alp, **alps, **alpp;
9396228Sstephh uint_t alpc = 0, i;
9406228Sstephh uint_t h;
9416228Sstephh
9426228Sstephh (void) pthread_rwlock_rdlock(&ahp->ah_lock);
9436228Sstephh
9446869Seschrock h = fmd_asru_strhash(ahp, name);
9456228Sstephh
9466228Sstephh for (alp = hash[h]; alp != NULL; alp =
9476228Sstephh /* LINTED pointer alignment */
9486228Sstephh FMD_ASRU_AL_HASH_NEXT(alp, next_offset))
9496869Seschrock if (fmd_asru_strcmp(ahp,
9506869Seschrock /* LINTED pointer alignment */
9516869Seschrock FMD_ASRU_AL_HASH_NAME(alp, match_offset), name))
9526228Sstephh alpc++;
9536228Sstephh
9546228Sstephh alps = alpp = fmd_alloc(alpc * sizeof (fmd_asru_link_t *), FMD_SLEEP);
9556228Sstephh
9566228Sstephh for (alp = hash[h]; alp != NULL; alp =
9576228Sstephh /* LINTED pointer alignment */
9586228Sstephh FMD_ASRU_AL_HASH_NEXT(alp, next_offset))
9596869Seschrock if (fmd_asru_strcmp(ahp,
9606869Seschrock /* LINTED pointer alignment */
9616869Seschrock FMD_ASRU_AL_HASH_NAME(alp, match_offset), name))
9626228Sstephh *alpp++ = fmd_asru_al_hold(alp);
9636228Sstephh
9646228Sstephh ASSERT(alpp == alps + alpc);
9656228Sstephh (void) pthread_rwlock_unlock(&ahp->ah_lock);
9666228Sstephh
9676228Sstephh for (i = 0; i < alpc; i++) {
9686228Sstephh func(alps[i], arg);
9696228Sstephh fmd_asru_al_hash_release(ahp, alps[i]);
9706228Sstephh }
9716228Sstephh
9726228Sstephh fmd_free(alps, alpc * sizeof (fmd_asru_link_t *));
9736228Sstephh }
9746228Sstephh
9756228Sstephh void
fmd_asru_hash_apply_by_asru(fmd_asru_hash_t * ahp,const char * name,void (* func)(fmd_asru_link_t *,void *),void * arg)9769728SEric.Schrock@Sun.COM fmd_asru_hash_apply_by_asru(fmd_asru_hash_t *ahp, const char *name,
9776228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg)
9786228Sstephh {
9796228Sstephh fmd_asru_do_hash_apply(ahp, name, func, arg, ahp->ah_asru_hash,
9806228Sstephh offsetof(fmd_asru_link_t, al_asru_name),
9816228Sstephh offsetof(fmd_asru_link_t, al_asru_next));
9826228Sstephh }
9836228Sstephh
9846228Sstephh void
fmd_asru_hash_apply_by_case(fmd_asru_hash_t * ahp,fmd_case_t * cp,void (* func)(fmd_asru_link_t *,void *),void * arg)9856228Sstephh fmd_asru_hash_apply_by_case(fmd_asru_hash_t *ahp, fmd_case_t *cp,
9866228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg)
9876228Sstephh {
9886228Sstephh fmd_asru_do_hash_apply(ahp, ((fmd_case_impl_t *)cp)->ci_uuid, func, arg,
9896228Sstephh ahp->ah_case_hash, offsetof(fmd_asru_link_t, al_case_uuid),
9906228Sstephh offsetof(fmd_asru_link_t, al_case_next));
9916228Sstephh }
9926228Sstephh
9936228Sstephh void
fmd_asru_hash_apply_by_fru(fmd_asru_hash_t * ahp,const char * name,void (* func)(fmd_asru_link_t *,void *),void * arg)9949728SEric.Schrock@Sun.COM fmd_asru_hash_apply_by_fru(fmd_asru_hash_t *ahp, const char *name,
9956228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg)
9966228Sstephh {
9976228Sstephh fmd_asru_do_hash_apply(ahp, name, func, arg, ahp->ah_fru_hash,
9986228Sstephh offsetof(fmd_asru_link_t, al_fru_name),
9996228Sstephh offsetof(fmd_asru_link_t, al_fru_next));
10006228Sstephh }
10016228Sstephh
10026228Sstephh void
fmd_asru_hash_apply_by_rsrc(fmd_asru_hash_t * ahp,const char * name,void (* func)(fmd_asru_link_t *,void *),void * arg)10039728SEric.Schrock@Sun.COM fmd_asru_hash_apply_by_rsrc(fmd_asru_hash_t *ahp, const char *name,
10046228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg)
10056228Sstephh {
10066228Sstephh fmd_asru_do_hash_apply(ahp, name, func, arg, ahp->ah_rsrc_hash,
10076228Sstephh offsetof(fmd_asru_link_t, al_rsrc_name),
10086228Sstephh offsetof(fmd_asru_link_t, al_rsrc_next));
10096228Sstephh }
10106228Sstephh
10116228Sstephh void
fmd_asru_hash_apply_by_label(fmd_asru_hash_t * ahp,const char * name,void (* func)(fmd_asru_link_t *,void *),void * arg)10129728SEric.Schrock@Sun.COM fmd_asru_hash_apply_by_label(fmd_asru_hash_t *ahp, const char *name,
10136228Sstephh void (*func)(fmd_asru_link_t *, void *), void *arg)
10146228Sstephh {
10156228Sstephh fmd_asru_do_hash_apply(ahp, name, func, arg, ahp->ah_label_hash,
10166228Sstephh offsetof(fmd_asru_link_t, al_label),
10176228Sstephh offsetof(fmd_asru_link_t, al_label_next));
10186228Sstephh }
10196228Sstephh
10200Sstevel@tonic-gate /*
10210Sstevel@tonic-gate * Lookup an asru in the hash by name and place a hold on it. If the asru is
10220Sstevel@tonic-gate * not found, no entry is created and NULL is returned.
10230Sstevel@tonic-gate */
10240Sstevel@tonic-gate fmd_asru_t *
fmd_asru_hash_lookup_name(fmd_asru_hash_t * ahp,const char * name)10250Sstevel@tonic-gate fmd_asru_hash_lookup_name(fmd_asru_hash_t *ahp, const char *name)
10260Sstevel@tonic-gate {
10270Sstevel@tonic-gate fmd_asru_t *ap;
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&ahp->ah_lock);
10300Sstevel@tonic-gate ap = fmd_asru_hash_lookup(ahp, name);
10310Sstevel@tonic-gate (void) pthread_rwlock_unlock(&ahp->ah_lock);
10320Sstevel@tonic-gate
10330Sstevel@tonic-gate return (ap);
10340Sstevel@tonic-gate }
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate /*
10376228Sstephh * Create a resource cache entry using the fault event "nvl" for one of the
10386228Sstephh * suspects from the case "cp".
10396228Sstephh *
10406228Sstephh * The fault event can have the following components : FM_FAULT_ASRU,
10416228Sstephh * FM_FAULT_FRU, FM_FAULT_RESOURCE. These should be set by the Diagnosis Engine
10426228Sstephh * when calling fmd_nvl_create_fault(). In the general case, these are all
10436228Sstephh * optional and an entry will always be added into the cache even if one or all
10446228Sstephh * of these fields is missing.
10456228Sstephh *
10466228Sstephh * However, for hardware faults the recommended practice is that the fault
10476228Sstephh * event should always have the FM_FAULT_RESOURCE field present and that this
10486228Sstephh * should be represented in hc-scheme.
10496228Sstephh *
10506228Sstephh * Currently the DE should also add the FM_FAULT_ASRU and FM_FAULT_FRU fields
10516228Sstephh * where known, though at some future stage fmd might be able to fill these
10526228Sstephh * in automatically from the topology.
10536228Sstephh */
10546228Sstephh fmd_asru_link_t *
fmd_asru_hash_create_entry(fmd_asru_hash_t * ahp,fmd_case_t * cp,nvlist_t * nvl)10556228Sstephh fmd_asru_hash_create_entry(fmd_asru_hash_t *ahp, fmd_case_t *cp, nvlist_t *nvl)
10566228Sstephh {
10576228Sstephh char *parsed_uuid;
10586228Sstephh uuid_t uuid;
10596228Sstephh int uuidlen;
10606228Sstephh fmd_asru_link_t *alp;
10610Sstevel@tonic-gate
10620Sstevel@tonic-gate /*
10636228Sstephh * Generate a UUID for the ASRU. libuuid cleverly gives us no
10646228Sstephh * interface for specifying or learning the buffer size. Sigh.
10656228Sstephh * The spec says 36 bytes but we use a tunable just to be safe.
10660Sstevel@tonic-gate */
10676228Sstephh (void) fmd_conf_getprop(fmd.d_conf, "uuidlen", &uuidlen);
10686228Sstephh parsed_uuid = fmd_zalloc(uuidlen + 1, FMD_SLEEP);
10696228Sstephh uuid_generate(uuid);
10706228Sstephh uuid_unparse(uuid, parsed_uuid);
10710Sstevel@tonic-gate
10726228Sstephh /*
10736228Sstephh * Now create the resource cache entries.
10746228Sstephh */
10756228Sstephh fmd_case_hold_locked(cp);
10766228Sstephh alp = fmd_asru_al_create(ahp, nvl, cp, parsed_uuid);
10776228Sstephh TRACE((FMD_DBG_ASRU, "asru %s created as %p",
10786228Sstephh alp->al_uuid, (void *)alp->al_asru));
10790Sstevel@tonic-gate
10806228Sstephh fmd_free(parsed_uuid, uuidlen + 1);
10816228Sstephh return (alp);
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate /*
10860Sstevel@tonic-gate * Release the reference count on an asru obtained using fmd_asru_hash_lookup.
10870Sstevel@tonic-gate * We take 'ahp' for symmetry and in case we need to use it in future work.
10880Sstevel@tonic-gate */
10890Sstevel@tonic-gate /*ARGSUSED*/
10900Sstevel@tonic-gate void
fmd_asru_hash_release(fmd_asru_hash_t * ahp,fmd_asru_t * ap)10910Sstevel@tonic-gate fmd_asru_hash_release(fmd_asru_hash_t *ahp, fmd_asru_t *ap)
10920Sstevel@tonic-gate {
10930Sstevel@tonic-gate (void) pthread_mutex_lock(&ap->asru_lock);
10940Sstevel@tonic-gate
10950Sstevel@tonic-gate ASSERT(ap->asru_refs != 0);
10960Sstevel@tonic-gate if (--ap->asru_refs == 0)
10970Sstevel@tonic-gate fmd_asru_destroy(ap);
10980Sstevel@tonic-gate else
10990Sstevel@tonic-gate (void) pthread_mutex_unlock(&ap->asru_lock);
11000Sstevel@tonic-gate }
11010Sstevel@tonic-gate
11026228Sstephh static void
fmd_asru_do_delete_entry(fmd_asru_hash_t * ahp,fmd_case_t * cp,fmd_asru_link_t ** hash,size_t next_offset,char * name)11036228Sstephh fmd_asru_do_delete_entry(fmd_asru_hash_t *ahp, fmd_case_t *cp,
11046228Sstephh fmd_asru_link_t **hash, size_t next_offset, char *name)
11050Sstevel@tonic-gate {
11060Sstevel@tonic-gate uint_t h;
11076228Sstephh fmd_asru_link_t *alp, **pp, *alpnext, **alpnextp;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&ahp->ah_lock);
11106869Seschrock h = fmd_asru_strhash(ahp, name);
11116228Sstephh pp = &hash[h];
11126228Sstephh for (alp = *pp; alp != NULL; alp = alpnext) {
11136228Sstephh /* LINTED pointer alignment */
11146228Sstephh alpnextp = FMD_ASRU_AL_HASH_NEXTP(alp, next_offset);
11156228Sstephh alpnext = *alpnextp;
11166228Sstephh if (alp->al_case == cp) {
11176228Sstephh *pp = *alpnextp;
11186228Sstephh *alpnextp = NULL;
11196228Sstephh } else
11206228Sstephh pp = alpnextp;
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate (void) pthread_rwlock_unlock(&ahp->ah_lock);
11230Sstevel@tonic-gate }
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate static void
fmd_asru_do_hash_delete(fmd_asru_hash_t * ahp,fmd_case_susp_t * cis,fmd_case_t * cp,fmd_asru_link_t ** hash,size_t next_offset,char * nvname)11266228Sstephh fmd_asru_do_hash_delete(fmd_asru_hash_t *ahp, fmd_case_susp_t *cis,
11276228Sstephh fmd_case_t *cp, fmd_asru_link_t **hash, size_t next_offset, char *nvname)
11286228Sstephh {
11296228Sstephh nvlist_t *nvl;
11306228Sstephh char *name = NULL;
11316228Sstephh ssize_t namelen;
11326228Sstephh
11336228Sstephh if (nvlist_lookup_nvlist(cis->cis_nvl, nvname, &nvl) == 0 &&
11346228Sstephh (namelen = fmd_fmri_nvl2str(nvl, NULL, 0)) != -1 &&
11356228Sstephh (name = fmd_alloc(namelen + 1, FMD_SLEEP)) != NULL) {
11366228Sstephh if (fmd_fmri_nvl2str(nvl, name, namelen + 1) != -1)
11376228Sstephh fmd_asru_do_delete_entry(ahp, cp, hash, next_offset,
11386228Sstephh name);
11396228Sstephh fmd_free(name, namelen + 1);
11406228Sstephh } else
11416228Sstephh fmd_asru_do_delete_entry(ahp, cp, hash, next_offset, "");
11426228Sstephh }
11436228Sstephh
11446228Sstephh void
fmd_asru_hash_delete_case(fmd_asru_hash_t * ahp,fmd_case_t * cp)11456228Sstephh fmd_asru_hash_delete_case(fmd_asru_hash_t *ahp, fmd_case_t *cp)
11460Sstevel@tonic-gate {
11476228Sstephh fmd_case_impl_t *cip = (fmd_case_impl_t *)cp;
11486228Sstephh fmd_case_susp_t *cis;
11496228Sstephh fmd_asru_link_t *alp, **plp, *alpnext;
11506228Sstephh fmd_asru_t *ap;
11516228Sstephh char path[PATH_MAX];
11526228Sstephh char *label;
11536228Sstephh uint_t h;
11546228Sstephh
11556228Sstephh /*
11566228Sstephh * first delete hash entries for each suspect
11576228Sstephh */
11586228Sstephh for (cis = cip->ci_suspects; cis != NULL; cis = cis->cis_next) {
11596228Sstephh fmd_asru_do_hash_delete(ahp, cis, cp, ahp->ah_fru_hash,
11606228Sstephh offsetof(fmd_asru_link_t, al_fru_next), FM_FAULT_FRU);
11616228Sstephh fmd_asru_do_hash_delete(ahp, cis, cp, ahp->ah_rsrc_hash,
11626228Sstephh offsetof(fmd_asru_link_t, al_rsrc_next), FM_FAULT_RESOURCE);
11636228Sstephh if (nvlist_lookup_string(cis->cis_nvl, FM_FAULT_LOCATION,
11646228Sstephh &label) != 0)
11656228Sstephh label = "";
11666228Sstephh fmd_asru_do_delete_entry(ahp, cp, ahp->ah_label_hash,
11676228Sstephh offsetof(fmd_asru_link_t, al_label_next), label);
11686228Sstephh fmd_asru_do_hash_delete(ahp, cis, cp, ahp->ah_asru_hash,
11696228Sstephh offsetof(fmd_asru_link_t, al_asru_next), FM_FAULT_ASRU);
11706228Sstephh }
11716228Sstephh
11726228Sstephh /*
11736228Sstephh * then delete associated case hash entries
11746228Sstephh */
11756228Sstephh (void) pthread_rwlock_wrlock(&ahp->ah_lock);
11766869Seschrock h = fmd_asru_strhash(ahp, cip->ci_uuid);
11776228Sstephh plp = &ahp->ah_case_hash[h];
11786228Sstephh for (alp = *plp; alp != NULL; alp = alpnext) {
11796228Sstephh alpnext = alp->al_case_next;
11806228Sstephh if (alp->al_case == cp) {
11816228Sstephh *plp = alp->al_case_next;
11826228Sstephh alp->al_case_next = NULL;
11836228Sstephh ASSERT(ahp->ah_al_count != 0);
11846228Sstephh ahp->ah_al_count--;
11856228Sstephh
11866228Sstephh /*
11876228Sstephh * decrement case ref.
11886228Sstephh */
11896228Sstephh fmd_case_rele_locked(cp);
11906228Sstephh alp->al_case = NULL;
11916228Sstephh
11926228Sstephh /*
11936228Sstephh * If we found a matching ASRU, unlink its log file and
11946228Sstephh * then release the hash entry. Note that it may still
11956228Sstephh * be referenced if another thread is manipulating it;
11966228Sstephh * this is ok because once we unlink, the log file will
11976228Sstephh * not be restored, and the log data will be freed when
11986228Sstephh * all of the referencing threads release their
11996228Sstephh * respective references.
12006228Sstephh */
12016228Sstephh (void) snprintf(path, sizeof (path), "%s/%s",
12026228Sstephh ahp->ah_dirpath, alp->al_uuid);
12039120SStephen.Hanson@Sun.COM if (cip->ci_xprt == NULL && unlink(path) != 0)
12046228Sstephh fmd_error(EFMD_ASRU_UNLINK,
12056228Sstephh "failed to unlink asru %s", path);
12066228Sstephh
12076228Sstephh /*
12086228Sstephh * Now unlink from the global per-resource cache
12096228Sstephh * and if this is the last link then remove that from
12106228Sstephh * it's own hash too.
12116228Sstephh */
12126228Sstephh ap = alp->al_asru;
12136228Sstephh (void) pthread_mutex_lock(&ap->asru_lock);
12146228Sstephh fmd_list_delete(&ap->asru_list, alp);
12156228Sstephh if (ap->asru_list.l_next == NULL) {
12166228Sstephh uint_t h;
12176228Sstephh fmd_asru_t *ap2, **pp;
12186228Sstephh fmd_asru_t *apnext, **apnextp;
12196228Sstephh
12206228Sstephh ASSERT(ahp->ah_count != 0);
12216228Sstephh ahp->ah_count--;
12226869Seschrock h = fmd_asru_strhash(ahp, ap->asru_name);
12236869Seschrock pp = &ahp->ah_hash[h];
12246228Sstephh for (ap2 = *pp; ap2 != NULL; ap2 = apnext) {
12256228Sstephh apnextp = &ap2->asru_next;
12266228Sstephh apnext = *apnextp;
12276228Sstephh if (ap2 == ap) {
12286228Sstephh *pp = *apnextp;
12296228Sstephh *apnextp = NULL;
12306228Sstephh } else
12316228Sstephh pp = apnextp;
12326228Sstephh }
12336228Sstephh }
12346228Sstephh (void) pthread_mutex_unlock(&ap->asru_lock);
12356228Sstephh fmd_asru_al_hash_release(ahp, alp);
12366228Sstephh } else
12376228Sstephh plp = &alp->al_case_next;
12386228Sstephh }
12396228Sstephh (void) pthread_rwlock_unlock(&ahp->ah_lock);
12406228Sstephh }
12416228Sstephh
12429120SStephen.Hanson@Sun.COM typedef struct {
12439120SStephen.Hanson@Sun.COM nvlist_t *farc_parent_fmri;
12449120SStephen.Hanson@Sun.COM uint8_t farc_reason;
12459120SStephen.Hanson@Sun.COM } fmd_asru_farc_t;
12466228Sstephh
12479120SStephen.Hanson@Sun.COM static void
fmd_asru_repair_containee(fmd_asru_link_t * alp,void * arg)12489120SStephen.Hanson@Sun.COM fmd_asru_repair_containee(fmd_asru_link_t *alp, void *arg)
12496228Sstephh {
12509120SStephen.Hanson@Sun.COM fmd_asru_farc_t *farcp = (fmd_asru_farc_t *)arg;
12516228Sstephh
12529120SStephen.Hanson@Sun.COM if ((alp->al_asru->asru_flags & FMD_ASRU_INVISIBLE) &&
12539120SStephen.Hanson@Sun.COM alp->al_asru_fmri &&
12549120SStephen.Hanson@Sun.COM fmd_fmri_contains(farcp->farc_parent_fmri, alp->al_asru_fmri) > 0) {
12559120SStephen.Hanson@Sun.COM if (fmd_asru_clrflags(alp, FMD_ASRU_FAULTY,
12569120SStephen.Hanson@Sun.COM farcp->farc_reason)) {
12579120SStephen.Hanson@Sun.COM if (alp->al_flags & FMD_ASRU_PROXY)
12589120SStephen.Hanson@Sun.COM fmd_case_xprt_updated(alp->al_case);
12599120SStephen.Hanson@Sun.COM else
12609120SStephen.Hanson@Sun.COM fmd_case_update(alp->al_case);
12619120SStephen.Hanson@Sun.COM }
12626228Sstephh }
12636228Sstephh }
12646228Sstephh
12656228Sstephh static void
fmd_asru_do_repair_containees(fmd_asru_link_t * alp,uint8_t reason)12669120SStephen.Hanson@Sun.COM fmd_asru_do_repair_containees(fmd_asru_link_t *alp, uint8_t reason)
12677275Sstephh {
12687275Sstephh int flags;
12697275Sstephh
12707275Sstephh /*
12719120SStephen.Hanson@Sun.COM * Check if all entries associated with this asru are acquitted and
12729120SStephen.Hanson@Sun.COM * if so acquit containees. Don't try to repair containees on proxy
12739120SStephen.Hanson@Sun.COM * side unless we have local asru.
12747275Sstephh */
12759120SStephen.Hanson@Sun.COM if (alp->al_asru_fmri != NULL && (!(alp->al_flags & FMD_ASRU_PROXY) ||
12769120SStephen.Hanson@Sun.COM (alp->al_flags & FMD_ASRU_PROXY_WITH_ASRU))) {
12779120SStephen.Hanson@Sun.COM (void) pthread_mutex_lock(&alp->al_asru->asru_lock);
12789120SStephen.Hanson@Sun.COM flags = alp->al_asru->asru_flags;
12799120SStephen.Hanson@Sun.COM (void) pthread_mutex_unlock(&alp->al_asru->asru_lock);
12809120SStephen.Hanson@Sun.COM if (!(flags & (FMD_ASRU_FAULTY | FMD_ASRU_INVISIBLE))) {
12819120SStephen.Hanson@Sun.COM fmd_asru_farc_t farc;
12827275Sstephh
12839120SStephen.Hanson@Sun.COM farc.farc_parent_fmri = alp->al_asru_fmri;
12849120SStephen.Hanson@Sun.COM farc.farc_reason = reason;
12859120SStephen.Hanson@Sun.COM fmd_asru_al_hash_apply(fmd.d_asrus,
12869120SStephen.Hanson@Sun.COM fmd_asru_repair_containee, &farc);
12879120SStephen.Hanson@Sun.COM }
12889120SStephen.Hanson@Sun.COM }
12897275Sstephh }
12907275Sstephh
12917275Sstephh void
fmd_asru_repaired(fmd_asru_link_t * alp,void * arg)12929120SStephen.Hanson@Sun.COM fmd_asru_repaired(fmd_asru_link_t *alp, void *arg)
12937275Sstephh {
12949120SStephen.Hanson@Sun.COM int cleared;
12959120SStephen.Hanson@Sun.COM fmd_asru_rep_arg_t *farap = (fmd_asru_rep_arg_t *)arg;
12969120SStephen.Hanson@Sun.COM
12979120SStephen.Hanson@Sun.COM /*
12989120SStephen.Hanson@Sun.COM * don't allow remote repair over readonly transport
12999120SStephen.Hanson@Sun.COM */
13009120SStephen.Hanson@Sun.COM if (alp->al_flags & FMD_ASRU_PROXY_RDONLY)
13019120SStephen.Hanson@Sun.COM return;
13029120SStephen.Hanson@Sun.COM
13039120SStephen.Hanson@Sun.COM /*
13049120SStephen.Hanson@Sun.COM * don't allow repair etc by asru on proxy unless asru is local
13059120SStephen.Hanson@Sun.COM */
13069120SStephen.Hanson@Sun.COM if (farap->fara_bywhat == FARA_BY_ASRU &&
13079120SStephen.Hanson@Sun.COM (alp->al_flags & FMD_ASRU_PROXY) &&
13089120SStephen.Hanson@Sun.COM !(alp->al_flags & FMD_ASRU_PROXY_WITH_ASRU))
13099120SStephen.Hanson@Sun.COM return;
13109120SStephen.Hanson@Sun.COM /*
13119120SStephen.Hanson@Sun.COM * For acquit, need to check both name and uuid if specified
13129120SStephen.Hanson@Sun.COM */
13139120SStephen.Hanson@Sun.COM if (farap->fara_reason == FMD_ASRU_ACQUITTED &&
13149120SStephen.Hanson@Sun.COM farap->fara_rval != NULL && strcmp(farap->fara_uuid, "") != 0 &&
13159120SStephen.Hanson@Sun.COM strcmp(farap->fara_uuid, alp->al_case_uuid) != 0)
13169120SStephen.Hanson@Sun.COM return;
13177275Sstephh
13189120SStephen.Hanson@Sun.COM /*
13199874SStephen.Hanson@Sun.COM * For replaced, verify it has been replaced if we have serial number.
13209874SStephen.Hanson@Sun.COM * If not set *farap->fara_rval to FARA_ERR_RSRCNOTR.
13219120SStephen.Hanson@Sun.COM */
13229120SStephen.Hanson@Sun.COM if (farap->fara_reason == FMD_ASRU_REPLACED &&
13239120SStephen.Hanson@Sun.COM !(alp->al_flags & FMD_ASRU_PROXY_EXTERNAL) &&
13249120SStephen.Hanson@Sun.COM fmd_asru_replacement_state(alp->al_event,
13259120SStephen.Hanson@Sun.COM (alp->al_flags & FMD_ASRU_PROXY) ? HC_ONLY_TRUE : HC_ONLY_FALSE) ==
13269120SStephen.Hanson@Sun.COM FMD_OBJ_STATE_STILL_PRESENT) {
13279874SStephen.Hanson@Sun.COM if (farap->fara_rval)
13289874SStephen.Hanson@Sun.COM *farap->fara_rval = FARA_ERR_RSRCNOTR;
13299120SStephen.Hanson@Sun.COM return;
13309120SStephen.Hanson@Sun.COM }
13319120SStephen.Hanson@Sun.COM
13329120SStephen.Hanson@Sun.COM cleared = fmd_asru_clrflags(alp, FMD_ASRU_FAULTY, farap->fara_reason);
13339120SStephen.Hanson@Sun.COM fmd_asru_do_repair_containees(alp, farap->fara_reason);
13349120SStephen.Hanson@Sun.COM
13359120SStephen.Hanson@Sun.COM /*
13369120SStephen.Hanson@Sun.COM * if called from fmd_adm_*() and we really did clear the bit then
13379120SStephen.Hanson@Sun.COM * we need to do a case update to see if the associated case can be
13389120SStephen.Hanson@Sun.COM * repaired. No need to do this if called from fmd_case_*() (ie
13399120SStephen.Hanson@Sun.COM * when arg is NULL) as the case will be explicitly repaired anyway.
13409120SStephen.Hanson@Sun.COM */
13419120SStephen.Hanson@Sun.COM if (farap->fara_rval) {
13429874SStephen.Hanson@Sun.COM /*
13439874SStephen.Hanson@Sun.COM * *farap->fara_rval defaults to FARA_ERR_RSRCNOTF (not found).
13449874SStephen.Hanson@Sun.COM * If we find a valid cache entry which we repair then we
13459874SStephen.Hanson@Sun.COM * set it to FARA_OK. However we don't want to do this if
13469874SStephen.Hanson@Sun.COM * we have already set it to FARA_ERR_RSRCNOTR (not replaced)
13479874SStephen.Hanson@Sun.COM * in a previous iteration (see above). So only set it to
13489874SStephen.Hanson@Sun.COM * FARA_OK if the current value is still FARA_ERR_RSRCNOTF.
13499874SStephen.Hanson@Sun.COM */
13509874SStephen.Hanson@Sun.COM if (*farap->fara_rval == FARA_ERR_RSRCNOTF)
13519874SStephen.Hanson@Sun.COM *farap->fara_rval = FARA_OK;
13529120SStephen.Hanson@Sun.COM if (cleared) {
13539120SStephen.Hanson@Sun.COM if (alp->al_flags & FMD_ASRU_PROXY)
13549120SStephen.Hanson@Sun.COM fmd_case_xprt_updated(alp->al_case);
13559120SStephen.Hanson@Sun.COM else
13569120SStephen.Hanson@Sun.COM fmd_case_update(alp->al_case);
13579120SStephen.Hanson@Sun.COM }
13589120SStephen.Hanson@Sun.COM }
13599120SStephen.Hanson@Sun.COM }
13609120SStephen.Hanson@Sun.COM
13619120SStephen.Hanson@Sun.COM /*
136210656SStephen.Hanson@Sun.COM * Discard the case associated with this alp if it is in resolved state.
136310656SStephen.Hanson@Sun.COM * Called on "fmadm flush".
136410656SStephen.Hanson@Sun.COM */
136510656SStephen.Hanson@Sun.COM /*ARGSUSED*/
136610656SStephen.Hanson@Sun.COM void
fmd_asru_flush(fmd_asru_link_t * alp,void * arg)136710656SStephen.Hanson@Sun.COM fmd_asru_flush(fmd_asru_link_t *alp, void *arg)
136810656SStephen.Hanson@Sun.COM {
136910656SStephen.Hanson@Sun.COM int check_if_aged = 0;
137010656SStephen.Hanson@Sun.COM int *rval = (int *)arg;
137110656SStephen.Hanson@Sun.COM
137210656SStephen.Hanson@Sun.COM if (alp->al_case)
137310656SStephen.Hanson@Sun.COM fmd_case_discard_resolved(alp->al_case, &check_if_aged);
137410656SStephen.Hanson@Sun.COM *rval = 0;
137510656SStephen.Hanson@Sun.COM }
137610656SStephen.Hanson@Sun.COM
137710656SStephen.Hanson@Sun.COM /*
13789120SStephen.Hanson@Sun.COM * This is only called for proxied faults. Set various flags so we can
13799120SStephen.Hanson@Sun.COM * find the nature of the transport from the resource cache code.
13809120SStephen.Hanson@Sun.COM */
13819120SStephen.Hanson@Sun.COM /*ARGSUSED*/
13829120SStephen.Hanson@Sun.COM void
fmd_asru_set_on_proxy(fmd_asru_link_t * alp,void * arg)13839120SStephen.Hanson@Sun.COM fmd_asru_set_on_proxy(fmd_asru_link_t *alp, void *arg)
13849120SStephen.Hanson@Sun.COM {
13859120SStephen.Hanson@Sun.COM fmd_asru_set_on_proxy_t *entryp = (fmd_asru_set_on_proxy_t *)arg;
13869120SStephen.Hanson@Sun.COM
13879120SStephen.Hanson@Sun.COM if (*entryp->fasp_countp >= entryp->fasp_maxcount)
13887275Sstephh return;
13897275Sstephh
13907275Sstephh /*
13919120SStephen.Hanson@Sun.COM * Note that this is a proxy fault and save whetehr transport is
13929120SStephen.Hanson@Sun.COM * RDONLY or EXTERNAL.
13937275Sstephh */
13949120SStephen.Hanson@Sun.COM alp->al_flags |= FMD_ASRU_PROXY;
13959120SStephen.Hanson@Sun.COM alp->al_asru->asru_flags |= FMD_ASRU_PROXY;
13969120SStephen.Hanson@Sun.COM
13979120SStephen.Hanson@Sun.COM if (entryp->fasp_proxy_external) {
13989120SStephen.Hanson@Sun.COM alp->al_flags |= FMD_ASRU_PROXY_EXTERNAL;
13999120SStephen.Hanson@Sun.COM alp->al_asru->asru_flags |= FMD_ASRU_PROXY_EXTERNAL;
14009120SStephen.Hanson@Sun.COM }
14019120SStephen.Hanson@Sun.COM
14029120SStephen.Hanson@Sun.COM if (entryp->fasp_proxy_rdonly)
14039120SStephen.Hanson@Sun.COM alp->al_flags |= FMD_ASRU_PROXY_RDONLY;
14047275Sstephh
14057275Sstephh /*
14069120SStephen.Hanson@Sun.COM * Save whether asru is accessible in local domain
14077275Sstephh */
14089120SStephen.Hanson@Sun.COM if (entryp->fasp_proxy_asru[*entryp->fasp_countp]) {
14099120SStephen.Hanson@Sun.COM alp->al_flags |= FMD_ASRU_PROXY_WITH_ASRU;
14109120SStephen.Hanson@Sun.COM alp->al_asru->asru_flags |= FMD_ASRU_PROXY_WITH_ASRU;
14119120SStephen.Hanson@Sun.COM }
14129120SStephen.Hanson@Sun.COM (*entryp->fasp_countp)++;
14139120SStephen.Hanson@Sun.COM }
14147275Sstephh
14159120SStephen.Hanson@Sun.COM /*ARGSUSED*/
14169120SStephen.Hanson@Sun.COM void
fmd_asru_update_containees(fmd_asru_link_t * alp,void * arg)14179120SStephen.Hanson@Sun.COM fmd_asru_update_containees(fmd_asru_link_t *alp, void *arg)
14189120SStephen.Hanson@Sun.COM {
14199120SStephen.Hanson@Sun.COM fmd_asru_do_repair_containees(alp, alp->al_reason);
14207275Sstephh }
14217275Sstephh
14229120SStephen.Hanson@Sun.COM /*
14239120SStephen.Hanson@Sun.COM * This function is used for fault proxying. It updates the resource status in
14249120SStephen.Hanson@Sun.COM * the resource cache based on information that has come from the other side of
14259120SStephen.Hanson@Sun.COM * the transport. This can be called on either the proxy side or the
14269120SStephen.Hanson@Sun.COM * diagnosing side.
14279120SStephen.Hanson@Sun.COM */
14289120SStephen.Hanson@Sun.COM void
fmd_asru_update_status(fmd_asru_link_t * alp,void * arg)14299120SStephen.Hanson@Sun.COM fmd_asru_update_status(fmd_asru_link_t *alp, void *arg)
14307275Sstephh {
14319120SStephen.Hanson@Sun.COM fmd_asru_update_status_t *entryp = (fmd_asru_update_status_t *)arg;
14329120SStephen.Hanson@Sun.COM uint8_t status;
14339120SStephen.Hanson@Sun.COM
14349120SStephen.Hanson@Sun.COM if (*entryp->faus_countp >= entryp->faus_maxcount)
14359120SStephen.Hanson@Sun.COM return;
14369120SStephen.Hanson@Sun.COM
14379120SStephen.Hanson@Sun.COM status = entryp->faus_ba[*entryp->faus_countp];
14387275Sstephh
14399120SStephen.Hanson@Sun.COM /*
14409120SStephen.Hanson@Sun.COM * For proxy, if there is no asru on the proxy side, but there is on
14419120SStephen.Hanson@Sun.COM * the diag side, then take the diag side asru status.
14429120SStephen.Hanson@Sun.COM * For diag, if there is an asru on the proxy side, then take the proxy
14439120SStephen.Hanson@Sun.COM * side asru status.
14449120SStephen.Hanson@Sun.COM */
14459120SStephen.Hanson@Sun.COM if (entryp->faus_is_proxy ?
14469120SStephen.Hanson@Sun.COM (entryp->faus_diag_asru[*entryp->faus_countp] &&
14479120SStephen.Hanson@Sun.COM !entryp->faus_proxy_asru[*entryp->faus_countp]) :
14489120SStephen.Hanson@Sun.COM entryp->faus_proxy_asru[*entryp->faus_countp]) {
14499120SStephen.Hanson@Sun.COM if (status & FM_SUSPECT_DEGRADED)
14509120SStephen.Hanson@Sun.COM alp->al_flags |= FMD_ASRU_DEGRADED;
14519120SStephen.Hanson@Sun.COM else
14529120SStephen.Hanson@Sun.COM alp->al_flags &= ~FMD_ASRU_DEGRADED;
14539120SStephen.Hanson@Sun.COM if (status & FM_SUSPECT_UNUSABLE)
14549120SStephen.Hanson@Sun.COM (void) fmd_asru_setflags(alp, FMD_ASRU_UNUSABLE);
14559120SStephen.Hanson@Sun.COM else
14569120SStephen.Hanson@Sun.COM (void) fmd_asru_clrflags(alp, FMD_ASRU_UNUSABLE, 0);
14579120SStephen.Hanson@Sun.COM }
14587275Sstephh
14597275Sstephh /*
14609120SStephen.Hanson@Sun.COM * Update the faulty status too.
14617275Sstephh */
14629120SStephen.Hanson@Sun.COM if (!(status & FM_SUSPECT_FAULTY))
14639120SStephen.Hanson@Sun.COM (void) fmd_asru_clrflags(alp, FMD_ASRU_FAULTY,
14649120SStephen.Hanson@Sun.COM (status & FM_SUSPECT_REPAIRED) ? FMD_ASRU_REPAIRED :
14659120SStephen.Hanson@Sun.COM (status & FM_SUSPECT_REPLACED) ? FMD_ASRU_REPLACED :
14669120SStephen.Hanson@Sun.COM (status & FM_SUSPECT_ACQUITTED) ? FMD_ASRU_ACQUITTED :
14679120SStephen.Hanson@Sun.COM FMD_ASRU_REMOVED);
14689120SStephen.Hanson@Sun.COM else if (entryp->faus_is_proxy)
14699120SStephen.Hanson@Sun.COM (void) fmd_asru_setflags(alp, FMD_ASRU_FAULTY);
14707275Sstephh
14717275Sstephh /*
14729120SStephen.Hanson@Sun.COM * for proxy only, update the present status too.
14737275Sstephh */
14749120SStephen.Hanson@Sun.COM if (entryp->faus_is_proxy) {
14759120SStephen.Hanson@Sun.COM if (!(status & FM_SUSPECT_NOT_PRESENT)) {
14769120SStephen.Hanson@Sun.COM alp->al_flags |= FMD_ASRU_PRESENT;
14779120SStephen.Hanson@Sun.COM alp->al_asru->asru_flags |= FMD_ASRU_PRESENT;
14789120SStephen.Hanson@Sun.COM } else {
14799120SStephen.Hanson@Sun.COM alp->al_flags &= ~FMD_ASRU_PRESENT;
14809120SStephen.Hanson@Sun.COM alp->al_asru->asru_flags &= ~FMD_ASRU_PRESENT;
14819120SStephen.Hanson@Sun.COM }
14829120SStephen.Hanson@Sun.COM }
14839120SStephen.Hanson@Sun.COM (*entryp->faus_countp)++;
14849120SStephen.Hanson@Sun.COM }
14859120SStephen.Hanson@Sun.COM
14869120SStephen.Hanson@Sun.COM /*
14879120SStephen.Hanson@Sun.COM * This function is called on the diagnosing side when fault proxying is
14889120SStephen.Hanson@Sun.COM * in use and the proxy has sent a uuclose. It updates the status of the
14899120SStephen.Hanson@Sun.COM * resource cache entries.
14909120SStephen.Hanson@Sun.COM */
14919120SStephen.Hanson@Sun.COM void
fmd_asru_close_status(fmd_asru_link_t * alp,void * arg)14929120SStephen.Hanson@Sun.COM fmd_asru_close_status(fmd_asru_link_t *alp, void *arg)
14939120SStephen.Hanson@Sun.COM {
14949120SStephen.Hanson@Sun.COM fmd_asru_close_status_t *entryp = (fmd_asru_close_status_t *)arg;
14959120SStephen.Hanson@Sun.COM
14969120SStephen.Hanson@Sun.COM if (*entryp->facs_countp >= entryp->facs_maxcount)
14979120SStephen.Hanson@Sun.COM return;
14989120SStephen.Hanson@Sun.COM alp->al_flags &= ~FMD_ASRU_DEGRADED;
14999120SStephen.Hanson@Sun.COM (void) fmd_asru_setflags(alp, FMD_ASRU_UNUSABLE);
15009120SStephen.Hanson@Sun.COM (*entryp->facs_countp)++;
15017275Sstephh }
15027275Sstephh
15037275Sstephh static void
fmd_asru_logevent(fmd_asru_link_t * alp)15046228Sstephh fmd_asru_logevent(fmd_asru_link_t *alp)
15056228Sstephh {
15066228Sstephh fmd_asru_t *ap = alp->al_asru;
15077275Sstephh boolean_t faulty = (alp->al_flags & FMD_ASRU_FAULTY) != 0;
15087275Sstephh boolean_t unusable = (alp->al_flags & FMD_ASRU_UNUSABLE) != 0;
15097275Sstephh boolean_t message = (ap->asru_flags & FMD_ASRU_INVISIBLE) == 0;
15107275Sstephh boolean_t repaired = (alp->al_reason == FMD_ASRU_REPAIRED);
15117275Sstephh boolean_t replaced = (alp->al_reason == FMD_ASRU_REPLACED);
15127275Sstephh boolean_t acquitted = (alp->al_reason == FMD_ASRU_ACQUITTED);
15130Sstevel@tonic-gate
15141193Smws fmd_case_impl_t *cip;
15150Sstevel@tonic-gate fmd_event_t *e;
15160Sstevel@tonic-gate fmd_log_t *lp;
15170Sstevel@tonic-gate nvlist_t *nvl;
15180Sstevel@tonic-gate char *class;
15190Sstevel@tonic-gate
15200Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ap->asru_lock));
15216228Sstephh cip = (fmd_case_impl_t *)alp->al_case;
15225255Sstephh ASSERT(cip != NULL);
15230Sstevel@tonic-gate
15249120SStephen.Hanson@Sun.COM /*
15259120SStephen.Hanson@Sun.COM * Don't log to disk on proxy side
15269120SStephen.Hanson@Sun.COM */
15279120SStephen.Hanson@Sun.COM if (cip->ci_xprt != NULL)
15289120SStephen.Hanson@Sun.COM return;
15299120SStephen.Hanson@Sun.COM
15306228Sstephh if ((lp = alp->al_log) == NULL)
15316228Sstephh lp = fmd_log_open(ap->asru_root, alp->al_uuid, FMD_LOG_ASRU);
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate if (lp == NULL)
15340Sstevel@tonic-gate return; /* can't log events if we can't open the log */
15350Sstevel@tonic-gate
15367275Sstephh nvl = fmd_protocol_rsrc_asru(_fmd_asru_events[faulty | (unusable << 1)],
15377275Sstephh alp->al_asru_fmri, cip->ci_uuid, cip->ci_code, faulty, unusable,
15389120SStephen.Hanson@Sun.COM message, alp->al_event, &cip->ci_tv, repaired, replaced, acquitted,
153910656SStephen.Hanson@Sun.COM cip->ci_state == FMD_CASE_RESOLVED, cip->ci_diag_de == NULL ?
154010928SStephen.Hanson@Sun.COM cip->ci_mod->mod_fmri : cip->ci_diag_de, cip->ci_injected == 1);
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate (void) nvlist_lookup_string(nvl, FM_CLASS, &class);
15430Sstevel@tonic-gate e = fmd_event_create(FMD_EVT_PROTOCOL, FMD_HRT_NOW, nvl, class);
15440Sstevel@tonic-gate
15450Sstevel@tonic-gate fmd_event_hold(e);
15460Sstevel@tonic-gate fmd_log_append(lp, e, NULL);
15470Sstevel@tonic-gate fmd_event_rele(e);
15480Sstevel@tonic-gate
15490Sstevel@tonic-gate /*
15500Sstevel@tonic-gate * For now, we close the log file after every update to conserve file
15510Sstevel@tonic-gate * descriptors and daemon overhead. If this becomes a performance
15520Sstevel@tonic-gate * issue this code can change to keep a fixed-size LRU cache of logs.
15530Sstevel@tonic-gate */
15540Sstevel@tonic-gate fmd_log_rele(lp);
15556228Sstephh alp->al_log = NULL;
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate int
fmd_asru_setflags(fmd_asru_link_t * alp,uint_t sflag)15596228Sstephh fmd_asru_setflags(fmd_asru_link_t *alp, uint_t sflag)
15600Sstevel@tonic-gate {
15616228Sstephh fmd_asru_t *ap = alp->al_asru;
15620Sstevel@tonic-gate uint_t nstate, ostate;
15630Sstevel@tonic-gate
15640Sstevel@tonic-gate ASSERT(!(sflag & ~FMD_ASRU_STATE));
15650Sstevel@tonic-gate ASSERT(sflag != FMD_ASRU_STATE);
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate (void) pthread_mutex_lock(&ap->asru_lock);
15680Sstevel@tonic-gate
15696228Sstephh ostate = alp->al_flags & FMD_ASRU_STATE;
15706228Sstephh alp->al_flags |= sflag;
15716228Sstephh nstate = alp->al_flags & FMD_ASRU_STATE;
15726228Sstephh
15736228Sstephh if (nstate == ostate) {
15746228Sstephh (void) pthread_mutex_unlock(&ap->asru_lock);
15756228Sstephh return (0);
15766228Sstephh }
15776228Sstephh
15786228Sstephh ap->asru_flags |= sflag;
15796228Sstephh TRACE((FMD_DBG_ASRU, "asru %s %s->%s", alp->al_uuid,
15806228Sstephh _fmd_asru_snames[ostate], _fmd_asru_snames[nstate]));
15816228Sstephh
15826228Sstephh fmd_asru_logevent(alp);
15836228Sstephh
15846228Sstephh (void) pthread_cond_broadcast(&ap->asru_cv);
15856228Sstephh (void) pthread_mutex_unlock(&ap->asru_lock);
15866228Sstephh return (1);
15876228Sstephh }
15886228Sstephh
15896228Sstephh int
fmd_asru_clrflags(fmd_asru_link_t * alp,uint_t sflag,uint8_t reason)15907275Sstephh fmd_asru_clrflags(fmd_asru_link_t *alp, uint_t sflag, uint8_t reason)
15916228Sstephh {
15926228Sstephh fmd_asru_t *ap = alp->al_asru;
15936228Sstephh fmd_asru_link_t *nalp;
15946228Sstephh uint_t nstate, ostate, flags = 0;
15956228Sstephh
15966228Sstephh ASSERT(!(sflag & ~FMD_ASRU_STATE));
15976228Sstephh ASSERT(sflag != FMD_ASRU_STATE);
15986228Sstephh
15996228Sstephh (void) pthread_mutex_lock(&ap->asru_lock);
16006228Sstephh
16016228Sstephh ostate = alp->al_flags & FMD_ASRU_STATE;
16026228Sstephh alp->al_flags &= ~sflag;
16036228Sstephh nstate = alp->al_flags & FMD_ASRU_STATE;
16040Sstevel@tonic-gate
16051193Smws if (nstate == ostate) {
160610656SStephen.Hanson@Sun.COM if (reason > alp->al_reason &&
160710656SStephen.Hanson@Sun.COM ((fmd_case_impl_t *)alp->al_case)->ci_state <
160810656SStephen.Hanson@Sun.COM FMD_CASE_REPAIRED) {
16097275Sstephh alp->al_reason = reason;
16107275Sstephh fmd_asru_logevent(alp);
16117275Sstephh (void) pthread_cond_broadcast(&ap->asru_cv);
16127275Sstephh }
16131193Smws (void) pthread_mutex_unlock(&ap->asru_lock);
16141193Smws return (0);
16151193Smws }
16167275Sstephh if (reason > alp->al_reason)
16177275Sstephh alp->al_reason = reason;
16181193Smws
16196228Sstephh if (sflag == FMD_ASRU_UNUSABLE)
16206228Sstephh ap->asru_flags &= ~sflag;
16216228Sstephh else if (sflag == FMD_ASRU_FAULTY) {
16226228Sstephh /*
16236228Sstephh * only clear the faulty bit if all links are clear
16246228Sstephh */
16256228Sstephh for (nalp = fmd_list_next(&ap->asru_list); nalp != NULL;
16266228Sstephh nalp = fmd_list_next(nalp))
16276228Sstephh flags |= nalp->al_flags;
16286228Sstephh if (!(flags & FMD_ASRU_FAULTY))
16296228Sstephh ap->asru_flags &= ~sflag;
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate
16326228Sstephh TRACE((FMD_DBG_ASRU, "asru %s %s->%s", alp->al_uuid,
16331193Smws _fmd_asru_snames[ostate], _fmd_asru_snames[nstate]));
16341193Smws
16356228Sstephh fmd_asru_logevent(alp);
16360Sstevel@tonic-gate
16371193Smws (void) pthread_cond_broadcast(&ap->asru_cv);
16380Sstevel@tonic-gate (void) pthread_mutex_unlock(&ap->asru_lock);
16391193Smws
16406228Sstephh return (1);
16416228Sstephh }
16426228Sstephh
164310656SStephen.Hanson@Sun.COM /*ARGSUSED*/
164410656SStephen.Hanson@Sun.COM void
fmd_asru_log_resolved(fmd_asru_link_t * alp,void * unused)164510656SStephen.Hanson@Sun.COM fmd_asru_log_resolved(fmd_asru_link_t *alp, void *unused)
164610656SStephen.Hanson@Sun.COM {
164710656SStephen.Hanson@Sun.COM fmd_asru_t *ap = alp->al_asru;
164810656SStephen.Hanson@Sun.COM
164910656SStephen.Hanson@Sun.COM (void) pthread_mutex_lock(&ap->asru_lock);
165010656SStephen.Hanson@Sun.COM fmd_asru_logevent(alp);
165110656SStephen.Hanson@Sun.COM (void) pthread_cond_broadcast(&ap->asru_cv);
165210656SStephen.Hanson@Sun.COM (void) pthread_mutex_unlock(&ap->asru_lock);
165310656SStephen.Hanson@Sun.COM }
165410656SStephen.Hanson@Sun.COM
16556228Sstephh /*
16566228Sstephh * Report the current known state of the link entry (ie this particular fault
16576228Sstephh * affecting this particular ASRU).
16586228Sstephh */
16596228Sstephh int
fmd_asru_al_getstate(fmd_asru_link_t * alp)16606228Sstephh fmd_asru_al_getstate(fmd_asru_link_t *alp)
16616228Sstephh {
16629120SStephen.Hanson@Sun.COM int us, st = (alp->al_flags & (FMD_ASRU_FAULTY | FMD_ASRU_UNUSABLE));
16636228Sstephh nvlist_t *asru;
16649120SStephen.Hanson@Sun.COM int ps = FMD_OBJ_STATE_UNKNOWN;
16651193Smws
16669120SStephen.Hanson@Sun.COM /*
16679120SStephen.Hanson@Sun.COM * For fault proxying with an EXTERNAL transport, believe the presence
16689120SStephen.Hanson@Sun.COM * state as sent by the diagnosing side. Otherwise find the presence
16699120SStephen.Hanson@Sun.COM * state here. Note that if fault proxying with an INTERNAL transport
16709120SStephen.Hanson@Sun.COM * we can only trust the presence state where we are using hc-scheme
16719120SStephen.Hanson@Sun.COM * fmris which should be consistant across domains in the same system -
16729120SStephen.Hanson@Sun.COM * other schemes can refer to different devices in different domains.
16739120SStephen.Hanson@Sun.COM */
16749120SStephen.Hanson@Sun.COM if (!(alp->al_flags & FMD_ASRU_PROXY_EXTERNAL)) {
16759120SStephen.Hanson@Sun.COM ps = fmd_asru_replacement_state(alp->al_event, (alp->al_flags &
16769120SStephen.Hanson@Sun.COM FMD_ASRU_PROXY)? HC_ONLY_TRUE : HC_ONLY_FALSE);
16779120SStephen.Hanson@Sun.COM if (ps == FMD_OBJ_STATE_NOT_PRESENT)
16789120SStephen.Hanson@Sun.COM return (st | FMD_ASRU_UNUSABLE);
16799120SStephen.Hanson@Sun.COM if (ps == FMD_OBJ_STATE_REPLACED) {
16809120SStephen.Hanson@Sun.COM if (alp->al_reason < FMD_ASRU_REPLACED)
16819120SStephen.Hanson@Sun.COM alp->al_reason = FMD_ASRU_REPLACED;
16829120SStephen.Hanson@Sun.COM return (st | FMD_ASRU_UNUSABLE);
16839120SStephen.Hanson@Sun.COM }
16847275Sstephh }
16859120SStephen.Hanson@Sun.COM if (ps == FMD_OBJ_STATE_UNKNOWN && (alp->al_flags & FMD_ASRU_PROXY))
16869120SStephen.Hanson@Sun.COM st |= (alp->al_flags & (FMD_ASRU_DEGRADED | FMD_ASRU_PRESENT));
16879120SStephen.Hanson@Sun.COM else
16889120SStephen.Hanson@Sun.COM st |= (alp->al_flags & (FMD_ASRU_DEGRADED)) | FMD_ASRU_PRESENT;
16891552Smws
16909120SStephen.Hanson@Sun.COM /*
16919120SStephen.Hanson@Sun.COM * For fault proxying, unless we have a local ASRU, then believe the
16929120SStephen.Hanson@Sun.COM * service state sent by the diagnosing side. Otherwise find the service
16939120SStephen.Hanson@Sun.COM * state here. Try fmd_fmri_service_state() first, but if that's not
16949120SStephen.Hanson@Sun.COM * supported by the scheme then fall back to fmd_fmri_unusable().
16959120SStephen.Hanson@Sun.COM */
16969120SStephen.Hanson@Sun.COM if ((!(alp->al_flags & FMD_ASRU_PROXY) ||
16979120SStephen.Hanson@Sun.COM (alp->al_flags & FMD_ASRU_PROXY_WITH_ASRU)) &&
16989120SStephen.Hanson@Sun.COM nvlist_lookup_nvlist(alp->al_event, FM_FAULT_ASRU, &asru) == 0) {
16997275Sstephh us = fmd_fmri_service_state(asru);
17007275Sstephh if (us == -1 || us == FMD_SERVICE_STATE_UNKNOWN) {
17017275Sstephh /* not supported by scheme - try fmd_fmri_unusable */
17027275Sstephh us = fmd_fmri_unusable(asru);
17039120SStephen.Hanson@Sun.COM if (us > 0)
17049120SStephen.Hanson@Sun.COM st |= FMD_ASRU_UNUSABLE;
17059120SStephen.Hanson@Sun.COM else if (us == 0)
17069120SStephen.Hanson@Sun.COM st &= ~FMD_ASRU_UNUSABLE;
17079120SStephen.Hanson@Sun.COM } else {
17089120SStephen.Hanson@Sun.COM if (us == FMD_SERVICE_STATE_UNUSABLE) {
17099120SStephen.Hanson@Sun.COM st &= ~FMD_ASRU_DEGRADED;
17109120SStephen.Hanson@Sun.COM st |= FMD_ASRU_UNUSABLE;
17119120SStephen.Hanson@Sun.COM } else if (us == FMD_SERVICE_STATE_OK) {
17129120SStephen.Hanson@Sun.COM st &= ~(FMD_ASRU_DEGRADED | FMD_ASRU_UNUSABLE);
17139120SStephen.Hanson@Sun.COM } else if (us == FMD_SERVICE_STATE_ISOLATE_PENDING) {
17149120SStephen.Hanson@Sun.COM st &= ~(FMD_ASRU_DEGRADED | FMD_ASRU_UNUSABLE);
17159120SStephen.Hanson@Sun.COM } else if (us == FMD_SERVICE_STATE_DEGRADED) {
17169120SStephen.Hanson@Sun.COM st &= ~FMD_ASRU_UNUSABLE;
17179120SStephen.Hanson@Sun.COM st |= FMD_ASRU_DEGRADED;
17189120SStephen.Hanson@Sun.COM }
17197275Sstephh }
17209120SStephen.Hanson@Sun.COM }
17216228Sstephh return (st);
17220Sstevel@tonic-gate }
17230Sstevel@tonic-gate
17240Sstevel@tonic-gate /*
17250Sstevel@tonic-gate * Report the current known state of the ASRU by refreshing its unusable status
17260Sstevel@tonic-gate * based upon the routines provided by the scheme module. If the unusable bit
17270Sstevel@tonic-gate * is different, we do *not* generate a state change here because that change
17280Sstevel@tonic-gate * may be unrelated to fmd activities and therefore we have no case or event.
17290Sstevel@tonic-gate * The absence of the transition is harmless as this function is only provided
17300Sstevel@tonic-gate * for RPC observability and fmd's clients are only concerned with ASRU_FAULTY.
17310Sstevel@tonic-gate */
17320Sstevel@tonic-gate int
fmd_asru_getstate(fmd_asru_t * ap)17330Sstevel@tonic-gate fmd_asru_getstate(fmd_asru_t *ap)
17340Sstevel@tonic-gate {
17359120SStephen.Hanson@Sun.COM int us, st, p = -1;
17369120SStephen.Hanson@Sun.COM char *s;
17370Sstevel@tonic-gate
17389120SStephen.Hanson@Sun.COM /* do not report non-fmd non-present resources */
17399120SStephen.Hanson@Sun.COM if (!(ap->asru_flags & FMD_ASRU_INTERNAL)) {
17409120SStephen.Hanson@Sun.COM /*
17419120SStephen.Hanson@Sun.COM * As with fmd_asru_al_getstate(), we can only trust the
17429120SStephen.Hanson@Sun.COM * local presence state on a proxy if the transport is
17439120SStephen.Hanson@Sun.COM * internal and the scheme is hc. Otherwise we believe the
17449120SStephen.Hanson@Sun.COM * state as sent by the diagnosing side.
17459120SStephen.Hanson@Sun.COM */
17469120SStephen.Hanson@Sun.COM if (!(ap->asru_flags & FMD_ASRU_PROXY) ||
17479120SStephen.Hanson@Sun.COM (!(ap->asru_flags & FMD_ASRU_PROXY_EXTERNAL) &&
17489120SStephen.Hanson@Sun.COM (nvlist_lookup_string(ap->asru_fmri, FM_FMRI_SCHEME,
17499120SStephen.Hanson@Sun.COM &s) == 0 && strcmp(s, FM_FMRI_SCHEME_HC) == 0))) {
17509120SStephen.Hanson@Sun.COM if (fmd_asru_fake_not_present >=
17519120SStephen.Hanson@Sun.COM FMD_OBJ_STATE_REPLACED)
17529120SStephen.Hanson@Sun.COM return (0);
17539120SStephen.Hanson@Sun.COM p = fmd_fmri_present(ap->asru_fmri);
17549120SStephen.Hanson@Sun.COM }
17559120SStephen.Hanson@Sun.COM if (p == 0 || (p < 0 && !(ap->asru_flags & FMD_ASRU_PROXY) ||
17569120SStephen.Hanson@Sun.COM !(ap->asru_flags & FMD_ASRU_PRESENT)))
17579120SStephen.Hanson@Sun.COM return (0);
17589120SStephen.Hanson@Sun.COM }
17590Sstevel@tonic-gate
17609120SStephen.Hanson@Sun.COM /*
17619120SStephen.Hanson@Sun.COM * As with fmd_asru_al_getstate(), we can only trust the local unusable
17629120SStephen.Hanson@Sun.COM * state on a proxy if there is a local ASRU.
17639120SStephen.Hanson@Sun.COM */
17649120SStephen.Hanson@Sun.COM st = ap->asru_flags & (FMD_ASRU_FAULTY | FMD_ASRU_UNUSABLE);
17659120SStephen.Hanson@Sun.COM if (!(ap->asru_flags & FMD_ASRU_PROXY) ||
17669120SStephen.Hanson@Sun.COM (ap->asru_flags & FMD_ASRU_PROXY_WITH_ASRU)) {
17679120SStephen.Hanson@Sun.COM us = fmd_fmri_unusable(ap->asru_fmri);
17689120SStephen.Hanson@Sun.COM if (us > 0)
17699120SStephen.Hanson@Sun.COM st |= FMD_ASRU_UNUSABLE;
17709120SStephen.Hanson@Sun.COM else if (us == 0)
17719120SStephen.Hanson@Sun.COM st &= ~FMD_ASRU_UNUSABLE;
17729120SStephen.Hanson@Sun.COM }
17730Sstevel@tonic-gate return (st);
17740Sstevel@tonic-gate }
1775