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 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #ifdef _SOLARIS 00040 #include "solaris_port.h" 00041 #endif 00042 00043 #include "log.h" 00044 #include "ganesha_fuse_wrap.h" 00045 #include "nfs_init.h" 00046 #include "fsal.h" 00047 #include <stdio.h> 00048 #include <string.h> 00049 #include <pthread.h> 00050 #include <signal.h> /* for sigaction */ 00051 #include <errno.h> 00052 00053 /* parameters for NFSd startup and default values */ 00054 00055 static nfs_start_info_t nfs_start_info = { 00056 .flush_datacache_mode = FALSE, 00057 .nb_flush_threads = 1, 00058 .flush_behaviour = CACHE_CONTENT_FLUSH_AND_DELETE, 00059 }; 00060 00061 char log_path[MAXPATHLEN] = ""; 00062 char exec_name[MAXPATHLEN] = "ganesha-nfsd"; 00063 char host_name[MAXHOSTNAMELEN] = "localhost"; 00064 int debug_level = -1; 00065 int detach_flag = FALSE; 00066 int single_threaded = FALSE; 00067 struct ganefuse_operations ops; 00068 00069 char ganesha_exec_path[MAXPATHLEN]; 00070 00071 /* command line syntax */ 00072 00073 char options[] = "h@Rds:F:S:f:L:N:"; 00074 char usage[] = 00075 "Usage: %s [-hds][-L <logfile>][-N <dbg_lvl>][-f <config_file>]\n" 00076 "\t[-h] display this help\n" 00077 "\t[-s] single-threaded (for MT-unsafe filesystems)\n" 00078 "\t[-L <logfile>] set the default logfile for the daemon\n" 00079 "\t[-N <dbg_lvl>] set the verbosity level\n" 00080 "\t[-f <config_file>] set the config file to be used\n" 00081 "\t[-d] the daemon starts in background, in a new process group\n" 00082 "\t[-R] daemon will manage RPCSEC_GSS (default is no RPCSEC_GSS)\n" 00083 "\t[-F] <nb_flushers> flushes the data cache with purge, but do not answer to requests\n" 00084 "\t[-S] <nb_flushers> flushes the data cache without purge, but do not answer to requests\n" 00085 "----------------- Signals ----------------\n" 00086 "SIGUSR1 : Enable/Disable File Content Cache forced flush\n" 00087 "------------- Default Values -------------\n" 00088 "LogFile : /tmp/ganesha_nfsd.log\n" 00089 "DebugLevel : NIV_EVENT\n" "ConfigFile : None\n"; 00090 00103 int ganefuse_main(int argc, char *argv[], 00104 const struct ganefuse_operations *op, void *user_data) 00105 { 00106 char *tempo_exec_name = NULL; 00107 char localmachine[MAXHOSTNAMELEN]; 00108 int c; 00109 pid_t son_pid; 00110 00111 int argc_local = argc; 00112 char **argv_local = argv; 00113 00114 /* local copy for keeping it read only */ 00115 ops = *op; 00116 00117 /* retrieve executable file's name */ 00118 strncpy(ganesha_exec_path, argv[0], MAXPATHLEN); 00119 00120 if((tempo_exec_name = strrchr(argv_local[0], '/')) != NULL) 00121 strcpy((char *)exec_name, tempo_exec_name + 1); 00122 00123 if(*exec_name == '\0') 00124 strcpy((char *)exec_name, argv_local[0]); 00125 00126 /* get host name */ 00127 00128 if(gethostname(localmachine, sizeof(localmachine)) != 0) 00129 { 00130 fprintf(stderr, "Could not get local host name, exiting..."); 00131 exit(1); 00132 } 00133 else 00134 strncpy(host_name, localmachine, MAXHOSTNAMELEN); 00135 00136 /* now parsing options with getopt */ 00137 while((c = getopt(argc_local, argv_local, options)) != EOF) 00138 { 00139 00140 switch (c) 00141 { 00142 case '@': 00143 /* A litlle backdoor to keep track of binary versions */ 00144 printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); 00145 printf("Release = %s\n", VERSION); 00146 printf("Release comment = %s\n", VERSION_COMMENT); 00147 exit(0); 00148 break; 00149 00150 case 'L': 00151 /* Default Log */ 00152 strncpy(log_path, optarg, MAXPATHLEN); 00153 break; 00154 00155 case 'N': 00156 /* debug level */ 00157 debug_level = ReturnLevelAscii(optarg); 00158 if(debug_level == -1) 00159 { 00160 fprintf(stderr, 00161 "Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n"); 00162 exit(1); 00163 } 00164 break; 00165 00166 case 'f': 00167 /* config file */ 00168 strncpy(config_path, optarg, MAXPATHLEN); 00169 break; 00170 00171 case 's': 00172 /* single threaded */ 00173 single_threaded = TRUE; 00174 break; 00175 00176 case 'd': 00177 /* Detach or not detach ? */ 00178 detach_flag = TRUE; 00179 break; 00180 00181 case 'R': 00182 /* Shall we manage RPCSEC_GSS ? */ 00183 fprintf(stderr, 00184 "\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n"); 00185 fprintf(stderr, "NFS_KRB5\n"); 00186 fprintf(stderr, "{\n"); 00187 fprintf(stderr, "\tPrincipalName = nfs@<your_host> ;\n"); 00188 fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n"); 00189 fprintf(stderr, "\tActive_krb5 = TRUE ;\n"); 00190 fprintf(stderr, "}\n\n\n"); 00191 exit(1); 00192 00193 break; 00194 00195 case 'F': 00196 /* Flushes the data cache to the FSAL and purges the cache */ 00197 nfs_start_info.flush_datacache_mode = TRUE; 00198 nfs_start_info.flush_behaviour = CACHE_CONTENT_FLUSH_AND_DELETE; 00199 nfs_start_info.nb_flush_threads = (unsigned int)atoi(optarg); 00200 00201 if(nfs_start_info.nb_flush_threads > NB_MAX_FLUSHER_THREAD) 00202 nfs_start_info.nb_flush_threads = NB_MAX_FLUSHER_THREAD; 00203 break; 00204 00205 case 'S': 00206 /* Flushes the data cache to the FSAL, without purging the cache */ 00207 nfs_start_info.flush_datacache_mode = TRUE; 00208 nfs_start_info.flush_behaviour = CACHE_CONTENT_FLUSH_SYNC_ONLY; 00209 nfs_start_info.nb_flush_threads = (unsigned int)atoi(optarg); 00210 00211 if(nfs_start_info.nb_flush_threads > NB_MAX_FLUSHER_THREAD) 00212 nfs_start_info.nb_flush_threads = NB_MAX_FLUSHER_THREAD; 00213 break; 00214 00215 case 'h': 00216 /* display the help */ 00217 fprintf(stderr, usage, exec_name); 00218 exit(0); 00219 break; 00220 00221 case '?': 00222 default: 00223 /* ignore unsupported options */ 00224 fprintf(stderr, "WARNING: unknown GANESHA NFS daemon option: %c\n", 00225 (char)optopt); 00226 00227 } 00228 } 00229 00230 /* initialize memory and logging */ 00231 00232 nfs_prereq_init(exec_name, host_name, debug_level, log_path); 00233 00234 /* Start in background, if wanted */ 00235 if(detach_flag) 00236 { 00237 /* Step 1: forking a service process */ 00238 switch (son_pid = fork()) 00239 { 00240 case -1: 00241 /* Fork failed */ 00242 LogError(COMPONENT_MAIN, ERR_SYS, ERR_FORK, errno); 00243 LogCrit(COMPONENT_MAIN, 00244 "Could nout start nfs daemon, exiting..."); 00245 exit(1); 00246 00247 case 0: 00248 /* This code is within the son (that will actually work) 00249 * Let's make it the leader of its group of process */ 00250 if(setsid() == -1) 00251 { 00252 LogError(COMPONENT_MAIN, ERR_SYS, ERR_SETSID, errno); 00253 LogCrit(COMPONENT_MAIN, 00254 "Could nout start nfs daemon, exiting..."); 00255 exit(1); 00256 } 00257 break; 00258 00259 default: 00260 /* This code is within the father, it is useless, it must die */ 00261 LogFullDebug(COMPONENT_MAIN, 00262 "Starting a son of pid %d\n", son_pid); 00263 exit(0); 00264 break; 00265 } 00266 } 00267 00268 /* Get the FSAL functions */ 00269 FSAL_LoadFunctions(); 00270 00271 /* Get the FSAL consts */ 00272 FSAL_LoadConsts(); 00273 00274 LogEvent(COMPONENT_MAIN, 00275 ">>>>>>>>>> Starting GANESHA NFS Daemon on FSAL/%s <<<<<<<<<<", 00276 FSAL_GetFSName()); 00277 00278 /* initialize default parameters */ 00279 nfs_set_param_default(); 00280 00281 /* return all errors */ 00282 nfs_param.core_param.drop_io_errors = FALSE; 00283 nfs_param.core_param.drop_inval_errors = FALSE; 00284 nfs_param.core_param.drop_delay_errors = FALSE; 00285 00286 /* parse configuration file (if specified) */ 00287 00288 if(strlen(config_path) > 0) 00289 { 00290 if(nfs_set_param_from_conf(&nfs_start_info)) 00291 { 00292 LogCrit(COMPONENT_MAIN, 00293 "NFS MAIN: Error parsing configuration file."); 00294 exit(1); 00295 } 00296 } 00297 00298 /* set filesystem relative info */ 00299 00300 ((fusefs_specific_initinfo_t *) &nfs_param.fsal_param.fs_specific_info)->fs_ops = &ops; 00301 ((fusefs_specific_initinfo_t *) &nfs_param.fsal_param.fs_specific_info)->user_data = user_data; 00302 00303 #ifdef _SNMP_ADM_ACTIVE 00304 if(!nfs_param.extern_param.snmp_adm.snmp_log_file[0]) 00305 strcpy(nfs_param.extern_param.snmp_adm.snmp_log_file, log_path); 00306 #endif 00307 00308 /* add export by hand if no export was defined 00309 * in config file (always '/') 00310 */ 00311 00312 if(!nfs_param.pexportlist) 00313 { 00314 nfs_param.pexportlist = BuildDefaultExport(); 00315 if(nfs_param.pexportlist == NULL) 00316 { 00317 LogCrit(COMPONENT_MAIN, 00318 "NFS MAIN: Could not create export entry for '/'"); 00319 exit(1); 00320 } 00321 } 00322 00323 /* if this is a single threaded application, set worker count */ 00324 if(single_threaded) 00325 nfs_param.core_param.nb_worker = 1; 00326 00327 /* check parameters consitency */ 00328 00329 if(nfs_check_param_consistency()) 00330 { 00331 LogMajor(COMPONENT_MAIN, 00332 "NFS MAIN: Inconsistent parameters found"); 00333 LogMajor(COMPONENT_MAIN, 00334 "MAJOR WARNING: /!\\ | Bad Parameters could have significant impact on the daemon behavior"); 00335 exit(1); 00336 } 00337 00338 /* Everything seems to be OK! We can now start service threads */ 00339 nfs_start(&nfs_start_info); 00340 00341 return 0; 00342 00343 }