Exemple #1
0
int main(int argc, char *argv[])
{
  int c;
  int exportid = 0;
  char buffer[CMD_BUFFER_SIZE];
  char str[2 * CMD_BUFFER_SIZE];
  fhandle2 filehandle_v2;
  struct nfs_fh3 filehandle_v3;
  nfs_fh4 filehandle_v4;
  int flag_i = FALSE;
  char exec_name[MAXPATHLEN];
  char *tempo_exec_name = NULL;
  cache_inode_fsal_data_t fsal_data;
  fsal_op_context_t fsal_op_context;
  fsal_export_context_t fsal_export_context;
  exportlist_t *pexportlist = NULL;
  exportlist_t *pexport = NULL;
  nfs_start_info_t nfs_start_info;
  fsal_status_t fsal_status;
  unsigned int nfs_version = 3;
  path_str_t fsal_path_lib[NB_AVAILABLE_FSAL];
#ifdef _USE_SHARED_FSAL
  int lentab = NB_AVAILABLE_FSAL ;
#endif

  short cache_content_hash;
  char entry_path[MAXPATHLEN];
  int i, nb_char;

  fsal_path_t export_path = FSAL_PATH_INITIALIZER;
  unsigned int cookie;
  fsal_xattrent_t xattr_array[256];
  unsigned int nb_returned;
  int eol;
  char attr_buffer[4096];
  size_t sz_returned;
  fsal_u64_t objid;
  char options[] = "h@f:v:i:";
  char usage[] = "%s [-h][-f <cfg_path>] {-v 2|3|4 <NFS_FileHandle> | -i <inum>}\n"
      "   -h               : prints this help\n"
      "   -f <config_file> : sets the ganesha configuration file to be used\n"
      "   -v <nfs_version> : sets the NFS version the file handle passed as argument\n"
      "   -i <inum>        : get datacache path for the given inode number (decimal)\n";

  ServerBootTime = time(NULL);

  SetDefaultLogging("STDERR");

  /* What is the executable file's name */
  if((tempo_exec_name = strrchr(argv[0], '/')) != NULL)
    strcpy((char *)exec_name, tempo_exec_name + 1);

  strncpy(config_path, DEFAULT_CONFIG_FILE, MAXPATHLEN);

  /* now parsing options with getopt */
  while((c = getopt(argc, argv, options)) != EOF)
    {
      switch (c)
        {
        case '@':
          printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__);
          exit(0);
          break;

        case 'h':
          printf(usage, exec_name);
          exit(0);
          break;

        case 'f':
          strncpy(config_path, optarg, MAXPATHLEN);
          break;

        case 'i':
          if(sscanf(optarg, "%llu", &objid) != 1)
            {
              fprintf(stderr, "Invalid object_id %s (base-10 integer expected)\n",
                      optarg);
              exit(1);
            }
          flag_i = TRUE;
          break;

        case 'v':
          nfs_version = atoi(optarg);
          if((nfs_version < 2) || (nfs_version > 4))
            {
              fprintf(stderr, "Invalid nfs version %u\n", nfs_version);
              exit(1);
            }
          break;
        case '?':
          printf("Unknown option: %c\n", optopt);
          printf(usage, exec_name);
          exit(1);
        }
    }

  if(!flag_i && (optind != argc - 1))
    {
      printf("Missing argument: <NFS_FileHandle>\n");
      printf(usage, exec_name);
      exit(1);
    }

  /* initialize memory and logging */

  nfs_prereq_init("convert_fh", "localhost", NIV_MAJ, "/dev/tty");

#ifdef _USE_SHARED_FSAL
  if(nfs_get_fsalpathlib_conf(config_path, fsal_path_lib, &lentab))
    {
      fprintf(stderr, "NFS MAIN: Error parsing configuration file.");
      exit(1);
    }
#endif                          /* _USE_SHARED_FSAL */

  /* Load the FSAL library (if needed) */
  if(!FSAL_LoadLibrary((char *)fsal_path_lib))  /** @todo: this part of the code and this utility has to be checked */
    {
      fprintf(stderr, "NFS MAIN: Could not load FSAL dynamic library %s", (char *)fsal_path_lib[0]);
      exit(1);
    }

  /* Get the FSAL functions */
  FSAL_LoadFunctions();

  /* Get the FSAL consts */
  FSAL_LoadConsts();

  /* initialize default parameters */

  nfs_set_param_default();

  /* parse configuration file */

  if(nfs_set_param_from_conf(&nfs_start_info))
    {
      fprintf(stderr, "Error parsing configuration file '%s'", config_path);
      exit(1);
    }

  /* check parameters consitency */

  if(nfs_check_param_consistency())
    {
      fprintf(stderr, "Inconsistent parameters found");
      exit(1);
    }

  if(!nfs_param.pexportlist)
    {
      fprintf(stderr, "No export entries found in configuration file !!!\n");
      return -1;
    }

  pexportlist = nfs_param.pexportlist;

  /* not initialization is needed for converting fileid to path in datacache */
  if(!flag_i)
    {

#ifdef _USE_SHARED_FSAL
      fsal_status = FSAL_Init(&nfs_param.fsal_param[0]);
#else
      fsal_status = FSAL_Init(&nfs_param.fsal_param);
#endif
      if(FSAL_IS_ERROR(fsal_status))
        {
          /* Failed init */
          fprintf(stderr, "FSAL library could not be initialized, major=%d minor=%d\n",
                  fsal_status.major, fsal_status.minor);
          exit(1);
        }

      strncpy(str, argv[optind], 2 * CMD_BUFFER_SIZE);

      switch (nfs_version)
        {
        case 2:
          if(sscanmem(filehandle_v2, sizeof(file_handle_v2_t), (char *)str) == -1)
            {
              fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n",
                      (unsigned long)sizeof(file_handle_v2_t));
              exit(1);
            }

          exportid = nfs2_FhandleToExportId(&filehandle_v2);

          break;

        case 3:
          if(sscanmem(buffer, sizeof(file_handle_v3_t), (char *)str) == -1)
            {
              fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n",
                      (unsigned long)sizeof(file_handle_v3_t));
              exit(1);
            }
          filehandle_v3.data.data_val = (char *)buffer;
          filehandle_v3.data.data_len = sizeof(file_handle_v3_t);

          exportid = nfs3_FhandleToExportId(&filehandle_v3);
          break;

        case 4:
          if(sscanmem(buffer, sizeof(file_handle_v4_t), (char *)str) == -1)
            {
              fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n",
                      (unsigned long)sizeof(file_handle_v4_t));
              exit(1);
            }
          filehandle_v4.nfs_fh4_val = (char *)buffer;
          filehandle_v4.nfs_fh4_len = sizeof(file_handle_v4_t);

          exportid = nfs4_FhandleToExportId(&filehandle_v4);
          break;

        }
      if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL)
        {
          fprintf(stderr, "NFS FH has exportid %u which is invalid....\n", exportid);
          exit(1);
        }

      /* INITIALIZING A CLIENT CONTEXT FOR FSAL */

      FSAL_str2path(pexport->fullpath, MAXPATHLEN, &export_path);

      if(FSAL_IS_ERROR
         (fsal_status =
          FSAL_BuildExportContext(&fsal_export_context, &export_path,
                                  pexport->FS_specific)))
        {
          fprintf(stderr, "Error in FSAL_BuildExportContext, major=%u, minor=%u\n",
                  fsal_status.major, fsal_status.minor);
          exit(1);
        }

      fsal_status = FSAL_InitClientContext(&fsal_op_context);
      if(FSAL_IS_ERROR(fsal_status))
        {
          /* Failed init */
          fprintf(stderr, "Could not init client context... major=%d minor=%d\n",
                  fsal_status.major, fsal_status.minor);
          exit(1);
        }

      fsal_status = FSAL_GetClientContext(&fsal_op_context,
                                          &fsal_export_context, 0, 0, NULL, 0);

      if(FSAL_IS_ERROR(fsal_status))
        {
          /* Failed init */
          fprintf(stderr, "Could not get cred for uid=%d gid=%d, major=%d minor=%d\n",
                  getuid(), getgid(), fsal_status.major, fsal_status.minor);
          exit(1);
        }

      /* now, can use the fsal_op_context */
      switch (nfs_version)
        {
        case 2:
          if(!nfs2_FhandleToFSAL(&filehandle_v2, &fsal_data.handle, &fsal_op_context))
            {
              fprintf(stderr, "Cannot convert Fhandle to FSAL\n");
              exit(1);
            }
          break;

        case 3:
          if(!nfs3_FhandleToFSAL(&filehandle_v3, &fsal_data.handle, &fsal_op_context))
            {
              fprintf(stderr, "Cannot convert Fhandle to FSAL\n");
              exit(1);
            }
          break;

        case 4:
          if(!nfs4_FhandleToFSAL(&filehandle_v4, &fsal_data.handle, &fsal_op_context))
            {
              fprintf(stderr, "Cannot convert Fhandle to FSAL\n");
              exit(1);
            }
          break;
        }

      printf("\n");

      snprintmem((caddr_t) str, 2 * CMD_BUFFER_SIZE, (caddr_t) & fsal_data.handle,
                 sizeof(fsal_data.handle));

      printf("%-18s = %s\n", "FSAL Handle", str);

      /* Now, list FSAL extended attributes */

      cookie = XATTRS_READLIST_FROM_BEGINNING;
      eol = FALSE;

      while(!eol)
        {
          unsigned int index;

          fsal_status = FSAL_ListXAttrs(&fsal_data.handle, cookie, &fsal_op_context,
                                        xattr_array, 256, &nb_returned, &eol);

          if(FSAL_IS_ERROR(fsal_status))
            {
              fprintf(stderr, "Error executing FSAL_ListXAttrs\n");
              exit(1);
            }

          /* list attributes and get their value */

          for(index = 0; index < nb_returned; index++)
            {
              cookie = xattr_array[index].xattr_cookie;

              printf("%-18s = ", xattr_array[index].xattr_name.name);

              fsal_status =
                  FSAL_GetXAttrValueByName(&fsal_data.handle,
                                           &xattr_array[index].xattr_name,
                                           &fsal_op_context, attr_buffer, 4096,
                                           &sz_returned);

              if(FSAL_IS_ERROR(fsal_status))
                {
                  fprintf(stderr, "Error executing FSAL_GetXAttrValueByName\n");
                }

              /* Display it */
              print_buffer(attr_buffer, sz_returned);

            }

        }

      /* get object ID */
      fsal_status =
          FSAL_DigestHandle(&fsal_export_context, FSAL_DIGEST_FILEID4, &fsal_data.handle,
                            (caddr_t) & objid);

      if(FSAL_IS_ERROR(fsal_status))
        {
          fprintf(stderr, "Error retrieving fileid from handle\n");
        }
      else
        {
          printf("%-18s = %llu\n", "FileId", objid);
        }

    }

  /* end of retrieval of objid */
  /* build the path in the datacache */
  cache_content_hash = HashFileID4(objid);

  /* for limiting the number of entries into each datacache directory
   * we create 256 subdirectories on 2 levels, depending on the entry's fileid.
   */
  nb_char = snprintf(entry_path, MAXPATHLEN, "export_id=%d", 0);

  for(i = 0; i <= 8; i += 8)
    {
      /* concatenation of hashval */
      nb_char += snprintf((char *)(entry_path + nb_char), MAXPATHLEN - nb_char,
                          "/%02hhX", (char)((cache_content_hash >> i) & 0xFF));
    }

  /* displays the node name */

  printf("%-18s = %s/%s/node=%llx*\n", "DataCache path",
         nfs_param.cache_layers_param.cache_content_client_param.cache_dir, entry_path,
         objid);

  exit(0);
}
Exemple #2
0
int main(int argc, char *argv[])
{
	char *tempo_exec_name = NULL;
	char localmachine[MAXHOSTNAMELEN + 1];
	int c;
	int pidfile;
#ifndef HAVE_DAEMON
	pid_t son_pid;
#endif
	sigset_t signals_to_block;

	/* Set the server's boot time and epoch */
	now(&ServerBootTime);
	ServerEpoch = (time_t) ServerBootTime.tv_sec;

	tempo_exec_name = strrchr(argv[0], '/');
	if (tempo_exec_name != NULL) {
		exec_name = gsh_strdup(tempo_exec_name + 1);
		if (!exec_name) {
			fprintf(stderr,
				"Unable to allocate memory for exec name, exiting...\n");
			exit(1);
		}
	}

	if (*exec_name == '\0')
		exec_name = argv[0];

	/* get host name */
	if (gethostname(localmachine, sizeof(localmachine)) != 0) {
		fprintf(stderr, "Could not get local host name, exiting...\n");
		exit(1);
	} else {
		host_name = gsh_strdup(localmachine);
		if (!host_name) {
			fprintf(stderr,
				"Unable to allocate memory for hostname, exiting...\n");
			exit(1);
		}
	}

	/* now parsing options with getopt */
	while ((c = getopt(argc, argv, options)) != EOF) {
		switch (c) {
		case '@':
			/* A litlle backdoor to keep track of binary versions */
			printf("%s compiled on %s at %s\n", exec_name, __DATE__,
			       __TIME__);
			printf("Release = %s\n", VERSION);
			printf("Release comment = %s\n", VERSION_COMMENT);
			printf("Git HEAD = %s\n", _GIT_HEAD_COMMIT);
			printf("Git Describe = %s\n", _GIT_DESCRIBE);
			exit(0);
			break;

		case 'L':
			/* Default Log */
			log_path = gsh_strdup(optarg);
			if (!log_path) {
				fprintf(stderr,
					"Unable to allocate memory for log path.\n");
				exit(1);
			}
			break;

		case 'N':
			/* debug level */
			debug_level = ReturnLevelAscii(optarg);
			if (debug_level == -1) {
				fprintf(stderr,
					"Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n");
				exit(1);
			}
			break;

		case 'f':
			/* config file */

			config_path = gsh_strdup(optarg);
			if (!config_path) {
				fprintf(stderr,
					"Unable to allocate memory for config path.\n");
				exit(1);
			}
			break;

		case 'p':
			/* PID file */
			pidfile_path = gsh_strdup(optarg);
			if (!pidfile_path) {
				fprintf(stderr,
					"Path %s too long for option 'f'.\n",
					optarg);
				exit(1);
			}
			break;

		case 'd':
			/* Detach or not detach ? */
			detach_flag = true;
			break;

		case 'R':
			/* Shall we manage  RPCSEC_GSS ? */
			fprintf(stderr,
				"\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n");
			fprintf(stderr, "NFS_KRB5\n");
			fprintf(stderr, "{\n");
			fprintf(stderr,
				"\tPrincipalName = nfs@<your_host> ;\n");
			fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n");
			fprintf(stderr, "\tActive_krb5 = true ;\n");
			fprintf(stderr, "}\n\n\n");
			exit(1);
			break;

		case 'T':
			/* Dump the default configuration on stdout */
			my_nfs_start_info.dump_default_config = true;
			break;

		case 'E':
			ServerEpoch = (time_t) atoll(optarg);
			break;

		case '?':
		case 'h':
		default:
			/* display the help */
			fprintf(stderr, usage, exec_name);
			exit(0);
			break;
		}
	}

	/* initialize memory and logging */
	nfs_prereq_init(exec_name, host_name, debug_level, log_path);
	LogEvent(COMPONENT_MAIN,
		 "%s Starting: Version %s, built at %s %s on %s",
		 exec_name, GANESHA_VERSION, __DATE__, __TIME__, BUILD_HOST);

	/* Start in background, if wanted */
	if (detach_flag) {
#ifdef HAVE_DAEMON
		/* daemonize the process (fork, close xterm fds,
		 * detach from parent process) */
		if (daemon(0, 0))
			LogFatal(COMPONENT_MAIN,
				 "Error detaching process from parent: %s",
				 strerror(errno));
#else
		/* Step 1: forking a service process */
		switch (son_pid = fork()) {
		case -1:
			/* Fork failed */
			LogFatal(COMPONENT_MAIN,
				 "Could not start nfs daemon (fork error %d (%s)",
				 errno, strerror(errno));
			break;

		case 0:
			/* This code is within the son (that will actually work)
			 * Let's make it the leader of its group of process */
			if (setsid() == -1) {
				LogFatal(COMPONENT_MAIN,
					 "Could not start nfs daemon (setsid error %d (%s)",
					 errno, strerror(errno));
			}
			break;

		default:
			/* This code is within the parent process,
			 * it is useless, it must die */
			LogFullDebug(COMPONENT_MAIN,
				     "Starting a child of pid %d",
				     son_pid);
			exit(0);
			break;
		}
#endif
	}

	/* Make sure Linux file i/o will return with error
	 * if file size is exceeded. */
#ifdef _LINUX
	signal(SIGXFSZ, SIG_IGN);
#endif

	/* Echo PID into pidfile */
	pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0644);
	if (pidfile == -1) {
		LogFatal(COMPONENT_MAIN, "Can't open pid file %s for writing",
			 pidfile_path);
	} else {
		char linebuf[1024];
		struct flock lk;

		/* Try to obtain a lock on the file */
		lk.l_type = F_WRLCK;
		lk.l_whence = SEEK_SET;
		lk.l_start = (off_t) 0;
		lk.l_len = (off_t) 0;
		if (fcntl(pidfile, F_SETLK, &lk) == -1)
			LogFatal(COMPONENT_MAIN, "Ganesha already started");

		/* Put pid into file, then close it */
		(void)snprintf(linebuf, sizeof(linebuf), "%u\n", getpid());
		if (write(pidfile, linebuf, strlen(linebuf)) == -1)
			LogCrit(COMPONENT_MAIN, "Couldn't write pid to file %s",
				pidfile_path);
	}

	/* Set up for the signal handler.
	 * Blocks the signals the signal handler will handle.
	 */
	sigemptyset(&signals_to_block);
	sigaddset(&signals_to_block, SIGTERM);
	sigaddset(&signals_to_block, SIGHUP);
	sigaddset(&signals_to_block, SIGPIPE);
	if (pthread_sigmask(SIG_BLOCK, &signals_to_block, NULL) != 0)
		LogFatal(COMPONENT_MAIN,
			 "Could not start nfs daemon, pthread_sigmask failed");

	/* Parse the configuration file so we all know what is going on. */

	if (config_path == NULL) {
		LogFatal(COMPONENT_INIT,
			 "start_fsals: No configuration file named.");
		return 1;
	}
	config_struct = config_ParseFile(config_path);

	if (!config_struct) {
		LogFatal(COMPONENT_INIT, "Error while parsing %s: %s",
			 config_path, config_GetErrorMsg());
	}

	/* We need all the fsal modules loaded so we can have
	 * the list available at exports parsing time.
	 */
	start_fsals(config_struct);

	/* parse configuration file */

	if (nfs_set_param_from_conf(config_struct, &my_nfs_start_info)) {
		LogFatal(COMPONENT_INIT,
			 "Error setting parameters from configuration file.");
	}

	if (nfs_check_param_consistency()) {
		LogFatal(COMPONENT_INIT,
			 "Inconsistent parameters found. Exiting...");
	}
	if (init_fsals(config_struct)) { /* init the FSALs from the config */
		LogFatal(COMPONENT_INIT,
			 "FSALs could not initialize. Exiting...");
	}

	/* freeing syntax tree : */

	config_Free(config_struct);

	/* Everything seems to be OK! We can now start service threads */
	nfs_start(&my_nfs_start_info);

	return 0;

}
int ganefuse_main(int argc, char *argv[],
                  const struct ganefuse_operations *op, void *user_data)
{
  char *tempo_exec_name = NULL;
  char localmachine[MAXHOSTNAMELEN];
  int c;
  pid_t son_pid;

  int argc_local = argc;
  char **argv_local = argv;

  /* local copy for keeping it read only */
  ops = *op;

  /* retrieve executable file's name */
  strncpy(ganesha_exec_path, argv[0], MAXPATHLEN);

  if((tempo_exec_name = strrchr(argv_local[0], '/')) != NULL)
    strcpy((char *)exec_name, tempo_exec_name + 1);

  if(*exec_name == '\0')
    strcpy((char *)exec_name, argv_local[0]);

  /* get host name */

  if(gethostname(localmachine, sizeof(localmachine)) != 0)
    {
      fprintf(stderr, "Could not get local host name, exiting...");
      exit(1);
    }
  else
    strncpy(host_name, localmachine, MAXHOSTNAMELEN);

  /* now parsing options with getopt */
  while((c = getopt(argc_local, argv_local, options)) != EOF)
    {

      switch (c)
        {
        case '@':
          /* A litlle backdoor to keep track of binary versions */
          printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__);
          printf("Release = %s\n", VERSION);
          printf("Release comment = %s\n", VERSION_COMMENT);
          exit(0);
          break;

        case 'L':
          /* Default Log */
          strncpy(log_path, optarg, MAXPATHLEN);
          break;

        case 'N':
          /* debug level */
          debug_level = ReturnLevelAscii(optarg);
          if(debug_level == -1)
            {
              fprintf(stderr,
                      "Invalid value for option 'N': NIV_NULL, NIV_MAJ, NIV_CRIT, NIV_EVENT, NIV_DEBUG, NIV_MID_DEBUG or NIV_FULL_DEBUG expected.\n");
              exit(1);
            }
          break;

        case 'f':
          /* config file */
          strncpy(config_path, optarg, MAXPATHLEN);
          break;

        case 's':
          /* single threaded */
          single_threaded = TRUE;
          break;

        case 'd':
          /* Detach or not detach ? */
          detach_flag = TRUE;
          break;

        case 'R':
          /* Shall we manage  RPCSEC_GSS ? */
          fprintf(stderr,
                  "\n\nThe -R flag is deprecated, use this syntax in the configuration file instead:\n\n");
          fprintf(stderr, "NFS_KRB5\n");
          fprintf(stderr, "{\n");
          fprintf(stderr, "\tPrincipalName = nfs@<your_host> ;\n");
          fprintf(stderr, "\tKeytabPath = /etc/krb5.keytab ;\n");
          fprintf(stderr, "\tActive_krb5 = TRUE ;\n");
          fprintf(stderr, "}\n\n\n");
          exit(1);

          break;

        case 'F':
          /* Flushes the data cache to the FSAL and purges the cache */
          nfs_start_info.flush_datacache_mode = TRUE;
          nfs_start_info.flush_behaviour = CACHE_CONTENT_FLUSH_AND_DELETE;
          nfs_start_info.nb_flush_threads = (unsigned int)atoi(optarg);

          if(nfs_start_info.nb_flush_threads > NB_MAX_FLUSHER_THREAD)
            nfs_start_info.nb_flush_threads = NB_MAX_FLUSHER_THREAD;
          break;

        case 'S':
          /* Flushes the data cache to the FSAL, without purging the cache */
          nfs_start_info.flush_datacache_mode = TRUE;
          nfs_start_info.flush_behaviour = CACHE_CONTENT_FLUSH_SYNC_ONLY;
          nfs_start_info.nb_flush_threads = (unsigned int)atoi(optarg);

          if(nfs_start_info.nb_flush_threads > NB_MAX_FLUSHER_THREAD)
            nfs_start_info.nb_flush_threads = NB_MAX_FLUSHER_THREAD;
          break;

        case 'h':
          /* display the help */
          fprintf(stderr, usage, exec_name);
          exit(0);
          break;

        case '?':
        default:
          /* ignore unsupported options */
          fprintf(stderr, "WARNING: unknown GANESHA NFS daemon option: %c\n",
                  (char)optopt);

        }
    }

  /* initialize memory and logging */

  nfs_prereq_init(exec_name, host_name, debug_level, log_path);

  /* Start in background, if wanted */
  if(detach_flag)
    {
      /* Step 1: forking a service process */
      switch (son_pid = fork())
        {
        case -1:
          /* Fork failed */
          LogError(COMPONENT_MAIN, ERR_SYS, ERR_FORK, errno);
          LogCrit(COMPONENT_MAIN,
                  "Could nout start nfs daemon, exiting...");
          exit(1);

        case 0:
          /* This code is within the son (that will actually work)
           * Let's make it the leader of its group of process */
          if(setsid() == -1)
            {
              LogError(COMPONENT_MAIN, ERR_SYS, ERR_SETSID, errno);
              LogCrit(COMPONENT_MAIN,
                      "Could nout start nfs daemon, exiting...");
              exit(1);
            }
          break;

        default:
          /* This code is within the father, it is useless, it must die */
          LogFullDebug(COMPONENT_MAIN,
                       "Starting a son of pid %d\n", son_pid);
          exit(0);
          break;
        }
    }

  /* Get the FSAL functions */
  FSAL_LoadFunctions();

  /* Get the FSAL consts */
  FSAL_LoadConsts();

  LogEvent(COMPONENT_MAIN,
           ">>>>>>>>>> Starting GANESHA NFS Daemon on FSAL/%s <<<<<<<<<<",
           FSAL_GetFSName());

  /* initialize default parameters */
  nfs_set_param_default();

  /* return all errors */
  nfs_param.core_param.drop_io_errors = FALSE;
  nfs_param.core_param.drop_inval_errors = FALSE;
  nfs_param.core_param.drop_delay_errors = FALSE;

  /* parse configuration file (if specified) */

  if(strlen(config_path) > 0)
    {
      if(nfs_set_param_from_conf(&nfs_start_info))
        {
          LogCrit(COMPONENT_MAIN,
                  "NFS MAIN: Error parsing configuration file.");
          exit(1);
        }
    }

  /* set filesystem relative info */

  ((fusefs_specific_initinfo_t *) &nfs_param.fsal_param.fs_specific_info)->fs_ops = &ops;
  ((fusefs_specific_initinfo_t *) &nfs_param.fsal_param.fs_specific_info)->user_data = user_data;

#ifdef _SNMP_ADM_ACTIVE
  if(!nfs_param.extern_param.snmp_adm.snmp_log_file[0])
    strcpy(nfs_param.extern_param.snmp_adm.snmp_log_file, log_path);
#endif

  /* add export by hand if no export was defined
   * in config file (always '/')
   */

  if(!nfs_param.pexportlist)
    {
      nfs_param.pexportlist = BuildDefaultExport();
      if(nfs_param.pexportlist == NULL)
        {
          LogCrit(COMPONENT_MAIN,
                  "NFS MAIN: Could not create export entry for '/'");
          exit(1);
        }
    }

  /* if this is a single threaded application, set worker count */
  if(single_threaded)
    nfs_param.core_param.nb_worker = 1;

  /* check parameters consitency */

  if(nfs_check_param_consistency())
    {
      LogMajor(COMPONENT_MAIN,
               "NFS MAIN: Inconsistent parameters found");
      LogMajor(COMPONENT_MAIN,
               "MAJOR WARNING: /!\\ | Bad Parameters could have significant impact on the daemon behavior");
      exit(1);
    }

  /* Everything seems to be OK! We can now start service threads */
  nfs_start(&nfs_start_info);

  return 0;

}