Print this page
NEX-9654 sd(7D) leaks memory when posting ereports
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
   1 /*
   2  * CDDL HEADER START
   3  *
   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  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  23  */
  24 
  25 /*
  26  * SCSI FMA implementation
  27  */
  28 
  29 #include <sys/scsi/scsi_types.h>
  30 #include <sys/sunmdi.h>
  31 #include <sys/va_list.h>
  32 
  33 #include <sys/ddi_impldefs.h>
  34 
  35 /* consolidation private interface to generate dev scheme ereport */
  36 extern void fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
  37     const char *devpath, const char *minor_name, const char *devid,
  38     const char *tpl0, const char *error_class, uint64_t ena, int sflag,
  39     nvlist_t *, va_list ap);
  40 extern char *mdi_pi_pathname_by_instance(int);
  41 
  42 #define FM_SCSI_CLASS   "scsi"


  82 {
  83         dev_info_t      *dip = sd->sd_dev;
  84 
  85         if (sd->sd_fm_capable != DDI_FM_NOT_CAPABLE)
  86                 ddi_fm_fini(dip);
  87 }
  88 
  89 /*
  90  *
  91  * scsi_fm_ereport_post - Post an ereport
  92  */
  93 void
  94 scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
  95     char *devpath, const char *error_class, uint64_t ena,
  96     char *devid, char *tpl0, int sflag, nvlist_t *pl, ...)
  97 {
  98         char            class[ERPT_CLASS_SZ];
  99         dev_info_t      *dip = sd->sd_dev;
 100         dev_info_t      *eqdip = dip;
 101         char            *minor_name;


 102         va_list         ap;
 103 
 104         /*
 105          * If the scsi_device eqdip is not yet ereport capable, send the
 106          * report based on parent capabilities.  This is needed for
 107          * telemetry during enumeration.
 108          */
 109         if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(eqdip)))
 110                 eqdip = ddi_get_parent(eqdip);
 111 
 112         /* Add "scsi." as a prefix to the class */
 113         (void) snprintf(class, ERPT_CLASS_SZ, "%s.%s",
 114             FM_SCSI_CLASS, error_class);
 115 
 116         /*
 117          * Get the path:
 118          *
 119          * If path_instance is non-zero then the packet was
 120          * sent to scsi_vhci. We return the pathinfo path_string associated
 121          * with the path_instance path - which refers to the actual hardware.
 122          *
 123          * If path_instance is zero then use the devpath provided by the
 124          * caller;  if it was NULL then this will cause fm_dev_ereport_post
 125          * to use the devinfo path of the first devi we pass to it, ie
 126          * sd->sd_dev.
 127          */
 128         if (path_instance)
 129                 devpath = mdi_pi_pathname_by_instance(path_instance);
 130 
 131         /*
 132          * Set the minor_name to NULL. The block location of a media error
 133          * is described by the 'lba' property. We use the 'lba' instead of
 134          * the partition (minor_name) because the defect stays in the same
 135          * place even when a repartition operation may result in the defect
 136          * showing up in a different partition (minor_name). To support
 137          * retire at the block/partition level, the user level retire agent
 138          * should map the 'lba' to the current effected partition.
 139          */
 140         minor_name = NULL;
 141 




























 142         /*
 143          * NOTE: If there is a 'linked' ena to be had, it should likely come
 144          * from the buf structure via the scsi_pkt pkt->pkt_bp.
 145          */
 146 
 147         /* Post the ereport */
 148         va_start(ap, pl);
 149         fm_dev_ereport_postv(dip, eqdip, devpath, minor_name, devid, tpl0,
 150             class, ena, sflag, pl, ap);
 151         va_end(ap);


 152 }
   1 /*
   2  * CDDL HEADER START
   3  *
   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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2017 Nexenta Systems, Inc.
  25  */
  26 
  27 /*
  28  * SCSI FMA implementation
  29  */
  30 
  31 #include <sys/scsi/scsi_types.h>
  32 #include <sys/sunmdi.h>
  33 #include <sys/va_list.h>
  34 
  35 #include <sys/ddi_impldefs.h>
  36 
  37 /* consolidation private interface to generate dev scheme ereport */
  38 extern void fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
  39     const char *devpath, const char *minor_name, const char *devid,
  40     const char *tpl0, const char *error_class, uint64_t ena, int sflag,
  41     nvlist_t *, va_list ap);
  42 extern char *mdi_pi_pathname_by_instance(int);
  43 
  44 #define FM_SCSI_CLASS   "scsi"


  84 {
  85         dev_info_t      *dip = sd->sd_dev;
  86 
  87         if (sd->sd_fm_capable != DDI_FM_NOT_CAPABLE)
  88                 ddi_fm_fini(dip);
  89 }
  90 
  91 /*
  92  *
  93  * scsi_fm_ereport_post - Post an ereport
  94  */
  95 void
  96 scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
  97     char *devpath, const char *error_class, uint64_t ena,
  98     char *devid, char *tpl0, int sflag, nvlist_t *pl, ...)
  99 {
 100         char            class[ERPT_CLASS_SZ];
 101         dev_info_t      *dip = sd->sd_dev;
 102         dev_info_t      *eqdip = dip;
 103         char            *minor_name;
 104         nvlist_t        *nvl;
 105         char            *prop;
 106         va_list         ap;
 107 
 108         /*
 109          * If the scsi_device eqdip is not yet ereport capable, send the
 110          * report based on parent capabilities.  This is needed for
 111          * telemetry during enumeration.
 112          */
 113         if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(eqdip)))
 114                 eqdip = ddi_get_parent(eqdip);
 115 
 116         /* Add "scsi." as a prefix to the class */
 117         (void) snprintf(class, ERPT_CLASS_SZ, "%s.%s",
 118             FM_SCSI_CLASS, error_class);
 119 
 120         /*
 121          * Get the path:
 122          *
 123          * If path_instance is non-zero then the packet was
 124          * sent to scsi_vhci. We return the pathinfo path_string associated
 125          * with the path_instance path - which refers to the actual hardware.
 126          *
 127          * If path_instance is zero then use the devpath provided by the
 128          * caller;  if it was NULL then this will cause fm_dev_ereport_post
 129          * to use the devinfo path of the first devi we pass to it, ie
 130          * sd->sd_dev.
 131          */
 132         if (path_instance)
 133                 devpath = mdi_pi_pathname_by_instance(path_instance);
 134 
 135         /*
 136          * Set the minor_name to NULL. The block location of a media error
 137          * is described by the 'lba' property. We use the 'lba' instead of
 138          * the partition (minor_name) because the defect stays in the same
 139          * place even when a repartition operation may result in the defect
 140          * showing up in a different partition (minor_name). To support
 141          * retire at the block/partition level, the user level retire agent
 142          * should map the 'lba' to the current effected partition.
 143          */
 144         minor_name = NULL;
 145 
 146         /* Create nvlist containing inquiry properties (if available) */
 147         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, (sflag & DDI_NOSLEEP) ?
 148             KM_NOSLEEP : KM_SLEEP) != 0)
 149                 return;
 150         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 151             INQUIRY_VENDOR_ID, &prop) == DDI_PROP_SUCCESS) {
 152                 (void) nvlist_add_string(nvl, "vendor", prop);
 153                 ddi_prop_free(prop);
 154         }
 155         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 156             INQUIRY_PRODUCT_ID, &prop) == DDI_PROP_SUCCESS) {
 157                 (void) nvlist_add_string(nvl, "product", prop);
 158                 ddi_prop_free(prop);
 159         }
 160         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 161             INQUIRY_REVISION_ID, &prop) == DDI_PROP_SUCCESS) {
 162                 (void) nvlist_add_string(nvl, "revision", prop);
 163                 ddi_prop_free(prop);
 164         }
 165         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 166             INQUIRY_SERIAL_NO, &prop) == DDI_PROP_SUCCESS) {
 167                 (void) nvlist_add_string(nvl, "serial", prop);
 168                 ddi_prop_free(prop);
 169         }
 170         /* Merge the provided payload if any */
 171         if (pl != NULL)
 172                 (void) nvlist_merge(nvl, pl, 0);
 173 
 174         /*
 175          * NOTE: If there is a 'linked' ena to be had, it should likely come
 176          * from the buf structure via the scsi_pkt pkt->pkt_bp.
 177          */
 178 
 179         /* Post the ereport */
 180         va_start(ap, pl);
 181         fm_dev_ereport_postv(dip, eqdip, devpath, minor_name, devid, tpl0,
 182             class, ena, sflag, nvl, ap);
 183         va_end(ap);
 184 
 185         nvlist_free(nvl);
 186 }