Statistics Kernel Information

Purpose

A performance statistics operation that returns kernel counters, including the number of kernel operations and average time for the operation.

Format

Start of change
syscall_parmlist
   opcode                int              246    STATOP_KNPFS
   parms[0]              int              Offset to STAT_API
   parms[1]              int              offset of output following STAT_API
   parms[2]              int              Offset to system name (optional)
   parms[3]              int              0
   parms[4]              int              0
   parms[5]              int              0
   parms[6]              int              0
STAT_API
   sa_eye                char[4]          "STAP"
   sa_len                int              Length of buffer following STAT_API
   sa_ver                int              1 or 2
   sa_flags              char[1]          0x80 - Reset statistics
   sa_fill               char[3]          Reserved
   sa_supported_ver      int              Version of data returned or 0
   sa_reserve            int[3]           Reserved
   posix_time_high       unsigned int     High order 32 bits since epoch
   posix_time_low        unsigned int     Low order 32 bits since epoch
   posix_useconds        unsigned int     Microseconds
   pad1                  int              Reserved
KERNEL_CALL_STATS
   kc_eye                char[8]          Reserved
   kc_version            short            Reserved
   kc_len                short            Reserved
   pad1                  int              Reserved
  KERNEL_LINE[40]
     kl_operation_name   char[27]         Operation name string
     kl_valid            char             Operation entry is valid (0x01)
     kl_count            unsigned int     Count of operations
     kl_time             two_words        High - integer part of average time
                                          Low - fractional part of average time
     kl_bytes            hyper            Bytes associated with read and write
                                          operations, 0 otherwise 
     kl_reserved         int[6]           Reserved
   kc_totalops           unsigned int     Grand total operations
   pad2                  int              Reserved
   kc_totaltime          hyper            High=integer part of average
                                          wait time
                                          Low=fractional part of average
                                          wait time
   kc_valid_slots        int              Number of slots in above array that
                                          actually contains data
   kc_reserved           int[10]          Reserved
   pad3                  int              Reserved
End of change Start of change
-- or --
KERNEL_CALL_STATS2
   kc_eye                      char [8]             "KCSTAT2"
   kc_version                  short                1
   kc_len                      short                Size of KERNEL_CALL_STATS2
   pad1                        int                  Reserved
   kc_kernel_line_count        unsigned int         Number of KERNEL_LINE2s
                                                    for kernel
   kc_client_line_count        unsigned int         Number of KERNEL_LINE2s
                                                    for clients
   kc_totalops                 unsigned long long   Total operations
   kc_totalxcfops              unsigned long long   Total xcf operations
   kc_client_totalops          unsigned long long   Total operations for
                                                    clients
   kc_client_totalxcfops       unsigned long long   Total xcf operations for
                                                    clients
   kc_totaltime_whole          unsigned int         Whole portion of average
                                                    total time
   kc_totaltime_decimal        unsigned int         Decimal portion of average
                                                    total time
   kc_client_totaltime_whole   unsigned int         Whole portion of average
                                                    client total time
   kc_client_totaltime_decimal unsigned int         Decimal portion of average
                                                    client total time
   kc_reserved[10]             int                  Reserved
KERNEL_LINE2[n]
   kl_operation_name           char[27]             operation name string
   kl_valid                    char                 1 - operation entry valid
   pad1                        int                  Reserved
   kl_count                    unsigned long long   Count of operations
   kl_xcfcount                 unsigned long long   Count of xcf operations
   kl_time                     hyper                High=integer part of
                                                    average time
                                                    Low=fractional part of
                                                    average time
   kl_bytes                    unsigned long long   Bytes in read and write
                                                    operations, otherwise 0
   kl_reserved                 int[4]               Reserved
systemname                     char[9]              System to get stats from

Return_value     0 if request is successful, -1 if it is not successful

Return_code
  EINTR          zFS is shutting down
  EINVAL         Invalid parameter list
  EMVSERR        Internal error occurred
  E2BIG          Information too big for buffer supplied
Reason_code
  0xEFnnxxxx     See z/OS Distributed File Service Messages and Codes
End of change

Usage notes

  • Reserved fields and undefined flags must be set to binary zeros.
  • Start of changeWhen a_supported_ver is 0 or 1, output consists of KERNEL_CALL_STATS and KERNEL_LINE. When sa_supported_ver is 2, output consists of KERNEL_CALL_STATS2 and KERNEL_LINE2.End of change
  • Start of changeWhen a_supported_ver is 2, the KERNEL_LINE2 follows the KERNEL_CALL_STATS2 structure. There are kc_kernel_line_count KERNEL_LINE2 structures to represent kernel lines of output. These are followed by kc_client_line_count KERNEL_LINE2 structures of client output lines.End of change

Privilege required

None.

Related services

  • Statistics Vnode Cache Information
  • Statistics Metadata Cache Information

Restrictions

None.

Examples

Start of change
#pragma linkage(BPX1PCT, OS)
#pragma LANGLVL(EXTENDED)

extern void BPX1PCT(char *, int, int, char *, int *, int *, int *);

#include <stdio.h>
#include <stdlib.h> 
#include <stdint.h>
#include <time.h>

#define ZFSCALL_STATS 0x40000007
#define STATOP_KNPFS  246
#define BUFFER_SIZE   1024 * 64
#define SA_VER_INIT   0x01

typedef struct syscall_parmlist_t
{
  int opcode;   /* Operation code to perform             */
  int parms[7]; /* Specific to type of operation,        */
                /* provides access to the parms          */
                /* parms[4]-parms[6] are currently unused*/
} syscall_parmlist;

typedef union {
  struct double_word_t {
    unsigned int first_word;
    unsigned int second_word;
  } double_word;

  double alignment_dummy;
} two_words;

#define MAX_KERNEL_LINES 40

typedef struct KERNEL_line_t2 {
  char               kl_operation_name[27];
  char               kl_valid;
  int                pad1;
  unsigned long long kl_count;
  unsigned long long kl_xcfcount;
  two_words          kl_time;
  uint64_t           kl_bytes;
  int                kl_reserved[4];
} KERNEL_LINE2;

typedef struct kernel_call_stats_t2 {
  char               kc_eye[8];  /*eye catcher */
  short              kc_version;
  short              kc_len;
  int                pad1;
  int                kc_kernel_line_count;  
  int                kc_client_line_count;    
  unsigned long long kc_totalops;        /*Owner grand Total operations*/
  unsigned long long kc_totalxcfops;     /*Owner grand Total xcf operations*/
  unsigned long long kc_client_totalops;    /*Client grand Total operations*/
  unsigned long long kc_client_totalxcfops; /*Client grand Total operations*/
  two_words          kc_totaltime;          /*Owner Grand Total wait time*/
  two_words          kc_client_totaltime;   /*Client Grand Total wait time*/
  int                kc_reserved[10];
} KERNEL_CALL_STATS2;

/* Version 1 Output Structures */
typedef struct KERNEL_line_t {
  char              kl_operation_name[27];
  char              kl_valid;
  unsigned int      kl_count;
  two_words         kl_time;
  int               kl_reserved[6];
} KERNEL_LINE;

typedef struct kernel_call_stats_t {
  char           kc_eye[8];      /*eye catcher */
  short          kc_version;
  short          kc_len;
  int            pad1;
  KERNEL_LINE    OUTPUT[MAX_KERNEL_LINES];
  unsigned int   kc_totalops;    /*Grand Total operations */
  int            pad2;
  two_words      kc_totaltime;   /*Grand Total wait time*/
  int            kc_valid_slots; /* Number of slots in the above array*/
                                 /* that actually contain data*/
  int            kc_reserved[10];
  int            pad3;
} KERNEL_CALL_STATS;

/* reset timestamp */
typedef struct reset_time {
  unsigned int             posix_time_high; /*high order 32 bits since epoc*/
  unsigned int             posix_time_low;  /*low order 32 bits since epoch*/
  unsigned int             posix_usecs;     /*microseconds*/
  int                      pad1;
} RESET_TIME;

/*********************************************************************/
/* The following structure is the api query control block            */
/* It is used for all api query commands                             */
/*********************************************************************/
typedef struct stat_api_t
{
#define             SA_EYE "STAP"
  char              sa_eye[4];     /* 4 byte identifier must be */
  int               sa_len;        /* length of the buffer to put data into*/
                                   /* this buffer area follows this struct*/
  int               sa_ver;        /* the version number currently always 1*/
#define             SA_VER_2 0x02
  char              sa_flags;      /* flags field must be x00 or x80, 
                                      x80 means reset statistics*/
#define             SA_RESET 0x80
  char              sa_fill[3];       /* spare bytes */
  int               sa_supported_ver; /* version of data returned */
  int               sa_reserve[3];    /* Reserved */
  struct reset_time reset_time_info;
} STAT_API;

struct parmstruct {
  syscall_parmlist   myparms;
  STAT_API           myapi;
  KERNEL_CALL_STATS2 mystats;
  KERNEL_LINE2       mykernline;
  char               systemname[9];
} myparmstruct;

int print_stat_kern_version1(STAT_API* stapptr);

int main(int argc, char **argv) 
{
  int                bpxrv;
  int                bpxrc;
  int                bpxrs;
  int                i,j;
  int                processing_server_data = 1;
  int                lines;
  int                buff_fill_len;
  char               itoaBuff[11];
  two_words          totaltime;
  unsigned long long totalops;
  unsigned long long totalxcfops;

  STAT_API            local_req;    
  char*               buffp   = NULL;
  syscall_parmlist*   parmp   = NULL;
  STAT_API*           stapptr = NULL;
  KERNEL_CALL_STATS2* kcp     = NULL;
  KERNEL_LINE2*       klp     = NULL;
  char                buf[33];
  
  stapptr = &local_req;
  memset(stapptr, 0x00, sizeof(STAT_API));
  memcpy(stapptr->sa_eye, SA_EYE, 4);

  stapptr->sa_ver = SA_VER_2;
  stapptr->sa_len = ((2 * MAX_KERNEL_LINES) * sizeof(KERNEL_LINE2)) +
    sizeof(KERNEL_CALL_STATS2);

  buffp = (char*) malloc(BUFFER_SIZE);
  if( buffp == NULL )
  {
    printf("Malloc Error\n");
    return 0;
  }
  memset( buffp, 0x00, sizeof(syscall_parmlist) + sizeof(STAT_API));


  parmp = (syscall_parmlist*) &buffp[0];
  parmp->opcode   = STATOP_KNPFS;
  parmp->parms[0] = sizeof(syscall_parmlist);
  parmp->parms[1] = sizeof(syscall_parmlist) + sizeof(STAT_API);
  parmp->parms[2] = 0;

  /* Only specify a non-zero offset for the next field (parms[2]) if      */
  /* you are running z/OS 1.7 and above, and you want to query the kernel */
  /* statistics of a different system than this one                       */
  /* parmp->parms[2] = sizeof(syscall_parmlist) + sizeof(STAT_API) +      */
  /* sizeof(KERNEL_CALL_STATS2);                                          */

  parmp->parms[3] = 0;
  parmp->parms[4] = 0;
  parmp->parms[5] = 0;
  parmp->parms[6] = 0;

  buff_fill_len = sizeof(syscall_parmlist);
  stapptr = (STAT_API*) &buffp[buff_fill_len];
  memcpy( stapptr, &local_req, sizeof(STAT_API) );
  buff_fill_len += sizeof(STAT_API);

  /* This next field should only be set if parms[2] is non-zero */
  /* strcpy(myparmstruct.systemname,"DCEIMGVQ"); */

  BPX1PCT("ZFS     ",
          ZFSCALL_STATS,              /* Perf statistics operation */
          BUFFER_SIZE,                /* Length of Argument */
          (char *) buffp,             /* Pointer to Argument */
          &bpxrv,                     /* Pointer to Return_value */
          &bpxrc,                     /* Pointer to Return_code */
          &bpxrs);                    /* Pointer to Reason_code */

  if (bpxrv < 0) 
  {
    printf("Error querying kernel calls, "
           "BPXRV = %d BPXRC = %d BPXRS = %x\n",
           bpxrv, bpxrc, bpxrs);
    return bpxrc;
  } 
  else 
  {
    if (stapptr->sa_supported_ver == SA_VER_INIT)
    {
      print_stat_kern_version1(stapptr);
    }
    else
    {
      /* Get the pointers to the output structures */
      kcp = (KERNEL_CALL_STATS2*) &buffp[buff_fill_len];
      buff_fill_len += sizeof(KERNEL_CALL_STATS2);
      klp = (KERNEL_LINE2*) &buffp[buff_fill_len];

      lines = kcp->kc_kernel_line_count;
      totaltime = kcp->kc_totaltime;
      totalops = kcp->kc_totalops;
      totalxcfops = kcp->kc_totalxcfops;                    
        
      printf("          zFS Kernel PFS Calls\n");
      printf("          ---------------------\n\n");

      /* Do once if no client information,              */
      /* otherwise loop again printing out client stats */
      int do_client = 1;
      while( do_client )
      {
        if( processing_server_data )
          printf("%15c On Owner \n", ' ');
        else
          printf("%15c On Client \n", ' ');
            
        printf("          ---------------------\n\n");

        printf("Operation          Count       XCF req          "
               "Avg Time    Bytes     \n");
        printf("---------          ----------  ----------       "
               "---------   ----------\n");

        for (j = 0; j < lines; j++)
        {
          if ( !(klp->kl_valid) )
            break;

          sprintf( itoaBuff, "%d", klp->kl_bytes );

          printf("%13s    %10llu   %10llu   %9u.%3.3u   %10s\n",   
                 klp->kl_operation_name,
                 klp->kl_count,                                     
                 klp->kl_xcfcount,                                    
                 klp->kl_time.double_word.first_word,
                 klp->kl_time.double_word.second_word,
                 klp->kl_bytes ? itoaBuff : "");         
          klp++;
        }

        /* Print out the Totals */
        printf("------------      ----------   ----------      ----------\n"); 
        printf("%13s     %10llu   %10llu   %9u.%3.3u\n\n\n",           
               "TOTALS*",
               totalops, 
               totalxcfops,                                       
               totaltime.double_word.first_word,
               totaltime.double_word.second_word);

        /* If client data exists, and we have not already processed it */
        if ( (processing_server_data) && (kcp->kc_client_line_count) )
        {
          /* setup the client data */
          lines = kcp->kc_client_line_count;
          totaltime = kcp->kc_client_totaltime;
          totalops = kcp->kc_client_totalops;
          totalxcfops = kcp->kc_client_totalxcfops;
          processing_server_data = 0;
          do_client = 1;
        }
        else
          do_client = 0;
      }
    }

    if (0 == ctime_r((time_t*) & stapptr->reset_time_info.posix_time_low, buf))
      printf("Could not get timestamp.\n");
    else 
    { /* Insert the microseconds into the displayable time value */
      strncpy(&(buf[27]), &(buf[20]), 6);
      sprintf(&(buf[20]), "%06d", stapptr->reset_time_info.posix_usecs);
      buf[26] = ' ';
      buf[19] = '.';
      printf("Last Reset Time: %s", buf);
    }
  }
  return 0;
}

int print_stat_kern_version1(STAT_API* stapptr)
{
  int i;
  char *p = (char*) stapptr;
  p += sizeof(STAT_API);
  KERNEL_CALL_STATS *stkcptr = (KERNEL_CALL_STATS*) p;

  printf("Displaying the Version 1 Stats\n");
  printf("\n%34s\n", "zFS Kernel PFS Calls");
  printf("%34s\n",   "--------------------");
  printf("\n");
  printf("Operation          Count              Avg Time  \n");
  printf("---------          ----------         ----------\n");

  i = 0;
  while (stkcptr->OUTPUT[i].kl_valid == 1) 
  {
    printf("%13s     %10u     %9u.%3.3u\n", 
           stkcptr->OUTPUT[i].kl_operation_name,
           stkcptr->OUTPUT[i].kl_count,
           stkcptr->OUTPUT[i].kl_time.double_word.first_word,
           stkcptr->OUTPUT[i].kl_time.double_word.second_word);
    i += 1;
  }
  printf("---------          ----------         ----------\n");
  printf("*TOTALS*           %10u     %9u.%3.3u\n",
         stkcptr->kc_totalops,
         stkcptr->kc_totaltime.double_word.first_word,
         stkcptr->kc_totaltime.double_word.second_word);
}
End of change