Print this page
NEX-14898 Null message (cfga_msg: NULL msgp) printed for sata devices with cfgadm
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.

  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/stat.h>
  29 #include <errno.h>
  30 #include <string.h>
  31 #include <dirent.h>
  32 #include "cfga_sata.h"
  33 
  34 /*
  35  * This file contains the entry points to the plug-in as defined in the
  36  * config_admin(3X) man page.
  37  */
  38 
  39 /*
  40  * Set the version number for the cfgadm library's use.
  41  */
  42 int cfga_version = CFGA_HSL_V2;
  43 


 697 
 698                 len = strlen(SATA_CONFIRM_DEVICE) +
 699                     strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
 700                     strlen("Unconfigure") + strlen(ap_id);
 701                 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 702                         (void) snprintf(msg, len + 3, "Unconfigure"
 703                             " %s%s\n%s",
 704                             SATA_CONFIRM_DEVICE, ap_id,
 705                             SATA_CONFIRM_DEVICE_SUSPEND);
 706                 }
 707 
 708                 if (!sata_confirm(confp, msg)) {
 709                         free(msg);
 710                         rv = CFGA_SATA_NACK;
 711                         break;
 712                 }
 713                 free(msg);
 714 
 715                 devpath = sata_get_devicepath(ap_id);
 716                 if (devpath == NULL) {
 717                         (void) printf(
 718                             "cfga_change_state: get device path failed\n");
 719                         rv = CFGA_SATA_DEV_UNCONFIGURE;
 720                         break;
 721                 }
 722 
 723                 if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
 724                     != CFGA_SATA_OK) {
 725                         break;
 726                 }
 727 
 728                 ret = devctl_ap_unconfigure(hdl, nvl);
 729 
 730                 if (ret != 0) {
 731                         rv = CFGA_SATA_DEV_UNCONFIGURE;
 732                         if (errno == EBUSY) {
 733                                 rv = CFGA_SATA_BUSY;
 734                         }
 735                         (void) sata_rcm_online(ap_id, errstring, devpath,
 736                             flags);
 737                 } else {


 754                 }
 755 
 756                 /* Strip off AP name dynamic component, if present */
 757                 if ((pdyn = GET_DYN(ap_id)) != NULL) {
 758                         *pdyn = '\0';
 759                 }
 760 
 761 
 762                 rv = CFGA_SATA_OK; /* other statuses don't matter */
 763 
 764                 /*
 765                  * If the port originally with device attached and was
 766                  * unconfigured already, the devicepath for the sd will be
 767                  * removed. sata_get_devicepath in this case is not necessary.
 768                  */
 769                 /* only call rcm_offline if the state was CONFIGURED */
 770                 if (ostate == AP_OSTATE_CONFIGURED &&
 771                     pmult == B_FALSE) {
 772                         devpath = sata_get_devicepath(ap_id);
 773                         if (devpath == NULL) {
 774                                 (void) printf(
 775                                     "cfga_change_state: get path failed\n");
 776                                 rv = CFGA_SATA_DEV_UNCONFIGURE;
 777                                 break;
 778                         }
 779 
 780                         len = strlen(SATA_CONFIRM_DEVICE) +
 781                             strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
 782                             strlen("Disconnect") + strlen(ap_id);
 783                         if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 784                                 (void) snprintf(msg, len + 3,
 785                                     "Disconnect"
 786                                     " %s%s\n%s",
 787                                     SATA_CONFIRM_DEVICE, ap_id,
 788                                     SATA_CONFIRM_DEVICE_SUSPEND);
 789                         }
 790                         if (!sata_confirm(confp, msg)) {
 791                                 free(msg);
 792                                 rv = CFGA_SATA_NACK;
 793                                 break;
 794                         }


 929         devctl_hdl_t            hdl = NULL;
 930         cfga_sata_ret_t         rv;
 931         char                    *str_p;
 932         size_t                  size;
 933 
 934         if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
 935                 (void) cfga_help(msgp, options, flags);
 936                 return (sata_err_msg(errstring, rv, ap_id, errno));
 937         }
 938 
 939         /*
 940          * All subcommands which can change state of device require
 941          * root privileges.
 942          */
 943         if (geteuid() != 0) {
 944                 rv = CFGA_SATA_PRIV;
 945                 goto bailout;
 946         }
 947 
 948         if (func == NULL) {
 949                 (void) printf("No valid option specified\n");
 950                 rv = CFGA_SATA_OPTIONS;
 951                 goto bailout;
 952         }
 953 
 954         if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
 955             CFGA_SATA_OK) {
 956                 goto bailout;
 957         }
 958 
 959         /* We do not care here about dynamic AP name component */
 960         if ((str_p = GET_DYN(ap_id)) != NULL) {
 961                 *str_p = '\0';
 962         }
 963 
 964         rv = CFGA_SATA_OK;
 965 
 966         if (strcmp(func, SATA_RESET_PORT) == 0) {
 967                 len = strlen(SATA_CONFIRM_PORT) +
 968                     strlen(SATA_CONFIRM_DEVICE_ABORT) +
 969                     strlen("Reset Port") + strlen(ap_id);


1240         char    minor_path[MAXPATHLEN];
1241         char    name_part[MAXNAMELEN];
1242         char    *devlink = NULL;
1243         char    *minor_portion = NULL;
1244         int     deplen;
1245         int     err;
1246         DIR     *dp = NULL;
1247         struct stat sb;
1248         struct dirent *dep = NULL;
1249         struct dirent *newdep = NULL;
1250         char    *p;
1251 
1252         assert(dyncomp != NULL);
1253 
1254         /*
1255          * Get target node path
1256          */
1257         devpath = sata_get_devicepath(ap_id);
1258         if (devpath == NULL) {
1259 
1260                 (void) printf("cfga_list_ext: cannot locate target device\n");
1261                 return (CFGA_SATA_DYNAMIC_AP);
1262 
1263         } else {
1264 
1265                 cp = strrchr(devpath, *PATH_SEP);
1266                 assert(cp != NULL);
1267                 *cp = 0;        /* terminate path for opendir() */
1268 
1269                 (void) strncpy(name_part, cp + 1, MAXNAMELEN);
1270 
1271                 /*
1272                  * Using libdevinfo for this is overkill and kills
1273                  * performance when many consumers are using libcfgadm
1274                  * concurrently.
1275                  */
1276                 if ((dp = opendir(devpath)) == NULL) {
1277                         goto bailout;
1278                 }
1279 
1280                 /*


1556         default:
1557                 rv = CFGA_SATA_STATE;
1558                 goto bailout;
1559         }
1560 
1561         (*ap_id_list)->ap_class[0] = '\0';   /* Filled by libcfgadm */
1562         (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
1563         (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
1564         (*ap_id_list)->ap_info[0] = NULL;
1565 
1566         if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
1567                 char *str_p;
1568                 int skip, i;
1569 
1570                 /*
1571                  * Fill in the 'Information' field for the -v option
1572                  * Model (MOD:)
1573                  */
1574                 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
1575                     NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1576                         (void) printf(
1577                             "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
1578                         goto bailout;
1579                 }
1580                 /* drop leading and trailing spaces */
1581                 skip = strspn(str_p, " ");
1582                 for (i = size - 1; i >= 0; i--) {
1583                         if (str_p[i] == '\040')
1584                                 str_p[i] = '\0';
1585                         else if (str_p[i] != '\0')
1586                                 break;
1587                 }
1588 
1589                 (void) strlcpy((*ap_id_list)->ap_info, "Mod: ",
1590                     sizeof ((*ap_id_list)->ap_info));
1591                 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1592                     sizeof ((*ap_id_list)->ap_info));
1593 
1594                 free(str_p);
1595 
1596                 /*
1597                  * Fill in the 'Information' field for the -v option
1598                  * Firmware revision (FREV:)
1599                  */
1600                 if ((rv = do_control_ioctl(ap_id,
1601                     SATA_CFGA_GET_REVFIRMWARE_INFO,
1602                     NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1603                         (void) printf(
1604                             "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
1605                         goto bailout;
1606                 }
1607                 /* drop leading and trailing spaces */
1608                 skip = strspn(str_p, " ");
1609                 for (i = size - 1; i >= 0; i--) {
1610                         if (str_p[i] == '\040')
1611                                 str_p[i] = '\0';
1612                         else if (str_p[i] != '\0')
1613                                 break;
1614                 }
1615                 (void) strlcat((*ap_id_list)->ap_info, " FRev: ",
1616                     sizeof ((*ap_id_list)->ap_info));
1617                 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1618                     sizeof ((*ap_id_list)->ap_info));
1619 
1620                 free(str_p);
1621 
1622 
1623                 /*
1624                  * Fill in the 'Information' field for the -v option
1625                  * Serial Number (SN:)
1626                  */
1627                 if ((rv = do_control_ioctl(ap_id,
1628                     SATA_CFGA_GET_SERIALNUMBER_INFO,
1629                     NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1630                         (void) printf(
1631                             "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
1632                         goto bailout;
1633                 }
1634                 /* drop leading and trailing spaces */
1635                 skip = strspn(str_p, " ");
1636                 for (i = size - 1; i >= 0; i--) {
1637                         if (str_p[i] == '\040')
1638                                 str_p[i] = '\0';
1639                         else if (str_p[i] != '\0')
1640                                 break;
1641                 }
1642                 (void) strlcat((*ap_id_list)->ap_info, " SN: ",
1643                     sizeof ((*ap_id_list)->ap_info));
1644                 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1645                     sizeof ((*ap_id_list)->ap_info));
1646 
1647                 free(str_p);
1648 
1649 
1650 
1651                 /* Fill in ap_type which is collected from HBA driver */
1652                 /* call do_control_ioctl TBD */
1653                 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
1654                     (void **)&str_p, &size)) != CFGA_SATA_OK) {
1655                         (void) printf(
1656                             "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
1657                         goto bailout;
1658                 }
1659 
1660                 (void) strlcpy((*ap_id_list)->ap_type, str_p,
1661                     sizeof ((*ap_id_list)->ap_type));
1662 
1663                 free(str_p);
1664 
1665                 /*
1666                  * Checking device type. Port multiplier has no dynamic
1667                  * suffix.
1668                  */
1669                 if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
1670                     sizeof ("sata-pmult")) == 0)
1671                         pmult = B_TRUE;
1672 
1673                 if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
1674                     pmult == B_FALSE) {
1675 


1714         if (*ap_id_list != NULL) {
1715                 free(*ap_id_list);
1716         }
1717         if (ap_id_log != NULL) {
1718                 free(ap_id_log);
1719         }
1720 
1721         return (sata_err_msg(errstring, rv, ap_id, errno));
1722 }
1723 /*
1724  * This routine accepts a string adn prints it using
1725  * the message print routine argument.
1726  */
1727 static void
1728 cfga_msg(struct cfga_msg *msgp, const char *str)
1729 {
1730         int len;
1731         char *q;
1732 
1733         if (msgp == NULL || msgp->message_routine == NULL) {
1734                 (void) printf("cfga_msg: NULL msgp\n");
1735                 return;
1736         }
1737 
1738         if ((len = strlen(str)) == 0) {
1739                 (void) printf("cfga_msg: null str\n");
1740                 return;
1741         }
1742 
1743         if ((q = (char *)calloc(len + 1, 1)) == NULL) {
1744                 perror("cfga_msg");
1745                 return;
1746         }
1747 
1748         (void) strcpy(q, str);
1749         (*msgp->message_routine)(msgp->appdata_ptr, q);
1750 
1751         free(q);
1752 }
1753 
1754 /* cfgadm entry point */
1755 /* ARGSUSED */
1756 cfga_err_t
1757 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1758 {
1759         if (options != NULL) {
1760                 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
1761                 cfga_msg(msgp, options);
1762         }
1763         cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
1764         cfga_msg(msgp, sata_help[HELP_CONFIG]);


1807 
1808 
1809 
1810 /*
1811  * Verify the params passed in are valid.
1812  */
1813 static cfga_sata_ret_t
1814 verify_params(
1815     const char *ap_id,
1816     const char *options,
1817     char **errstring)
1818 {
1819         char *pdyn, *lap_id;
1820         int rv;
1821 
1822         if (errstring != NULL) {
1823                 *errstring = NULL;
1824         }
1825 
1826         if (options != NULL) {


1827                 return (CFGA_SATA_OPTIONS);
1828         }
1829 
1830         /* Strip dynamic AP name component if it is present. */
1831         lap_id = strdup(ap_id);
1832         if (lap_id == NULL) {
1833                 return (CFGA_SATA_ALLOC_FAIL);
1834         }
1835         if ((pdyn = GET_DYN(lap_id)) != NULL) {
1836                 *pdyn = '\0';
1837         }
1838 
1839         if (verify_valid_apid(lap_id) != 0) {

1840                 rv = CFGA_SATA_AP;
1841         } else {
1842                 rv = CFGA_SATA_OK;
1843         }
1844         free(lap_id);
1845 
1846         return (rv);
1847 }
1848 
1849 /*
1850  * Takes a validated ap_id and extracts the port number.
1851  * Port multiplier is supported now.
1852  */
1853 static cfga_sata_ret_t
1854 get_port_num(const char *ap_id, uint32_t *port)
1855 {
1856         uint32_t        cport, pmport = 0, qual = 0;
1857         char            *cport_str, *pmport_str;
1858 
1859         /* Get the cport number */


1909         lap_id = strdup(ap_id);
1910         if (lap_id == NULL)
1911                 return (CFGA_SATA_ALLOC_FAIL);
1912         if ((pdyn = GET_DYN(lap_id)) != NULL) {
1913                 *pdyn = '\0';
1914         }
1915 
1916         /* Get a devctl handle to pass to the devctl_ap_XXX functions */
1917         if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
1918                 (void) fprintf(stderr, "[libcfgadm:sata] "
1919                     "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
1920                     strerror(errno));
1921                 rv = CFGA_SATA_DEVCTL;
1922                 goto bailout;
1923         }
1924 
1925         /* Set up nvlist to pass the port number down to the driver */
1926         if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
1927                 *user_nvlistp = NULL;
1928                 rv = CFGA_SATA_NVLIST;
1929                 (void) printf("nvlist_alloc failed\n");
1930                 goto bailout;
1931         }
1932 
1933         /*
1934          * Get port id, for Port Multiplier port, things could be a little bit
1935          * complicated because of "port.port" format in ap_id, thus for
1936          * port multiplier port, port number should be coded as 32bit int
1937          * with the sig 16 bit as sata channel number, least 16 bit as
1938          * the port number of sata port multiplier port.
1939          */
1940         if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
1941                 (void) printf(
1942                     "setup_for_devctl_cmd: get_port_num, errno: %d\n",
1943                     errno);
1944                 goto bailout;
1945         }
1946 
1947         /* Creates an int32_t entry */
1948         if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
1949                 (void) printf("nvlist_add_int32 failed\n");
1950                 rv = CFGA_SATA_NVLIST;
1951                 goto bailout;
1952         }
1953 
1954         free(lap_id);
1955         return (rv);
1956 
1957 bailout:
1958         free(lap_id);
1959         (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
1960 
1961         return (rv);
1962 }
1963 
1964 
1965 static cfga_sata_ret_t
1966 port_state(devctl_hdl_t hdl, nvlist_t *list,
1967     ap_rstate_t *rstate, ap_ostate_t *ostate)
1968 {
1969         devctl_ap_state_t       devctl_ap_state;
1970 
1971         if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
1972                 (void) printf("devctl_ap_getstate failed, errno: %d\n", errno);
1973                 return (CFGA_SATA_IOCTL);
1974         }
1975         *rstate = devctl_ap_state.ap_rstate;
1976         *ostate =  devctl_ap_state.ap_ostate;
1977         return (CFGA_SATA_OK);
1978 }
1979 
1980 
1981 /*
1982  * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
1983  * the data to be returned, allocate a buffer, then get the data.
1984  * Returns *descrp (which must be freed) and size.
1985  *
1986  * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
1987  * not a string descr.
1988  */
1989 cfga_sata_ret_t
1990 do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
1991     void **descrp, size_t *sizep)
1992 {
1993         int                     fd = -1;
1994         uint_t                  port;
1995         uint32_t                local_size;
1996         cfga_sata_ret_t         rv = CFGA_SATA_OK;
1997         struct sata_ioctl_data  ioctl_data;
1998 
1999         assert(descrp != NULL);
2000         *descrp = NULL;
2001         assert(sizep != NULL);
2002 
2003         if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
2004                 goto bailout;
2005         }
2006 
2007         if ((fd = open(ap_id, O_RDONLY)) == -1) {
2008                 (void) printf("do_control_ioctl: open failed: errno:%d\n",
2009                     errno);
2010                 rv = CFGA_SATA_OPEN;
2011                 if (errno == EBUSY) {
2012                         rv = CFGA_SATA_BUSY;
2013                 }
2014                 goto bailout;
2015         }
2016 
2017         ioctl_data.cmd = subcommand;
2018         ioctl_data.port = port;
2019         ioctl_data.misc_arg = (uint_t)arg;
2020 
2021         /*
2022          * Find out how large a buf we need to get the data.
2023          * Note the ioctls only accept/return a 32-bit int for a get_size
2024          * to avoid 32/64 and BE/LE issues.
2025          */
2026         if ((subcommand == SATA_CFGA_GET_AP_TYPE) ||
2027             (subcommand == SATA_CFGA_GET_DEVICE_PATH) ||
2028             (subcommand == SATA_CFGA_GET_MODEL_INFO) ||
2029             (subcommand == SATA_CFGA_GET_REVFIRMWARE_INFO) ||
2030             (subcommand == SATA_CFGA_GET_SERIALNUMBER_INFO)) {
2031                 ioctl_data.get_size = B_TRUE;
2032                 ioctl_data.buf = (caddr_t)&local_size;
2033                 ioctl_data.bufsiz = sizeof (local_size);
2034 
2035                 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2036                         perror("ioctl failed (size)");
2037                         rv = CFGA_SATA_IOCTL;
2038                         goto bailout;
2039                 }
2040                 *sizep = local_size;
2041 
2042                 if (local_size == 0) {
2043                         (void) printf("zero length data\n");
2044                         rv = CFGA_SATA_ZEROLEN;
2045                         goto bailout;
2046                 }
2047                 if ((*descrp = malloc(*sizep)) == NULL) {
2048                         (void) printf("do_control_ioctl: malloc failed\n");
2049                         rv = CFGA_SATA_ALLOC_FAIL;
2050                         goto bailout;
2051                 }
2052         } else {
2053                 *sizep = 0;
2054         }
2055         ioctl_data.get_size = B_FALSE;
2056         ioctl_data.buf = *descrp;
2057         ioctl_data.bufsiz = *sizep;
2058 
2059         /* Execute IOCTL */
2060 
2061         if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2062                 rv = CFGA_SATA_IOCTL;
2063                 goto bailout;
2064         }
2065 
2066         (void) close(fd);
2067 
2068         return (rv);




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
  25  * Use is subject to license terms.
  26  */
  27 
  28 #include <sys/param.h>
  29 #include <sys/stat.h>
  30 #include <errno.h>
  31 #include <string.h>
  32 #include <dirent.h>
  33 #include "cfga_sata.h"
  34 
  35 /*
  36  * This file contains the entry points to the plug-in as defined in the
  37  * config_admin(3X) man page.
  38  */
  39 
  40 /*
  41  * Set the version number for the cfgadm library's use.
  42  */
  43 int cfga_version = CFGA_HSL_V2;
  44 


 698 
 699                 len = strlen(SATA_CONFIRM_DEVICE) +
 700                     strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
 701                     strlen("Unconfigure") + strlen(ap_id);
 702                 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 703                         (void) snprintf(msg, len + 3, "Unconfigure"
 704                             " %s%s\n%s",
 705                             SATA_CONFIRM_DEVICE, ap_id,
 706                             SATA_CONFIRM_DEVICE_SUSPEND);
 707                 }
 708 
 709                 if (!sata_confirm(confp, msg)) {
 710                         free(msg);
 711                         rv = CFGA_SATA_NACK;
 712                         break;
 713                 }
 714                 free(msg);
 715 
 716                 devpath = sata_get_devicepath(ap_id);
 717                 if (devpath == NULL) {
 718                         DPRINTF(
 719                             "cfga_change_state: get device path failed\n");
 720                         rv = CFGA_SATA_DEV_UNCONFIGURE;
 721                         break;
 722                 }
 723 
 724                 if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
 725                     != CFGA_SATA_OK) {
 726                         break;
 727                 }
 728 
 729                 ret = devctl_ap_unconfigure(hdl, nvl);
 730 
 731                 if (ret != 0) {
 732                         rv = CFGA_SATA_DEV_UNCONFIGURE;
 733                         if (errno == EBUSY) {
 734                                 rv = CFGA_SATA_BUSY;
 735                         }
 736                         (void) sata_rcm_online(ap_id, errstring, devpath,
 737                             flags);
 738                 } else {


 755                 }
 756 
 757                 /* Strip off AP name dynamic component, if present */
 758                 if ((pdyn = GET_DYN(ap_id)) != NULL) {
 759                         *pdyn = '\0';
 760                 }
 761 
 762 
 763                 rv = CFGA_SATA_OK; /* other statuses don't matter */
 764 
 765                 /*
 766                  * If the port originally with device attached and was
 767                  * unconfigured already, the devicepath for the sd will be
 768                  * removed. sata_get_devicepath in this case is not necessary.
 769                  */
 770                 /* only call rcm_offline if the state was CONFIGURED */
 771                 if (ostate == AP_OSTATE_CONFIGURED &&
 772                     pmult == B_FALSE) {
 773                         devpath = sata_get_devicepath(ap_id);
 774                         if (devpath == NULL) {
 775                                 DPRINTF(
 776                                     "cfga_change_state: get path failed\n");
 777                                 rv = CFGA_SATA_DEV_UNCONFIGURE;
 778                                 break;
 779                         }
 780 
 781                         len = strlen(SATA_CONFIRM_DEVICE) +
 782                             strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
 783                             strlen("Disconnect") + strlen(ap_id);
 784                         if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 785                                 (void) snprintf(msg, len + 3,
 786                                     "Disconnect"
 787                                     " %s%s\n%s",
 788                                     SATA_CONFIRM_DEVICE, ap_id,
 789                                     SATA_CONFIRM_DEVICE_SUSPEND);
 790                         }
 791                         if (!sata_confirm(confp, msg)) {
 792                                 free(msg);
 793                                 rv = CFGA_SATA_NACK;
 794                                 break;
 795                         }


 930         devctl_hdl_t            hdl = NULL;
 931         cfga_sata_ret_t         rv;
 932         char                    *str_p;
 933         size_t                  size;
 934 
 935         if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
 936                 (void) cfga_help(msgp, options, flags);
 937                 return (sata_err_msg(errstring, rv, ap_id, errno));
 938         }
 939 
 940         /*
 941          * All subcommands which can change state of device require
 942          * root privileges.
 943          */
 944         if (geteuid() != 0) {
 945                 rv = CFGA_SATA_PRIV;
 946                 goto bailout;
 947         }
 948 
 949         if (func == NULL) {
 950                 DPRINTF("No valid option specified\n");
 951                 rv = CFGA_SATA_OPTIONS;
 952                 goto bailout;
 953         }
 954 
 955         if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
 956             CFGA_SATA_OK) {
 957                 goto bailout;
 958         }
 959 
 960         /* We do not care here about dynamic AP name component */
 961         if ((str_p = GET_DYN(ap_id)) != NULL) {
 962                 *str_p = '\0';
 963         }
 964 
 965         rv = CFGA_SATA_OK;
 966 
 967         if (strcmp(func, SATA_RESET_PORT) == 0) {
 968                 len = strlen(SATA_CONFIRM_PORT) +
 969                     strlen(SATA_CONFIRM_DEVICE_ABORT) +
 970                     strlen("Reset Port") + strlen(ap_id);


1241         char    minor_path[MAXPATHLEN];
1242         char    name_part[MAXNAMELEN];
1243         char    *devlink = NULL;
1244         char    *minor_portion = NULL;
1245         int     deplen;
1246         int     err;
1247         DIR     *dp = NULL;
1248         struct stat sb;
1249         struct dirent *dep = NULL;
1250         struct dirent *newdep = NULL;
1251         char    *p;
1252 
1253         assert(dyncomp != NULL);
1254 
1255         /*
1256          * Get target node path
1257          */
1258         devpath = sata_get_devicepath(ap_id);
1259         if (devpath == NULL) {
1260 
1261                 DPRINTF("cfga_list_ext: cannot locate target device\n");
1262                 return (CFGA_SATA_DYNAMIC_AP);
1263 
1264         } else {
1265 
1266                 cp = strrchr(devpath, *PATH_SEP);
1267                 assert(cp != NULL);
1268                 *cp = 0;        /* terminate path for opendir() */
1269 
1270                 (void) strncpy(name_part, cp + 1, MAXNAMELEN);
1271 
1272                 /*
1273                  * Using libdevinfo for this is overkill and kills
1274                  * performance when many consumers are using libcfgadm
1275                  * concurrently.
1276                  */
1277                 if ((dp = opendir(devpath)) == NULL) {
1278                         goto bailout;
1279                 }
1280 
1281                 /*


1557         default:
1558                 rv = CFGA_SATA_STATE;
1559                 goto bailout;
1560         }
1561 
1562         (*ap_id_list)->ap_class[0] = '\0';   /* Filled by libcfgadm */
1563         (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
1564         (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
1565         (*ap_id_list)->ap_info[0] = NULL;
1566 
1567         if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
1568                 char *str_p;
1569                 int skip, i;
1570 
1571                 /*
1572                  * Fill in the 'Information' field for the -v option
1573                  * Model (MOD:)
1574                  */
1575                 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
1576                     NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1577                         DPRINTF(
1578                             "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
1579                         goto bailout;
1580                 }
1581                 /* drop leading and trailing spaces */
1582                 skip = strspn(str_p, " ");
1583                 for (i = size - 1; i >= 0; i--) {
1584                         if (str_p[i] == '\040')
1585                                 str_p[i] = '\0';
1586                         else if (str_p[i] != '\0')
1587                                 break;
1588                 }
1589 
1590                 (void) strlcpy((*ap_id_list)->ap_info, "Mod: ",
1591                     sizeof ((*ap_id_list)->ap_info));
1592                 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1593                     sizeof ((*ap_id_list)->ap_info));
1594 
1595                 free(str_p);
1596 
1597                 /*
1598                  * Fill in the 'Information' field for the -v option
1599                  * Firmware revision (FREV:)
1600                  */
1601                 if ((rv = do_control_ioctl(ap_id,
1602                     SATA_CFGA_GET_REVFIRMWARE_INFO,
1603                     NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1604                         DPRINTF(
1605                             "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
1606                         goto bailout;
1607                 }
1608                 /* drop leading and trailing spaces */
1609                 skip = strspn(str_p, " ");
1610                 for (i = size - 1; i >= 0; i--) {
1611                         if (str_p[i] == '\040')
1612                                 str_p[i] = '\0';
1613                         else if (str_p[i] != '\0')
1614                                 break;
1615                 }
1616                 (void) strlcat((*ap_id_list)->ap_info, " FRev: ",
1617                     sizeof ((*ap_id_list)->ap_info));
1618                 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1619                     sizeof ((*ap_id_list)->ap_info));
1620 
1621                 free(str_p);
1622 
1623 
1624                 /*
1625                  * Fill in the 'Information' field for the -v option
1626                  * Serial Number (SN:)
1627                  */
1628                 if ((rv = do_control_ioctl(ap_id,
1629                     SATA_CFGA_GET_SERIALNUMBER_INFO,
1630                     NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1631                         DPRINTF(
1632                             "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
1633                         goto bailout;
1634                 }
1635                 /* drop leading and trailing spaces */
1636                 skip = strspn(str_p, " ");
1637                 for (i = size - 1; i >= 0; i--) {
1638                         if (str_p[i] == '\040')
1639                                 str_p[i] = '\0';
1640                         else if (str_p[i] != '\0')
1641                                 break;
1642                 }
1643                 (void) strlcat((*ap_id_list)->ap_info, " SN: ",
1644                     sizeof ((*ap_id_list)->ap_info));
1645                 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1646                     sizeof ((*ap_id_list)->ap_info));
1647 
1648                 free(str_p);
1649 
1650 
1651 
1652                 /* Fill in ap_type which is collected from HBA driver */
1653                 /* call do_control_ioctl TBD */
1654                 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
1655                     (void **)&str_p, &size)) != CFGA_SATA_OK) {
1656                         DPRINTF(
1657                             "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
1658                         goto bailout;
1659                 }
1660 
1661                 (void) strlcpy((*ap_id_list)->ap_type, str_p,
1662                     sizeof ((*ap_id_list)->ap_type));
1663 
1664                 free(str_p);
1665 
1666                 /*
1667                  * Checking device type. Port multiplier has no dynamic
1668                  * suffix.
1669                  */
1670                 if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
1671                     sizeof ("sata-pmult")) == 0)
1672                         pmult = B_TRUE;
1673 
1674                 if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
1675                     pmult == B_FALSE) {
1676 


1715         if (*ap_id_list != NULL) {
1716                 free(*ap_id_list);
1717         }
1718         if (ap_id_log != NULL) {
1719                 free(ap_id_log);
1720         }
1721 
1722         return (sata_err_msg(errstring, rv, ap_id, errno));
1723 }
1724 /*
1725  * This routine accepts a string adn prints it using
1726  * the message print routine argument.
1727  */
1728 static void
1729 cfga_msg(struct cfga_msg *msgp, const char *str)
1730 {
1731         int len;
1732         char *q;
1733 
1734         if (msgp == NULL || msgp->message_routine == NULL) {
1735                 DPRINTF("cfga_msg: msg\n");
1736                 return;
1737         }
1738 
1739         if ((len = strlen(str)) == 0) {
1740                 DPRINTF("cfga_msg: null str\n");
1741                 return;
1742         }
1743 
1744         if ((q = (char *)calloc(len + 1, 1)) == NULL) {
1745                 DPRINTF("cfga_msg: null q\n");
1746                 return;
1747         }
1748 
1749         (void) strcpy(q, str);
1750         (*msgp->message_routine)(msgp->appdata_ptr, q);
1751 
1752         free(q);
1753 }
1754 
1755 /* cfgadm entry point */
1756 /* ARGSUSED */
1757 cfga_err_t
1758 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1759 {
1760         if (options != NULL) {
1761                 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
1762                 cfga_msg(msgp, options);
1763         }
1764         cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
1765         cfga_msg(msgp, sata_help[HELP_CONFIG]);


1808 
1809 
1810 
1811 /*
1812  * Verify the params passed in are valid.
1813  */
1814 static cfga_sata_ret_t
1815 verify_params(
1816     const char *ap_id,
1817     const char *options,
1818     char **errstring)
1819 {
1820         char *pdyn, *lap_id;
1821         int rv;
1822 
1823         if (errstring != NULL) {
1824                 *errstring = NULL;
1825         }
1826 
1827         if (options != NULL) {
1828                 DPRINTF("verify_params: hardware-specific options not "
1829                     "supported.\n");
1830                 return (CFGA_SATA_OPTIONS);
1831         }
1832 
1833         /* Strip dynamic AP name component if it is present. */
1834         lap_id = strdup(ap_id);
1835         if (lap_id == NULL) {
1836                 return (CFGA_SATA_ALLOC_FAIL);
1837         }
1838         if ((pdyn = GET_DYN(lap_id)) != NULL) {
1839                 *pdyn = '\0';
1840         }
1841 
1842         if (verify_valid_apid(lap_id) != 0) {
1843                 DPRINTF("verify_params: not a SATA ap_id.\n");
1844                 rv = CFGA_SATA_AP;
1845         } else {
1846                 rv = CFGA_SATA_OK;
1847         }
1848         free(lap_id);
1849 
1850         return (rv);
1851 }
1852 
1853 /*
1854  * Takes a validated ap_id and extracts the port number.
1855  * Port multiplier is supported now.
1856  */
1857 static cfga_sata_ret_t
1858 get_port_num(const char *ap_id, uint32_t *port)
1859 {
1860         uint32_t        cport, pmport = 0, qual = 0;
1861         char            *cport_str, *pmport_str;
1862 
1863         /* Get the cport number */


1913         lap_id = strdup(ap_id);
1914         if (lap_id == NULL)
1915                 return (CFGA_SATA_ALLOC_FAIL);
1916         if ((pdyn = GET_DYN(lap_id)) != NULL) {
1917                 *pdyn = '\0';
1918         }
1919 
1920         /* Get a devctl handle to pass to the devctl_ap_XXX functions */
1921         if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
1922                 (void) fprintf(stderr, "[libcfgadm:sata] "
1923                     "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
1924                     strerror(errno));
1925                 rv = CFGA_SATA_DEVCTL;
1926                 goto bailout;
1927         }
1928 
1929         /* Set up nvlist to pass the port number down to the driver */
1930         if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
1931                 *user_nvlistp = NULL;
1932                 rv = CFGA_SATA_NVLIST;
1933                 DPRINTF("nvlist_alloc failed\n");
1934                 goto bailout;
1935         }
1936 
1937         /*
1938          * Get port id, for Port Multiplier port, things could be a little bit
1939          * complicated because of "port.port" format in ap_id, thus for
1940          * port multiplier port, port number should be coded as 32bit int
1941          * with the sig 16 bit as sata channel number, least 16 bit as
1942          * the port number of sata port multiplier port.
1943          */
1944         if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
1945                 DPRINTF(
1946                     "setup_for_devctl_cmd: get_port_num, errno: %d\n",
1947                     errno);
1948                 goto bailout;
1949         }
1950 
1951         /* Creates an int32_t entry */
1952         if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
1953                 DPRINTF("nvlist_add_int32 failed\n");
1954                 rv = CFGA_SATA_NVLIST;
1955                 goto bailout;
1956         }
1957 
1958         free(lap_id);
1959         return (rv);
1960 
1961 bailout:
1962         free(lap_id);
1963         (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
1964 
1965         return (rv);
1966 }
1967 
1968 
1969 static cfga_sata_ret_t
1970 port_state(devctl_hdl_t hdl, nvlist_t *list,
1971     ap_rstate_t *rstate, ap_ostate_t *ostate)
1972 {
1973         devctl_ap_state_t       devctl_ap_state;
1974 
1975         if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
1976                 DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno);
1977                 return (CFGA_SATA_IOCTL);
1978         }
1979         *rstate = devctl_ap_state.ap_rstate;
1980         *ostate =  devctl_ap_state.ap_ostate;
1981         return (CFGA_SATA_OK);
1982 }
1983 
1984 
1985 /*
1986  * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
1987  * the data to be returned, allocate a buffer, then get the data.
1988  * Returns *descrp (which must be freed) and size.
1989  *
1990  * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
1991  * not a string descr.
1992  */
1993 cfga_sata_ret_t
1994 do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
1995     void **descrp, size_t *sizep)
1996 {
1997         int                     fd = -1;
1998         uint_t                  port;
1999         uint32_t                local_size;
2000         cfga_sata_ret_t         rv = CFGA_SATA_OK;
2001         struct sata_ioctl_data  ioctl_data;
2002 
2003         assert(descrp != NULL);
2004         *descrp = NULL;
2005         assert(sizep != NULL);
2006 
2007         if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
2008                 goto bailout;
2009         }
2010 
2011         if ((fd = open(ap_id, O_RDONLY)) == -1) {
2012                 DPRINTF("do_control_ioctl: open failed: errno:%d\n",
2013                     errno);
2014                 rv = CFGA_SATA_OPEN;
2015                 if (errno == EBUSY) {
2016                         rv = CFGA_SATA_BUSY;
2017                 }
2018                 goto bailout;
2019         }
2020 
2021         ioctl_data.cmd = subcommand;
2022         ioctl_data.port = port;
2023         ioctl_data.misc_arg = (uint_t)arg;
2024 
2025         /*
2026          * Find out how large a buf we need to get the data.
2027          * Note the ioctls only accept/return a 32-bit int for a get_size
2028          * to avoid 32/64 and BE/LE issues.
2029          */
2030         if ((subcommand == SATA_CFGA_GET_AP_TYPE) ||
2031             (subcommand == SATA_CFGA_GET_DEVICE_PATH) ||
2032             (subcommand == SATA_CFGA_GET_MODEL_INFO) ||
2033             (subcommand == SATA_CFGA_GET_REVFIRMWARE_INFO) ||
2034             (subcommand == SATA_CFGA_GET_SERIALNUMBER_INFO)) {
2035                 ioctl_data.get_size = B_TRUE;
2036                 ioctl_data.buf = (caddr_t)&local_size;
2037                 ioctl_data.bufsiz = sizeof (local_size);
2038 
2039                 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2040                         perror("ioctl failed (size)");
2041                         rv = CFGA_SATA_IOCTL;
2042                         goto bailout;
2043                 }
2044                 *sizep = local_size;
2045 
2046                 if (local_size == 0) {
2047                         DPRINTF("zero length data\n");
2048                         rv = CFGA_SATA_ZEROLEN;
2049                         goto bailout;
2050                 }
2051                 if ((*descrp = malloc(*sizep)) == NULL) {
2052                         DPRINTF("do_control_ioctl: malloc failed\n");
2053                         rv = CFGA_SATA_ALLOC_FAIL;
2054                         goto bailout;
2055                 }
2056         } else {
2057                 *sizep = 0;
2058         }
2059         ioctl_data.get_size = B_FALSE;
2060         ioctl_data.buf = *descrp;
2061         ioctl_data.bufsiz = *sizep;
2062 
2063         /* Execute IOCTL */
2064 
2065         if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2066                 rv = CFGA_SATA_IOCTL;
2067                 goto bailout;
2068         }
2069 
2070         (void) close(fd);
2071 
2072         return (rv);