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 00038 #ifdef HAVE_CONFIG_H 00039 #include "config.h" 00040 #endif 00041 00042 #ifdef _SOLARIS 00043 #include "solaris_port.h" 00044 #endif 00045 00046 #include <stdio.h> 00047 #include <string.h> 00048 #include <pthread.h> 00049 #include "nfs_core.h" 00050 #include "log.h" 00051 #include "nfs_tcb.h" 00052 00053 exportlist_t *temp_pexportlist; 00054 pthread_cond_t admin_condvar = PTHREAD_COND_INITIALIZER; 00055 pthread_mutex_t mutex_admin_condvar = PTHREAD_MUTEX_INITIALIZER; 00056 bool_t reload_exports; 00057 00058 void nfs_Init_admin_data(void) 00059 { 00060 return; 00061 } 00062 00063 void admin_replace_exports() 00064 { 00065 P(mutex_admin_condvar); 00066 reload_exports = TRUE; 00067 if(pthread_cond_signal(&(admin_condvar)) == -1) 00068 LogCrit(COMPONENT_MAIN, 00069 "admin_replace_exports - admin cond signal failed , errno = %d (%s)", 00070 errno, strerror(errno)); 00071 V(mutex_admin_condvar); 00072 } 00073 00074 /* Skips deleting first entry of export list. */ 00075 int rebuild_export_list() 00076 { 00077 int status = 0; 00078 config_file_t config_struct; 00079 00080 /* If no configuration file is given, then the caller must want to reparse the 00081 * configuration file from startup. */ 00082 if(config_path[0] == '\0') 00083 { 00084 LogCrit(COMPONENT_CONFIG, 00085 "Error: No configuration file was specified for reloading exports."); 00086 return 0; 00087 } 00088 00089 /* Attempt to parse the new configuration file */ 00090 config_struct = config_ParseFile(config_path); 00091 if(!config_struct) 00092 { 00093 LogCrit(COMPONENT_CONFIG, 00094 "rebuild_export_list: Error while parsing new configuration file %s: %s", 00095 config_path, config_GetErrorMsg()); 00096 return 0; 00097 } 00098 00099 /* Create the new exports list */ 00100 status = ReadExports(config_struct, &temp_pexportlist); 00101 if(status < 0) 00102 { 00103 LogCrit(COMPONENT_CONFIG, 00104 "rebuild_export_list: Error while parsing export entries"); 00105 return status; 00106 } 00107 else if(status == 0) 00108 { 00109 LogWarn(COMPONENT_CONFIG, 00110 "rebuild_export_list: No export entries found in configuration file !!!"); 00111 return 0; 00112 } 00113 00114 /* At least one worker thread should exist. Each worker thread has a pointer to 00115 * the same hash table. */ 00116 if(nfs_export_create_root_entry(temp_pexportlist) != TRUE) 00117 { 00118 LogCrit(COMPONENT_MAIN, 00119 "replace_exports: Error initializing Cache Inode root entries"); 00120 return 0; 00121 } 00122 00123 return 1; 00124 } 00125 00126 static int ChangeoverExports() 00127 { 00128 00129 exportlist_t *pcurrent = NULL; 00130 00131 /* Now we know that the configuration was parsed successfully. 00132 * And that worker threads are no longer accessing the export list. 00133 * Remove all but the first export entry in the exports list. 00134 */ 00135 if (nfs_param.pexportlist) 00136 pcurrent = nfs_param.pexportlist->next; 00137 00138 while(pcurrent != NULL) 00139 { 00140 /* Leave the head so that the list may be replaced later without 00141 * changing the reference pointer in worker threads. */ 00142 CleanUpExportContext(&pcurrent->FS_export_context); 00143 00144 if (pcurrent == nfs_param.pexportlist) 00145 break; 00146 00147 nfs_param.pexportlist->next = RemoveExportEntry(pcurrent); 00148 pcurrent = nfs_param.pexportlist->next; 00149 } 00150 00151 /* Allocate memory if needed, could have started with NULL exports */ 00152 if (nfs_param.pexportlist == NULL) 00153 nfs_param.pexportlist = gsh_malloc(sizeof(exportlist_t)); 00154 00155 if (nfs_param.pexportlist == NULL) 00156 return ENOMEM; 00157 00158 /* Changed the old export list head to the new export list head. 00159 * All references to the exports list should be up-to-date now. */ 00160 memcpy(nfs_param.pexportlist, temp_pexportlist, sizeof(exportlist_t)); 00161 00162 /* We no longer need the head that was created for 00163 * the new list since the export list is built as a linked list. */ 00164 gsh_free(temp_pexportlist); 00165 temp_pexportlist = NULL; 00166 return 0; 00167 } 00168 00169 void *admin_thread(void *UnusedArg) 00170 { 00171 SetNameFunction("admin_thr"); 00172 00173 while(1) 00174 { 00175 P(mutex_admin_condvar); 00176 while(reload_exports == FALSE) 00177 pthread_cond_wait(&(admin_condvar), &(mutex_admin_condvar)); 00178 reload_exports = FALSE; 00179 V(mutex_admin_condvar); 00180 00181 if (rebuild_export_list() <= 0) 00182 { 00183 LogCrit(COMPONENT_MAIN, "Could not reload the exports list."); 00184 continue; 00185 } 00186 00187 if(pause_threads(PAUSE_RELOAD_EXPORTS) == PAUSE_EXIT) 00188 { 00189 LogDebug(COMPONENT_MAIN, 00190 "Export reload interrupted by shutdown while pausing threads"); 00191 /* Be helpfull and exit 00192 * (other termination will just blow us away, and that's ok... 00193 */ 00194 break; 00195 } 00196 00197 /* Clear the id mapping cache for gss principals to uid/gid. 00198 * The id mapping may have changed. 00199 */ 00200 #ifdef _HAVE_GSSAPI 00201 #ifdef _USE_NFSIDMAP 00202 uidgidmap_clear(); 00203 idmap_clear(); 00204 namemap_clear(); 00205 #endif /* _USE_NFSIDMAP */ 00206 #endif /* _HAVE_GSSAPI */ 00207 00208 if (ChangeoverExports()) 00209 { 00210 LogCrit(COMPONENT_MAIN, "ChangeoverExports failed."); 00211 continue; 00212 } 00213 00214 LogEvent(COMPONENT_MAIN, 00215 "Exports reloaded and active"); 00216 00217 /* wake_workers could return PAUSE_PAUSE, but we don't have to do 00218 * anything special in that case. 00219 */ 00220 if(wake_threads(AWAKEN_RELOAD_EXPORTS) == PAUSE_EXIT) 00221 { 00222 LogDebug(COMPONENT_MAIN, 00223 "Export reload interrupted by shutdown while waking threads"); 00224 /* Be helpfull and exit 00225 * (other termination will just blow us away, and that's ok... 00226 */ 00227 break; 00228 } 00229 } 00230 00231 return NULL; 00232 } /* admin_thread */