nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 3 of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 * --------------------------------------- 00024 */ 00025 00050 #ifdef HAVE_CONFIG_H 00051 #include "config.h" 00052 #endif 00053 00054 #ifdef _SOLARIS 00055 #include "solaris_port.h" 00056 #endif 00057 00058 #include "HashData.h" 00059 #include "HashTable.h" 00060 #include "log.h" 00061 #include "nfs_core.h" 00062 #include "nfs_exports.h" 00063 #include "config_parsing.h" 00064 #include "nfs_ip_stats.h" 00065 #include <stdlib.h> 00066 #include <string.h> 00067 00083 uint32_t ip_stats_value_hash_func(hash_parameter_t * p_hparam, 00084 hash_buffer_t * buffclef) 00085 { 00086 return hash_sockaddr((sockaddr_t *)buffclef->pdata, IGNORE_PORT) % p_hparam->index_size; 00087 } 00088 00104 uint64_t ip_stats_rbt_hash_func(hash_parameter_t * p_hparam, 00105 hash_buffer_t * buffclef) 00106 { 00107 return hash_sockaddr((sockaddr_t *)buffclef->pdata, IGNORE_PORT); 00108 } 00109 00123 int compare_ip_stats(hash_buffer_t * buff1, hash_buffer_t * buff2) 00124 { 00125 return (cmp_sockaddr((sockaddr_t *)(buff1->pdata), (sockaddr_t *)(buff2->pdata), IGNORE_PORT) != 0) ? 0 : 1; 00126 } 00127 00140 int display_ip_stats_key(hash_buffer_t * pbuff, char *str) 00141 { 00142 sockaddr_t *addr = (sockaddr_t *)(pbuff->pdata); 00143 00144 sprint_sockaddr(addr, str, HASHTABLE_DISPLAY_STRLEN); 00145 return strlen(str); 00146 } 00147 00160 int display_ip_stats_val(hash_buffer_t * pbuff, char *str) 00161 { 00162 nfs_ip_stats_t *ip_stats = (nfs_ip_stats_t *)(pbuff->pdata); 00163 00164 return snprintf(str, HASHTABLE_DISPLAY_STRLEN, 00165 "calls %u nfs2 %u nfs3 %u nfs4 %u mnt1 %u mnt3 %u", 00166 ip_stats->nb_call, 00167 ip_stats->nb_req_nfs2, 00168 ip_stats->nb_req_nfs3, 00169 ip_stats->nb_req_nfs4, 00170 ip_stats->nb_req_mnt1, 00171 ip_stats->nb_req_mnt3); 00172 } 00173 00189 int nfs_ip_stats_add(hash_table_t * ht_ip_stats, 00190 sockaddr_t * ipaddr, pool_t *ip_stats_pool) 00191 { 00192 hash_buffer_t buffkey; 00193 hash_buffer_t buffdata; 00194 nfs_ip_stats_t *g = NULL; 00195 sockaddr_t *pipaddr = NULL; 00196 00197 /* Do nothing if configuration disables IP_Stats */ 00198 if(nfs_param.core_param.dump_stats_per_client == 0) 00199 return IP_STATS_SUCCESS; 00200 00201 /* Entry to be cached */ 00202 g = pool_alloc(ip_stats_pool, NULL); 00203 00204 if(g == NULL) 00205 return IP_STATS_INSERT_MALLOC_ERROR; 00206 00207 if((pipaddr = gsh_malloc(sizeof(sockaddr_t))) == NULL) 00208 { 00209 pool_free(ip_stats_pool, g); 00210 return IP_STATS_INSERT_MALLOC_ERROR; 00211 } 00212 00213 /* I have to keep an integer as key, I wil use the pointer 00214 * buffkey->pdata for this, this also means that buffkey->len will 00215 * be 0 */ 00216 memcpy(pipaddr, ipaddr, sizeof(sockaddr_t)); 00217 00218 buffkey.pdata = pipaddr; 00219 buffkey.len = sizeof(sockaddr_t); 00220 00221 /* I build the data with the request pointer that should be in state 'IN USE' */ 00222 g->nb_call = 0; 00223 g->nb_req_nfs2 = 0; 00224 g->nb_req_nfs3 = 0; 00225 g->nb_req_nfs4 = 0; 00226 g->nb_req_mnt1 = 0; 00227 g->nb_req_mnt3 = 0; 00228 00229 memset(g->req_mnt1, 0, MNT_V1_NB_COMMAND * sizeof(int)); 00230 memset(g->req_mnt3, 0, MNT_V3_NB_COMMAND * sizeof(int)); 00231 memset(g->req_nfs2, 0, NFS_V2_NB_COMMAND * sizeof(int)); 00232 memset(g->req_nfs3, 0, NFS_V3_NB_COMMAND * sizeof(int)); 00233 00234 buffdata.pdata = (caddr_t) g; 00235 buffdata.len = sizeof(nfs_ip_stats_t); 00236 00237 if(HashTable_Set(ht_ip_stats, &buffkey, &buffdata) != HASHTABLE_SUCCESS) 00238 return IP_STATS_INSERT_MALLOC_ERROR; 00239 00240 return IP_STATS_SUCCESS; 00241 } /* nfs_ip_stats_add */ 00242 00254 int nfs_ip_stats_incr(hash_table_t * ht_ip_stats, 00255 sockaddr_t * ipaddr, 00256 unsigned int nfs_prog, 00257 unsigned int mnt_prog, struct svc_req *ptr_req) 00258 { 00259 hash_buffer_t buffkey; 00260 hash_buffer_t buffval; 00261 int status; 00262 nfs_ip_stats_t *g; 00263 00264 buffkey.pdata = (caddr_t) ipaddr; 00265 buffkey.len = sizeof(sockaddr_t); 00266 00267 /* Do nothing if configuration disables IP_Stats */ 00268 if(nfs_param.core_param.dump_stats_per_client == 0) 00269 return IP_STATS_SUCCESS; 00270 00271 if(HashTable_Get(ht_ip_stats, &buffkey, &buffval) == HASHTABLE_SUCCESS) 00272 { 00273 g = (nfs_ip_stats_t *) buffval.pdata; 00274 g->nb_call += 1; 00275 00276 status = IP_STATS_SUCCESS; 00277 00278 if(ptr_req->rq_prog == nfs_prog) 00279 { 00280 switch (ptr_req->rq_vers) 00281 { 00282 case NFS_V2: 00283 g->nb_req_nfs2 += 1; 00284 g->req_nfs2[ptr_req->rq_proc] += 1; 00285 break; 00286 00287 case NFS_V3: 00288 g->nb_req_nfs3 += 1; 00289 g->req_nfs3[ptr_req->rq_proc] += 1; 00290 break; 00291 00292 case NFS_V4: 00293 g->nb_req_nfs4 += 1; 00294 break; 00295 } 00296 } 00297 else if(ptr_req->rq_prog == mnt_prog) 00298 { 00299 switch (ptr_req->rq_vers) 00300 { 00301 case MOUNT_V1: 00302 g->nb_req_mnt1 += 1; 00303 g->req_mnt1[ptr_req->rq_proc] += 1; 00304 break; 00305 00306 case MOUNT_V3: 00307 g->nb_req_mnt3 += 1; 00308 g->req_mnt3[ptr_req->rq_proc] += 1; 00309 break; 00310 } 00311 } 00312 } 00313 else 00314 { 00315 status = IP_STATS_NOT_FOUND; 00316 } 00317 return status; 00318 } /* nfs_ip_stats_incr */ 00319 00320 00332 int nfs_ip_stats_get(hash_table_t * ht_ip_stats, 00333 sockaddr_t * ipaddr, nfs_ip_stats_t ** g) 00334 { 00335 hash_buffer_t buffkey; 00336 hash_buffer_t buffval; 00337 int status; 00338 00339 buffkey.pdata = (caddr_t) ipaddr; 00340 buffkey.len = sizeof(sockaddr_t); 00341 00342 /* Do nothing if configuration disables IP_Stats */ 00343 if(nfs_param.core_param.dump_stats_per_client == 0) 00344 return IP_STATS_SUCCESS; 00345 00346 if(HashTable_Get(ht_ip_stats, &buffkey, &buffval) == HASHTABLE_SUCCESS) 00347 { 00348 *g = (nfs_ip_stats_t *) buffval.pdata; 00349 00350 status = IP_STATS_SUCCESS; 00351 } 00352 else 00353 { 00354 status = IP_STATS_NOT_FOUND; 00355 } 00356 return status; 00357 } /* nfs_ip_stats_get */ 00358 00371 int nfs_ip_stats_remove(hash_table_t * ht_ip_stats, 00372 sockaddr_t * ipaddr, pool_t *ip_stats_pool) 00373 { 00374 hash_buffer_t buffkey, old_key, old_value; 00375 int status = IP_STATS_SUCCESS; 00376 nfs_ip_stats_t *g = NULL; 00377 00378 buffkey.pdata = (caddr_t) ipaddr; 00379 buffkey.len = sizeof(sockaddr_t); 00380 00381 /* Do nothing if configuration disables IP_Stats */ 00382 if(nfs_param.core_param.dump_stats_per_client == 0) 00383 return IP_STATS_SUCCESS; 00384 00385 if(HashTable_Del(ht_ip_stats, &buffkey, &old_key, &old_value) == HASHTABLE_SUCCESS) 00386 { 00387 gsh_free(old_key.pdata); 00388 g = old_value.pdata; 00389 pool_free(ip_stats_pool, g); 00390 } 00391 else 00392 { 00393 status = IP_STATS_NOT_FOUND; 00394 } 00395 00396 return status; 00397 } /* nfs_ip_stats_remove */ 00398 00410 hash_table_t *nfs_Init_ip_stats(nfs_ip_stats_parameter_t param) 00411 { 00412 hash_table_t *ht_ip_stats; 00413 00414 if((ht_ip_stats = HashTable_Init(¶m.hash_param)) == NULL) 00415 { 00416 LogCrit(COMPONENT_INIT, "NFS IP_STATS: Cannot init IP stats cache"); 00417 return NULL; 00418 } 00419 00420 return ht_ip_stats; 00421 } /* nfs_Init_ip_stats */ 00422 00433 void nfs_ip_stats_dump(hash_table_t ** ht_ip_stats, 00434 unsigned int nb_worker, char *path_stat) 00435 { 00436 struct rbt_node *it; 00437 struct rbt_head *tete_rbt; 00438 hash_data_t *pdata = NULL; 00439 unsigned int i = 0; 00440 unsigned int j = 0; 00441 unsigned int k = 0; 00442 nfs_ip_stats_t *g[NB_MAX_WORKER_THREAD]; 00443 nfs_ip_stats_t ip_stats_aggreg; 00444 // enough to hold an IPv4 or IPv6 address as a string 00445 char ipaddrbuf[40]; 00446 char ifpathdump[MAXPATHLEN]; 00447 sockaddr_t * ipaddr; 00448 time_t current_time; 00449 struct tm current_time_struct; 00450 char strdate[1024]; 00451 FILE *flushipstat = NULL; 00452 00453 /* Do nothing if configuration disables IP_Stats */ 00454 if(nfs_param.core_param.dump_stats_per_client == 0) 00455 return; 00456 00457 /* Compute the current time */ 00458 current_time = time(NULL); 00459 memcpy(¤t_time_struct, localtime(¤t_time), sizeof(current_time_struct)); 00460 snprintf(strdate, 1024, "%u, %.2d/%.2d/%.4d %.2d:%.2d:%.2d ", 00461 (unsigned int)current_time, 00462 current_time_struct.tm_mday, 00463 current_time_struct.tm_mon + 1, 00464 1900 + current_time_struct.tm_year, 00465 current_time_struct.tm_hour, 00466 current_time_struct.tm_min, current_time_struct.tm_sec); 00467 00468 /* All clients are supposed to have call at least one time worker #0 00469 * we loop on every client in the HashTable */ 00470 for(i = 0; i < ht_ip_stats[0]->parameter.index_size; i++) 00471 { 00472 tete_rbt = &ht_ip_stats[0]->partitions[i].rbt; 00473 RBT_LOOP(tete_rbt, it) 00474 { 00475 pdata = (hash_data_t *) it->rbt_opaq; 00476 00477 ipaddr = (sockaddr_t *) pdata->buffkey.pdata; 00478 00479 sprint_sockaddr(ipaddr, ipaddrbuf, sizeof(ipaddrbuf)); 00480 00481 snprintf(ifpathdump, MAXPATHLEN, "%s/stats_nfs-%s", path_stat, ipaddrbuf); 00482 00483 if((flushipstat = fopen(ifpathdump, "a")) == NULL) 00484 return; 00485 00486 /* Collect stats for each worker and aggregate them */ 00487 memset(&ip_stats_aggreg, 0, sizeof(ip_stats_aggreg)); 00488 for(j = 0; j < nb_worker; j++) 00489 { 00490 if(nfs_ip_stats_get(ht_ip_stats[j], 00491 ipaddr, &g[j]) != IP_STATS_SUCCESS) 00492 { 00493 fclose(flushipstat); 00494 return; 00495 } 00496 ip_stats_aggreg.nb_call += (g[j])->nb_call; 00497 00498 ip_stats_aggreg.nb_req_nfs2 += (g[j])->nb_req_nfs2; 00499 ip_stats_aggreg.nb_req_nfs3 += (g[j])->nb_req_nfs3; 00500 ip_stats_aggreg.nb_req_nfs4 += (g[j])->nb_req_nfs4; 00501 ip_stats_aggreg.nb_req_mnt1 += (g[j])->nb_req_mnt1; 00502 ip_stats_aggreg.nb_req_mnt3 += (g[j])->nb_req_mnt3; 00503 00504 for(k = 0; k < MNT_V1_NB_COMMAND; k++) 00505 ip_stats_aggreg.req_mnt1[k] += (g[j])->req_mnt1[k]; 00506 00507 for(k = 0; k < MNT_V3_NB_COMMAND; k++) 00508 ip_stats_aggreg.req_mnt3[k] += (g[j])->req_mnt3[k]; 00509 00510 for(k = 0; k < NFS_V2_NB_COMMAND; k++) 00511 ip_stats_aggreg.req_nfs2[k] += (g[j])->req_nfs2[k]; 00512 00513 for(k = 0; k < NFS_V3_NB_COMMAND; k++) 00514 ip_stats_aggreg.req_nfs3[k] += (g[j])->req_nfs3[k]; 00515 } 00516 00517 /* Write stats to file */ 00518 fprintf(flushipstat, "NFS/MOUNT STATISTICS,%s;%u|%u,%u,%u,%u,%u\n", 00519 strdate, 00520 ip_stats_aggreg.nb_call, 00521 ip_stats_aggreg.nb_req_mnt1, 00522 ip_stats_aggreg.nb_req_mnt3, 00523 ip_stats_aggreg.nb_req_nfs2, 00524 ip_stats_aggreg.nb_req_nfs3, ip_stats_aggreg.nb_req_nfs4); 00525 00526 fprintf(flushipstat, "MNT V1 REQUEST,%s;%u|", strdate, 00527 ip_stats_aggreg.nb_req_mnt1); 00528 for(k = 0; k < MNT_V1_NB_COMMAND - 1; k++) 00529 fprintf(flushipstat, "%u,", ip_stats_aggreg.req_mnt1[k]); 00530 fprintf(flushipstat, "%u\n", ip_stats_aggreg.req_mnt1[MNT_V1_NB_COMMAND - 1]); 00531 00532 fprintf(flushipstat, "MNT V3 REQUEST,%s;%u|", strdate, 00533 ip_stats_aggreg.nb_req_mnt3); 00534 for(k = 0; k < MNT_V3_NB_COMMAND - 1; k++) 00535 fprintf(flushipstat, "%u,", ip_stats_aggreg.req_mnt3[k]); 00536 fprintf(flushipstat, "%u\n", ip_stats_aggreg.req_mnt3[MNT_V3_NB_COMMAND - 1]); 00537 00538 fprintf(flushipstat, "NFS V2 REQUEST,%s;%u|", strdate, 00539 ip_stats_aggreg.nb_req_nfs2); 00540 for(k = 0; k < NFS_V2_NB_COMMAND - 1; k++) 00541 fprintf(flushipstat, "%u,", ip_stats_aggreg.req_nfs2[k]); 00542 fprintf(flushipstat, "%u\n", ip_stats_aggreg.req_nfs2[NFS_V2_NB_COMMAND - 1]); 00543 00544 fprintf(flushipstat, "NFS V3 REQUEST,%s;%u|", strdate, 00545 ip_stats_aggreg.nb_req_nfs3); 00546 for(k = 0; k < NFS_V3_NB_COMMAND - 1; k++) 00547 fprintf(flushipstat, "%u,", ip_stats_aggreg.req_nfs3[k]); 00548 fprintf(flushipstat, "%u\n", ip_stats_aggreg.req_nfs3[NFS_V3_NB_COMMAND - 1]); 00549 00550 fprintf(flushipstat, "END, ----- NO MORE STATS FOR THIS PASS ----\n"); 00551 00552 fflush(flushipstat); 00553 00554 /* Check next client */ 00555 RBT_INCREMENT(it); 00556 00557 fclose(flushipstat); 00558 } 00559 00560 } 00561 } /* nfs_ip_stats_dump */