e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * CDDL HEADER START
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * The contents of this file are subject to the terms of the
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Common Development and Distribution License (the "License").
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * You may not use this file except in compliance with the License.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * or http://www.opensolaris.org/os/licensing.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * See the License for the specific language governing permissions
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * and limitations under the License.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * When distributing Covered Code, include this CDDL HEADER in each
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * If applicable, add the following below this CDDL HEADER, with the
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * fields enclosed by brackets "[]" replaced with your own identifying
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * information: Portions Copyright [yyyy] [name of copyright owner]
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * CDDL HEADER END
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Use is subject to license terms.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * libfmd_agent contains the low-level operations that needed by the fmd
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * agents, such as page operations (status/retire/unretire), cpu operations
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * (status/online/offline), etc.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Some operations are implemented by /dev/fm ioctls. Those ioctls are
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * heavily versioned to allow userland patching without requiring a reboot
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * to get a matched /dev/fm. All the ioctls use packed nvlist to interact
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * between userland and kernel. (see fmd_agent_nvl_ioctl()).
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <fcntl.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <errno.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <unistd.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <strings.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <libnvpair.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <string.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <sys/types.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <sys/devfm.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <fmd_agent_impl.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_errno(fmd_agent_hdl_t *hdl)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (hdl->agent_errno);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_seterrno(fmd_agent_hdl_t *hdl, int err)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye hdl->agent_errno = err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (-1);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeconst char *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_strerr(int err)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (strerror(err));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeconst char *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_errmsg(fmd_agent_hdl_t *hdl)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (fmd_agent_strerr(hdl->agent_errno));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yestatic int
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yecleanup_set_errno(fmd_agent_hdl_t *hdl, nvlist_t *innvl, nvlist_t *outnvl,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(innvl);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(outnvl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (fmd_agent_seterrno(hdl, err));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Perform /dev/fm ioctl. The input and output data are represented by
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * name-value lists (nvlists).
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_nvl_ioctl(fmd_agent_hdl_t *hdl, int cmd, uint32_t ver,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_t *innvl, nvlist_t **outnvlp)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye fm_ioc_data_t fid;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err = 0;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye char *inbuf = NULL, *outbuf = NULL;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye size_t insz = 0, outsz = 0;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (innvl != NULL) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((err = nvlist_size(innvl, &insz, NV_ENCODE_NATIVE)) != 0)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (err);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (insz > FM_IOC_MAXBUFSZ)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (ENAMETOOLONG);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((inbuf = umem_alloc(insz, UMEM_DEFAULT)) == NULL)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (errno);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((err = nvlist_pack(innvl, &inbuf, &insz,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye NV_ENCODE_NATIVE, 0)) != 0) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye umem_free(inbuf, insz);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (err);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (outnvlp != NULL) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost outsz = FM_IOC_OUT_BUFSZ;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost for (;;) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost if (outnvlp != NULL) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost outbuf = umem_alloc(outsz, UMEM_DEFAULT);
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost if (outbuf == NULL) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost err = errno;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost break;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost }
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost fid.fid_version = ver;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost fid.fid_insz = insz;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost fid.fid_inbuf = inbuf;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost fid.fid_outsz = outsz;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost fid.fid_outbuf = outbuf;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost if (ioctl(hdl->agent_devfd, cmd, &fid) < 0) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost if (errno == ENAMETOOLONG && outsz != 0 &&
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost outsz < (FM_IOC_OUT_MAXBUFSZ / 2)) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost umem_free(outbuf, outsz);
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost outsz *= 2;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost outbuf = umem_alloc(outsz, UMEM_DEFAULT);
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost if (outbuf == NULL) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost err = errno;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost break;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost }
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost } else {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost err = errno;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost break;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost }
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost } else if (outnvlp != NULL) {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost err = nvlist_unpack(fid.fid_outbuf, fid.fid_outsz,
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost outnvlp, 0);
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost break;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost } else {
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost break;
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost }
211eb17a9612ace1f2dee156ee66d097e28d9faaAdrian Frost }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (inbuf != NULL)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye umem_free(inbuf, insz);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (outbuf != NULL)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye umem_free(outbuf, outsz);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (err);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Open /dev/fm and return a handle. ver is the overall interface version.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yestatic fmd_agent_hdl_t *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_open_dev(int ver, int mode)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye fmd_agent_hdl_t *hdl;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int fd, err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_t *nvl;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((fd = open("/dev/fm", mode)) < 0)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (NULL); /* errno is set for us */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((hdl = umem_alloc(sizeof (fmd_agent_hdl_t),
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye UMEM_DEFAULT)) == NULL) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye err = errno;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (void) close(fd);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye errno = err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (NULL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye hdl->agent_devfd = fd;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye hdl->agent_version = ver;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye /*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Get the individual interface versions.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((err = fmd_agent_nvl_ioctl(hdl, FM_IOC_VERSIONS, ver, NULL, &nvl))
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye < 0) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (void) close(fd);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye umem_free(hdl, sizeof (fmd_agent_hdl_t));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye errno = err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (NULL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye hdl->agent_ioc_versions = nvl;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_hdl_t *
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_open(int ver)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (ver > FMD_AGENT_VERSION) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye errno = ENOTSUP;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (NULL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (fmd_agent_open_dev(ver, O_RDONLY));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yevoid
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_close(fmd_agent_hdl_t *hdl)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (void) close(hdl->agent_devfd);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_free(hdl->agent_ioc_versions);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye umem_free(hdl, sizeof (fmd_agent_hdl_t));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Given a interface name, return the kernel interface version.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_version(fmd_agent_hdl_t *hdl, const char *op, uint32_t *verp)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye err = nvlist_lookup_uint32(hdl->agent_ioc_versions,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye op, verp);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (err != 0) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye errno = err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (-1);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (0);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yestatic int
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_pageop_v1(fmd_agent_hdl_t *hdl, int cmd, nvlist_t *fmri)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_t *nvl = NULL;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, 0)) != 0 ||
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (err = nvlist_add_nvlist(nvl, FM_PAGE_RETIRE_FMRI, fmri)) != 0 ||
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (err = fmd_agent_nvl_ioctl(hdl, cmd, 1, nvl, NULL)) != 0)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (cleanup_set_errno(hdl, nvl, NULL, err));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_free(nvl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (0);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yestatic int
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_pageop(fmd_agent_hdl_t *hdl, int cmd, nvlist_t *fmri)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye uint32_t ver;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (fmd_agent_version(hdl, FM_PAGE_OP_VERSION, &ver) == -1)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (fmd_agent_seterrno(hdl, errno));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye switch (ver) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye case 1:
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (fmd_agent_pageop_v1(hdl, cmd, fmri));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye default:
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (fmd_agent_seterrno(hdl, ENOTSUP));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_page_retire(fmd_agent_hdl_t *hdl, nvlist_t *fmri)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int rc = fmd_agent_pageop(hdl, FM_IOC_PAGE_RETIRE, fmri);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err = fmd_agent_errno(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye /*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * FM_IOC_PAGE_RETIRE ioctl returns:
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * 0 - success in retiring page
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = EIO - page is already retired
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = EAGAIN - page is scheduled for retirement
1db96d3b343c9ab3090da5b745f1cd9de2f192efCheng Sean Ye * -1, errno = EINVAL - page fmri is invalid
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = any else - error
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (rc == 0 || err == EIO || err == EINVAL) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (rc == 0)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (void) fmd_agent_seterrno(hdl, 0);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_DONE);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (err == EAGAIN)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_ASYNC);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_FAIL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_page_unretire(fmd_agent_hdl_t *hdl, nvlist_t *fmri)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int rc = fmd_agent_pageop(hdl, FM_IOC_PAGE_UNRETIRE, fmri);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err = fmd_agent_errno(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye /*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * FM_IOC_PAGE_UNRETIRE ioctl returns:
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * 0 - success in unretiring page
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = EIO - page is already unretired
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = EAGAIN - page couldn't be locked, still retired
1db96d3b343c9ab3090da5b745f1cd9de2f192efCheng Sean Ye * -1, errno = EINVAL - page fmri is invalid
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = any else - error
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
1db96d3b343c9ab3090da5b745f1cd9de2f192efCheng Sean Ye if (rc == 0 || err == EIO || err == EINVAL) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (rc == 0)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (void) fmd_agent_seterrno(hdl, 0);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_DONE);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_FAIL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeint
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yefmd_agent_page_isretired(fmd_agent_hdl_t *hdl, nvlist_t *fmri)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int rc = fmd_agent_pageop(hdl, FM_IOC_PAGE_STATUS, fmri);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye int err = fmd_agent_errno(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye /*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * FM_IOC_PAGE_STATUS returns:
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * 0 - page is retired
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = EAGAIN - page is scheduled for retirement
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = EIO - page not scheduled for retirement
1db96d3b343c9ab3090da5b745f1cd9de2f192efCheng Sean Ye * -1, errno = EINVAL - page fmri is invalid
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * -1, errno = any else - error
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (rc == 0 || err == EINVAL) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (rc == 0)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (void) fmd_agent_seterrno(hdl, 0);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_DONE);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (err == EAGAIN)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_ASYNC);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (FMD_AGENT_RETIRE_FAIL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}