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