1 /*
2 * vim:noexpandtab:shiftwidth=8:tabstop=8:
3 *
4 * Copyright CEA/DAM/DIF (2008)
5 * contributeur : Philippe DENIEL philippe.deniel@cea.fr
6 * Thomas LEIBOVICI thomas.leibovici@cea.fr
7 *
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 3 of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 * ---------------------------------------
25 */
26
27 /**
28 * @file nfs_init.c
29 * @brief Most of the init routines
30 */
31 #include "config.h"
32 #include "nfs_init.h"
33 #include "log.h"
34 #include "fsal.h"
35 #include "rquota.h"
36 #include "nfs_core.h"
37 #include "nfs_file_handle.h"
38 #include "nfs_exports.h"
39 #include "nfs_ip_stats.h"
40 #include "nfs_proto_functions.h"
41 #include "nfs_dupreq.h"
42 #include "config_parsing.h"
43 #include "nfs4_acls.h"
44 #include "nfs_rpc_callback.h"
45 #ifdef USE_DBUS
46 #include "gsh_dbus.h"
47 #endif
48 #include "FSAL/fsal_commonlib.h"
49 #ifdef _USE_CB_SIMULATOR
50 #include "nfs_rpc_callback_simulator.h"
51 #endif
52 #include <sys/time.h>
53 #include <sys/resource.h>
54 #include <unistd.h>
55 #include <string.h>
56 #include <signal.h>
57 #include <math.h>
58 #ifdef _USE_NLM
59 #include "nlm_util.h"
60 #endif /* _USE_NLM */
61 #include "nsm.h"
62 #include "sal_functions.h"
63 #include "fridgethr.h"
64 #include "idmapper.h"
65 #include "delayed_exec.h"
66 #include "client_mgr.h"
67 #include "export_mgr.h"
68 #ifdef USE_CAPS
69 #include <sys/capability.h> /* For capget/capset */
70 #endif
71 #include "uid2grp.h"
72 #include "netgroup_cache.h"
73 #include "pnfs_utils.h"
74 #include "mdcache.h"
75 #include "common_utils.h"
76 #include "nfs_init.h"
77 #include "conf_url_rados.h"
78 #include <urcu-bp.h>
79
80 /**
81 * @brief init_complete used to indicate if ganesha is during
82 * startup or not
83 */
84 struct nfs_init nfs_init;
85
86 /* global information exported to all layers (as extern vars) */
87 nfs_parameter_t nfs_param;
88 struct _nfs_health nfs_health_;
89
90 static struct _nfs_health healthstats;
91
92 /* ServerEpoch is ServerBootTime unless overriden by -E command line option */
93 struct timespec nfs_ServerBootTime;
94 time_t nfs_ServerEpoch;
95
96 verifier4 NFS4_write_verifier; /* NFS V4 write verifier */
97 writeverf3 NFS3_write_verifier; /* NFS V3 write verifier */
98
99 /* node ID used to identify an individual node in a cluster */
100 int g_nodeid;
101
102 nfs_start_info_t nfs_start_info;
103
104 pthread_t admin_thrid;
105 pthread_t sigmgr_thrid;
106
107 tirpc_pkg_params ntirpc_pp = {
108 TIRPC_DEBUG_FLAG_DEFAULT,
109 0,
110 SetNameFunction,
111 (mem_format_t)rpc_warnx,
112 gsh_free_size,
113 gsh_malloc__,
114 gsh_malloc_aligned__,
115 gsh_calloc__,
116 gsh_realloc__,
117 };
118
119 #ifdef _USE_9P
120 pthread_t _9p_dispatcher_thrid;
121 #endif
122
123 #ifdef _USE_9P_RDMA
124 pthread_t _9p_rdma_dispatcher_thrid;
125 #endif
126
127 #ifdef _USE_NFS_RDMA
128 pthread_t nfs_rdma_dispatcher_thrid;
129 #endif
130
131 char *nfs_config_path = GANESHA_CONFIG_PATH;
132
133 char *nfs_pidfile_path = GANESHA_PIDFILE_PATH;
134
135 /**
136 * @brief Reread the configuration file to accomplish update of options.
137 *
138 * The following option blocks are currently supported for update:
139 *
140 * LOG {}
141 * LOG { COMPONENTS {} }
142 * LOG { FACILITY {} }
143 * LOG { FORMAT {} }
144 * EXPORT {}
145 * EXPORT { CLIENT {} }
146 *
147 */
148
149 struct config_error_type err_type;
150
151 void reread_config(void)
152 {
153 int status = 0;
154 int i;
155 config_file_t config_struct;
156
157 /* Clear out the flag indicating component was set from environment. */
158 for (i = COMPONENT_ALL; i < COMPONENT_COUNT; i++)
159 LogComponents[i].comp_env_set = false;
160
161 /* If no configuration file is given, then the caller must want to
162 * reparse the configuration file from startup.
163 */
164 if (nfs_config_path[0] == '\0') {
165 LogCrit(COMPONENT_CONFIG,
166 "No configuration file was specified for reloading log config.");
167 return;
168 }
169
170 /* Create a memstream for parser+processing error messages */
171 if (!init_error_type(&err_type))
172 return;
173 /* Attempt to parse the new configuration file */
174 config_struct = config_ParseFile(nfs_config_path, &err_type);
175 if (!config_error_no_error(&err_type)) {
176 config_Free(config_struct);
177 LogCrit(COMPONENT_CONFIG,
178 "Error while parsing new configuration file %s",
179 nfs_config_path);
180 report_config_errors(&err_type, NULL, config_errs_to_log);
181 return;
182 }
183
184 /* Update the logging configuration */
185 status = read_log_config(config_struct, &err_type);
186 if (status < 0)
187 LogCrit(COMPONENT_CONFIG, "Error while parsing LOG entries");
188
189 /* Update the export configuration */
190 status = reread_exports(config_struct, &err_type);
191 if (status < 0)
192 LogCrit(COMPONENT_CONFIG, "Error while parsing EXPORT entries");
193
194 report_config_errors(&err_type, NULL, config_errs_to_log);
195 config_Free(config_struct);
196 }
197
198 /**
199 * @brief This thread is in charge of signal management
200 *
201 * @param[in] UnusedArg Unused
202 *
203 * @return NULL.
204 */
205 static void *sigmgr_thread(void *UnusedArg)
206 {
207 int signal_caught = 0;
208
209 SetNameFunction("sigmgr");
210 rcu_register_thread();
211
212 /* Loop until we catch SIGTERM */
213 while (signal_caught != SIGTERM) {
214 sigset_t signals_to_catch;
215
216 sigemptyset(&signals_to_catch);
217 sigaddset(&signals_to_catch, SIGTERM);
218 sigaddset(&signals_to_catch, SIGHUP);
219 if (sigwait(&signals_to_catch, &signal_caught) != 0) {
220 LogFullDebug(COMPONENT_THREAD,
221 "sigwait exited with error");
222 continue;
223 }
224 if (signal_caught == SIGHUP) {
225 LogEvent(COMPONENT_MAIN,
226 "SIGHUP_HANDLER: Received SIGHUP.... initiating export list reload");
227 reread_config();
228 #ifdef _HAVE_GSSAPI
229 svcauth_gss_release_cred();
230 #endif /* _HAVE_GSSAPI */
231 }
232 }
233 LogDebug(COMPONENT_THREAD, "sigmgr thread exiting");
234
235 admin_halt();
236
237 /* Might as well exit - no need for this thread any more */
238 rcu_unregister_thread();
239 return NULL;
240 }
241
242
243 static void crash_handler(int signo, siginfo_t *info, void *ctx)
244 {
245 gsh_backtrace();
246 /* re-raise the signal for the default signal handler to dump core */
247 raise(signo);
248 }
249
250 static void install_sighandler(int signo,
251 void (*handler)(int, siginfo_t *, void *))
252 {
253 struct sigaction sa = {};
254 int ret;
255
256 sa.sa_sigaction = handler;
257 /* set SA_RESETHAND to restore default handler */
258 sa.sa_flags = SA_SIGINFO | SA_RESETHAND | SA_NODEFER;
259
260 sigemptyset(&sa.sa_mask);
261
262 ret = sigaction(signo, &sa, NULL);
263 if (ret) {
264 LogWarn(COMPONENT_INIT,
265 "Install handler for signal (%s) failed",
266 strsignal(signo));
267 }
268 }
269
270 static void init_crash_handlers(void)
271 {
272 install_sighandler(SIGSEGV, crash_handler);
273 install_sighandler(SIGABRT, crash_handler);
274 install_sighandler(SIGBUS, crash_handler);
275 install_sighandler(SIGILL, crash_handler);
276 install_sighandler(SIGFPE, crash_handler);
277 install_sighandler(SIGQUIT, crash_handler);
278 }
279
280 /**
281 * @brief Initialize NFSd prerequisites
282 *
283 * @param[in] program_name Name of the program
284 * @param[in] host_name Server host name
285 * @param[in] debug_level Debug level
286 * @param[in] log_path Log path
287 * @param[in] dump_trace Dump trace when segfault
288 */
289 void nfs_prereq_init(const char *program_name, const char *host_name,
290 int debug_level, const char *log_path, bool dump_trace)
291 {
292 healthstats.enqueued_reqs = nfs_health_.enqueued_reqs = 0;
293 healthstats.enqueued_reqs = nfs_health_.dequeued_reqs = 0;
294
295 /* Initialize logging */
296 SetNamePgm(program_name);
297 SetNameFunction("main");
298 SetNameHost(host_name);
299
300 init_logging(log_path, debug_level);
301 if (dump_trace) {
302 init_crash_handlers();
303 }
304
305 /* Redirect TI-RPC allocators, log channel */
306 if (!tirpc_control(TIRPC_PUT_PARAMETERS, &ntirpc_pp)) {
307 LogFatal(COMPONENT_INIT, "Setting nTI-RPC parameters failed");
308 }
309 }
310
311 /**
312 * @brief Print the nfs_parameter_structure
313 */
314 void nfs_print_param_config(void)
315 {
316 printf("NFS_Core_Param\n{\n");
317
318 printf("\tNFS_Port = %u ;\n", nfs_param.core_param.port[P_NFS]);
319 printf("\tMNT_Port = %u ;\n", nfs_param.core_param.port[P_MNT]);
320 printf("\tNFS_Program = %u ;\n", nfs_param.core_param.program[P_NFS]);
321 printf("\tMNT_Program = %u ;\n", nfs_param.core_param.program[P_NFS]);
322 printf("\tDRC_TCP_Npart = %u ;\n", nfs_param.core_param.drc.tcp.npart);
323 printf("\tDRC_TCP_Size = %u ;\n", nfs_param.core_param.drc.tcp.size);
324 printf("\tDRC_TCP_Cachesz = %u ;\n",
325 nfs_param.core_param.drc.tcp.cachesz);
326 printf("\tDRC_TCP_Hiwat = %u ;\n", nfs_param.core_param.drc.tcp.hiwat);
327 printf("\tDRC_TCP_Recycle_Npart = %u ;\n",
328 nfs_param.core_param.drc.tcp.recycle_npart);
329 printf("\tDRC_TCP_Recycle_Expire_S = %u ;\n",
330 nfs_param.core_param.drc.tcp.recycle_expire_s);
331 printf("\tDRC_TCP_Checksum = %u ;\n",
332 nfs_param.core_param.drc.tcp.checksum);
333 printf("\tDRC_UDP_Npart = %u ;\n", nfs_param.core_param.drc.udp.npart);
334 printf("\tDRC_UDP_Size = %u ;\n", nfs_param.core_param.drc.udp.size);
335 printf("\tDRC_UDP_Cachesz = %u ;\n",
336 nfs_param.core_param.drc.udp.cachesz);
337 printf("\tDRC_UDP_Hiwat = %u ;\n", nfs_param.core_param.drc.udp.hiwat);
338 printf("\tDRC_UDP_Checksum = %u ;\n",
339 nfs_param.core_param.drc.udp.checksum);
340 printf("\tBlocked_Lock_Poller_Interval = %" PRIu64 " ;\n",
341 (uint64_t) nfs_param.core_param.blocked_lock_poller_interval);
342
343 printf("\tManage_Gids_Expiration = %" PRIu64 " ;\n",
344 (uint64_t) nfs_param.core_param.manage_gids_expiration);
345
346 printf("\tDrop_IO_Errors = %s ;\n",
347 nfs_param.core_param.drop_io_errors ? "true" : "false");
348
349 printf("\tDrop_Inval_Errors = %s ;\n",
350 nfs_param.core_param.drop_inval_errors ? "true" : "false");
351
352 printf("\tDrop_Delay_Errors = %s ;\n",
353 nfs_param.core_param.drop_delay_errors ? "true" : "false");
354
355 printf("\tEnable UDP = %s ;\n", nfs_param.core_param.enable_UDP ?
356 "true" : "false");
357
358 printf("}\n\n");
359 }
360
361 /**
362 * @brief Load parameters from config file
363 *
364 * @param[in] config_struct Parsed config file
365 * @param[out] p_start_info Startup parameters
366 * @param[out] err_type error reporting state
367 *
368 * @return -1 on failure.
369 */
370 int nfs_set_param_from_conf(config_file_t parse_tree,
371 nfs_start_info_t *p_start_info,
372 struct config_error_type *err_type)
373 {
374 /*
375 * Initialize exports and clients so config parsing can use them
376 * early.
377 */
378 client_pkginit();
379 export_pkginit();
380 server_pkginit();
381
382 /* Core parameters */
383 (void) load_config_from_parse(parse_tree,
384 &nfs_core,
385 &nfs_param.core_param,
386 true,
387 err_type);
388 if (!config_error_is_harmless(err_type)) {
389 LogCrit(COMPONENT_INIT,
390 "Error while parsing core configuration");
391 return -1;
392 }
393
394 /* Worker paramters: ip/name hash table and expiration for each entry */
395 (void) load_config_from_parse(parse_tree,
396 &nfs_ip_name,
397 NULL,
398 true,
399 err_type);
400 if (!config_error_is_harmless(err_type)) {
401 LogCrit(COMPONENT_INIT,
402 "Error while parsing IP/name configuration");
403 return -1;
404 }
405
406 #ifdef _HAVE_GSSAPI
407 /* NFS kerberos5 configuration */
408 (void) load_config_from_parse(parse_tree,
409 &krb5_param,
410 &nfs_param.krb5_param,
411 true,
412 err_type);
413 if (!config_error_is_harmless(err_type)) {
414 LogCrit(COMPONENT_INIT,
415 "Error while parsing NFS/KRB5 configuration for RPCSEC_GSS");
416 return -1;
417 }
418 #endif
419
420 /* NFSv4 specific configuration */
421 (void) load_config_from_parse(parse_tree,
422 &version4_param,
423 &nfs_param.nfsv4_param,
424 true,
425 err_type);
426 if (!config_error_is_harmless(err_type)) {
427 LogCrit(COMPONENT_INIT,
428 "Error while parsing NFSv4 specific configuration");
429 return -1;
430 }
431
432 #ifdef _USE_9P
433 (void) load_config_from_parse(parse_tree,
434 &_9p_param_blk,
435 NULL,
436 true,
437 err_type);
438 if (!config_error_is_harmless(err_type)) {
439 LogCrit(COMPONENT_INIT,
440 "Error while parsing 9P specific configuration");
441 return -1;
442 }
443 #endif
444
445 if (mdcache_set_param_from_conf(parse_tree, err_type) < 0)
446 return -1;
447
448 #ifdef USE_RADOS_RECOV
449 if (rados_kv_set_param_from_conf(parse_tree, err_type) < 0)
450 return -1;
451 #endif
452
453 if (rados_url_setup_watch() != 0)
454 return -1;
455
456 LogEvent(COMPONENT_INIT, "Configuration file successfully parsed");
457
458 return 0;
459 }
460
461 int init_server_pkgs(void)
462 {
463 fsal_status_t fsal_status;
464 state_status_t state_status;
465
466 /* init uid2grp cache */
467 uid2grp_cache_init();
468
469 ng_cache_init(); /* netgroup cache */
470
471 /* MDCACHE Initialisation */
472 fsal_status = mdcache_pkginit();
473 if (FSAL_IS_ERROR(fsal_status)) {
474 LogCrit(COMPONENT_INIT,
475 "MDCACHE FSAL could not be initialized, status=%s",
476 fsal_err_txt(fsal_status));
477 return -1;
478 }
479
480 state_status = state_lock_init();
481 if (state_status != STATE_SUCCESS) {
482 LogCrit(COMPONENT_INIT,
483 "State Lock Layer could not be initialized, status=%s",
484 state_err_str(state_status));
485 return -1;
486 }
487 LogInfo(COMPONENT_INIT, "State lock layer successfully initialized");
488
489 /* Init the IP/name cache */
490 LogDebug(COMPONENT_INIT, "Now building IP/name cache");
491 if (nfs_Init_ip_name() != IP_NAME_SUCCESS) {
492 LogCrit(COMPONENT_INIT,
493 "Error while initializing IP/name cache");
494 return -1;
495 }
496 LogInfo(COMPONENT_INIT, "IP/name cache successfully initialized");
497
498 LogEvent(COMPONENT_INIT, "Initializing ID Mapper.");
499 if (!idmapper_init()) {
500 LogCrit(COMPONENT_INIT, "Failed initializing ID Mapper.");
501 return -1;
502 }
503 LogEvent(COMPONENT_INIT, "ID Mapper successfully initialized.");
504 return 0;
505 }
506
507 static void nfs_Start_threads(void)
508 {
509 int rc = 0;
510 pthread_attr_t attr_thr;
511
512 LogDebug(COMPONENT_THREAD, "Starting threads");
513
514 /* Init for thread parameter (mostly for scheduling) */
515 if (pthread_attr_init(&attr_thr) != 0)
516 LogDebug(COMPONENT_THREAD, "can't init pthread's attributes");
517
518 if (pthread_attr_setscope(&attr_thr, PTHREAD_SCOPE_SYSTEM) != 0)
519 LogDebug(COMPONENT_THREAD, "can't set pthread's scope");
520
521 if (pthread_attr_setdetachstate(&attr_thr,
522 PTHREAD_CREATE_JOINABLE) != 0)
523 LogDebug(COMPONENT_THREAD, "can't set pthread's join state");
524
525 LogEvent(COMPONENT_THREAD, "Starting delayed executor.");
526 delayed_start();
527
528 /* Starting the thread dedicated to signal handling */
529 rc = pthread_create(&sigmgr_thrid, &attr_thr, sigmgr_thread, NULL);
530 if (rc != 0) {
531 LogFatal(COMPONENT_THREAD,
532 "Could not create sigmgr_thread, error = %d (%s)",
533 errno, strerror(errno));
534 }
535 LogDebug(COMPONENT_THREAD, "sigmgr thread started");
536
537 #ifdef _USE_9P
538 if (nfs_param.core_param.core_options & CORE_OPTION_9P) {
539 /* Start 9P worker threads */
540 rc = _9p_worker_init();
541 if (rc != 0) {
542 LogFatal(COMPONENT_THREAD,
543 "Could not start worker threads: %d", errno);
544 }
545
546 /* Starting the 9P/TCP dispatcher thread */
547 rc = pthread_create(&_9p_dispatcher_thrid, &attr_thr,
548 _9p_dispatcher_thread, NULL);
549 if (rc != 0) {
550 LogFatal(COMPONENT_THREAD,
551 "Could not create 9P/TCP dispatcher, error = %d (%s)",
552 errno, strerror(errno));
553 }
554 LogEvent(COMPONENT_THREAD,
555 "9P/TCP dispatcher thread was started successfully");
556 }
557 #endif
558
559 #ifdef _USE_9P_RDMA
560 /* Starting the 9P/RDMA dispatcher thread */
561 if (nfs_param.core_param.core_options & CORE_OPTION_9P) {
562 rc = pthread_create(&_9p_rdma_dispatcher_thrid, &attr_thr,
563 _9p_rdma_dispatcher_thread, NULL);
564 if (rc != 0) {
565 LogFatal(COMPONENT_THREAD,
566 "Could not create 9P/RDMA dispatcher, error = %d (%s)",
567 errno, strerror(errno));
568 }
569 LogEvent(COMPONENT_THREAD,
570 "9P/RDMA dispatcher thread was started successfully");
571 }
572 #endif
573
574 #ifdef USE_DBUS
575 /* DBUS event thread */
576 rc = pthread_create(&gsh_dbus_thrid, &attr_thr, gsh_dbus_thread, NULL);
577 if (rc != 0) {
578 LogFatal(COMPONENT_THREAD,
579 "Could not create gsh_dbus_thread, error = %d (%s)",
580 errno, strerror(errno));
581 }
582 LogEvent(COMPONENT_THREAD, "gsh_dbusthread was started successfully");
583 #endif
584
585 /* Starting the admin thread */
586 rc = pthread_create(&admin_thrid, &attr_thr, admin_thread, NULL);
587 if (rc != 0) {
588 LogFatal(COMPONENT_THREAD,
589 "Could not create admin_thread, error = %d (%s)",
590 errno, strerror(errno));
591 }
592 LogEvent(COMPONENT_THREAD, "admin thread was started successfully");
593
594 /* Starting the reaper thread */
595 rc = reaper_init();
596 if (rc != 0) {
597 LogFatal(COMPONENT_THREAD,
598 "Could not create reaper_thread, error = %d (%s)",
599 errno, strerror(errno));
600 }
601 LogEvent(COMPONENT_THREAD, "reaper thread was started successfully");
602
603 /* Starting the general fridge */
604 rc = general_fridge_init();
605 if (rc != 0) {
606 LogFatal(COMPONENT_THREAD,
607 "Could not create general fridge, error = %d (%s)",
608 errno, strerror(errno));
609 }
610 LogEvent(COMPONENT_THREAD, "General fridge was started successfully");
611
612 pthread_attr_destroy(&attr_thr);
613 }
614
615 /**
616 * @brief Init the nfs daemon
617 *
618 * @param[in] p_start_info Unused
619 */
620
621 static void nfs_Init(const nfs_start_info_t *p_start_info)
622 {
623 #ifdef _HAVE_GSSAPI
624 gss_buffer_desc gss_service_buf;
625 OM_uint32 maj_stat, min_stat;
626 char GssError[MAXNAMLEN + 1];
627 #endif
628
629 #ifdef USE_DBUS
630 /* DBUS init */
631 gsh_dbus_pkginit();
632 dbus_export_init();
633 dbus_client_init();
634 dbus_cache_init();
635 #endif
636
637 /* acls cache may be needed by exports_pkginit */
638 LogDebug(COMPONENT_INIT, "Now building NFSv4 ACL cache");
639 if (nfs4_acls_init() != 0)
640 LogFatal(COMPONENT_INIT, "Error while initializing NFSv4 ACLs");
641 LogInfo(COMPONENT_INIT, "NFSv4 ACL cache successfully initialized");
642
643 /* finish the job with exports by caching the root entries
644 */
645 exports_pkginit();
646
647 nfs41_session_pool =
648 pool_basic_init("NFSv4.1 session pool", sizeof(nfs41_session_t));
649
650 /* If rpcsec_gss is used, set the path to the keytab */
651 #ifdef _HAVE_GSSAPI
652 #ifdef HAVE_KRB5
653 if (nfs_param.krb5_param.active_krb5) {
654 OM_uint32 gss_status = GSS_S_COMPLETE;
655
656 if (*nfs_param.krb5_param.keytab != '\0')
657 gss_status = krb5_gss_register_acceptor_identity(
658 nfs_param.krb5_param.keytab);
659
660 if (gss_status != GSS_S_COMPLETE) {
661 log_sperror_gss(GssError, gss_status, 0);
662 LogFatal(COMPONENT_INIT,
663 "Error setting krb5 keytab to value %s is %s",
664 nfs_param.krb5_param.keytab, GssError);
665 }
666 LogInfo(COMPONENT_INIT,
667 "krb5 keytab path successfully set to %s",
668 nfs_param.krb5_param.keytab);
669 #endif /* HAVE_KRB5 */
670
671 /* Set up principal to be use for GSSAPPI within GSSRPC/KRB5 */
672 gss_service_buf.value = nfs_param.krb5_param.svc.principal;
673 gss_service_buf.length =
674 strlen(nfs_param.krb5_param.svc.principal) + 1;
675 /* The '+1' is not to be forgotten, for the '\0' at the end */
676
677 maj_stat = gss_import_name(&min_stat, &gss_service_buf,
678 (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
679 &nfs_param.krb5_param.svc.gss_name);
680 if (maj_stat != GSS_S_COMPLETE) {
681 log_sperror_gss(GssError, maj_stat, min_stat);
682 LogFatal(COMPONENT_INIT,
683 "Error importing gss principal %s is %s",
684 nfs_param.krb5_param.svc.principal, GssError);
685 }
686
687 if (nfs_param.krb5_param.svc.gss_name == GSS_C_NO_NAME)
688 LogInfo(COMPONENT_INIT,
689 "Regression: svc.gss_name == GSS_C_NO_NAME");
690
691 LogInfo(COMPONENT_INIT, "gss principal \"%s\" successfully set",
692 nfs_param.krb5_param.svc.principal);
693
694 /* Set the principal to GSSRPC */
695 if (!svcauth_gss_set_svc_name
696 (nfs_param.krb5_param.svc.gss_name)) {
697 LogFatal(COMPONENT_INIT,
698 "Impossible to set gss principal to GSSRPC");
699 }
700
701 /* Don't release name until shutdown, it will be used by the
702 * backchannel. */
703
704 #ifdef HAVE_KRB5
705 } /* if( nfs_param.krb5_param.active_krb5 ) */
706 #endif /* HAVE_KRB5 */
707 #endif /* _HAVE_GSSAPI */
708 /* Init the NFSv4 Clientid cache */
709 LogDebug(COMPONENT_INIT, "Now building NFSv4 clientid cache");
710 if (nfs_Init_client_id() !=
711 CLIENT_ID_SUCCESS) {
712 LogFatal(COMPONENT_INIT,
713 "Error while initializing NFSv4 clientid cache");
714 }
715 LogInfo(COMPONENT_INIT,
716 "NFSv4 clientid cache successfully initialized");
717
718 /* Init duplicate request cache */
719 dupreq2_pkginit();
720 LogInfo(COMPONENT_INIT,
721 "duplicate request hash table cache successfully initialized");
722
723 /* Init The NFSv4 State id cache */
724 LogDebug(COMPONENT_INIT, "Now building NFSv4 State Id cache");
725 if (nfs4_Init_state_id() != 0) {
726 LogFatal(COMPONENT_INIT,
727 "Error while initializing NFSv4 State Id cache");
728 }
729 LogInfo(COMPONENT_INIT,
730 "NFSv4 State Id cache successfully initialized");
731
732 /* Init The NFSv4 Open Owner cache */
733 LogDebug(COMPONENT_INIT, "Now building NFSv4 Owner cache");
734 if (Init_nfs4_owner() != 0) {
735 LogFatal(COMPONENT_INIT,
736 "Error while initializing NFSv4 Owner cache");
737 }
738 LogInfo(COMPONENT_INIT,
739 "NFSv4 Open Owner cache successfully initialized");
740
741 #ifdef _USE_NLM
742 if (nfs_param.core_param.enable_NLM) {
743 /* Init The NLM Owner cache */
744 LogDebug(COMPONENT_INIT, "Now building NLM Owner cache");
745 if (Init_nlm_hash() != 0) {
746 LogFatal(COMPONENT_INIT,
747 "Error while initializing NLM Owner cache");
748 }
749 LogInfo(COMPONENT_INIT,
750 "NLM Owner cache successfully initialized");
751 /* Init The NLM Owner cache */
752 LogDebug(COMPONENT_INIT, "Now building NLM State cache");
753 if (Init_nlm_state_hash() != 0) {
754 LogFatal(COMPONENT_INIT,
755 "Error while initializing NLM State cache");
756 }
757 LogInfo(COMPONENT_INIT,
758 "NLM State cache successfully initialized");
759 nlm_init();
760 }
761 #endif /* _USE_NLM */
762 #ifdef _USE_9P
763 /* Init the 9P lock owner cache */
764 LogDebug(COMPONENT_INIT, "Now building 9P Owner cache");
765 if (Init_9p_hash() != 0) {
766 LogFatal(COMPONENT_INIT,
767 "Error while initializing 9P Owner cache");
768 }
769 LogInfo(COMPONENT_INIT, "9P Owner cache successfully initialized");
770 #endif
771
772 LogDebug(COMPONENT_INIT, "Now building NFSv4 Session Id cache");
773 if (nfs41_Init_session_id() != 0) {
774 LogFatal(COMPONENT_INIT,
775 "Error while initializing NFSv4 Session Id cache");
776 }
777 LogInfo(COMPONENT_INIT,
778 "NFSv4 Session Id cache successfully initialized");
779
780 #ifdef _USE_9P
781 LogDebug(COMPONENT_INIT, "Now building 9P resources");
782 if (_9p_init()) {
783 LogCrit(COMPONENT_INIT,
784 "Error while initializing 9P Resources");
785 exit(1);
786 }
787 LogInfo(COMPONENT_INIT, "9P resources successfully initialized");
788 #endif /* _USE_9P */
789
790 /* Creates the pseudo fs */
791 LogDebug(COMPONENT_INIT, "Now building pseudo fs");
792
793 create_pseudofs();
794
795 LogInfo(COMPONENT_INIT,
796 "NFSv4 pseudo file system successfully initialized");
797
798 /* Save Ganesha thread credentials with Frank's routine for later use */
799 fsal_save_ganesha_credentials();
800
801 /* RPC Initialisation - exits on failure */
802 nfs_Init_svc();
803 LogInfo(COMPONENT_INIT, "RPC resources successfully initialized");
804
805 /* Admin initialisation */
806 nfs_Init_admin_thread();
807
808 /* callback dispatch */
809 nfs_rpc_cb_pkginit();
810 #ifdef _USE_CB_SIMULATOR
811 nfs_rpc_cbsim_pkginit();
812 #endif /* _USE_CB_SIMULATOR */
813
814 } /* nfs_Init */
815
816 #ifdef USE_CAPS
817 /**
818 * @brief Lower my capabilities (privs) so quotas work right
819 *
820 * This will/should be moved to set_credentials where it belongs
821 * Deal with capabilities in order to remove CAP_SYS_RESOURCE (needed
822 * for proper management of data quotas)
823 */
824
825 static void lower_my_caps(void)
826 {
827 cap_value_t cap_values[] = {CAP_SYS_RESOURCE};
828 cap_t cap;
829 char *cap_text;
830 ssize_t capstrlen = 0;
831 int ret;
832
833 if (!nfs_start_info.drop_caps) {
834 /* Skip dropping caps by request */
835 return;
836 }
837
838 cap = cap_get_proc();
839 if (cap == NULL) {
840 LogFatal(COMPONENT_INIT,
841 "cap_get_proc() failed, %s", strerror(errno));
842 }
843
844 ret = cap_set_flag(cap, CAP_EFFECTIVE,
845 sizeof(cap_values) / sizeof(cap_values[0]),
846 cap_values, CAP_CLEAR);
847 if (ret != 0) {
848 LogFatal(COMPONENT_INIT,
849 "cap_set_flag() failed, %s", strerror(errno));
850 }
851
852 ret = cap_set_flag(cap, CAP_PERMITTED,
853 sizeof(cap_values) / sizeof(cap_values[0]),
854 cap_values, CAP_CLEAR);
855 if (ret != 0) {
856 LogFatal(COMPONENT_INIT,
857 "cap_set_flag() failed, %s", strerror(errno));
858 }
859
860 ret = cap_set_flag(cap, CAP_INHERITABLE,
861 sizeof(cap_values) / sizeof(cap_values[0]),
862 cap_values, CAP_CLEAR);
863 if (ret != 0) {
864 LogFatal(COMPONENT_INIT,
865 "cap_set_flag() failed, %s", strerror(errno));
866 }
867
868 ret = cap_set_proc(cap);
869 if (ret != 0) {
870 LogFatal(COMPONENT_INIT,
871 "Failed to set capabilities for process, %s",
872 strerror(errno));
873 }
874
875 LogEvent(COMPONENT_INIT,
876 "CAP_SYS_RESOURCE was successfully removed for proper quota management in FSAL");
877
878 /* Print newly set capabilities (same as what CLI "getpcaps" displays */
879 cap_text = cap_to_text(cap, &capstrlen);
880 LogEvent(COMPONENT_INIT, "currenty set capabilities are: %s",
881 cap_text);
882 cap_free(cap_text);
883 cap_free(cap);
884 }
885 #endif
886
887 /**
888 * @brief Start NFS service
889 *
890 * @param[in] p_start_info Startup parameters
891 */
892 void nfs_start(nfs_start_info_t *p_start_info)
893 {
894 /* store the start info so it is available for all layers */
895 nfs_start_info = *p_start_info;
896
897 if (p_start_info->dump_default_config == true) {
898 nfs_print_param_config();
899 exit(0);
900 }
901
902 /* Make sure Ganesha runs with a 0000 umask. */
903 umask(0000);
904
905 {
906 /* Set the write verifiers */
907 union {
908 verifier4 NFS4_write_verifier;
909 writeverf3 NFS3_write_verifier;
910 uint64_t epoch;
911 } build_verifier;
912
913 build_verifier.epoch = (uint64_t) nfs_ServerEpoch;
914
915 memcpy(NFS3_write_verifier, build_verifier.NFS3_write_verifier,
916 sizeof(NFS3_write_verifier));
917 memcpy(NFS4_write_verifier, build_verifier.NFS4_write_verifier,
918 sizeof(NFS4_write_verifier));
919 }
920
921 #ifdef USE_CAPS
922 lower_my_caps();
923 #endif
924
925 /* Initialize all layers and service threads */
926 nfs_Init(p_start_info);
927 nfs_Start_threads(); /* Spawns service threads */
928
929 nfs_init_complete();
930
931 #ifdef _USE_NLM
932 if (nfs_param.core_param.enable_NLM) {
933 /* NSM Unmonitor all */
934 nsm_unmonitor_all();
935 }
936 #endif /* _USE_NLM */
937
938 LogEvent(COMPONENT_INIT,
939 "-------------------------------------------------");
940 LogEvent(COMPONENT_INIT, " NFS SERVER INITIALIZED");
941 LogEvent(COMPONENT_INIT,
942 "-------------------------------------------------");
943
944 /* Set the time of NFS stat counting */
945 now(&nfs_stats_time);
946
947 /* Wait for dispatcher to exit */
948 LogDebug(COMPONENT_THREAD, "Wait for admin thread to exit");
949 pthread_join(admin_thrid, NULL);
950
951 /* Regular exit */
952 LogEvent(COMPONENT_MAIN, "NFS EXIT: regular exit");
953
954 Cleanup();
955 /* let main return 0 to exit */
956 }
957
958 void nfs_init_init(void)
959 {
960 PTHREAD_MUTEX_init(&nfs_init.init_mutex, NULL);
961 PTHREAD_COND_init(&nfs_init.init_cond, NULL);
962 nfs_init.init_complete = false;
963 }
964
965 void nfs_init_complete(void)
966 {
967 PTHREAD_MUTEX_lock(&nfs_init.init_mutex);
968 nfs_init.init_complete = true;
969 pthread_cond_broadcast(&nfs_init.init_cond);
970 PTHREAD_MUTEX_unlock(&nfs_init.init_mutex);
971 }
972
973 void nfs_init_wait(void)
974 {
975 PTHREAD_MUTEX_lock(&nfs_init.init_mutex);
976 while (!nfs_init.init_complete) {
977 pthread_cond_wait(&nfs_init.init_cond, &nfs_init.init_mutex);
978 }
979 PTHREAD_MUTEX_unlock(&nfs_init.init_mutex);
980 }
981
982 bool nfs_health(void)
983 {
984 uint64_t newenq, newdeq;
985 uint64_t dequeue_diff, enqueue_diff;
986 bool healthy;
987
988 newenq = nfs_health_.enqueued_reqs;
989 newdeq = nfs_health_.dequeued_reqs;
990 enqueue_diff = newenq - healthstats.enqueued_reqs;
991 dequeue_diff = newdeq - healthstats.dequeued_reqs;
992
993 /* Consider healthy and making progress if we have dequeued some
994 * requests or there is nothing to dequeue.
995 */
996 healthy = dequeue_diff > 0 || enqueue_diff == 0;
997
998 if (!healthy) {
999 LogWarn(COMPONENT_DBUS,
1000 "Health status is unhealthy. "
1001 "enq new: %" PRIu64 ", old: %" PRIu64 "; "
1002 "deq new: %" PRIu64 ", old: %" PRIu64,
1003 newenq, healthstats.enqueued_reqs,
1004 newdeq, healthstats.dequeued_reqs);
1005 }
1006
1007 healthstats.enqueued_reqs = newenq;
1008 healthstats.dequeued_reqs = newdeq;
1009
1010 return healthy;
1011 }
1012