|
PAPI
5.0.1.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 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