nfs-ganesha 1.4

fuse_binding.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 
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 }