Examples
#pragma linkage(BPX1PCT, OS)
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
#define u_long unsigned long
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 {
u_long posix_time_high; /* high order 32 bits since epoc */
u_long posix_time_low; /* low order 32 bits since epoch */
u_long posix_usecs; /* microseconds */
int pad1;
} RESET_TIME;
typedef struct hyper_t {
unsigned long high; /* unsigned long reserved */
unsigned long 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_INITIAL 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_reserve[4]; /* 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 thousanths */
/* of milliseconds */
/* for example, 3 means .003 and 300 means .3 */ } API_IOBYDASD_HDR;
typedef struct api_iobydasd_data
{
int spare;
char volser[6];
char filler[2];
unsigned long pavios;
unsigned long reads;
unsigned long read_bytes;
unsigned long writes;
unsigned long write_bytes;
unsigned long 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_DATAs */
char systemname[9];
} myparmstruct;
int main(int argc, char **argv)
{
int bpxrv;
int bpxrc;
int bpxrs;
int i;
API_IOBYDASD_HDR *stdh;
API_IOBYDASD_DATA *stdd;
char *stsy;
char buf[33];
struct parmstruct *myp = &myparmstruct;
int mypsize, 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_INITIAL;
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 */
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);
myp = (struct parmstruct *) malloc ((long) 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_INITIAL;
stapptr->sa_len=buflen;
stdh = (API_IOBYDASD_HDR *)((char *)myp + sizeof(syscall_parmlist) + sizeof(STAT_API));
stdd = (API_IOBYDASD_DATA *)((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 )
{
printf(" 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");
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);
}
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);
}
}
return 0;
}