nfs-ganesha 1.4

nfs_admin_thread.c

Go to the documentation of this file.
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 */