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
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
-- 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
Usage notes
- Reserved fields and undefined flags must be set to binary zeros.
- When 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.
- When 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.
Privilege required
None.
Related services
- Statistics Vnode Cache Information
- Statistics Metadata Cache Information
Restrictions
None.
Examples
#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);
}