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 00037 #ifdef HAVE_CONFIG_H 00038 #include "config.h" 00039 #endif 00040 00041 #ifdef _SOLARIS 00042 #include "solaris_port.h" 00043 #endif /* _SOLARIS */ 00044 00045 #include "log.h" 00046 #include "HashData.h" 00047 #include "HashTable.h" 00048 #include "fsal.h" 00049 #include "cache_inode.h" 00050 #include "config_parsing.h" 00051 00052 #include <unistd.h> 00053 #include <sys/types.h> 00054 #include <sys/param.h> 00055 #include <time.h> 00056 #include <pthread.h> 00057 #include <string.h> 00058 00059 static const char *CONF_LABEL_CACHE_INODE_GCPOL = "CacheInode_GC_Policy"; 00060 static const char *CONF_LABEL_CACHE_INODE = "CacheInode"; 00061 static const char *CONF_LABEL_CACHE_INODE_HASH = "CacheInode_Hash"; 00062 00063 00079 cache_inode_status_t 00080 cache_inode_read_conf_hash_parameter(config_file_t config, 00081 cache_inode_parameter_t *param) 00082 { 00083 int var_max; 00084 int var_index; 00085 int err; 00086 char *key_name; 00087 char *key_value; 00088 config_item_t block; 00089 00090 /* Is the config tree initialized ? */ 00091 if(config == NULL || param == NULL) 00092 return CACHE_INODE_INVALID_ARGUMENT; 00093 00094 /* Get the config BLOCK */ 00095 if((block = config_FindItemByName(config, 00096 CONF_LABEL_CACHE_INODE_HASH)) == NULL) 00097 { 00098 LogDebug(COMPONENT_CONFIG, 00099 "Cannot read item \"%s\" from configuration file", 00100 CONF_LABEL_CACHE_INODE_HASH); 00101 return CACHE_INODE_NOT_FOUND; 00102 } 00103 else if(config_ItemType(block) != CONFIG_ITEM_BLOCK) 00104 { 00105 /* Expected to be a block */ 00106 LogCrit(COMPONENT_CONFIG, 00107 "Item \"%s\" is expected to be a block", 00108 CONF_LABEL_CACHE_INODE_HASH); 00109 return CACHE_INODE_INVALID_ARGUMENT; 00110 } 00111 00112 var_max = config_GetNbItems(block); 00113 00114 for(var_index = 0; var_index < var_max; var_index++) 00115 { 00116 config_item_t item; 00117 00118 item = config_GetItemByIndex(block, var_index); 00119 00120 /* Get key's name */ 00121 if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0) 00122 { 00123 LogCrit(COMPONENT_CONFIG, 00124 "Error reading key[%d] from section \"%s\" of configuration file.", 00125 var_index, CONF_LABEL_CACHE_INODE_HASH); 00126 return CACHE_INODE_INVALID_ARGUMENT; 00127 } 00128 00129 if(!strcasecmp(key_name, "Index_Size")) 00130 { 00131 param->hparam.index_size = atoi(key_value); 00132 } 00133 else if(!strcasecmp(key_name, "Alphabet_Length")) 00134 { 00135 param->hparam.alphabet_length = atoi(key_value); 00136 } 00137 else 00138 { 00139 LogCrit(COMPONENT_CONFIG, 00140 "Unknown or unsettable key: %s (item %s)", 00141 key_name, CONF_LABEL_CACHE_INODE_HASH); 00142 return CACHE_INODE_INVALID_ARGUMENT; 00143 } 00144 } 00145 00146 return CACHE_INODE_SUCCESS; 00147 } /* cache_inode_read_conf_hash_parameter */ 00148 00149 int parse_cache_expire(cache_inode_expire_type_t *type, time_t *value, char *key_value) 00150 { 00151 if(key_value[0] >= '0' && key_value[0] <= '9') 00152 { 00153 *value = atoi(key_value); 00154 /* special case backwards compatible meaning of 0 */ 00155 if (*value == 0) 00156 *type = CACHE_INODE_EXPIRE_NEVER; 00157 else 00158 *type = CACHE_INODE_EXPIRE; 00159 return CACHE_INODE_SUCCESS; 00160 } 00161 00162 /* 00163 * Note the CACHE_INODE_EXPIRE_IMMEDIATE is now a special value that works 00164 * fine with the value being set to 0, there will not need to be special 00165 * tests for CACHE_INODE_EXPIRE_IMMEDIATE. 00166 */ 00167 *value = 0; 00168 00169 if(strcasecmp(key_value, "Never") == 0) 00170 *type = CACHE_INODE_EXPIRE_NEVER; 00171 else if (strcasecmp(key_value, "Immediate") == 0) 00172 *type = CACHE_INODE_EXPIRE_IMMEDIATE; 00173 else 00174 return CACHE_INODE_INVALID_ARGUMENT; 00175 00176 return CACHE_INODE_SUCCESS; 00177 } 00178 00179 void cache_inode_expire_to_str(cache_inode_expire_type_t type, time_t value, char *out) 00180 { 00181 switch(type) 00182 { 00183 case CACHE_INODE_EXPIRE: 00184 sprintf(out, "%u", (unsigned int) value); 00185 break; 00186 case CACHE_INODE_EXPIRE_NEVER: 00187 strcpy(out, "Never"); 00188 break; 00189 case CACHE_INODE_EXPIRE_IMMEDIATE: 00190 strcpy(out, "Immediate"); 00191 break; 00192 } 00193 } 00194 00205 cache_inode_status_t 00206 cache_inode_read_conf_parameter(config_file_t config, 00207 cache_inode_parameter_t *param) 00208 { 00209 int var_max; 00210 int var_index; 00211 int err; 00212 char *key_name; 00213 char *key_value; 00214 config_item_t block; 00215 00216 int DebugLevel = -1; 00217 char *LogFile = NULL; 00218 00219 /* Is the config tree initialized ? */ 00220 if(config == NULL || param == NULL) 00221 return CACHE_INODE_INVALID_ARGUMENT; 00222 00223 /* Get the config BLOCK */ 00224 if((block = config_FindItemByName(config, 00225 CONF_LABEL_CACHE_INODE)) == NULL) 00226 { 00227 LogDebug(COMPONENT_CONFIG, 00228 "Cannot read item \"%s\" from configuration file", 00229 CONF_LABEL_CACHE_INODE); 00230 return CACHE_INODE_NOT_FOUND; 00231 } 00232 else if(config_ItemType(block) != CONFIG_ITEM_BLOCK) 00233 { 00234 /* Expected to be a block */ 00235 LogCrit(COMPONENT_CONFIG, 00236 "Item \"%s\" is expected to be a block", 00237 CONF_LABEL_CACHE_INODE); 00238 return CACHE_INODE_INVALID_ARGUMENT; 00239 } 00240 00241 var_max = config_GetNbItems(block); 00242 00243 for(var_index = 0; var_index < var_max; var_index++) 00244 { 00245 config_item_t item; 00246 00247 item = config_GetItemByIndex(block, var_index); 00248 00249 /* Get key's name */ 00250 if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0) 00251 { 00252 LogCrit(COMPONENT_CONFIG, 00253 "Error reading key[%d] from section \"%s\" of configuration file.", 00254 var_index, CONF_LABEL_CACHE_INODE); 00255 return CACHE_INODE_INVALID_ARGUMENT; 00256 } 00257 00258 else if(!strcasecmp(key_name, "Attr_Expiration_Time")) 00259 { 00260 err = parse_cache_expire(¶m->expire_type_attr, 00261 ¶m->grace_period_attr, 00262 key_value); 00263 if(err != CACHE_INODE_SUCCESS) 00264 return err; 00265 } 00266 else if(!strcasecmp(key_name, "Symlink_Expiration_Time")) 00267 { 00268 err = parse_cache_expire(¶m->expire_type_link, 00269 ¶m->grace_period_link, 00270 key_value); 00271 if(err != CACHE_INODE_SUCCESS) 00272 return err; 00273 } 00274 else if(!strcasecmp(key_name, "Directory_Expiration_Time")) 00275 { 00276 err = parse_cache_expire(¶m->expire_type_dirent, 00277 ¶m->grace_period_dirent, 00278 key_value); 00279 if(err != CACHE_INODE_SUCCESS) 00280 return err; 00281 } 00282 else if(!strcasecmp(key_name, "Use_Getattr_Directory_Invalidation")) 00283 { 00284 param->getattr_dir_invalidation = StrToBoolean(key_value); 00285 } 00286 else if(!strcasecmp(key_name, "Use_Test_Access")) 00287 { 00288 param->use_test_access = atoi(key_value); 00289 } 00290 else if(!strcasecmp( key_name, "Use_FSAL_Hash" ) ) 00291 { 00292 param->use_fsal_hash = StrToBoolean(key_value); 00293 } 00294 else if(!strcasecmp(key_name, "DebugLevel")) 00295 { 00296 DebugLevel = ReturnLevelAscii(key_value); 00297 00298 if(DebugLevel == -1) 00299 { 00300 LogDebug(COMPONENT_CACHE_INODE, 00301 "cache_inode_read_conf: ERROR: Invalid debug level name: \"%s\".", 00302 key_value); 00303 return CACHE_INODE_INVALID_ARGUMENT; 00304 } 00305 } 00306 else if(!strcasecmp(key_name, "LogFile")) 00307 { 00308 00309 LogFile = key_value; 00310 00311 } 00312 else 00313 { 00314 LogCrit(COMPONENT_CONFIG, 00315 "Unknown or unsettable key: %s (item %s)", 00316 key_name, CONF_LABEL_CACHE_INODE); 00317 return CACHE_INODE_INVALID_ARGUMENT; 00318 } 00319 } 00320 00321 /* init logging */ 00322 if(LogFile) 00323 SetComponentLogFile(COMPONENT_CACHE_INODE, LogFile); 00324 00325 if(DebugLevel > -1) 00326 SetComponentLogLevel(COMPONENT_CACHE_INODE, DebugLevel); 00327 00328 return CACHE_INODE_SUCCESS; 00329 } /* cache_inode_read_conf_parameter */ 00330 00346 cache_inode_status_t 00347 cache_inode_read_conf_gc_policy(config_file_t config, 00348 cache_inode_gc_policy_t *policy) 00349 { 00350 int var_max; 00351 int var_index; 00352 int err; 00353 char *key_name; 00354 char *key_value; 00355 config_item_t block; 00356 00357 /* Is the config tree initialized ? */ 00358 if(config == NULL || policy == NULL) 00359 return CACHE_INODE_INVALID_ARGUMENT; 00360 00361 /* Get the config BLOCK */ 00362 if((block = config_FindItemByName(config, 00363 CONF_LABEL_CACHE_INODE_GCPOL)) == NULL) 00364 { 00365 LogDebug(COMPONENT_CONFIG, 00366 "Cannot read item \"%s\" from configuration file", 00367 CONF_LABEL_CACHE_INODE_GCPOL); 00368 return CACHE_INODE_NOT_FOUND; 00369 } 00370 else if(config_ItemType(block) != CONFIG_ITEM_BLOCK) 00371 { 00372 /* Expected to be a block */ 00373 LogCrit(COMPONENT_CONFIG, 00374 "Item \"%s\" is expected to be a block", 00375 CONF_LABEL_CACHE_INODE_GCPOL); 00376 return CACHE_INODE_INVALID_ARGUMENT; 00377 } 00378 00379 var_max = config_GetNbItems(block); 00380 00381 for(var_index = 0; var_index < var_max; var_index++) 00382 { 00383 config_item_t item; 00384 00385 item = config_GetItemByIndex(block, var_index); 00386 00387 /* Get key's name */ 00388 if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0) 00389 { 00390 LogCrit(COMPONENT_CONFIG, 00391 "Error reading key[%d] from section \"%s\" of configuration file.", 00392 var_index, CONF_LABEL_CACHE_INODE_GCPOL); 00393 return CACHE_INODE_INVALID_ARGUMENT; 00394 } 00395 else if(!strcasecmp(key_name, "Entries_HWMark")) 00396 { 00397 policy->entries_hwmark = atoi(key_value); 00398 } 00399 else if(!strcasecmp(key_name, "Entries_LWMark")) 00400 { 00401 policy->entries_lwmark = atoi(key_value); 00402 } 00403 else if(!strcasecmp(key_name, "Cache_FDs")) 00404 { 00405 policy->use_fd_cache = StrToBoolean(key_value); 00406 } 00407 else if(!strcasecmp(key_name, "LRU_Run_Interval")) 00408 { 00409 policy->lru_run_interval = atoi(key_value); 00410 } 00411 else if(!strcasecmp(key_name, "FD_Limit_Percent")) 00412 { 00413 policy->fd_limit_percent = atoi(key_value); 00414 } 00415 else if(!strcasecmp(key_name, "FD_HWMark_Percent")) 00416 { 00417 policy->fd_hwmark_percent = atoi(key_value); 00418 } 00419 else if(!strcasecmp(key_name, "FD_LWMark_Percent")) 00420 { 00421 policy->fd_lwmark_percent = atoi(key_value); 00422 } 00423 else if(!strcasecmp(key_name, "Reaper_Work")) 00424 { 00425 policy->reaper_work = atoi(key_value); 00426 } 00427 else if(!strcasecmp(key_name, "Biggest_Window")) 00428 { 00429 policy->biggest_window = atoi(key_value); 00430 } 00431 else if(!strcasecmp(key_name, "Required_Progress")) 00432 { 00433 policy->required_progress = atoi(key_value); 00434 } 00435 else if(!strcasecmp(key_name, "Futility_Count")) 00436 { 00437 policy->futility_count = atoi(key_value); 00438 } 00439 else 00440 { 00441 LogCrit(COMPONENT_CONFIG, 00442 "Unknown or unsettable key: %s (item %s)", 00443 key_name, CONF_LABEL_CACHE_INODE_GCPOL); 00444 return CACHE_INODE_INVALID_ARGUMENT; 00445 } 00446 00447 } 00448 00449 return CACHE_INODE_SUCCESS; 00450 } /* cache_inode_read_conf_gc_policy */ 00451 00463 void cache_inode_print_conf_hash_parameter(FILE *output, 00464 cache_inode_parameter_t *param) 00465 { 00466 fprintf(output, "CacheInode Hash: Index_Size = %d\n", 00467 param->hparam.index_size); 00468 fprintf(output, "CacheInode Hash: Alphabet_Length = %d\n", 00469 param->hparam.alphabet_length); 00470 } /* cache_inode_print_conf_hash_parameter */ 00471 00481 void cache_inode_print_conf_parameter(FILE *output, 00482 cache_inode_parameter_t *param) 00483 { 00484 fprintf(output, "CacheInode: Attr_Expiration_Time = %jd\n", 00485 param->grace_period_attr); 00486 fprintf(output, "CacheInode: Symlink_Expiration_Time = %jd\n", 00487 param->grace_period_link); 00488 fprintf(output, "CacheInode: Directory_Expiration_Time = %jd\n", 00489 param->grace_period_dirent); 00490 fprintf(output, "CacheInode: Use_Test_Access = %s\n", 00491 (param->use_test_access ? "TRUE" : "FALSE")); 00492 } /* cache_inode_print_conf_parameter */ 00493 00504 void cache_inode_print_conf_gc_policy(FILE *output, 00505 cache_inode_gc_policy_t *gcpolicy) 00506 { 00507 fprintf(output, 00508 "CacheInode_GC_Policy: HWMark_Entries = %d\n" 00509 "CacheInode_GC_Policy: LWMark_Entries = %d\n" 00510 "CacheInode_GC_Policy: Cache_FDs = %s\n" 00511 "CacheInode_GC_Policy: LRU_Run_Interval = %d\n" 00512 "CacheInode_GC_Policy: FD_Limit_Percent = %d\n" 00513 "CacheInode_GC_Policy: FD_HWMark_Percent = %d\n" 00514 "CacheInode_GC_Policy: FD_LWMark_Percent = %d\n" 00515 "CacheInode_GC_Policy: Reaper_Work = %d\n" 00516 "CacheInode_GC_Policy: Biggest_Window = %d\n" 00517 "CacheInode_GC_Policy: Required_Progress = %d\n" 00518 "CacheInode_GC_Policy: Futility_Count = %d\n", 00519 gcpolicy->entries_lwmark, 00520 gcpolicy->entries_hwmark, 00521 (gcpolicy->use_fd_cache ? 00522 "TRUE" : 00523 "FALSE"), 00524 gcpolicy->lru_run_interval, 00525 gcpolicy->fd_limit_percent, 00526 gcpolicy->fd_hwmark_percent, 00527 gcpolicy->fd_lwmark_percent, 00528 gcpolicy->reaper_work, 00529 gcpolicy->biggest_window, 00530 gcpolicy->required_progress, 00531 gcpolicy->futility_count); 00532 } /* cache_inode_print_gc_policy */