Пример #1
0
static int
__osd_sa_xattr_get(const struct lu_env *env, struct osd_object *obj,
		   const struct lu_buf *buf, const char *name, int *sizep)
{
	uchar_t *nv_value;
	int      rc;

	LASSERT(obj->oo_sa_hdl);

	if (obj->oo_sa_xattr == NULL) {
		rc = __osd_xattr_cache(env, obj);
		if (rc)
			return rc;
	}

	LASSERT(obj->oo_sa_xattr);
	rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
			sizep);
	if (rc)
		return rc;

	if (buf == NULL || buf->lb_buf == NULL) {
		/* return the required size by *sizep */
		return 0;
	}

	if (*sizep > buf->lb_len)
		return -ERANGE; /* match ldiskfs error */

	memcpy(buf->lb_buf, nv_value, *sizep);
	return 0;
}
Пример #2
0
/*
 * Convert a device path/nvlist pair to an nvp_list_t
 * Used to parse the nvlist format when reading
 * /etc/devices/devid_cache
 */
static nvp_list_t *
devid_nvl2nvp(nvlist_t *nvl, char *name)
{
	nvp_devid_t *np;
	ddi_devid_t devidp;
	int rval;
	uint_t n;

	np = kmem_zalloc(sizeof (nvp_devid_t), KM_SLEEP);
	np->nvp_devpath = i_ddi_strdup(name, KM_SLEEP);

	NVP_DEVID_DEBUG_PATH((np->nvp_devpath));

	/*
	 * check path for a devid
	 */
	np->nvp_devid = NULL;
	rval = nvlist_lookup_byte_array(nvl,
		DP_DEVID_ID, (uchar_t **)&devidp, &n);
	if (rval == 0) {
		if (ddi_devid_valid(devidp) == DDI_SUCCESS) {
			ASSERT(n == ddi_devid_sizeof(devidp));
			np->nvp_devid = kmem_alloc(n, KM_SLEEP);
			(void) bcopy(devidp, np->nvp_devid, n);
			NVP_DEVID_DEBUG_DEVID((np->nvp_devid));
		} else {
			DEVIDERR((CE_CONT,
			    "%s: invalid devid\n", np->nvp_devpath));
		}
	}

	return (NVPLIST(np));
}
Пример #3
0
static int
zpl_xattr_get_sa(struct inode *ip, const char *name, void *value, size_t size)
{
	znode_t *zp = ITOZ(ip);
	uchar_t *nv_value;
	uint_t nv_size;
	int error = 0;

	ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock));

	mutex_enter(&zp->z_lock);
	if (zp->z_xattr_cached == NULL)
		error = -zfs_sa_get_xattr(zp);
	mutex_exit(&zp->z_lock);

	if (error)
		return (error);

	ASSERT(zp->z_xattr_cached);
	error = -nvlist_lookup_byte_array(zp->z_xattr_cached, name,
	    &nv_value, &nv_size);
	if (error)
		return (error);

	if (!size)
		return (nv_size);

	if (size < nv_size)
		return (-ERANGE);

	memcpy(value, nv_value, nv_size);

	return (nv_size);
}
Пример #4
0
static boolean_t
sfunc_probe_target(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
{
	ipmpstat_sfunc_arg_t *arg = ofmtarg->ofmt_cbarg;
	uint_t nelem;
	struct sockaddr_storage *target;
	nvlist_t *nvl = arg->sa_data;

	if (nvlist_lookup_byte_array(nvl, IPMP_PROBE_TARGET,
	    (uchar_t **)&target, &nelem) != 0)
		return (sfunc_nvwarn("IPMP_PROBE_TARGET"));

	sockaddr2str(target, buf, bufsize);
	return (B_TRUE);
}
Пример #5
0
static int
bi_getval_bootmisc(bi_param_t *bip, void *valbuf, size_t *vallenp)
{
	uchar_t		*val;
	uint_t		len;

	if (nvlist_lookup_byte_array(bi_nvl, (char *)bip->bi_name,
	    &val, &len) != 0) {
		return (BI_E_NOVAL);
	} else if (*vallenp < len) {
		*vallenp = len;
		return (BI_E_BUF2SMALL);
	}
	*vallenp = len;
	(void) memcpy(valbuf, val, *vallenp);

	return (BI_E_SUCCESS);
}
Пример #6
0
int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
		       const struct lu_buf *buf, const char *name, int fl,
		       struct osd_thandle *oh)
{
	dmu_buf_impl_t *db;
	uchar_t *nv_value;
	size_t  size;
	int	nv_size;
	int	rc;
	int	too_big = 0;

	LASSERT(obj->oo_sa_hdl);
	if (obj->oo_sa_xattr == NULL) {
		rc = __osd_xattr_cache(env, obj);
		if (rc)
			return rc;
	}

	LASSERT(obj->oo_sa_xattr);
	/* Limited to 32k to keep nvpair memory allocations small */
	if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
		too_big = 1;
	} else {
		/* Prevent the DXATTR SA from consuming the entire SA
		 * region */
		rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
		if (rc)
			return rc;

		if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
			too_big = 1;
	}

	/* even in case of -EFBIG we must lookup xattr and check can we
	 * rewrite it then delete from SA */
	rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
					&nv_size);
	if (rc == 0) {
		if (fl & LU_XATTR_CREATE) {
			return -EEXIST;
		} else if (too_big) {
			rc = -nvlist_remove(obj->oo_sa_xattr, name,
						DATA_TYPE_BYTE_ARRAY);
			if (rc < 0)
				return rc;
			rc = __osd_sa_xattr_schedule_update(env, obj, oh);
			return rc == 0 ? -EFBIG : rc;
		}
	} else if (rc == -ENOENT) {
		if (fl & LU_XATTR_REPLACE)
			return -ENODATA;
		else if (too_big)
			return -EFBIG;
	} else {
		return rc;
	}

	/* Ensure xattr doesn't exist in ZAP */
	if (obj->oo_xattr != ZFS_NO_OBJECT) {
		struct osd_device *osd = osd_obj2dev(obj);
		uint64_t           objid;
		rc = -zap_lookup(osd->od_os, obj->oo_xattr,
				 name, 8, 1, &objid);
		if (rc == 0) {
			rc = -dmu_object_free(osd->od_os, objid, oh->ot_tx);
			if (rc == 0)
				zap_remove(osd->od_os, obj->oo_xattr,
					   name, oh->ot_tx);
		}
	}

	rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
				    (uchar_t *)buf->lb_buf, buf->lb_len);
	if (rc)
		return rc;

	/* batch updates only for just created dnodes where we
	 * used to set number of EAs in a single transaction */
	db = (dmu_buf_impl_t *)obj->oo_db;
	if (DB_DNODE(db)->dn_allocated_txg == oh->ot_tx->tx_txg)
		rc = __osd_sa_xattr_schedule_update(env, obj, oh);
	else
		rc = __osd_sa_xattr_update(env, obj, oh);

	return rc;
}
Пример #7
0
int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
			const struct lu_buf *buf, const char *name, int fl,
			struct osd_thandle *oh)
{
	uchar_t *nv_value;
	size_t  size;
	int	nv_size;
	int	rc;
	int	too_big = 0;

	LASSERT(obj->oo_sa_hdl);
	if (obj->oo_sa_xattr == NULL) {
		rc = __osd_xattr_cache(env, obj);
		if (rc)
			return rc;
	}

	LASSERT(obj->oo_sa_xattr);
	/* Limited to 32k to keep nvpair memory allocations small */
	if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
		too_big = 1;
	} else {
		/* Prevent the DXATTR SA from consuming the entire SA
		 * region */
		rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
		if (rc)
			return rc;

		if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
			too_big = 1;
	}

	/* even in case of -EFBIG we must lookup xattr and check can we
	 * rewrite it then delete from SA */
	rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
					&nv_size);
	if (rc == 0) {
		if (fl & LU_XATTR_CREATE) {
			return -EEXIST;
		} else if (too_big) {
			rc = -nvlist_remove(obj->oo_sa_xattr, name,
						DATA_TYPE_BYTE_ARRAY);
			if (rc < 0)
				return rc;
			rc = __osd_sa_xattr_update(env, obj, oh);
			return rc == 0 ? -EFBIG : rc;
		}
	} else if (rc == -ENOENT) {
		if (fl & LU_XATTR_REPLACE)
			return -ENODATA;
		else if (too_big)
			return -EFBIG;
	} else {
		return rc;
	}

	rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
				    (uchar_t *)buf->lb_buf, buf->lb_len);
	if (rc)
		return rc;

	rc = __osd_sa_xattr_update(env, obj, oh);
	return rc;
}
Пример #8
0
/*ARGSUSED*/
static int
enc_parse_feature_block(ses_plugin_t *sp, ses_node_t *np)
{
	sun_feature_block_impl_t *sfbip;
	nvlist_t *encprops;
	uint8_t *vsp;
	uint_t vsp_len;
	uint_t cid_off, cid_len;
	uint16_t revision;
	uint64_t chunk;
	int nverr;

	encprops = ses_node_props(np);
	if (nvlist_lookup_byte_array(encprops, SES_EN_PROP_VS,
	    &vsp, &vsp_len) != 0 ||
	    vsp_len < offsetof(sun_feature_block_impl_t, _reserved2))
		return (0);

	sfbip = (sun_feature_block_impl_t *)vsp;

	if (strncmp((char *)sfbip->sfbi_spms_header, "SPMS", 4) != 0 ||
	    sfbip->sfbi_spms_major_ver != 1)
		return (0);

	revision = SCSI_READ16(&sfbip->sfbi_spms_revision);

	/*
	 * The offset read from the Sun Feature Block needs to be adjusted
	 * so that the difference in the sizes of the Enclosure
	 * Descriptor and the INQUIRY data format is accounted for.
	 */
	cid_len = sfbip->sfbi_chassis_id_len;

	if (sfbip->sfbi_chassis_id_off >= 96 && cid_len >= 4) {
		cid_off = sfbip->sfbi_chassis_id_off -
		    (sizeof (ses2_ed_impl_t) - 1);
		cid_off += offsetof(ses2_ed_impl_t, st_priv[0]) -
		    offsetof(spc3_inquiry_data_t, id_vs_36[0]);

		if (cid_off + cid_len <= vsp_len) {
			SES_NV_ADD(fixed_string, nverr, encprops,
			    LIBSES_EN_PROP_CSN, (char *)(vsp + cid_off),
			    cid_len);
		}
	}

	if (revision >= 104) {
		SES_NV_ADD(boolean_value, nverr, encprops,
		    LIBSES_EN_PROP_INTERNAL, sfbip->sfbi_int);
	}

	if (revision >= 105) {
		if (sfbip->sfbi_fw_upload_max_chunk_sz == 0)
			chunk = 512;
		else if (sfbip->sfbi_fw_upload_max_chunk_sz == 0x7f)
			chunk = 65536;
		else
			chunk = 512 * sfbip->sfbi_fw_upload_max_chunk_sz;

		SES_NV_ADD(uint64, nverr, encprops,
		    LIBSES_EN_PROP_FIRMWARE_CHUNK_SIZE, chunk);
	}

	/*
	 * If this is a subchassis, it will have a subchassis index field
	 * with a value other than 0.  See SPMS-1r111 4.1.3.1.  If not, we
	 * will see 0 and will not create the subchassis member at all; note
	 * that this is backward-compatible with pre-111 implementations that
	 * treated this as a reserved field.  No such implementation contains
	 * a subchassis.
	 */
	if (sfbip->sfbi_spms_revision >= 111 &&
	    sfbip->sfbi_subchassis_index != 0) {
		SES_NV_ADD(uint64, nverr, encprops,
		    LIBSES_EN_PROP_SUBCHASSIS_ID,
		    sfbip->sfbi_subchassis_index - 1);
	}

	return (0);
}
Пример #9
0
static int
osd_scrub_check_update(const struct lu_env *env, struct osd_device *dev,
		       const struct lu_fid *fid, uint64_t oid, int val)
{
	struct lustre_scrub *scrub = &dev->od_scrub;
	struct scrub_file *sf = &scrub->os_file;
	struct osd_inconsistent_item *oii = NULL;
	nvlist_t *nvbuf = NULL;
	dnode_t *dn = NULL;
	uint64_t oid2;
	int ops = DTO_INDEX_UPDATE;
	int rc;
	ENTRY;

	down_write(&scrub->os_rwsem);
	scrub->os_new_checked++;
	if (val < 0)
		GOTO(out, rc = val);

	if (scrub->os_in_prior)
		oii = list_entry(scrub->os_inconsistent_items.next,
				 struct osd_inconsistent_item, oii_list);

	if (oid < sf->sf_pos_latest_start && !oii)
		GOTO(out, rc = 0);

	if (oii && oii->oii_insert) {
		ops = DTO_INDEX_INSERT;
		goto zget;
	}

	rc = osd_fid_lookup(env, dev, fid, &oid2);
	if (rc) {
		if (rc != -ENOENT)
			GOTO(out, rc);

		ops = DTO_INDEX_INSERT;

zget:
		rc = __osd_obj2dnode(dev->od_os, oid, &dn);
		if (rc) {
			/* Someone removed the object by race. */
			if (rc == -ENOENT || rc == -EEXIST)
				rc = 0;
			GOTO(out, rc);
		}

		scrub->os_full_speed = 1;
		sf->sf_flags |= SF_INCONSISTENT;
	} else if (oid == oid2) {
		GOTO(out, rc = 0);
	} else {
		struct lustre_mdt_attrs *lma = NULL;
		int size;

		rc = __osd_xattr_load_by_oid(dev, oid2, &nvbuf);
		if (rc == -ENOENT || rc == -EEXIST || rc == -ENODATA)
			goto update;
		if (rc)
			GOTO(out, rc);

		rc = -nvlist_lookup_byte_array(nvbuf, XATTR_NAME_LMA,
					       (uchar_t **)&lma, &size);
		if (rc == -ENOENT || rc == -EEXIST || rc == -ENODATA)
			goto update;
		if (rc)
			GOTO(out, rc);

		lustre_lma_swab(lma);
		if (unlikely(lu_fid_eq(&lma->lma_self_fid, fid))) {
			CDEBUG(D_LFSCK, "%s: the FID "DFID" is used by "
			       "two objects: %llu and %llu (in OI)\n",
			       osd_name(dev), PFID(fid), oid, oid2);

			GOTO(out, rc = -EEXIST);
		}

update:
		scrub->os_full_speed = 1;
		sf->sf_flags |= SF_INCONSISTENT;
	}

	rc = osd_scrub_refresh_mapping(env, dev, fid, oid, ops, false, NULL);
	if (!rc) {
		if (scrub->os_in_prior)
			sf->sf_items_updated_prior++;
		else
			sf->sf_items_updated++;
	}

	GOTO(out, rc);

out:
	if (nvbuf)
		nvlist_free(nvbuf);

	if (rc < 0) {
		sf->sf_items_failed++;
		if (sf->sf_pos_first_inconsistent == 0 ||
		    sf->sf_pos_first_inconsistent > oid)
			sf->sf_pos_first_inconsistent = oid;
	} else {
		rc = 0;
	}

	/* There may be conflict unlink during the OI scrub,
	 * if happend, then remove the new added OI mapping. */
	if (ops == DTO_INDEX_INSERT && dn && dn->dn_free_txg)
		osd_scrub_refresh_mapping(env, dev, fid, oid,
					  DTO_INDEX_DELETE, false, NULL);
	up_write(&scrub->os_rwsem);

	if (dn)
		osd_dnode_rele(dn);

	if (oii) {
		spin_lock(&scrub->os_lock);
		if (likely(!list_empty(&oii->oii_list)))
			list_del(&oii->oii_list);
		spin_unlock(&scrub->os_lock);
		OBD_FREE_PTR(oii);
	}

	RETURN(sf->sf_param & SP_FAILOUT ? rc : 0);
}
Пример #10
0
/*
 * Create an instance of a transceiver with the specified id. We must create
 * both its port and the transceiver node.
 */
static int
nic_create_transceiver(topo_mod_t *mod, tnode_t *pnode, dladm_handle_t handle,
    datalink_id_t linkid, uint_t tranid)
{
	int ret;
	tnode_t *port;
	dld_ioc_gettran_t dgt;
	dld_ioc_tranio_t dti;
	uint8_t buf[256];
	char ouibuf[16];
	char *vendor = NULL, *part = NULL, *rev = NULL, *serial = NULL;
	nvlist_t *nvl = NULL;

	if ((ret = port_create_sff(mod, pnode, tranid, &port)) != 0)
		return (ret);

	bzero(&dgt, sizeof (dgt));
	dgt.dgt_linkid = linkid;
	dgt.dgt_tran_id = tranid;

	if (ioctl(dladm_dld_fd(handle), DLDIOC_GETTRAN, &dgt) != 0) {
		if (errno == ENOTSUP)
			return (0);
		return (-1);
	}

	if (dgt.dgt_present == 0)
		return (0);

	bzero(&dti, sizeof (dti));
	dti.dti_linkid = linkid;
	dti.dti_tran_id = tranid;
	dti.dti_page = 0xa0;
	dti.dti_nbytes = sizeof (buf);
	dti.dti_buf = (uintptr_t)buf;

	if (ioctl(dladm_dld_fd(handle), DLDIOC_READTRAN, &dti) == 0) {
		uchar_t *oui;
		uint_t nbyte;

		if (libsff_parse(buf, dti.dti_nbytes, dti.dti_page,
		    &nvl) == 0) {
			if ((ret = nvlist_lookup_string(nvl, LIBSFF_KEY_VENDOR,
			    &vendor)) != 0 && nvlist_lookup_byte_array(nvl,
			    LIBSFF_KEY_OUI, &oui, &nbyte) == 0 && nbyte == 3) {
				if (snprintf(ouibuf, sizeof (ouibuf),
				    "%02x:%02x:%02x", oui[0], oui[1], oui[2]) <
				    sizeof (ouibuf)) {
					vendor = ouibuf;
				}
			} else if (ret != 0) {
				vendor = NULL;
			}

			if (nvlist_lookup_string(nvl, LIBSFF_KEY_PART,
			    &part) != 0) {
				part = NULL;
			}

			if (nvlist_lookup_string(nvl, LIBSFF_KEY_REVISION,
			    &rev) != 0) {
				rev = NULL;
			}

			if (nvlist_lookup_string(nvl, LIBSFF_KEY_SERIAL,
			    &serial) != 0) {
				serial = NULL;
			}
		}
	}

	if (transceiver_range_create(mod, port, 0, 0) != 0) {
		nvlist_free(nvl);
		return (-1);
	}

	if (transceiver_create_sff(mod, port, 0, dgt.dgt_usable, vendor, part,
	    rev, serial, NULL) != 0) {
		nvlist_free(nvl);
		return (-1);
	}

	nvlist_free(nvl);
	return (0);
}
Пример #11
0
/*
 * as we don't know FID, we can't use LU object, so this function
 * partially duplicate __osd_xattr_get() which is built around
 * LU-object and uses it to cache data like regular EA dnode, etc
 */
static int osd_find_parent_by_dnode(const struct lu_env *env,
				    struct dt_object *o,
				    struct lu_fid *fid)
{
	struct lustre_mdt_attrs	*lma;
	udmu_objset_t		*uos = &osd_obj2dev(osd_dt_obj(o))->od_objset;
	struct lu_buf		 buf;
	sa_handle_t		*sa_hdl;
	nvlist_t		*nvbuf = NULL;
	uchar_t			*value;
	uint64_t		 dnode;
	int			 rc, size;
	ENTRY;

	/* first of all, get parent dnode from own attributes */
	LASSERT(osd_dt_obj(o)->oo_db);
	rc = -sa_handle_get(uos->os, osd_dt_obj(o)->oo_db->db_object,
			    NULL, SA_HDL_PRIVATE, &sa_hdl);
	if (rc)
		RETURN(rc);

	dnode = ZFS_NO_OBJECT;
	rc = -sa_lookup(sa_hdl, SA_ZPL_PARENT(uos), &dnode, 8);
	sa_handle_destroy(sa_hdl);
	if (rc)
		RETURN(rc);

	/* now get EA buffer */
	rc = __osd_xattr_load(uos, dnode, &nvbuf);
	if (rc)
		GOTO(regular, rc);

	/* XXX: if we get that far.. should we cache the result? */

	/* try to find LMA attribute */
	LASSERT(nvbuf != NULL);
	rc = -nvlist_lookup_byte_array(nvbuf, XATTR_NAME_LMA, &value, &size);
	if (rc == 0 && size >= sizeof(*lma)) {
		lma = (struct lustre_mdt_attrs *)value;
		lustre_lma_swab(lma);
		*fid = lma->lma_self_fid;
		GOTO(out, rc = 0);
	}

regular:
	/* no LMA attribute in SA, let's try regular EA */

	/* first of all, get parent dnode storing regular EA */
	rc = -sa_handle_get(uos->os, dnode, NULL, SA_HDL_PRIVATE, &sa_hdl);
	if (rc)
		GOTO(out, rc);

	dnode = ZFS_NO_OBJECT;
	rc = -sa_lookup(sa_hdl, SA_ZPL_XATTR(uos), &dnode, 8);
	sa_handle_destroy(sa_hdl);
	if (rc)
		GOTO(out, rc);

	CLASSERT(sizeof(*lma) <= sizeof(osd_oti_get(env)->oti_buf));
	buf.lb_buf = osd_oti_get(env)->oti_buf;
	buf.lb_len = sizeof(osd_oti_get(env)->oti_buf);

	/* now try to find LMA */
	rc = __osd_xattr_get_large(env, uos, dnode, &buf,
				   XATTR_NAME_LMA, &size);
	if (rc == 0 && size >= sizeof(*lma)) {
		lma = buf.lb_buf;
		lustre_lma_swab(lma);
		*fid = lma->lma_self_fid;
		GOTO(out, rc = 0);
	} else if (rc < 0) {
		GOTO(out, rc);
	} else {
		GOTO(out, rc = -EIO);
	}

out:
	if (nvbuf != NULL)
		nvlist_free(nvbuf);
	RETURN(rc);
}
Пример #12
0
/*
 * Actually processes events; returns a reply event
 */
static void
process_event(int cmd, int seq_num, nvlist_t *nvl, nvlist_t **ret)
{
	int i;
	int error;
	uint_t nvl_nrsrcs = 0;
	pid_t pid;
	uint32_t flag = (uint32_t)0;
	uint64_t pid64 = (uint64_t)0;
	size_t buflen = 0;
	size_t interval_size = 0;
	timespec_t *interval = NULL;
	nvlist_t *change_data = NULL;
	nvlist_t *event_data = NULL;
	rcm_info_t *info = NULL;
	char *modname = NULL;
	char *buf = NULL;
	char **rsrcnames = NULL;
	char **nvl_rsrcs = NULL;

	rcm_log_message(RCM_TRACE2, "servicing door command=%d\n", cmd);

	rcm_print_nvlist(nvl);

	/*
	 * Extract data from the door argument nvlist.  Not all arguments
	 * are needed; sanity checks are performed later.
	 */
	(void) nvlist_lookup_string_array(nvl, RCM_RSRCNAMES, &nvl_rsrcs,
	    &nvl_nrsrcs);
	(void) nvlist_lookup_string(nvl, RCM_CLIENT_MODNAME, &modname);
	(void) nvlist_lookup_uint64(nvl, RCM_CLIENT_ID, (uint64_t *)&pid64);
	pid = (pid_t)pid64;
	(void) nvlist_lookup_uint32(nvl, RCM_REQUEST_FLAG, (uint32_t *)&flag);
	(void) nvlist_lookup_byte_array(nvl, RCM_SUSPEND_INTERVAL,
	    (uchar_t **)&interval, &interval_size);
	(void) nvlist_lookup_byte_array(nvl, RCM_CHANGE_DATA, (uchar_t **)&buf,
	    &buflen);
	if (buf != NULL && buflen > 0) {
		(void) nvlist_unpack(buf, buflen, &change_data, 0);
		buf = NULL;
		buflen = 0;
	}
	(void) nvlist_lookup_byte_array(nvl, RCM_EVENT_DATA, (uchar_t **)&buf,
	    &buflen);
	if (buf != NULL && buflen > 0)
		(void) nvlist_unpack(buf, buflen, &event_data, 0);

	rsrcnames = s_calloc(nvl_nrsrcs + 1, sizeof (char *));
	for (i = 0; i < nvl_nrsrcs; i++) {
		rsrcnames[i] = nvl_rsrcs[i];
	}
	rsrcnames[nvl_nrsrcs] = NULL;

	/*
	 * Switch off the command being performed to do the appropriate
	 * sanity checks and dispatch the arguments to the appropriate
	 * implementation routine.
	 */
	switch (cmd) {
	case CMD_REGISTER:
		if ((modname == NULL) || (rsrcnames == NULL) ||
		    (rsrcnames[0] == NULL))
			goto faildata;
		error = add_resource_client(modname, rsrcnames[0], pid, flag,
		    &info);
		break;

	case CMD_UNREGISTER:
		if ((modname == NULL) || (rsrcnames == NULL) ||
		    (rsrcnames[0] == NULL))
			goto faildata;
		error = remove_resource_client(modname, rsrcnames[0], pid,
		    flag);
		break;

	case CMD_GETINFO:
		if ((rsrcnames == NULL) &&
		    ((flag & (RCM_DR_OPERATION | RCM_MOD_INFO)) == 0))
			goto faildata;
		if ((error = get_resource_info(rsrcnames, flag, seq_num, &info))
		    == EINVAL) {
			rcm_log_message(RCM_DEBUG,
			    "invalid argument in get info request\n");
			generate_reply_event(EINVAL, NULL, ret);
			return;
		}
		break;

	case CMD_SUSPEND:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
		    (interval == NULL))
			goto faildata;
		error = process_resource_suspend(rsrcnames, pid, flag, seq_num,
		    interval, &info);
		break;

	case CMD_RESUME:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
			goto faildata;
		error = notify_resource_resume(rsrcnames, pid, flag, seq_num,
		    &info);
		break;

	case CMD_OFFLINE:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
			goto faildata;
		error = process_resource_offline(rsrcnames, pid, flag, seq_num,
		    &info);
		break;

	case CMD_ONLINE:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
			goto faildata;
		error = notify_resource_online(rsrcnames, pid, flag, seq_num,
		    &info);
		break;

	case CMD_REMOVE:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
			goto faildata;
		error = notify_resource_remove(rsrcnames, pid, flag, seq_num,
		    &info);
		break;

	case CMD_EVENT:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
		    (event_data == NULL))
			goto faildata;
		error = notify_resource_event(rsrcnames[0], pid, flag, seq_num,
		    event_data, &info);
		nvlist_free(event_data);
		break;

	case CMD_REQUEST_CHANGE:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
		    (change_data == NULL))
			goto faildata;
		error = request_capacity_change(rsrcnames[0], pid, flag,
		    seq_num, change_data, &info);
		nvlist_free(change_data);
		break;

	case CMD_NOTIFY_CHANGE:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL) ||
		    (change_data == NULL))
			goto faildata;
		error = notify_capacity_change(rsrcnames[0], pid, flag, seq_num,
		    change_data, &info);
		nvlist_free(change_data);
		break;

	case CMD_GETSTATE:
		if ((rsrcnames == NULL) || (rsrcnames[0] == NULL))
			goto faildata;
		error = get_resource_state(rsrcnames[0], pid, &info);
		break;

	default:
		rcm_log_message(RCM_WARNING,
		    gettext("unknown door command: %d\n"), cmd);
		generate_reply_event(EFAULT, NULL, ret);
		(void) free(rsrcnames);
		return;
	}

	rcm_log_message(RCM_TRACE2, "finish processing event 0x%x\n", cmd);
	generate_reply_event(error, info, ret);
	(void) free(rsrcnames);
	return;

faildata:
	rcm_log_message(RCM_WARNING,
	    gettext("data error in door arguments for cmd 0x%x\n"), cmd);

	generate_reply_event(EFAULT, NULL, ret);
	(void) free(rsrcnames);
}
Пример #13
0
/*ARGSUSED*/
static int
sun_riverwalk_parse_node(ses_plugin_t *sp, ses_node_t *np)
{
	nvlist_t *props = ses_node_props(np);
	int nverr;
	ses_riverwalk_stringin_t *strp;
	char buf[32];
	uint64_t type, index;
	char *pn, *sn;
	ses_node_t *encp;
	nvlist_t *encprops;
	uint8_t *stringin;
	uint_t len;

	if (ses_node_type(np) != SES_NODE_ENCLOSURE &&
	    ses_node_type(np) != SES_NODE_ELEMENT)
		return (0);

	/*
	 * Find the containing enclosure node and extract the STRING IN
	 * information.
	 */
	for (encp = np; ses_node_type(encp) != SES_NODE_ENCLOSURE;
	    encp = ses_node_parent(encp))
		;

	encprops = ses_node_props(encp);
	if (nvlist_lookup_byte_array(encprops, SES_EN_PROP_STRING,
	    &stringin, &len) != 0)
		return (0);

	if (len < sizeof (ses_riverwalk_stringin_t))
		return (0);

	strp = (ses_riverwalk_stringin_t *)stringin;

	switch (ses_node_type(np)) {
	case SES_NODE_ELEMENT:
		/*
		 * We can get part and serial information for power supplies and
		 * the SIM cards (ESC_ELECTRONICS elements).
		 */
		VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
		    &type) == 0);
		VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_CLASS_INDEX,
		    &index) == 0);

		sn = pn = NULL;
		switch (type) {
		case SES_ET_POWER_SUPPLY:
			switch (index) {
			case 0:
				if (strncmp(strp->rws_ps0_id, "SPS0", 4) != 0)
					break;

				pn = strp->rws_ps0_pn;
				sn = strp->rws_ps0_sn;
				break;

			case 1:
				if (strncmp(strp->rws_ps1_id, "SPS1", 4) != 0)
					break;

				pn = strp->rws_ps1_pn;
				sn = strp->rws_ps1_sn;
				break;
			}
			break;

		case SES_ET_ESC_ELECTRONICS:
			switch (index) {
			case 0:
				if (strncmp(strp->rws_sim0_id, "SIM0", 4) != 0)
					break;

				pn = strp->rws_sim0_pn;
				sn = strp->rws_sim0_sn;
				break;

			case 1:
				if (strncmp(strp->rws_sim1_id, "SIM1", 4) != 0)
					break;

				pn = strp->rws_sim1_pn;
				sn = strp->rws_sim1_sn;
				break;
			}
			break;

		case SES_ET_COOLING:
			/*
			 * The J4200 uses identical STRING IN data except that
			 * the PSU part numbers are replaced with fan part
			 * numbers.  The power supply part and serial number
			 * information are not available.
			 */
			switch (index) {
			case 0:
				if (strncmp(strp->rws_ps0_id, "FAN0", 4) != 0)
					break;

				pn = strp->rws_ps0_pn;
				sn = strp->rws_ps0_sn;
				break;

			case 1:
				if (strncmp(strp->rws_ps1_id, "FAN1", 4) != 0)
					break;

				pn = strp->rws_ps1_pn;
				sn = strp->rws_ps1_sn;
				break;
			}
			break;

		}

		if (pn == NULL)
			return (0);

		if (pn[0] != '\0') {
			(void) bcopy(pn, buf, sizeof (strp->rws_ps0_pn));
			buf[sizeof (strp->rws_ps0_pn)] = '\0';
			SES_NV_ADD(string, nverr, props, LIBSES_PROP_PART,
			    buf);
		}

		if (sn[0] != '\0') {
			(void) bcopy(sn, buf, sizeof (strp->rws_ps0_sn));
			buf[sizeof (strp->rws_ps0_sn)] = '\0';
			SES_NV_ADD(string, nverr, props, LIBSES_PROP_SERIAL,
			    sn);
		}

		break;

	case SES_NODE_ENCLOSURE:
		/*
		 * The chassis serial number is derived from the MID FRU
		 * descriptor.
		 */
		if (strncmp(strp->rws_mid_id, "MID ", 4) == 0 &&
		    strp->rws_mid_sn[0] != '\0') {
			(void) bcopy(strp->rws_mid_sn, buf,
			    sizeof (strp->rws_mid_sn));
			buf[sizeof (strp->rws_mid_sn)] = '\0';
			SES_NV_ADD(string, nverr, props, LIBSES_EN_PROP_CSN,
			    buf);
		}

		break;
	}

	return (0);
}