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 "nfs_init.h" 00044 #include "fsal.h" 00045 #include "log.h" 00046 #include <stdio.h> 00047 #include <string.h> 00048 #include <pthread.h> 00049 #include <signal.h> /* for sigaction */ 00050 #include <errno.h> 00051 #ifdef _PNFS 00052 #include "fsal_pnfs.h" 00053 #endif /* _PNFS */ 00054 00055 /* parameters for NFSd startup and default values */ 00056 00057 nfs_start_info_t my_nfs_start_info = { 00058 .dump_default_config = FALSE, 00059 .lw_mark_trigger = FALSE 00060 }; 00061 00062 char *my_config_path = "/etc/ganesha/ganesha.conf"; 00063 char my_pidfile[] = "/var/run/ganesha.pid"; 00064 char log_path[MAXPATHLEN] = ""; 00065 char exec_name[MAXPATHLEN] = "nfs-ganesha"; 00066 char host_name[MAXHOSTNAMELEN] = "localhost"; 00067 int debug_level = -1; 00068 int detach_flag = FALSE; 00069 char ganesha_exec_path[MAXPATHLEN]; 00070 00071 /* command line syntax */ 00072 00073 char options[] = "h@RTdS:F:S:P:f:L:N:E:p:"; 00074 char usage[] = 00075 "Usage: %s [-hd][-L <logfile>][-N <dbg_lvl>][-f <config_file>]\n" 00076 "\t[-h] display this help\n" 00077 "\t[-L <logfile>] set the default logfile for the daemon\n" 00078 "\t[-N <dbg_lvl>] set the verbosity level\n" 00079 "\t[-f <config_file>] set the config file to be used\n" 00080 "\t[-p <pid_file>] set the pid file\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[-T] dump the default configuration on stdout\n" 00084 "\t[-E] <epoch<] overrides ServerBootTime for ServerEpoch\n" 00085 "----------------- Signals ----------------\n" 00086 "SIGUSR1 : Enable/Disable File Content Cache forced flush\n" 00087 "SIGTERM : Cleanly terminate the program\n" 00088 "------------- Default Values -------------\n" 00089 "LogFile : /tmp/nfs-ganesha.log\n" 00090 "PidFile : /var/run/ganesha.pid\n" 00091 "DebugLevel : NIV_EVENT\n" "ConfigFile : /etc/ganesha/ganesha.conf\n"; 00092 00105 int main(int argc, char *argv[]) 00106 { 00107 char *tempo_exec_name = NULL; 00108 char localmachine[MAXHOSTNAMELEN]; 00109 int c; 00110 int pidfile; 00111 #ifndef HAVE_DAEMON 00112 pid_t son_pid; 00113 #endif 00114 sigset_t signals_to_block; 00115 00116 /* Set the server's boot time and epoch */ 00117 ServerBootTime = time(NULL); 00118 ServerEpoch = ServerBootTime; 00119 00120 /* retrieve executable file's name */ 00121 strncpy(ganesha_exec_path, argv[0], MAXPATHLEN); 00122 00123 if((tempo_exec_name = strrchr(argv[0], '/')) != NULL) 00124 strcpy((char *)exec_name, tempo_exec_name + 1); 00125 00126 if(*exec_name == '\0') 00127 strcpy((char *)exec_name, argv[0]); 00128 00129 /* get host name */ 00130 if(gethostname(localmachine, sizeof(localmachine)) != 0) 00131 { 00132 fprintf(stderr, "Could not get local host name, exiting..."); 00133 exit(1); 00134 } 00135 else 00136 strncpy(host_name, localmachine, MAXHOSTNAMELEN); 00137 00138 strcpy(config_path, my_config_path); 00139 00140 strcpy( pidfile_path, my_pidfile ) ; 00141 00142 /* now parsing options with getopt */ 00143 while((c = getopt(argc, argv, options)) != EOF) 00144 { 00145 switch (c) 00146 { 00147 case '@': 00148 /* A litlle backdoor to keep track of binary versions */ 00149 printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); 00150 printf("Release = %s\n", VERSION); 00151 printf("Release comment = %s\n", VERSION_COMMENT); 00152 printf("Git HEAD = %s\n", _GIT_HEAD_COMMIT ) ; 00153 printf("Git Describe = %s\n", _GIT_DESCRIBE ) ; 00154 exit(0); 00155 break; 00156 00157 case 'L': 00158 /* Default Log */ 00159 strncpy(log_path, optarg, MAXPATHLEN); 00160 break; 00161 00162 case 'N': 00163 /* debug level */ 00164 debug_level = ReturnLevelAscii(optarg); 00165 if(debug_level == -1) 00166 { 00167 fprintf(stderr, 00168 "Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n"); 00169 exit(1); 00170 } 00171 break; 00172 00173 case 'f': 00174 /* config file */ 00175 strncpy(config_path, optarg, MAXPATHLEN); 00176 break; 00177 00178 case 'p': 00179 /* PID file */ 00180 strncpy( pidfile_path, optarg, MAXPATHLEN ) ; 00181 break ; 00182 00183 case 'd': 00184 /* Detach or not detach ? */ 00185 detach_flag = TRUE; 00186 break; 00187 00188 case 'R': 00189 /* Shall we manage RPCSEC_GSS ? */ 00190 fprintf(stderr, 00191 "\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n"); 00192 fprintf(stderr, "NFS_KRB5\n"); 00193 fprintf(stderr, "{\n"); 00194 fprintf(stderr, "\tPrincipalName = nfs@<your_host> ;\n"); 00195 fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n"); 00196 fprintf(stderr, "\tActive_krb5 = TRUE ;\n"); 00197 fprintf(stderr, "}\n\n\n"); 00198 exit(1); 00199 break; 00200 00201 case 'T': 00202 /* Dump the default configuration on stdout */ 00203 my_nfs_start_info.dump_default_config = TRUE; 00204 break; 00205 00206 case 'E': 00207 ServerEpoch = (time_t) atoll(optarg); 00208 break; 00209 00210 case '?': 00211 case 'h': 00212 default: 00213 /* display the help */ 00214 fprintf(stderr, usage, exec_name); 00215 exit(0); 00216 break; 00217 } 00218 } 00219 00220 /* initialize memory and logging */ 00221 nfs_prereq_init(exec_name, host_name, debug_level, log_path); 00222 00223 /* Start in background, if wanted */ 00224 if(detach_flag) 00225 { 00226 #ifdef HAVE_DAEMON 00227 /* daemonize the process (fork, close xterm fds, 00228 * detach from parent process) */ 00229 if (daemon(0, 0)) 00230 LogFatal(COMPONENT_MAIN, 00231 "Error detaching process from parent: %s", 00232 strerror(errno)); 00233 #else 00234 /* Step 1: forking a service process */ 00235 switch (son_pid = fork()) 00236 { 00237 case -1: 00238 /* Fork failed */ 00239 LogFatal(COMPONENT_MAIN, 00240 "Could not start nfs daemon (fork error %d (%s)", 00241 errno, strerror(errno)); 00242 break; 00243 00244 case 0: 00245 /* This code is within the son (that will actually work) 00246 * Let's make it the leader of its group of process */ 00247 if(setsid() == -1) 00248 { 00249 LogFatal(COMPONENT_MAIN, 00250 "Could not start nfs daemon (setsid error %d (%s)", 00251 errno, strerror(errno)); 00252 } 00253 break; 00254 00255 default: 00256 /* This code is within the father, it is useless, it must die */ 00257 LogFullDebug(COMPONENT_MAIN, "Starting a son of pid %d", son_pid); 00258 exit(0); 00259 break; 00260 } 00261 #endif 00262 } 00263 00264 /* Make sure Linux file i/o will return with error if file size is exceeded. */ 00265 #ifdef _LINUX 00266 signal(SIGXFSZ, SIG_IGN); 00267 #endif 00268 00269 /* Echo PID into pidfile */ 00270 if( ( pidfile = open(pidfile_path, O_CREAT|O_RDWR, 0644)) == -1 ) 00271 { 00272 LogFatal( COMPONENT_MAIN, "Can't open pid file %si for writing", pidfile_path ) ; 00273 } 00274 else 00275 { 00276 char linebuf[1024]; 00277 struct flock lk; 00278 00279 /* Try to obtain a lock on the file */ 00280 lk.l_type = F_WRLCK; 00281 lk.l_whence = SEEK_SET; 00282 lk.l_start = (off_t)0; 00283 lk.l_len = (off_t)0; 00284 if (fcntl(pidfile, F_SETLK, &lk) == -1) 00285 LogFatal( COMPONENT_MAIN, "Ganesha already started"); 00286 00287 /* Put pid into file, then close it */ 00288 (void) snprintf(linebuf, sizeof(linebuf), "%u\n", getpid() ) ; 00289 if (write(pidfile, linebuf, strlen(linebuf)) == -1) 00290 LogCrit( COMPONENT_MAIN, "Couldn't write pid to file %s", 00291 pidfile_path); 00292 } 00293 00294 /* Set up for the signal handler. 00295 * Blocks the signals the signal handler will handle. 00296 */ 00297 sigemptyset(&signals_to_block); 00298 sigaddset(&signals_to_block, SIGTERM); 00299 sigaddset(&signals_to_block, SIGHUP); 00300 sigaddset(&signals_to_block, SIGPIPE); 00301 if(pthread_sigmask(SIG_BLOCK, &signals_to_block, NULL) != 0) 00302 LogFatal(COMPONENT_MAIN, 00303 "Could not start nfs daemon, pthread_sigmask failed"); 00304 00305 /* Set the parameter to 0 before doing anything */ 00306 memset((char *)&nfs_param, 0, sizeof(nfs_parameter_t)); 00307 00308 /* Get the FSAL functions */ 00309 FSAL_LoadFunctions(); 00310 00311 /* Get the FSAL consts */ 00312 FSAL_LoadConsts(); 00313 00314 #ifdef _PNFS_MDS 00315 FSAL_LoadMDSFunctions(); 00316 #endif /* _PNFS_MDS */ 00317 #ifdef _PNFS_DS 00318 FSAL_LoadDSFunctions(); 00319 #endif 00320 00321 LogEvent(COMPONENT_MAIN, 00322 ">>>>>>>>>>--------------------------------------- <<<<<<<<<<" ) ; 00323 00324 LogEvent(COMPONENT_MAIN, 00325 ">>>>>>>>>> Starting GANESHA NFS Daemon on FSAL/%s <<<<<<<<<<", 00326 FSAL_GetFSName()); 00327 00328 LogEvent(COMPONENT_MAIN, 00329 ">>>>>>>>>>--------------------------------------- <<<<<<<<<<" ) ; 00330 00331 /* initialize default parameters */ 00332 00333 nfs_set_param_default(); 00334 00335 /* parse configuration file */ 00336 00337 if(nfs_set_param_from_conf(&my_nfs_start_info)) 00338 { 00339 LogFatal(COMPONENT_INIT, "Error parsing configuration file."); 00340 } 00341 00342 /* check parameters consitency */ 00343 00344 if(nfs_check_param_consistency()) 00345 { 00346 LogFatal(COMPONENT_INIT, 00347 "Inconsistent parameters found. Exiting..." ) ; 00348 } 00349 00350 /* Everything seems to be OK! We can now start service threads */ 00351 nfs_start(&my_nfs_start_info); 00352 00353 return 0; 00354 00355 }