Пример #1
0
diskmon_t *
dm_fmri_to_diskmon(fmd_hdl_t *hdl, nvlist_t *fmri)
{
	topo_hdl_t *thdl;
	nvlist_t *dupfmri;
	diskmon_t *diskp;
	char *buf;
	int err;

	if (nvlist_dup(fmri, &dupfmri, 0) != 0)
		return (NULL);

	(void) nvlist_remove(dupfmri, FM_FMRI_HC_REVISION, DATA_TYPE_STRING);
	(void) nvlist_remove(dupfmri, FM_FMRI_HC_SERIAL_ID, DATA_TYPE_STRING);
	(void) nvlist_remove(dupfmri, FM_FMRI_HC_PART, DATA_TYPE_STRING);

	thdl = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
	if (topo_fmri_nvl2str(thdl, dupfmri, &buf, &err) != 0) {
		fmd_hdl_topo_rele(hdl, thdl);
		nvlist_free(dupfmri);
		return (NULL);
	}
	fmd_hdl_topo_rele(hdl, thdl);

	diskp = dm_fmristring_to_diskmon(buf);

	nvlist_free(dupfmri);
	topo_hdl_strfree(thdl, buf);

	return (diskp);
}
Пример #2
0
/*
 * The cmd_dimm_t structure created for a DIMM in a branch never has a
 * Jxxx in its unum; the cmd_dimm_t structure created for a DIMM containing
 * a page, or in a bank (i.e. for ECC errors)-always-has a Jxxx in its
 * unum. Therefore the set of cmd_dimm_t's created for a branch is always
 * disjoint from the set of cmd_dimm_t's created for pages and/or banks, so
 * the cmd_dimm_create will never link a 'branch' cmd_dimm_t into bank.
 * Faulting a DIMM for ECC will not prevent subsequent faulting of "same"
 * dimm for FBR/FBU and vice versa
 */
static int
branch_dimmlist_create(fmd_hdl_t *hdl, cmd_branch_t *branch)
{
	topo_hdl_t *thp;
	topo_walk_t *twp;
	int err, dimm_count;
	cmd_list_t *bp;

	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
		return (0);
	if ((twp = topo_walk_init(thp,
	    FM_FMRI_SCHEME_MEM, branch_dimm_cb, branch, &err))
	    == NULL) {
		fmd_hdl_topo_rele(hdl, thp);
		return (0);
	}
	br_hdl = hdl;
	(void) topo_walk_step(twp, TOPO_WALK_CHILD);
	topo_walk_fini(twp);
	fmd_hdl_topo_rele(hdl, thp);

	for (dimm_count = 0, bp = cmd_list_next(&branch->branch_dimms);
	    bp != NULL; bp = cmd_list_next(bp), dimm_count++)
		;
	return (dimm_count);
}
Пример #3
0
nvlist_t *
cmd_find_dimm_by_sn(fmd_hdl_t *hdl, char *schemename, char *sn)
{
	topo_hdl_t *thp;
	topo_walk_t *twp;
	int err;

	dimm_nvl = NULL;

	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
		return (NULL);
	if (strcmp(schemename, FM_FMRI_SCHEME_MEM) == 0) {
		if ((twp = topo_walk_init(thp,
		    schemename, find_dimm_sn_mem, sn, &err)) == NULL) {
			fmd_hdl_topo_rele(hdl, thp);
			return (NULL);
		}
	} else {
		if ((twp = topo_walk_init(thp,
		    schemename, find_dimm_sn_hc, sn, &err)) == NULL) {
			fmd_hdl_topo_rele(hdl, thp);
			return (NULL);
		}
	}
	(void) topo_walk_step(twp, TOPO_WALK_CHILD);
	topo_walk_fini(twp);
	fmd_hdl_topo_rele(hdl, thp);
	return (dimm_nvl);
}
Пример #4
0
/*
 * Convert a shorthand svc FMRI into a full svc FMRI nvlist
 */
static nvlist_t *
shortfmri_to_fmri(fmd_hdl_t *hdl, const char *shortfmristr)
{
	nvlist_t *ret, *fmri;
	topo_hdl_t *thp;
	char *fmristr;
	int err;

	if ((fmristr = shortfmri_to_fmristr(hdl, shortfmristr)) == NULL)
		return (NULL);

	thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);

	if (topo_fmri_str2nvl(thp, fmristr, &fmri, &err) != 0) {
		fmd_hdl_error(hdl, "failed to convert '%s' to nvlist\n",
		    fmristr);
		fmd_hdl_strfree(hdl, fmristr);
		fmd_hdl_topo_rele(hdl, thp);
		return (NULL);
	}

	fmd_hdl_strfree(hdl, fmristr);

	if ((ret = fmd_nvl_dup(hdl, fmri, FMD_SLEEP)) == NULL) {
		fmd_hdl_error(hdl, "failed to dup fmri\n");
		nvlist_free(fmri);
		fmd_hdl_topo_rele(hdl, thp);
		return (NULL);
	}

	nvlist_free(fmri);
	fmd_hdl_topo_rele(hdl, thp);

	return (ret);
}
Пример #5
0
/*
 * Walk all of the topology nodes looking for DISKs that match the structure
 * described in the overview.  Once we find them, check their fault status
 * and update their fault indiciator accordingly.
 */
static void
dl_examine_topo(disk_lights_t *dl)
{
	int err;
	topo_hdl_t *thp = NULL;
	topo_walk_t *twp = NULL;

	thp = fmd_hdl_topo_hold(dl->dl_fmd, TOPO_VERSION);
	if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, dl_fault_walk_outer,
	    dl, &err)) == NULL) {
		fmd_hdl_error(dl->dl_fmd, "failed to get topology: %s\n",
		    topo_strerror(err));
		goto out;
	}

	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
		fmd_hdl_error(dl->dl_fmd, "failed to walk topology: %s\n",
		    topo_strerror(err));
		goto out;
	}

out:
	if (twp != NULL)
		topo_walk_fini(twp);
	if (thp != NULL)
		fmd_hdl_topo_rele(dl->dl_fmd, thp);
}
Пример #6
0
nvlist_t *
cmd_find_cpu_rsc_by_sn(fmd_hdl_t *hdl, cpuid_t *cpuid)
{
	topo_hdl_t *thp;
	topo_walk_t *twp;
	int err;

	rsc_nvl = NULL;
	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
		return (NULL);
	if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC,
	    find_cpu_rsc_by_sn, cpuid, &err)) == NULL) {
		fmd_hdl_topo_rele(hdl, thp);
		return (NULL);
	}
	(void) topo_walk_step(twp, TOPO_WALK_CHILD);
	topo_walk_fini(twp);
	fmd_hdl_topo_rele(hdl, thp);
	return (rsc_nvl);
}
Пример #7
0
nvlist_t *
init_mb(fmd_hdl_t *hdl)
{
	topo_hdl_t *thp;
	topo_walk_t *twp;
	int err;

	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
		return (NULL);
	if ((twp = topo_walk_init(thp,
	    FM_FMRI_SCHEME_HC, find_mb, NULL, &err))
	    == NULL) {
		fmd_hdl_topo_rele(hdl, thp);
		return (NULL);
	}
	(void) topo_walk_step(twp, TOPO_WALK_CHILD);
	topo_walk_fini(twp);
	fmd_hdl_topo_rele(hdl, thp);
	return (mb_nvl);
}
Пример #8
0
static int
branch_exist(fmd_hdl_t *hdl, cmd_branch_t *branch)
{
	topo_hdl_t *thp;
	topo_walk_t *twp;
	int err;

	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
		return (0);
	if ((twp = topo_walk_init(thp,
	    FM_FMRI_SCHEME_MEM, branch_exist_cb, branch, &err))
	    == NULL) {
		fmd_hdl_topo_rele(hdl, thp);
		return (0);
	}
	br_dimmcount = 0;
	(void) topo_walk_step(twp, TOPO_WALK_CHILD);
	topo_walk_fini(twp);
	fmd_hdl_topo_rele(hdl, thp);

	return (br_dimmcount);
}
Пример #9
0
/*ARGSUSED*/
int
update_configuration_from_topo(fmd_hdl_t *hdl, diskmon_t *diskp)
{
	int err;
	topo_hdl_t *thp;
	topo_walk_t *twp;
	walk_diskmon_t wd;

	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) {
		return (TOPO_OPEN_ERROR);
	}

	wd.target = diskp;
	wd.pfmri = NULL;
	if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, gather_topo_cfg,
	    &wd, &err)) == NULL) {
		fmd_hdl_topo_rele(hdl, thp);
		return (err ? TOPO_WALK_INIT_ERROR : TOPO_SUCCESS);
	}

	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {

		topo_walk_fini(twp);
		if (wd.pfmri != NULL)
			dstrfree(wd.pfmri);

		fmd_hdl_topo_rele(hdl, thp);
		return (TOPO_WALK_ERROR);
	}

	topo_walk_fini(twp);
	fmd_hdl_topo_rele(hdl, thp);
	if (wd.pfmri != NULL)
		dstrfree(wd.pfmri);

	return (TOPO_SUCCESS);
}
Пример #10
0
static nvlist_t *
fru_by_label(fmd_hdl_t *hdl, const char *target)
{
	topo_hdl_t *thp;
	topo_walk_t *twp;
	int err;

	br_memb_nvl = NULL;
	if (((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) &&
	    ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC,
	    fru_by_label_cb, (void *)target, &err)) != NULL)) {
		br_hdl = hdl;
		(void) topo_walk_step(twp, TOPO_WALK_CHILD);
		topo_walk_fini(twp);
	}
	fmd_hdl_topo_rele(hdl, thp);
	return (br_memb_nvl);
}
Пример #11
0
/*
 * Solve a given ZFS case.  This first checks to make sure the diagnosis is
 * still valid, as well as cleaning up any pending timer associated with the
 * case.
 */
static void
zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
    boolean_t checkunusable)
{
	libzfs_handle_t *zhdl = fmd_hdl_getspecific(hdl);
	nvlist_t *detector, *fault;
	boolean_t serialize;
	nvlist_t *fmri, *fru;
	topo_hdl_t *thp;
	int err;

	/*
	 * Construct the detector from the case data.  The detector is in the
	 * ZFS scheme, and is either the pool or the vdev, depending on whether
	 * this is a vdev or pool fault.
	 */
	detector = fmd_nvl_alloc(hdl, FMD_SLEEP);

	(void) nvlist_add_uint8(detector, FM_VERSION, ZFS_SCHEME_VERSION0);
	(void) nvlist_add_string(detector, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS);
	(void) nvlist_add_uint64(detector, FM_FMRI_ZFS_POOL,
	    zcp->zc_data.zc_pool_guid);
	if (zcp->zc_data.zc_vdev_guid != 0) {
		(void) nvlist_add_uint64(detector, FM_FMRI_ZFS_VDEV,
		    zcp->zc_data.zc_vdev_guid);
	}

	/*
	 * We also want to make sure that the detector (pool or vdev) properly
	 * reflects the diagnosed state, when the fault corresponds to internal
	 * ZFS state (i.e. not checksum or I/O error-induced).  Otherwise, a
	 * device which was unavailable early in boot (because the driver/file
	 * wasn't available) and is now healthy will be mis-diagnosed.
	 */
	if (!fmd_nvl_fmri_present(hdl, detector) ||
	    (checkunusable && !fmd_nvl_fmri_unusable(hdl, detector))) {
		fmd_case_close(hdl, zcp->zc_case);
		nvlist_free(detector);
		return;
	}


	fru = NULL;
	if (zcp->zc_fru != NULL &&
	    (thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) {
		/*
		 * If the vdev had an associated FRU, then get the FRU nvlist
		 * from the topo handle and use that in the suspect list.  We
		 * explicitly lookup the FRU because the fmri reported from the
		 * kernel may not have up to date details about the disk itself
		 * (serial, part, etc).
		 */
		if (topo_fmri_str2nvl(thp, zcp->zc_fru, &fmri, &err) == 0) {
			/*
			 * If the disk is part of the system chassis, but the
			 * FRU indicates a different chassis ID than our
			 * current system, then ignore the error.  This
			 * indicates that the device was part of another
			 * cluster head, and for obvious reasons cannot be
			 * imported on this system.
			 */
			if (libzfs_fru_notself(zhdl, zcp->zc_fru)) {
				fmd_case_close(hdl, zcp->zc_case);
				nvlist_free(fmri);
				fmd_hdl_topo_rele(hdl, thp);
				nvlist_free(detector);
				return;
			}

			/*
			 * If the device is no longer present on the system, or
			 * topo_fmri_fru() fails for other reasons, then fall
			 * back to the fmri specified in the vdev.
			 */
			if (topo_fmri_fru(thp, fmri, &fru, &err) != 0)
				fru = fmd_nvl_dup(hdl, fmri, FMD_SLEEP);
			nvlist_free(fmri);
		}

		fmd_hdl_topo_rele(hdl, thp);
	}

	fault = fmd_nvl_create_fault(hdl, faultname, 100, detector,
	    fru, detector);
	fmd_case_add_suspect(hdl, zcp->zc_case, fault);

	nvlist_free(fru);

	fmd_case_solve(hdl, zcp->zc_case);

	serialize = B_FALSE;
	if (zcp->zc_data.zc_has_remove_timer) {
		fmd_timer_remove(hdl, zcp->zc_remove_timer);
		zcp->zc_data.zc_has_remove_timer = 0;
		serialize = B_TRUE;
	}
	if (serialize)
		zfs_case_serialize(hdl, zcp);

	nvlist_free(detector);
}