Go to main content

man pages section 9: DDI and DKI Kernel Functions

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

kstat2_create (9F)

Name

kstat2_create - create and initialize a new kstat

Synopsis

#include <sys/types.h>
#include <sys/kstat2.h>

kstat2_t *kstat2_create(const char *pseg[], uint32_t npseg,
          const zoneid_t ks_zone, kstat2_named_t *ks_data,
          uint_t ks_ndata, uint32_t ks_flags,
          const kstat2_md_t *ks_metadata,
          const char *ks_desc, kstat2_metaflag_t ks_mflags);

Interface Level

Solaris DDI specific (Solaris DDI)

Parameters

ks_pseg

The segments used to construct a path which uniquely identifies this kstat. For example, “unix”, “cpu”, “cpu_info”, “1”.

ks_npseg

The number of path segments in the array kstat_pseg.

ks_zone

The ID of the zone in which kstat will initially be visible. The constant ALL_ZONES is used to make the kstat visible in all zones, and GLOBAL_ZONEID to make it visible only in the global zone. To make the kstat visible in other zones, see kstat2_zone_add(9F) and description of KSTAT2_FLAG_GZ_VIS later in the man page.

ks_data

This argument must be NULL for kstats whose storage is managed by the framework, and a pointer to an array of kstat2 name-value pairs for kstats whose data storage is managed by the kstat provider.

ks_ndata

The number of name-value pairs in the ks_data section of the kstat.

ks_flags

A bit-field of various flags for this kstat. The only flag which is available for use by kstat providers is:

KSTAT2_FLAG_PERSISTENT

Indicates that this kstat is persistent over time. For persistent kstats, kstat2_delete(9F) function marks the kstat as dormant; a subsequent kstat2_create() function reactivates the kstat. This feature is provided so that statistics are not lost across driver close or open (such as raw disk I/O on a disk with no mounted partitions). Note that persistent kstats cannot have their storage managed by the driver since ks_data points to garbage as soon as the driver goes away.

KSTAT2_FLAG_GZ_VIS

Indicates that this kstat is created and made visible in both the global zone and ks_zone, if kz_zone is the ID of a non-global zone.

ks_metadata

The metadata for the values held in the kstat's ks_data structure. This metadata is an array of kstat2_md_t structures of the same length and in the same order as the kstat name-value pairs in ks_data.

ks_desc

A brief string describing the purpose of this kstat. This string must be statically allocated as a pointer to it, which is held in the kstat.

ks_mflags

Meta-flags for the kstat as a whole.

KSTAT2_MF_NONE

Indicates that this kstat has no meta-flags set.

KSTAT2_MF_STABLE

Indicates that this kstat is considered stable and will not be removed from Oracle Solaris without prior notification.

KSTAT2_MF_PRIV

Indicates that this kstat contains sensitive content which can only be read by users having the appropriate RBAC privilege.

Description

kstat2_create() function is used in conjunction with kstat2_install(9F) to allocate and initialize a kstat2(9S) structure. The method is generally as follows:

kstat2_create() function allocates and performs necessary system initialization of a kstat2(9S) structure. kstat2_create() function allocates memory for the entire kstat (including data if necessary), initializes all header fields and the data section, assigns a unique kstat ID (KID), and then puts the kstat onto the system's kstat chain. The returned kstat is marked invalid because the provider (caller) may not have initialized the data section.

After a successful call to kstat2_create() function, the provider can set the ks2_update, ks2_private and ks2_lock fields if necessary, and must initialize the name-value pairs in ks2_data.

Once the kstat is completely initialized, kstat2_install(9F) function is used to make the kstat accessible to the outside world.

Kstats containing data which may be regarded as sensitive should have the KSTAT_MF_PRIV flag set in metadata. Kstats with this flag set are only visible to and readable by users having the RBAC privilege: kstat_rd_sensitive.

Return Values

If successful, the kstat2_create() function returns a pointer to the allocated kstat. NULL is returned upon failure.

Context

The kstat2_create() function can be called from user or kernel context.

Examples

Example 1 Create a kstat with framework allocated storage
#include <sys/types.h>
#include <sys/kstat2.h>

static const kstat2_md_t[2] md = {
    { KSTAT2_NVMT_CNT, KSTAT2_NVMF_NONE, 1UL,
        "Caller count", KSTAT1_DATA_NONE },
    { KSTAT2_NVMT_UNK, KSTAT2_NVMF_NONE, 0UL,
        "Last caller name", KSTAT1_DATA_NONE }
};
static const uint_t ndata = sizeof (md) / sizeof (kstat2_md_t);
static kmutex_t my_lock;

static kstat2_t
my_drv_create_kstat()
{
    kstat2_t *ksp;
    const char *pseg[] = { "misc", "my_drv", "data_in", "0" };

    ksp = kstat2_create(pseg, sizeof (pseg) / sizeof (char *),
        ALL_ZONES, NULL, ndata, 0, md,
        "data read by my_drv", KSTAT2_MF_NONE);

    if (ksp != NULL) {
        /*
         * Kstat name-value pairs must be initialized
         * before calling kstat2_install()
         */
        kstat2_named_t *knp = KSTAT2_NV_PTR(ksp);
        kstat2_nv_init(knp, "int_data", KSTAT2_NVVT_INT, KSTAT2_NVF_NONE);
        kstat2_nv_init(knp+1, "str_data", KSTAT2_NVVT_STR, KSTAT2_NVF_NONE);

        /*
         * Set kstat's lock because there is variable
         * data in the kstat (KSTAT2_NVVT_STR).
         */
        ksp->ks2_lock = &my_lock;
        kstat2_install(ksp);
    }
    return (ksp);
}
Example 2 Create a kstat with driver allocated storage
#include <sys/types.h>
#include <sys/kstat2.h>

static const kstat2_md_t[2] md = {
    { KSTAT2_NVMT_BYTES, KSTAT2_NVMF_NONE, 1UL,
        "int1 byte count", KSTAT1_DATA_NONE },
    { KSTAT2_NVMT_BYTES, KSTAT2_NVMF_NONE, 1UL,
        "int2 byte count", KSTAT1_DATA_NONE }
};
static const uint_t ndata = sizeof (md) / sizeof (kstat2_md_t);
static kstat2_named_t my_drv_kvals[2];
static kmutex_t my_lock;

static kstat2_t
my_drv_create_kstat()
{
    kstat2_t *ksp;
    const char *pseg[] = { "misc", "my_drv", "data_in", "0" };

    ksp = kstat2_create(pseg, sizeof (pseg) / sizeof (char *),
        ALL_ZONES, my_drv_kvals, ndata, 0, md,
        "data read by my_drv", KSTAT2_MF_NONE);

    if (ksp != NULL) {
        /*
         * Kstat name-value pairs must be initialized
         * before calling kstat2_install(). This could also be done
         * in a static initializer of my_drv_kvals.
         */
        kstat2_nv_init(my_drv_kvals[0], "int1",
            KSTAT2_NVVT_INT, KSTAT2_NVF_NONE);
        kstat2_nv_init(my_drv_kvals[1], "int2",
            KSTAT2_NVVT_INT, KSTAT2_NVF_NONE);

        kstat2_install(ksp);
    }
    return (ksp);
}
Example 3 Create a persistent kstat
#include <sys/types.h>
#include <sys/kstat2.h>

static const kstat2_md_t[2] md = {
    { KSTAT2_NVMT_CNT, KSTAT2_NVMF_NONE, 1UL,
       "data errors", KSTAT1_DATA_NONE },
    { KSTAT2_NVMT_CNT, KSTAT2_NVMF_NONE, 1UL,
      "transport errors", KSTAT1_DATA_NONE }
};
static const uint_t ndata = sizeof (md) / sizeof (kstat2_md_t);

static kstat2_t
create_dsk_error_kstat(const char *ddi_inst_str)
{
    kstat2_t *ksp;
    const char *pseg[] = { "disk", "mydrv", ddi_inst_str, "err" };

          /*
           * Create a persistent kstat for the disk error data.
           * Note that the kstat's framework must allocate and manage
           * the storage the data in a persistent kstat.
           */
    ksp = kstat2_create(pseg, sizeof (pseg) / sizeof (char *),
          ALL_ZONES, NULL, ndata, KSTAT2_FLAG_PERSISTENT, md,
                 "mydrv disk error kstat", KSTAT2_MF_NONE);

             if (ksp != NULL) {
                 /*
                  * Kstat name-value pairs must be initialized before
                  * calling the kstat2_install() function. However, a persistent kstat
                  * which is being reactivated has data which is already
                  * initialized, so there is no need to do it again. It would
                  * be an error to do so. So the kvals are
                  * only initialized if the kstat is not in a dormant state.
                  */
             if (! (ksp->ks2_flags & KSTAT_FLAG_DORMANT)) {
                     kstat2_named_t *err_kval = ksp->ks2_data;

                     kstat2_nv_init(err_kval, "data_errors",
                         KSTAT2_NVVT_INT, KSTAT2_NVF_NONE);
                     kstat2_nv_init(err_kval+1, "transport_errors",
                         KSTAT2_NVVT_INT, KSTAT2_NVF_NONE);
                 }

                 kstat2_install(ksp);
    }
    return (ksp);
}

See Also

user_attr(5), privileges(7), kstat2_create_histogram(9F), kstat2_delete(9F), kstat2_install(9F), kstat2_nv_init(9F), kstat2_zone_add(9F), kstat2_zone_remove(9F), kstat2(9S), kstat2_md(9S), kstat2_named(9S)

Notes

When creating persistent kstats, it is important to note that the kstats framework makes an internal copy of the metadata and the strings supplied for the kval (kstat value) names. This is to ensure that if the driver or module is unloaded, there are no stale references held to static data in the driver's address space. This copying only happens when the kstat is first installed by a call to the kstat2_install() function. Therefore, if a kval is reinitialized after a kstat is active from a dormant state, the kval name pointer points to an address in the driver's address space. This space becomes invalid if the driver were subsequently unloaded. For more information, see the kstat2_install(9F) man page.