perfstat_diskadapter Interface

The perfstat_diskadapter interface returns a set of structures of type perfstat_diskadapter_t, which is defined in the libperfstat.h file.

Selected fields from the perfstat_diskadapter_t structure include:
Item Descriptor
name Adapter name (from ODM)
description Adapter description (from ODM)
size Total disk size connected to this adapter (in MB)
free Total free space on disks connected to this adapter (in MB)
xfers Total transfers to/from this adapter (in KB)
Several other disk adapter-related metrics (such as the number of blocks read from and written to the adapter) are also returned. For a complete list, see the perfstat_diskadapter_t section in the libperfstat.h header file.
The following program emulates the diskadapterstat behavior and also shows an example of how the perfstat_diskadapter interface is used:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libperfstat.h>
#include <errno.h>
#include <wpars/wparcfg.h>

/* Non zero WPAR ID indicates WPAR */
#define IS_WPAR(X) ((X))


/* To Check whether malloc is successful or not */

#define CHECK_FOR_MALLOC_NULL(X) {  if ((X) == NULL) {\
                                       perror ("malloc");\
                                       exit(2);\
                                     }\
                                 }
/* Default values for interval and count  */
#define INTERVAL_DEFAULT 1
#define COUNT_DEFAULT 1

/* Function prototypes */

static int do_initialization(void);
static void do_cleanup(void);
static void collect_disk_metrics(void);
static void print_disk_header(void);
static void showusage(char *);

/* variables and data structures declaration */

static perfstat_diskadapter_t *statp, *statq;
static int num_adapt;
static int interval = INTERVAL_DEFAULT;
static int count = COUNT_DEFAULT;
static int rc;

/* support for remote node statistics collection in a cluster environment */
static perfstat_id_node_t nodeid;
static char nodename[MAXHOSTNAMELEN] = "";
static int collect_remote_node_stats = 0;

cid_t cid;               /* store the WPAR cid */



/*
 * NAME: do_initialization
 *       This function initializes the data structues.
 *       It also collects initial set of values.
 * 
 * RETURNS:
 * On successful completion:
 *    - returns 0.
 * In case of error
 *    - exit with code 1.
 */

static int do_initialization(void)
{
   if (collect_remote_node_stats){
       strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
       nodeid.spec = NODENAME;
       /* Get the total number of disk adapters available  in the current system */
       num_adapt = perfstat_diskadapter_node(&nodeid, NULL, sizeof(perfstat_diskadapter_t), 0);
   }
   else{
       /* Get the total number of disk adapters available  in the current system */
       num_adapt = perfstat_diskadapter(NULL, NULL, sizeof(perfstat_diskadapter_t), 0);
   } 

   if (num_adapt == 0) {
       printf("There are no disk adapters.\n");
       exit(0);
   }

   if (num_adapt < 0) {
       perror("perfstat_diskadapter: ");
       exit(1);
   }
		   
   /* Allocate sufficient memory for perfstat structures */
			
   statp = (perfstat_diskadapter_t *)malloc(sizeof(perfstat_diskadapter_t) * num_adapt);
   CHECK_FOR_MALLOC_NULL(statp);
  
   statq = (perfstat_diskadapter_t *)malloc(sizeof(perfstat_diskadapter_t) * num_adapt);
   CHECK_FOR_MALLOC_NULL(statq);
   
   /* Make the structures as 0 */  
   memset(statq, 0, (sizeof(perfstat_diskadapter_t) * num_adapt));

   memset(statp, 0, (sizeof(perfstat_diskadapter_t) * num_adapt));

   return (0);
}

/*
 *NAME:  Showusage
 *        This function displays the usage
 */


void showusage (char *cmd)
{
   fprintf (stderr, "usage: %s [-i <interval in seconds> ] [-c <number of iterations> ] [-n <node name in the cluster> ]\n", cmd);
   exit(1);
}


/*
 * NAME: do_cleanup
 *       This function frees the memory allocated for the perfstat structures.
 * 
 */

static void do_cleanup(void)
{
   if (statp) {
       free(statp);
   }

   if (statq) {
       free(statq);
   }
}


/*
 * NAME: collect_diskadapter_metrics
 *       This function collects the raw values in to
 *       the specified structures and derive the metrics from the
 *       raw values
 *
 */ 

void collect_diskadapter_metrics(void)
{
   perfstat_id_t first;
   unsigned long long delta_read, delta_write,delta_xfers, delta_xrate;

   if(collect_remote_node_stats) {
       strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
       nodeid.spec = NODENAME;
       strcpy(nodeid.name, FIRST_DISKADAPTER);
       rc = perfstat_diskadapter_node(&nodeid ,statq, sizeof(perfstat_diskadapter_t),num_adapt);			
   }
   else {
       strcpy(first.name, FIRST_DISKADAPTER);
       rc = perfstat_diskadapter(&first ,statq, sizeof(perfstat_diskadapter_t),num_adapt);			
   }

   if (rc < num_adapt){
       perror("perfstat_diskadapter: ");
       exit(1);
   }

   /* Name - name of the diskadapter
    * Disks- number of disks connected
    * Size - total size of all the disks
    * Free - free space on disk
    * ARS  - average read per second
    * AWS  - average write per second
    */

   printf("\n%-8s %7s %8s %8s %8s %8s\n", " Name ", " Disks ", " Size ", " Free ", " ARS ", " AWS ");
   printf("%-8s %7s %8s %8s %8s %8s\n", "======", "======", "======", "======", "=====", "=====");
	
   while (count > 0) {
       sleep(interval);
        
       if(collect_remote_node_stats) {
           rc = perfstat_diskadapter_node(&nodeid, statp, sizeof(perfstat_diskadapter_t), num_adapt);
       }
       else {
           rc = perfstat_diskadapter(&first ,statp, sizeof(perfstat_diskadapter_t),num_adapt);
       }

       if (rc < num_adapt ) {
	   perror("perfstat_diskadapter:");
           exit(-1);
       }

       /* print statistics for each of the diskadapter */
       for (int i = 0; i < rc; i++) {
            delta_write = statp[i].wblks - statq[i].wblks;
	    delta_read  = statp[i].rblks - statq[i].rblks;
            delta_xfers = statp[i].xfers - statq[i].xfers;
            delta_xrate = statp[i].xrate - statq[i].xrate;

	    printf("%-8s %7d %8llu %8llu %8llu %8llu\n", statp[i].name, statp[i].number,
	                 statp[i].size, statp[i].free, (u_longlong_t)(delta_read / (statp[i].xrate - statq[i].xrate)),
	                 (u_longlong_t)(delta_write / (delta_xfers - delta_xrate)));
       }

       /* copy to the old data structures */
       memcpy(statq, statp, sizeof(perfstat_diskadapter_t) * num_adapt);
       count--;
       printf("\n");
   }
   /* Free all the memory allocated for all the data structures */
   do_cleanup();
}


/*
 *NAME: main 
 *
 */

int main(int argc, char* argv[]) 
{
   int i;
   cid = corral_getcid();
		   
   /* Check Whether running Inside WPAR or on Global*/
   if(IS_WPAR(cid)) {
	  printf("The metrics requested for WPAR cannot be retrieved.\n");
	  exit(1);
   }

   /* Process the arguments */
   while ((i = getopt(argc, argv, "i:c:n:")) != EOF)
   {
       switch(i)
       {
           case 'i':               /* Interval */
                    interval = atoi(optarg);
                    if( interval <= 0 )
                        interval = INTERVAL_DEFAULT;
                    break;
           case 'c':               /* Number of interations */
                    count = atoi(optarg);
                    if( count <= 0 )
                        count = COUNT_DEFAULT;
                    break;
           case 'n':               /* Node name in a cluster environment */
                    strncpy(nodename, optarg, MAXHOSTNAMELEN);
                    nodename[MAXHOSTNAMELEN-1] = '\0';
                    collect_remote_node_stats = 1;
                    break;
           default:
                   /* Invalid arguments. Print the usage and terminate */
                   showusage(argv[0]);
       }
   }

   if(collect_remote_node_stats)
   {   /* perfstat_config needs to be called to enable cluster statistics collection */
       rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
       if (rc == -1)
       {
           perror("cluster statistics collection is not available");
           exit(-1);
       }
   }
   do_initialization();
   /* call the functions to collect the metrics and display them */
   collect_diskadapter_metrics();
   
   if(collect_remote_node_stats)
   {   /* Now disable cluster statistics by calling perfstat_config */
       perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
   }
   return (0);
}
The program displays an output that is similar to the following example output:
Name      Disks    Size     Free      ARS      AWS
======    ======   ======   ======    =====    =====
vscsi0     1       25568    19616      1        9