Statistics iobyaggr Information

Purpose

Displays information about the number of reads and writes (I/Os) and the amount of data in bytes that are transferred for each aggregate.

Format

Start of change
syscall_parmlist
   opcode                            int              244              STATOP_IOBYAGGR
   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
   sa_flags                          char[1]          0x80 - Reset statistics
   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
IO_REPORT2_2_GRAND_TOTALS
   io_count                          int              Count of IO_REPORT2 lines
   grand_total_reads                 unsigned int     Total reads
   grand_total_writes                unsigned int     Total writes
   grand_total_read_bytes            unsigned int     Total bytes read (in kilobytes)
   grand_total_write_bytes           unsigned int     Total bytes written (in kilobytes)
   grand_total_devices               unsigned int     Total number of aggregates
   total_number_waits_for_io         unsigned int     Total number of waits for I/O    
   average_wait_time_for_io_whole    unsigned int     Average wait time (whole number),
                                                      average wait time in milliseconds
   average_wait_time_for_io_decimal  unsigned int     Average wait time (decimal part)
                                                      decimal part is in thousanths
                                                      3 means .003 and 300 means .3
End of change Start of change
IO_REPORT2[io_count]
   volser                         char[8]             DASD volser where aggregate resides
   pavios                         unsigned int        Max number of concurrent I/Os that zFS will issue
   read_ind                       char[4]             R/O or R/W (how aggregate is attached)
   temp_reads                     unsigned int        Count of reads for this aggregate
   temp_read_bytes                unsigned int        Bytes read for this aggregate (in kilobytes)
   temp_writes                    unsigned int        Count of writes for this aggregate
   temp_write_bytes               unsigned int        Bytes written for this aggregate (in kilobytes)
   allocation_dsname              char[84]            Data set name of aggregate
--or--
IO_REPORT2_GRAND_TOTALS2
   io_count                       int                 Count of IO_REPORT2 lines
   grand_total_reads              unsigned long long  Total reads
   grand_total_writes             unsigned long long  Total writes
   grand_total_read_bytes         unsigned long long  Total bytes read (in kilobytes)
   grand_total_write_bytes        unsigned long long  Total bytes written (in kilobytes)
   grand_total_devices            unsigned long long  Total number of aggregates
   total_number_waits_for_io      unsigned long long  Total number of waits for I/O
   average_wait_time_for_io_whole    unsigned int     Average wait time (whole number),
                                                      average wait time in milliseconds
   average_wait_time_for_io_decimal  unsigned int     Average wait time (decimal part)
                                                      decimal part is in thousanths
                                                      3 means .003 and 300 means .3
IO_REPORT2_2[io_count]
   volser                         char[8]             DASD volser where aggregate resides
   pavios                         unsigned int        Max number of concurrent I/Os that zFS will issue
   read_ind                       char[4]             R/O or R/W (how aggregate is attached)
   temp_reads                     unsigned long long  Count of reads for this aggregate
   temp_read_bytes                unsigned long long  Bytes read for this aggregate (in kilobytes)
   temp_writes                    unsigned long long  Count of writes for this aggregate
   temp_write_bytes               unsigned long long  Bytes written for this aggregate (in kilobytes)
   allocation_dsname              char[84]            Data set name of aggregate

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, output consists of IO_REPORT2_GRAND_TOTALS and IO_REPORT2. When sa_supported_ver is 2, output consists of IO_REPORT2_GRAND_TOTALS2 and IO_REPORT2_2.End of change

Privilege required

None.

Related services

  • Statistics iobydasd 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>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define ZFSCALL_STATS   0x40000007
#define STATOP_IOBYAGGR 244           /* Performance API queries */
#define E2BIG           145

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;

/*********************************************************************/
/* 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 io_report2_2_t {
  char volser[8];
  unsigned int pavios;
  char read_ind[4];
  unsigned long long int temp_reads;
  unsigned long long int temp_read_bytes;
  unsigned long long int temp_writes;
  unsigned long long int temp_write_bytes;
  char  allocation_dsname[84];
  char reserved[4];
} IO_REPORT2_2;

typedef struct io_report2_grand_totals_2_t {
  int  io_count; /* number IO_REPORT2 structs in buffer */
  int pad;
  unsigned long long int grand_total_reads;       /* Total # reads      */
  unsigned long long int grand_total_writes;      /* Total # writes     */
  unsigned long long int grand_total_read_bytes;  /* Total bytes read   */
  unsigned long long int grand_total_write_bytes; /* Total bytes written*/
  unsigned long long int grand_total_devices;     /* total # aggregates */
  unsigned long long int total_number_waits_for_io;
  unsigned int average_wait_time_for_io_whole;
  unsigned int average_wait_time_for_io_decimal;
} IO_REPORT2_GRAND_TOTALS_2;

/* Version 1 Output structures */
typedef struct io_report2_t {
  char              volser[8];
  unsigned int      pavios;
  char              read_ind[4];
  unsigned int      temp_reads;
  unsigned int      temp_read_bytes;
  unsigned int      temp_writes;
  unsigned int      temp_write_bytes;
  char              allocation_dsname[84];
} IO_REPORT2;

typedef struct io_report2_grand_totals_t {
  int               io_count;                         /* number IO_REPORT2 
                                                           structs in buffer */
  unsigned int      grand_total_reads;                /* Total # reads */
  unsigned int      grand_total_writes;               /* Total # writes */
  unsigned int      grand_total_read_bytes;           /* Total bytes read */
  unsigned int      grand_total_write_bytes;          /* Total bytes written*/
  unsigned int      grand_total_devices;              /* total # aggregates */
  unsigned int      total_number_waits_for_io;
  unsigned int      average_wait_time_for_io_whole;   /* in milliseconds */
  unsigned int      average_wait_time_for_io_decimal; /* in thousandths  */
                                                      /* of milliseconds */
                                                      /* for example,    */
                                                      /*3 means .003 and 
                                                          300 means .3 */
} IO_REPORT2_GRAND_TOTALS;

struct parmstruct {
  syscall_parmlist myparms;
  STAT_API         myapi;

  /* output buffer IO_REPORT2_GRAND_TOTALS_2 + multiple IO_REPORT2_2s */
  char             systemname[9];
} myparmstruct;

int print_iobyaggr_version1(IO_REPORT2_GRAND_TOTALS *stgt,
                            IO_REPORT2              *str2);
int print_iobyaggr_version2(IO_REPORT2_GRAND_TOTALS_2 *stgt,
                            IO_REPORT2_2              *str2);

int main(int argc, char **argv) 
{
  int                       buffer_success = 0;
  int                       bpxrv;
  int                       bpxrc;
  int                       bpxrs;
  int                       i,t;
  IO_REPORT2_GRAND_TOTALS_2 *stgt;
  IO_REPORT2_2              *str2;
  char                      *stsy;
  char                      buf[33];
  struct parmstruct         *myp     = &myparmstruct;
  int                       mypsize;
  int                       buflen;
  STAT_API                  *stapptr = &(myparmstruct.myapi);
  
  myparmstruct.myparms.opcode = STATOP_IOBYAGGR;
  myparmstruct.myparms.parms[0] = sizeof(syscall_parmlist);
  myparmstruct.myparms.parms[1] = sizeof(syscall_parmlist) + sizeof(STAT_API);

  /* 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   */
  /* iobyaggr statistics of a different system than this one         */
  /* myparmstruct.myparms.parms[2] = sizeof(syscall_parmlist)        */
  /*                                 + sizeof(STAT_API);             */

  myparmstruct.myparms.parms[2] = 0;
  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\n", 
               buflen, mypsize);
        myp->myparms.opcode = STATOP_IOBYAGGR;
        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   */
        /* iobyaggr 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;
        stgt = (IO_REPORT2_GRAND_TOTALS_2 * )((char *)myp + 
                                              sizeof(syscall_parmlist) +
                                              sizeof(STAT_API));

        str2 = (IO_REPORT2_2*) ((char*) stgt + 
                                sizeof(IO_REPORT2_GRAND_TOTALS_2));
        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,      /* Aggregate 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) 
          {
            IO_REPORT2_GRAND_TOTALS *stgt_v1;
            IO_REPORT2 *str2_v1;
            stgt_v1 = (IO_REPORT2_GRAND_TOTALS * )((char *)myp + 
                   sizeof(syscall_parmlist) +
                   sizeof(STAT_API));

            str2_v1 = (IO_REPORT2 * ) ((char*) stgt + 
                   sizeof(IO_REPORT2_GRAND_TOTALS));
            print_iobyaggr_version1(stgt_v1,str2_v1);
          }
          else
            print_iobyaggr_version2(stgt, str2); 

          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 
        { /* iobyaggr failed with large enough buffer */
          printf("Error on iobyaggr with large enough buffer\n");
          printf("Error querying iobyaggr, BPXRV = %d BPXRC = %d BPXRS = %x\n", 
                  bpxrv, bpxrc, bpxrs);
          free(myp);
          return bpxrc;
        }
      } 
      else 
      { /* error was not E2BIG */
        printf("Error on iobyaggr 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_iobyaggr_version2(IO_REPORT2_GRAND_TOTALS_2 *stgt,
                            IO_REPORT2_2              *str2)
{
    int i;
    printf("                 zFS I/O by Currently Attached Aggregate\n");
    printf("\n");
    printf("DASD   PAV\n");
    printf("VOLSER IOs Mode Reads      K bytes    "
           "Writes     K bytes    Dataset Name\n");
    printf("------ --- ---- ---------- ---------- "
           "---------- ---------- ------------\n");

    for (i = 0; i < stgt->io_count; i++, str2++) 
    {
      printf("%6.6s %3u %s %10llu %10llu %10llu %10llu  %-44.44s\n",
             str2->volser,
             str2->pavios,
             str2->read_ind,
             str2->temp_reads,
             str2->temp_read_bytes,
             str2->temp_writes,
             str2->temp_write_bytes,
             str2->allocation_dsname);
    }
    printf("%6llu         %10llu %10llu %10llu %10llu  %-44.44s\n",
           stgt->grand_total_devices,
           stgt->grand_total_reads,
           stgt->grand_total_read_bytes,
           stgt->grand_total_writes,
           stgt->grand_total_write_bytes, "*TOTALS*");
    printf("\n");

    printf("Total number of waits for I/O: %10u\n", 
           stgt->total_number_waits_for_io);
    printf("Average I/O wait time:         %9u.%3.3u (msecs)\n",
           stgt->average_wait_time_for_io_whole,
           stgt->average_wait_time_for_io_decimal);
    printf("\n");
    return 1;
}

int print_iobyaggr_version1(IO_REPORT2_GRAND_TOTALS *stgt,
                            IO_REPORT2              *str2)
{
    int i;
    printf("Version 1 output is being displayed\n");

    printf("                 zFS I/O by Currently Attached Aggregate\n");
    printf("\n");
    printf("DASD PAV\n");
    printf("VOLSER IOs Mode Reads      K bytes    "
           "Writes     K bytes    Dataset Name\n");
    printf("------ --- ---- ---------- ---------- "
           "---------- ---------- ------------\n");

    for (i = 0; i < stgt->io_count; i++, str2++) {
        printf("%6.6s %3u %s %10u %10u %10u %10u  %-44.44s\n",
               str2->volser,
               str2->pavios,
               str2->read_ind,
               str2->temp_reads,
               str2->temp_read_bytes,
               str2->temp_writes,
               str2->temp_write_bytes,
               str2->allocation_dsname);
    }
    printf("%6u         %10u %10u %10u %10u  %-44.44s\n",
           stgt->grand_total_devices,
           stgt->grand_total_reads,
           stgt->grand_total_read_bytes,
           stgt->grand_total_writes,
           stgt->grand_total_write_bytes, "*TOTALS*");
    printf("\n");

    printf("Total number of waits for I/O: %10u\n", 
           stgt->total_number_waits_for_io);
    printf("Average I/O wait time:         %9u.%3.3u (msecs)\n",
           stgt->average_wait_time_for_io_whole,
           stgt->average_wait_time_for_io_decimal);
    printf("\n"); 
}
End of change