Statistics iobydasd Information

Purpose

Displays information about the number of reads and writes and the number of bytes transferred for each DASD volume. The number of I/Os and the amount of data transferred is determined on a DASD basis.

Format

Start of change
syscall_parmlist
   opcode                      int                245              STATOP_IOBYDASD
   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 that follows STAT_API
   sa_ver                      int                1 or 2
   sa_flags                    char[1]            0x00
     SA_RESET                  0x80               Reset statistics
   sa_fill                     char[3]            0
   sa_supported_ver            int                version of data returned
   sa_reserve                  int[3]             0
   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
                               int
API_IOBYDASD_HDR
   number_of_lines             int                count of API_IOBYDASD_DATA lines
   pad                         int                0
   grand_total_waits           hyper              total waits
   average_wait_time_whole     int                average wait time (whole number)
                                                  average wait time in milliseconds
   average_wait_time_decimal   int                average wait time (decimal part)
                                                  decimal part is in thousanths
                                                  3 means .003 and 300 means .3
API_IOBYDASD_DATA[number_of_lines]
   spare                      int                 0
   volser                     char[6]             DASD volser
   filler                     char[2]             reserved
   pavios                     unsigned int        max number of concurrent I/Os zFS will issue 
                                                  for this DASD
   reads                      unsigned int        count of reads for this DASD
   read_bytes                 unsigned int        bytes read for this DASD (in kilobytes)
   writes                     unsigned int        count of writes for this DASD
   write_bytes                unsigned int        bytes written for this DASD (in kilobytes)
   waits                      unsigned int        waits
   avg_wait_whole             int                 average wait time (whole number)
                                                  average wait time in milliseconds
   avg_wait_decimal           int                 average wait time (decimal part)
                                                  decimal part is in thousanths
                                                  3 means .003 and 300 means .3
End of change
Start of change
--or--
API_IOBYDASD_DATA2[number_of_lines]
   spare                    int                          0
   volser                   char[6]                      DASD volser
   filler                   char[2]                      reserved
   unsigned int             unsigned long long int       max number of concurrent I/Os zFS 
                                                         will issue for this DASD
   reads                    unsigned long long int       count of reads for this DASD
   read_bytes               unsigned long long int       bytes read for this DASD (in kilobytes)
   writes                   unsigned long long int       count of writes for this DASD
   write_bytes              unsigned long long int       bytes written for this DASD (in kilobytes)
   waits                    unsigned long long int       waits
   avg_wait_whole           int                          average wait time (whole number)
                                                         average wait time in milliseconds
   avg_wait_decimal         int                          average wait time (decimal part)
                                                         decimal part is in thousanths
                                                         3 means .003 and 300 means .3
systemname                  char[9]

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 sa_supported_ver is 0 or 1, the output consists of API_IOBYDASD_HDR and API_IOBYDASD_DATA. When sa_supported_ver is 2, the output consists of API_IOBYDADD_HDR and API_IOBYDASD_DATA2.End of change

Privilege required

None.

Related services

  • Statistics iobyaggr Information
  • Statistics iocounts 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>

#define ZFSCALL_STATS   0x40000007
#define STATOP_IOBYDASD 245     /* Performance API queries */
#define E2BIG           145
#define ENOMEM          132

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 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;

typedef struct hyper_t {
  unsigned int high; /* unsigned int reserved */
  unsigned int low;
} hyper;

/*********************************************************************/
/* 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
#define             SA_VER_INIT 0x01
  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;

typedef struct api_iobydasd_hdr
{
  int               number_of_lines;
  int               pad;
  hyper             grand_total_waits;
  int               avg_wait_time_whole;   /* in milliseconds */
  int               avg_wait_time_decimal; /* in thousandths */
                                           /* of milliseconds */
                                           /* for example, 3 means .003 */ 
                                           /* and 300 means .3          */ 
} API_IOBYDASD_HDR;

typedef struct api_iobydasd_data_2
{
  int                    spare;
  char                   volser[6];
  char                   filler[2];
  unsigned int           pavios;
  unsigned long long int reads;
  unsigned long long int read_bytes;
  unsigned long long int writes;
  unsigned long long int write_bytes;
  unsigned long long int waits;
  int                    avg_wait_whole;
  int                    avg_wait_decimal;
} API_IOBYDASD_DATA_2;

/* Version 1 output structure */
typedef struct api_iobydasd_data
{
  int               spare;
  char              volser[6];
  char              filler[2];
  unsigned int      pavios;
  unsigned int      reads;
  unsigned int      read_bytes;
  unsigned int      writes;
  unsigned int      write_bytes;
  unsigned int      waits;
  int               avg_wait_whole;
  int               avg_wait_decimal;
} API_IOBYDASD_DATA;

struct parmstruct {
  syscall_parmlist myparms;
  STAT_API         myapi;

  /* output buffer API_IOBYDASD_HDR + multiple API_IOBYDASD_DATA_2s */
  char             systemname[9];
} myparmstruct;

int print_iobydasd_version1(API_IOBYDASD_HDR* stdh, 
                            API_IOBYDASD_DATA *stdd);
int print_iobydasd_version2(API_IOBYDASD_HDR* stdh, 
                            API_IOBYDASD_DATA_2 *stdd);

int main(int argc, char **argv) 
{
  int                 buffer_success = 0;  
  int                 bpxrv;
  int                 bpxrc;
  int                 bpxrs;
  int                 i,t;
  API_IOBYDASD_HDR    *stdh;
  API_IOBYDASD_DATA_2 *stdd;
  char                *stsy;
  char                buf[33];
  struct parmstruct   *myp     = &myparmstruct;
  int                 mypsize;
  int                 buflen;
  STAT_API            *stapptr = &(myparmstruct.myapi);
  
  myparmstruct.myparms.opcode   = STATOP_IOBYDASD;
  myparmstruct.myparms.parms[0] = sizeof(syscall_parmlist);
  myparmstruct.myparms.parms[1] = sizeof(syscall_parmlist) + sizeof(STAT_API);
  myparmstruct.myparms.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   */
  /* iobydasd statistics of a different system than this one         */
  /* myparmstruct.myparms.parms[2] = sizeof(syscall_parmlist)        */
  /*                                 + sizeof(STAT_API);             */

  myparmstruct.myparms.parms[3] = 0;
  myparmstruct.myparms.parms[4] = 0;
  myparmstruct.myparms.parms[5] = 0;
  myparmstruct.myparms.parms[6] = 0;

  memset(stapptr, 0, sizeof(STAT_API));
  memcpy(stapptr->sa_eye, SA_EYE, 4);
  stapptr->sa_ver = SA_VER_2;
  stapptr->sa_len = 0;

  /* This next field should only be set if parms[2] is non-zero */
  /* strcpy(myparmstruct.systemname,"DCEIMGVQ"); */
  
  BPX1PCT("ZFS     ",
          ZFSCALL_STATS,              /* Perf statistics operation */
          sizeof(myparmstruct),       /* Length of Argument */
          (char *)&myparmstruct,      /* Pointer to Argument */
          &bpxrv,                     /* Pointer to Return_value */
          &bpxrc,                     /* Pointer to Return_code */
          &bpxrs);                    /* Pointer to Reason_code */

  for(t = 0; t < 1000 && buffer_success == 0; t++)
  {
    if (bpxrv < 0) 
    {
      if (bpxrc == E2BIG) 
      {
        buflen = stapptr->sa_len;   /* Get buffer size needed */
        mypsize = sizeof(syscall_parmlist) + sizeof(STAT_API) + buflen +
          sizeof(myparmstruct.systemname);

        free(myp);
        myp = (struct parmstruct *)malloc((int)mypsize);
        memset(myp, 0, mypsize);

        printf("Need buffer size of %d, for a total of %d\n\n", 
               buflen, mypsize);
        myp->myparms.opcode = STATOP_IOBYDASD;
        myp->myparms.parms[0] = sizeof(syscall_parmlist);
        myp->myparms.parms[1] = sizeof(syscall_parmlist) + sizeof(STAT_API);
        myp->myparms.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   */
        /* iobydasd statistics of a different system than this one         */
        /* myp->myparms.parms[2] = sizeof(syscall_parmlist)                */
        /*                         + sizeof(STAT_API) + buflen;            */

        myp->myparms.parms[3] = 0;
        myp->myparms.parms[4] = 0;
        myp->myparms.parms[5] = 0;
        myp->myparms.parms[6] = 0;

        stapptr = (STAT_API * )((char *)myp + sizeof(syscall_parmlist));
        memcpy(stapptr->sa_eye, SA_EYE, 4);
        stapptr->sa_ver = SA_VER_2;
        stapptr->sa_len = buflen;
        stdh = (API_IOBYDASD_HDR * )((char *)myp + 
               sizeof(syscall_parmlist) + sizeof(STAT_API));
        stdd = (API_IOBYDASD_DATA_2*)((char*)stdh + sizeof(API_IOBYDASD_HDR));
        stsy = (char *)((char *)myp + sizeof(syscall_parmlist) + 
               sizeof(STAT_API) + buflen);

        /* This next field should only be set if parms[2] is non-zero */
        /* strcpy(stsy,"DCEIMGVQ"); */
            
        BPX1PCT("ZFS     ",
                ZFSCALL_STATS,      /* Perf stats operation */
                mypsize,            /* Length of Argument */
                (char *)myp,        /* Pointer to Argument */
                &bpxrv,             /* Pointer to Return_value */
                &bpxrc,             /* Pointer to Return_code */
                &bpxrs);            /* Pointer to Reason_code */

        if( bpxrv != 0 && bpxrc == E2BIG )
          printf("E2BIG: %d times total\n", t++);
        else if( bpxrv == 0 )
        {
          buffer_success = 1;
          
          if( stapptr->sa_supported_ver == SA_VER_INIT )
          {
            API_IOBYDASD_DATA *stdd_v1; 
            stdd_v1 = (API_IOBYDASD_DATA * )((char *)stdh + 
                                             sizeof(API_IOBYDASD_HDR));
            print_iobydasd_version1(stdh,stdd_v1);
          }
          else
            print_iobydasd_version2(stdh,stdd);
          

          unsigned int ptl = stapptr->reset_time_info.posix_time_low;
          if (0 == ctime_r((time_t * ) & ptl, 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);
          }
          free(myp);
        } 
        else 
        {   /* iobydasd failed with large enough buffer */
          printf("Error on iobydasd with large enough buffer\n");
          printf("Error querying iobydasd, "
                 "BPXRV = %d BPXRC = %d BPXRS = %x\n", 
                 bpxrv, bpxrc, bpxrs);
          free(myp);
          return bpxrc;
        }
      } 
      else 
      {   /* error was not E2BIG */
        printf("Error on iobydasd trying to get required size\n");
        printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", bpxrv, bpxrc, bpxrs);
        free(myp);
        return bpxrc;
      }
    } 
    else 
    {   /* asking for buffer size gave rv = 0; maybe there is no data */
      if (myparmstruct.myapi.sa_len == 0) 
      {
        printf("No data\n");
        printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", bpxrv, bpxrc, bpxrs);
      } 
      else 
      {   /* No, there was some other problem with getting the size needed */
        printf("Error getting size required\n");
        printf("BPXRV = %d BPXRC = %d BPXRS = %x\n", bpxrv, bpxrc, bpxrs);
      }
      free(myp);
      return bpxrc;
    }
  }
  if( t == 1000 )
    printf("Number of failed buffer resizes exceeded.\n");

  free(myp);
  return 0;
}

int print_iobydasd_version2(API_IOBYDASD_HDR* stdh, 
                            API_IOBYDASD_DATA_2 *stdd)
{
  int i;
  printf("%40czFS I/O by Currently Attached DASD/VOLs\n", ' ');
  printf("\n");
  printf("DASD   PAV\n");
  printf("VOLSER IOs Reads                K bytes              "
         "Writes               ");
  printf("K bytes              Waits                Average Wait\n");
  printf("------ --- -------------------- -------------------- "
         "-------------------- ");
  printf("-------------------- -------------------- ------------\n");

  for (i = 0; i < stdh->number_of_lines; i++, stdd++) 
  {
    printf("%6.6s %3u %20llu %20llu %20llu %20llu %20llu %6u.%3.3u\n",
           stdd->volser,
           stdd->pavios,
           stdd->reads,
           stdd->read_bytes,
           stdd->writes,
           stdd->write_bytes,
           stdd->waits,
           stdd->avg_wait_whole,
           stdd->avg_wait_decimal);
  }
  printf("\n");
  printf("Total number of waits for I/O: %u,,%u\n",
         stdh->grand_total_waits.high, stdh->grand_total_waits.low);
  printf("Average I/O wait time:         %9u.%3.3u (msecs)\n",
         stdh->avg_wait_time_whole,
         stdh->avg_wait_time_decimal);
  printf("\n");
  
  return 1;
}

int print_iobydasd_version1(API_IOBYDASD_HDR* stdh, 
                            API_IOBYDASD_DATA *stdd)
{
  int i;
  printf("Version 1 output is being displayed\n\n");
  printf("%15c  zFS I/O by Currently Attached DASD/VOLs\n",' ');
  printf("\n");
  printf("DASD   PAV\n");
  printf("VOLSER IOs Reads      K bytes    Writes     "
         "K bytes    Waits      Average Wait\n");
  printf("------ --- ---------- ---------- ---------- "
         "---------- ---------- ------------\n");

  for (i = 0; i < stdh->number_of_lines; i++, stdd++) 
  {
    printf("%6.6s %3u %10u %10u %10u %10u %10u %6u.%3.3u\n",
           stdd->volser,
           stdd->pavios,
           stdd->reads,
           stdd->read_bytes,
           stdd->writes,
           stdd->write_bytes,
           stdd->waits,
           stdd->avg_wait_whole,
           stdd->avg_wait_decimal);
  }
  printf("\n");
  printf("Total number of waits for I/O: %u,,%u\n",
         stdh->grand_total_waits.high, stdh->grand_total_waits.low);
  printf("Average I/O wait time:         %9u.%3.3u (msecs)\n",
         stdh->avg_wait_time_whole,
         stdh->avg_wait_time_decimal);
  printf("\n");

  return 1;
}
End of change