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 00044 00045 #include <stdio.h> 00046 #include <string.h> 00047 #include <pthread.h> 00048 #include <fcntl.h> 00049 #include <sys/file.h> /* for having FNDELAY */ 00050 #include "HashData.h" 00051 #include "HashTable.h" 00052 #include "log.h" 00053 #include "ganesha_rpc.h" 00054 #include "nfs23.h" 00055 #include "nfs4.h" 00056 #include "mount.h" 00057 #include "nfs_core.h" 00058 #include "cache_inode.h" 00059 #include "nfs_exports.h" 00060 #include "nfs_creds.h" 00061 #include "nfs_proto_functions.h" 00062 #include "nfs_dupreq.h" 00063 #include "nfs_file_handle.h" 00064 #include "nfs_stat.h" 00065 #include "SemN.h" 00066 #include "nfs_tcb.h" 00067 00068 /* Structures from another module */ 00069 00070 extern char ganesha_exec_path[MAXPATHLEN]; 00071 extern char fcc_log_path[MAXPATHLEN]; 00072 extern int fcc_debug_level; 00073 00074 /* Use the same structure as the worker (but not all the fields will be used) */ 00075 nfs_worker_data_t fcc_gc_data; 00076 static fsal_op_context_t fsal_context; 00077 00078 /* Variable used for forcing flush via a signal */ 00079 unsigned int force_flush_by_signal; 00080 00081 int ___cache_content_invalidate_flushed(LRU_entry_t * plru_entry, void *addparam) 00082 { 00083 cache_content_entry_t *pentry = NULL; 00084 cache_content_client_t *pclient = NULL; 00085 00086 pentry = (cache_content_entry_t *) plru_entry->buffdata.pdata; 00087 pclient = (cache_content_client_t *) addparam; 00088 00089 if(pentry->local_fs_entry.sync_state != SYNC_OK) 00090 { 00091 /* Entry is not to be set invalid */ 00092 return LRU_LIST_DO_NOT_SET_INVALID; 00093 } 00094 00095 /* Release the entry */ 00096 pool_free(pclient->content_pool, pentry); 00097 00098 /* Retour de la pentry dans le pool */ 00099 return LRU_LIST_SET_INVALID; 00100 } /* cache_content_invalidate_flushed */ 00101 00102 int file_content_gc_manage_entry(LRU_entry_t * plru_entry, void *addparam) 00103 { 00104 cache_content_entry_t *pentry = NULL; 00105 cache_content_status_t cache_content_status; 00106 00107 pentry = (cache_content_entry_t *) plru_entry->buffdata.pdata; 00108 00109 if(pentry->local_fs_entry.sync_state == SYNC_OK) 00110 { 00111 /* No flush needed */ 00112 return TRUE; 00113 } 00114 if((cache_content_status = cache_content_flush(pentry, 00115 CACHE_CONTENT_FLUSH_AND_DELETE, 00116 &fcc_gc_data.cache_content_client, 00117 &fsal_context, 00118 &cache_content_status)) != 00119 CACHE_CONTENT_SUCCESS) 00120 { 00121 LogCrit(COMPONENT_MAIN, 00122 "NFS FILE CONTENT GARBAGE COLLECTION : /!\\ Can't flush %s : error %d", 00123 pentry->local_fs_entry.cache_path_data, cache_content_status); 00124 } 00125 00126 /* Continue with next entry in LRU_Apply_function */ 00127 return TRUE; 00128 } /* file_content_gc_manage_entry */ 00129 00130 extern nfs_tcb_t gccb; 00131 00132 void *file_content_gc_thread(void *UnusedArg) 00133 { 00134 char command[2 * MAXPATHLEN]; 00135 exportlist_t *pexport = NULL; 00136 int is_hw_reached = FALSE; 00137 int some_flush_to_do = FALSE; 00138 unsigned long nb_blocks_to_manage; 00139 char cache_sub_dir[MAXPATHLEN]; 00140 cache_content_status_t cache_content_status; 00141 FILE *command_stream = NULL; 00142 00143 char logfile_arg[MAXPATHLEN]; 00144 char *loglevel_arg; 00145 00146 SetNameFunction("file_content_gc_thread"); 00147 00148 LogEvent(COMPONENT_MAIN, 00149 "NFS FILE CONTENT GARBAGE COLLECTION : Starting GC thread"); 00150 00151 if(mark_thread_existing(&gccb) == PAUSE_EXIT) 00152 { 00153 /* Oops, that didn't last long... exit. */ 00154 mark_thread_done(&gccb); 00155 LogDebug(COMPONENT_DISPATCH, 00156 "NFS FILE CONTENT GARBAGE COLLECTION Thread exiting before initialization"); 00157 return NULL; 00158 } 00159 00160 LogDebug(COMPONENT_MAIN, 00161 "NFS FILE CONTENT GARBAGE COLLECTION : my pthread id is %p", 00162 (caddr_t) pthread_self()); 00163 00164 while(1) 00165 { 00166 /* Sleep until some work is to be done */ 00167 sleep(nfs_param.cache_layers_param.dcgcpol.run_interval); 00168 00169 if(gccb.tcb_state != STATE_AWAKE) 00170 { 00171 while(1) 00172 { 00173 P(gccb.tcb_mutex); 00174 if(gccb.tcb_state == STATE_AWAKE) 00175 { 00176 V(gccb.tcb_mutex); 00177 break; 00178 } 00179 switch(thread_sm_locked(&gccb)) 00180 { 00181 case THREAD_SM_RECHECK: 00182 V(gccb.tcb_mutex); 00183 continue; 00184 00185 case THREAD_SM_BREAK: 00186 V(gccb.tcb_mutex); 00187 break; 00188 00189 case THREAD_SM_EXIT: 00190 V(gccb.tcb_mutex); 00191 return NULL; 00192 } 00193 } 00194 } 00195 00196 LogEvent(COMPONENT_MAIN, 00197 "NFS FILE CONTENT GARBAGE COLLECTION : processing..."); 00198 for(pexport = nfs_param.pexportlist; pexport != NULL; pexport = pexport->next) 00199 { 00200 if(pexport->options & EXPORT_OPTION_USE_DATACACHE) 00201 { 00202 snprintf(cache_sub_dir, MAXPATHLEN, "%s/export_id=%d", 00203 nfs_param.cache_layers_param.cache_content_client_param.cache_dir, 00204 0); 00205 00206 if((cache_content_status = cache_content_check_threshold(cache_sub_dir, 00207 nfs_param. 00208 cache_layers_param. 00209 dcgcpol.lwmark_df, 00210 nfs_param. 00211 cache_layers_param. 00212 dcgcpol.hwmark_df, 00213 &is_hw_reached, 00214 &nb_blocks_to_manage)) 00215 == CACHE_CONTENT_SUCCESS) 00216 { 00217 if(is_hw_reached) 00218 { 00219 LogEvent(COMPONENT_MAIN, 00220 "NFS FILE CONTENT GARBAGE COLLECTION : High Water Mark is reached, %lu blocks to be removed", 00221 nb_blocks_to_manage); 00222 some_flush_to_do = TRUE; 00223 break; 00224 } 00225 else { 00226 LogEvent(COMPONENT_MAIN, 00227 "NFS FILE CONTENT GARBAGE COLLECTION : High Water Mark is not reached"); 00228 } 00229 00230 /* Use signal management */ 00231 if(force_flush_by_signal == TRUE) 00232 { 00233 some_flush_to_do = TRUE; 00234 break; 00235 } 00236 } 00237 } 00238 } /* for */ 00239 00240 if (strncmp(fcc_log_path, "/dev/null", 9) == 0) 00241 switch(LogComponents[COMPONENT_CACHE_INODE_GC].comp_log_type) 00242 { 00243 case FILELOG: 00244 strncpy(logfile_arg, LogComponents[COMPONENT_CACHE_INODE_GC].comp_log_file, MAXPATHLEN); 00245 break; 00246 case SYSLOG: 00247 strncpy(logfile_arg, "SYSLOG", MAXPATHLEN); 00248 break; 00249 case STDERRLOG: 00250 strncpy(logfile_arg, "STDERRLOG", MAXPATHLEN); 00251 break; 00252 case STDOUTLOG: 00253 strncpy(logfile_arg, "STDOUTLOG", MAXPATHLEN); 00254 break; 00255 default: 00256 LogCrit(COMPONENT_MAIN, 00257 "Could not figure out the proper -L option for emergency cache flush thread."); 00258 } 00259 else 00260 strncpy(logfile_arg, fcc_log_path, MAXPATHLEN); /* config variable */ 00261 00262 if(fcc_debug_level != -1) /* config variable */ 00263 loglevel_arg = ReturnLevelInt(fcc_debug_level); 00264 else 00265 loglevel_arg = ReturnLevelInt(ReturnLevelComponent(COMPONENT_CACHE_INODE_GC)); 00266 00267 snprintf(command, 2 * MAXPATHLEN, "%s -f %s -N %s -L %s", 00268 ganesha_exec_path, config_path, loglevel_arg, logfile_arg); 00269 00270 if(some_flush_to_do) 00271 strncat(command, " -P 3", 2 * MAXPATHLEN); /* Sync and erase */ 00272 else 00273 strncat(command, " -S 3", 2 * MAXPATHLEN); /* Sync Only */ 00274 00275 if((command_stream = popen(command, "r")) == NULL) 00276 LogCrit(COMPONENT_MAIN, 00277 "NFS FILE CONTENT GARBAGE COLLECTION : /!\\ Cannot lauch command %s", 00278 command); 00279 else 00280 LogEvent(COMPONENT_MAIN, 00281 "NFS FILE CONTENT GARBAGE COLLECTION : I launched command %s", 00282 command); 00283 00284 pclose(command_stream); 00285 } 00286 tcb_remove(&gccb); 00287 } /* file_content_gc_thread */