PAPI  5.0.1.0
linux-lustre.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00016 #include <string.h>
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <fcntl.h>
00020 #include <dirent.h>
00021 #include <stdint.h>
00022 #include <ctype.h>
00023 
00024 #include "papi.h"
00025 #include "papi_internal.h"
00026 #include "papi_vector.h"
00027 #include "papi_memory.h"
00028 
00030 typedef struct counter_info_struct
00031 {
00032     int idx;
00033     char *name;
00034     char *description;
00035     char *unit;
00036     unsigned long long value;
00037 } counter_info;
00038 
00039 typedef struct
00040 {
00041     int count;
00042     char **data;
00043 } string_list;
00044 
00045 
00047 typedef struct lustre_fs_struct
00048 {
00049     char *proc_file;
00050     char *proc_file_readahead;
00051     counter_info *write_cntr;
00052     counter_info *read_cntr;
00053     counter_info *readahead_cntr;
00054     struct lustre_fs_struct *next;
00055 } lustre_fs;
00056 
00057 #define LUSTRE_MAX_COUNTERS 100
00058 #define LUSTRE_MAX_COUNTER_TERMS  LUSTRE_MAX_COUNTERS
00059 
00060 typedef counter_info LUSTRE_register_t;
00061 typedef counter_info LUSTRE_native_event_entry_t;
00062 typedef counter_info LUSTRE_reg_alloc_t;
00063 
00064 
00065 typedef struct LUSTRE_control_state
00066 {
00067     long long start_count[LUSTRE_MAX_COUNTERS];
00068         long long current_count[LUSTRE_MAX_COUNTERS];
00069         long long difference[LUSTRE_MAX_COUNTERS];
00070         int which_counter[LUSTRE_MAX_COUNTERS];
00071     int num_events;
00072 } LUSTRE_control_state_t;
00073 
00074 
00075 typedef struct LUSTRE_context
00076 {
00077     LUSTRE_control_state_t state;
00078 } LUSTRE_context_t;
00079 
00080 /* Default path to lustre stats */
00081 const char proc_base_path[] = "/proc/fs/lustre/";
00082 //const char proc_base_path[] = "./components/lustre/fake_proc/fs/lustre/";
00083 
00084 static counter_info *lustre_native_table[LUSTRE_MAX_COUNTERS];
00085 static int num_events = 0;
00086 
00087 /* mount Lustre fs are kept in a list */
00088 static lustre_fs *root_lustre_fs = NULL;
00089 
00090 papi_vector_t _lustre_vector;
00091 
00092 /******************************************************************************
00093  ********  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT ********
00094  *****************************************************************************/
00095 
00102 static counter_info *
00103 addCounter( const char *name, const char *desc, const char *unit )
00104 {
00105     counter_info *cntr;
00106 
00107     cntr = malloc( sizeof ( counter_info ) );
00108 
00109     if ( cntr == NULL ) {
00110        SUBDBG("can not allocate memory for new counter\n" );
00111        return NULL;
00112     }
00113 
00114     cntr->idx=num_events;
00115     cntr->name = strdup( name );
00116     cntr->description = strdup( desc );
00117     cntr->unit = strdup( unit );
00118     cntr->value = 0;
00119 
00120     lustre_native_table[num_events]=cntr;
00121 
00122     num_events++;
00123 
00124     return cntr;
00125 }
00126 
00133 static int
00134 addLustreFS( const char *name,
00135          const char *procpath_general, 
00136          const char *procpath_readahead )
00137 {
00138     lustre_fs *fs, *last;
00139     char counter_name[512];
00140     FILE *fff;
00141 
00142     SUBDBG("Adding lustre fs\n");
00143 
00144     fs = malloc( sizeof ( lustre_fs ) );
00145     if ( fs == NULL ) {
00146        SUBDBG("can not allocate memory for new Lustre FS description\n" );
00147        return PAPI_ENOMEM;
00148     }
00149 
00150     fs->proc_file=strdup(procpath_general);
00151     fff = fopen( procpath_general, "r" );
00152     if ( fff == NULL ) {
00153       SUBDBG("can not open '%s'\n", procpath_general );
00154       free(fs);
00155       return PAPI_ESYS;
00156     }
00157     fclose(fff);
00158 
00159     fs->proc_file_readahead = strdup(procpath_readahead);
00160     fff = fopen( procpath_readahead, "r" );
00161     if ( fff == NULL ) {
00162       SUBDBG("can not open '%s'\n", procpath_readahead );
00163       free(fs);
00164       return PAPI_ESYS;
00165     }
00166     fclose(fff);
00167 
00168     sprintf( counter_name, "%s_llread", name );
00169     fs->read_cntr = addCounter( counter_name, 
00170                     "bytes read on this lustre client", 
00171                     "bytes" );
00172 
00173     sprintf( counter_name, "%s_llwrite", name );
00174     fs->write_cntr = addCounter( counter_name, 
00175                      "bytes written on this lustre client",
00176                      "bytes" );
00177 
00178     sprintf( counter_name, "%s_wrong_readahead", name );
00179     fs->readahead_cntr = addCounter( counter_name, 
00180                      "bytes read but discarded due to readahead",
00181                      "bytes" );
00182 
00183     fs->next = NULL;
00184 
00185     /* Insert into the linked list */
00186     /* Does this need locking? */
00187     if ( root_lustre_fs == NULL ) {
00188         root_lustre_fs = fs;
00189     } else {
00190         last = root_lustre_fs;
00191 
00192         while ( last->next != NULL )
00193             last = last->next;
00194 
00195         last->next = fs;
00196     }
00197     free(fs);
00198     return PAPI_OK;
00199 }
00200 
00201 
00205 static int
00206 init_lustre_counters( void  )
00207 {
00208         char lustre_dir[PATH_MAX];
00209     char path[PATH_MAX];
00210     char path_readahead[PATH_MAX],path_stats[PATH_MAX];
00211     char *ptr;
00212     char fs_name[100];
00213     int idx = 0;
00214     int tmp_fd;
00215     DIR *proc_dir;
00216     struct dirent *entry;
00217 
00218     sprintf(lustre_dir,"%s/llite",proc_base_path);
00219 
00220     proc_dir = opendir( lustre_dir );
00221     if ( proc_dir == NULL ) {
00222        SUBDBG("Cannot open %s\n",lustre_dir);
00223        return PAPI_ESYS;
00224     }
00225 
00226     entry = readdir( proc_dir );
00227 
00228     while ( entry != NULL ) {
00229        memset( path, 0, PATH_MAX );
00230        snprintf( path, PATH_MAX - 1, "%s/%s/stats", lustre_dir,
00231                   entry->d_name );
00232        SUBDBG("checking for file %s\n", path);
00233 
00234        if ( ( tmp_fd = open( path, O_RDONLY ) ) != -1 ) {
00235           close( tmp_fd );
00236 
00237           /* erase \r and \n at the end of path */
00238           /* why is this necessary?             */
00239 
00240           idx = strlen( path );
00241           idx--;
00242 
00243           while ( path[idx] == '\r' || path[idx] == '\n' )
00244             path[idx--] = 0;
00245 
00246           /* Lustre paths are of type server-UUID */
00247 
00248           idx = 0;
00249 
00250           ptr = strstr(path,"llite/") + 6;
00251 
00252           while ( *ptr && *ptr != '-' && idx < 100 ) {
00253              fs_name[idx] = *ptr;
00254          ptr++;
00255          idx++;
00256           }
00257 
00258           SUBDBG("found Lustre FS: %s\n", fs_name);
00259 
00260           snprintf( path_stats, PATH_MAX - 1, 
00261             "%s/%s/stats", 
00262             lustre_dir,
00263             entry->d_name );
00264           SUBDBG("Found file %s\n", path_stats);
00265 
00266           snprintf( path_readahead, PATH_MAX - 1, 
00267             "%s/%s/read_ahead_stats", 
00268             lustre_dir,
00269             entry->d_name );
00270           SUBDBG("Now checking for file %s\n", path_readahead);
00271 
00272 
00273           strcpy( ptr, "read_ahead_stats" );
00274           addLustreFS( fs_name, path_stats, path_readahead );
00275 
00276        }
00277        entry = readdir( proc_dir );
00278     }
00279     closedir( proc_dir );
00280 
00281     return PAPI_OK;
00282 
00283 }
00284 
00288 static void
00289 read_lustre_counter( )
00290 {
00291     lustre_fs *fs = root_lustre_fs;
00292     FILE *fff;
00293     char buffer[BUFSIZ];
00294 
00295     while ( fs != NULL ) {
00296 
00297       /* read values from stats file */
00298       fff=fopen(fs->proc_file,"r" );
00299       if (fff != NULL) {
00300           while(1) {
00301             if (fgets(buffer,BUFSIZ,fff)==NULL) break;
00302     
00303             if (strstr( buffer, "write_bytes" )) {
00304               sscanf(buffer,"%*s %*d %*s %*s %*d %*d %lld",&fs->write_cntr->value);
00305               SUBDBG("Read %lld write_bytes\n",fs->write_cntr->value);
00306             }
00307     
00308             if (strstr( buffer, "read_bytes" )) {
00309               sscanf(buffer,"%*s %*d %*s %*s %*d %*d %lld",&fs->read_cntr->value);
00310               SUBDBG("Read %lld read_bytes\n",fs->read_cntr->value);
00311             }
00312           }
00313           fclose(fff);
00314       }
00315 
00316       fff=fopen(fs->proc_file_readahead,"r");
00317       if (fff != NULL) {
00318           while(1) {
00319             if (fgets(buffer,BUFSIZ,fff)==NULL) break;
00320     
00321             if (strstr( buffer, "read but discarded")) {
00322                sscanf(buffer,"%*s %*s %*s %lld",&fs->readahead_cntr->value);
00323                SUBDBG("Read %lld discared\n",fs->readahead_cntr->value);
00324                break;
00325             }
00326           }
00327           fclose(fff);
00328       }
00329       fs = fs->next;
00330     }
00331 }
00332 
00333 
00337 static void
00338 host_finalize( void )
00339 {
00340         int i;
00341     lustre_fs *fs, *next_fs;
00342     counter_info *cntr;
00343 
00344     for(i=0;i<num_events;i++) {
00345        cntr=lustre_native_table[i];
00346        if ( cntr != NULL ) {
00347           free( cntr->name );
00348           free( cntr->description );
00349           free( cntr->unit );
00350           free( cntr );       
00351        }
00352        lustre_native_table[i]=NULL;
00353     }
00354 
00355     fs = root_lustre_fs;
00356 
00357     while ( fs != NULL ) {
00358         next_fs = fs->next;
00359         free(fs->proc_file);
00360         free(fs->proc_file_readahead);
00361         free( fs );
00362         fs = next_fs;
00363     }
00364 
00365     root_lustre_fs = NULL;
00366 }
00367 
00368 
00372 static int
00373 detect_lustre()
00374 {
00375         char lustre_directory[BUFSIZ];
00376     DIR *proc_dir;
00377 
00378     sprintf(lustre_directory,"%s/llite",proc_base_path);
00379 
00380     proc_dir = opendir( proc_base_path );
00381     if ( proc_dir == NULL ) {
00382       SUBDBG("we are not able to read %s\n",lustre_directory);
00383        return PAPI_ESYS;
00384     }
00385 
00386     closedir(proc_dir);
00387 
00388     return PAPI_OK;
00389 }
00390 
00391 
00392 /*****************************************************************************
00393  *******************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *************
00394  *****************************************************************************/
00395 
00396 /*
00397  * Component setup and shutdown
00398  */
00399 
00400 int
00401 _lustre_init_component(  )
00402 {
00403 
00404     int ret = PAPI_OK;
00405 
00406     /* See if lustre filesystem exists */
00407     ret=detect_lustre();
00408     if (ret!=PAPI_OK) {
00409        strncpy(_lustre_vector.cmp_info.disabled_reason,
00410            "No lustre filesystems found",PAPI_MAX_STR_LEN);
00411        return ret;
00412     }
00413 
00414     ret=init_lustre_counters();
00415 
00416     _lustre_vector.cmp_info.num_native_events=num_events;
00417 
00418     return ret;
00419 }
00420 
00421 
00422 
00423 
00424 
00425 /*
00426  * This is called whenever a thread is initialized
00427  */
00428 int
00429 _lustre_init_thread( hwd_context_t * ctx )
00430 {
00431   (void) ctx;
00432 
00433   return PAPI_OK;
00434 }
00435 
00436 
00437 /*
00438  *
00439  */
00440 int
00441 _lustre_shutdown_component( void )
00442 {
00443 
00444     host_finalize(  );
00445 
00446     return PAPI_OK;
00447 }
00448 
00449 /*
00450  *
00451  */
00452 int
00453 _lustre_shutdown_thread( hwd_context_t * ctx )
00454 {
00455     ( void ) ctx;
00456 
00457     return PAPI_OK;
00458 }
00459 
00460 
00461 
00462 /*
00463  * Control of counters (Reading/Writing/Starting/Stopping/Setup) functions
00464  */
00465 int
00466 _lustre_init_control_state( hwd_control_state_t *ctl )
00467 {
00468     LUSTRE_control_state_t *lustre_ctl = (LUSTRE_control_state_t *)ctl;
00469 
00470     memset(lustre_ctl->start_count,0,sizeof(long long)*LUSTRE_MAX_COUNTERS);
00471     memset(lustre_ctl->current_count,0,sizeof(long long)*LUSTRE_MAX_COUNTERS);
00472 
00473     return PAPI_OK;
00474 }
00475 
00476 
00477 /*
00478  *
00479  */
00480 int
00481 _lustre_update_control_state( hwd_control_state_t *ctl, 
00482                   NativeInfo_t *native,
00483                   int count, 
00484                   hwd_context_t *ctx )
00485 {
00486     LUSTRE_control_state_t *lustre_ctl = (LUSTRE_control_state_t *)ctl;
00487     ( void ) ctx;
00488     int i, index;
00489 
00490     for ( i = 0; i < count; i++ ) {
00491        index = native[i].ni_event;
00492        lustre_ctl->which_counter[i]=index;
00493        native[i].ni_position = i;
00494     }
00495 
00496     lustre_ctl->num_events=count;
00497 
00498     return PAPI_OK;
00499 }
00500 
00501 
00502 /*
00503  *
00504  */
00505 int
00506 _lustre_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
00507 {
00508     ( void ) ctx;
00509 
00510     LUSTRE_control_state_t *lustre_ctl = (LUSTRE_control_state_t *)ctl;
00511     int i;
00512 
00513     read_lustre_counter(  );
00514 
00515     for(i=0;i<lustre_ctl->num_events;i++) {
00516        lustre_ctl->current_count[i]=
00517                  lustre_native_table[lustre_ctl->which_counter[i]]->value;
00518     }
00519 
00520     memcpy( lustre_ctl->start_count,
00521         lustre_ctl->current_count,
00522         LUSTRE_MAX_COUNTERS * sizeof ( long long ) );
00523 
00524     return PAPI_OK;
00525 }
00526 
00527 
00528 /*
00529  *
00530  */
00531 int
00532 _lustre_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00533 {
00534 
00535     (void) ctx;
00536     LUSTRE_control_state_t *lustre_ctl = (LUSTRE_control_state_t *)ctl;
00537     int i;
00538 
00539     read_lustre_counter(  );
00540 
00541     for(i=0;i<lustre_ctl->num_events;i++) {
00542        lustre_ctl->current_count[i]=
00543                  lustre_native_table[lustre_ctl->which_counter[i]]->value;
00544     }
00545 
00546     return PAPI_OK;
00547 
00548 }
00549 
00550 
00551 
00552 /*
00553  *
00554  */
00555 int
00556 _lustre_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
00557              long long **events, int flags )
00558 {
00559     (void) ctx;
00560     ( void ) flags;
00561 
00562     LUSTRE_control_state_t *lustre_ctl = (LUSTRE_control_state_t *)ctl;
00563     int i;
00564 
00565     read_lustre_counter(  );
00566 
00567     for(i=0;i<lustre_ctl->num_events;i++) {
00568        lustre_ctl->current_count[i]=
00569                  lustre_native_table[lustre_ctl->which_counter[i]]->value;
00570        lustre_ctl->difference[i]=lustre_ctl->current_count[i]-
00571                                          lustre_ctl->start_count[i];
00572     }
00573 
00574     *events = lustre_ctl->difference;
00575 
00576     return PAPI_OK;
00577 
00578 }
00579 
00580 
00581 
00582 
00583 /*
00584  *
00585  */
00586 int
00587 _lustre_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl )
00588 {
00589 
00590   /* re-initializes counter_start values to current */
00591 
00592   _lustre_start(ctx,ctrl);
00593 
00594   return PAPI_OK;
00595 }
00596 
00597 
00598 /*
00599  *
00600  */
00601 int
00602 _lustre_write( hwd_context_t * ctx, hwd_control_state_t * ctrl, long long *from )
00603 {
00604     ( void ) ctx;
00605     ( void ) ctrl;
00606     ( void ) from;
00607 
00608     return PAPI_OK;
00609 }
00610 
00611 
00612 /*
00613  * Functions for setting up various options
00614  */
00615 
00616 /* This function sets various options in the component
00617  * The valid codes being passed in are PAPI_SET_DEFDOM,
00618  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00619  */
00620 int
00621 _lustre_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
00622 {
00623     ( void ) ctx;
00624     ( void ) code;
00625     ( void ) option;
00626 
00627     return PAPI_OK;
00628 }
00629 
00630 
00631 /*
00632  * This function has to set the bits needed to count different domains
00633  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00634  * By default return PAPI_EINVAL if none of those are specified
00635  * and PAPI_OK with success
00636  * PAPI_DOM_USER is only user context is counted
00637  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00638  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00639  * PAPI_DOM_ALL   is all of the domains
00640  */
00641 int
00642 _lustre_set_domain( hwd_control_state_t * cntrl, int domain )
00643 {
00644     ( void ) cntrl;
00645     int found = 0;
00646     if ( PAPI_DOM_USER & domain ) {
00647         found = 1;
00648     }
00649     if ( PAPI_DOM_KERNEL & domain ) {
00650         found = 1;
00651     }
00652     if ( PAPI_DOM_OTHER & domain ) {
00653         found = 1;
00654     }
00655     if ( !found )
00656         return PAPI_EINVAL;
00657 
00658     return PAPI_OK;
00659 }
00660 
00661 
00662 /*
00663  *
00664  */
00665 int
00666 _lustre_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00667 {
00668 
00669   int event=EventCode;
00670 
00671   if (event >=0 && event < num_events) {
00672      strncpy( name, lustre_native_table[event]->name, len );
00673      return PAPI_OK;
00674   }
00675   return PAPI_ENOEVNT;
00676 }
00677 
00678 
00679 /*
00680  *
00681  */
00682 int
00683 _lustre_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00684 {
00685 
00686   int event=EventCode;
00687 
00688   if (event >=0 && event < num_events) {
00689     strncpy( name, lustre_native_table[event]->description, len );
00690     return PAPI_OK;
00691   }
00692   return PAPI_ENOEVNT;
00693 }
00694 
00695 
00696 /*
00697  *
00698  */
00699 int
00700 _lustre_ntv_enum_events( unsigned int *EventCode, int modifier )
00701 {
00702 
00703     if ( modifier == PAPI_ENUM_FIRST ) {
00704        if (num_events==0) return PAPI_ENOEVNT;
00705        *EventCode = 0;
00706        return PAPI_OK;
00707     }
00708 
00709     if ( modifier == PAPI_ENUM_EVENTS ) {
00710         int index = *EventCode;
00711 
00712         if ( lustre_native_table[index + 1] ) {
00713             *EventCode = *EventCode + 1;
00714             return PAPI_OK;
00715         } else {
00716             return PAPI_ENOEVNT;
00717         }
00718     } 
00719         
00720 
00721     return PAPI_EINVAL;
00722 }
00723 
00724 
00725 /*
00726  *
00727  */
00728 papi_vector_t _lustre_vector = {
00729    .cmp_info = {
00730         /* component information (unspecified values initialized to 0) */
00731        .name = "lustre",
00732        .short_name = "lustre",
00733        .version = "1.9",
00734        .description = "Lustre filesystem statistics",
00735        .num_mpx_cntrs = LUSTRE_MAX_COUNTERS,
00736        .num_cntrs = LUSTRE_MAX_COUNTERS,
00737        .default_domain = PAPI_DOM_USER,
00738        .default_granularity = PAPI_GRN_THR,
00739        .available_granularities = PAPI_GRN_THR,
00740        .hardware_intr_sig = PAPI_INT_SIGNAL,
00741 
00742        /* component specific cmp_info initializations */
00743        .fast_real_timer = 0,
00744        .fast_virtual_timer = 0,
00745        .attach = 0,
00746        .attach_must_ptrace = 0,
00747        .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00748   },
00749 
00750      /* sizes of framework-opaque component-private structures */
00751   .size = {
00752        .context = sizeof ( LUSTRE_context_t ),
00753        .control_state = sizeof ( LUSTRE_control_state_t ),
00754        .reg_value = sizeof ( LUSTRE_register_t ),
00755        .reg_alloc = sizeof ( LUSTRE_reg_alloc_t ),
00756   },
00757 
00758      /* function pointers in this component */
00759   .init_thread =           _lustre_init_thread,
00760   .init_component =        _lustre_init_component,
00761   .init_control_state =    _lustre_init_control_state,
00762   .start =                 _lustre_start,
00763   .stop =                  _lustre_stop,
00764   .read =                  _lustre_read,
00765   .shutdown_thread =       _lustre_shutdown_thread,
00766   .shutdown_component =    _lustre_shutdown_component,
00767   .ctl =                   _lustre_ctl,
00768   .update_control_state =  _lustre_update_control_state,
00769   .set_domain =            _lustre_set_domain,
00770   .reset =                 _lustre_reset,
00771 
00772   .ntv_enum_events =   _lustre_ntv_enum_events,
00773   .ntv_code_to_name =  _lustre_ntv_code_to_name,
00774   .ntv_code_to_descr = _lustre_ntv_code_to_descr,
00775 
00776 };
00777 
00778 
00779 
00780 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines