glusterfs
2974 строки · 90.3 Кб
1/*
2Copyright (c) 2006-2016 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10#include <stdio.h>11#include <string.h>12#include <stdlib.h>13#include <sys/wait.h>14#include <dlfcn.h>15#include <pthread.h>16#include <errno.h>17#include <pwd.h>18
19#ifdef GF_LINUX_HOST_OS20#ifdef HAVE_LINUX_OOM_H21#include <linux/oom.h>22#else23#define OOM_SCORE_ADJ_MIN (-1000)24#define OOM_SCORE_ADJ_MAX 100025#define OOM_DISABLE (-17)26#define OOM_ADJUST_MAX 1527#endif28#endif29
30#ifdef HAVE_MALLOC_H31#include <malloc.h>32#endif33
34#include <glusterfs/compat.h>35#include <glusterfs/logging.h>36#include "glusterfsd-messages.h"37#include <glusterfs/dict.h>38#include <glusterfs/list.h>39#include <glusterfs/timer.h>40#include <glusterfs/revision.h>41#include <glusterfs/gf-event.h>42#include <glusterfs/statedump.h>43#include <glusterfs/latency.h>44#include "glusterfsd-mem-types.h"45#include <glusterfs/syscall.h>46#include <glusterfs/syncop.h>47#include <glusterfs/client_t.h>48#include <glusterfs/monitoring.h>49#include <glusterfs/gf-io.h>50#include <glusterfs/daemon.h>51
52#include "glusterfsd.h"53#include "rpc-clnt.h"54#include "netgroups.h"55#include "exports.h"56
57/* using argp for command line parsing */
58static char gf_doc[] = "";59static char argp_doc[] =60"--volfile-server=SERVER [MOUNT-POINT]\n"61"--volfile=VOLFILE [MOUNT-POINT]";62const char *argp_program_version =63"" PACKAGE_NAME " " PACKAGE_VERSION64"\nRepository revision: " GLUSTERFS_REPOSITORY_REVISION65"\n"66"Copyright (c) 2006-2016 Red Hat, Inc. "67"<https://www.gluster.org/>\n"68"GlusterFS comes with ABSOLUTELY NO WARRANTY.\n"69"It is licensed to you under your choice of the GNU Lesser\n"70"General Public License, version 3 or any later version (LGPLv3\n"71"or later), or the GNU General Public License, version 2 (GPLv2),\n"72"in all cases as published by the Free Software Foundation.";73const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";74
75static error_t76parse_opts(int32_t key, char *arg, struct argp_state *_state);77
78static struct argp_option gf_options[] = {79{0, 0, 0, 0, "Basic options:"},80{"volfile-server", ARGP_VOLFILE_SERVER_KEY, "SERVER", 0,81"Server to get the volume file from. Unix domain socket path when "82"transport type 'unix'. This option overrides --volfile option"},83{"volfile", ARGP_VOLUME_FILE_KEY, "VOLFILE", 0,84"File to use as VOLUME_FILE"},85{"spec-file", ARGP_VOLUME_FILE_KEY, "VOLFILE", OPTION_HIDDEN,86"File to use as VOLUME FILE"},87
88{"log-level", ARGP_LOG_LEVEL_KEY, "LOGLEVEL", 0,89"Logging severity. Valid options are DEBUG, INFO, WARNING, ERROR, "90"CRITICAL, TRACE and NONE [default: INFO]"},91{"log-file", ARGP_LOG_FILE_KEY, "LOGFILE", 0,92"File to use for logging [default: " DEFAULT_LOG_FILE_DIRECTORY93"/" PACKAGE_NAME ".log"94"]"},95{"logger", ARGP_LOGGER, "LOGGER", 0,96"Set which logging sub-system to "97"log to, valid options are: gluster-log and syslog, "98"[default: \"gluster-log\"]"},99{"log-format", ARGP_LOG_FORMAT, "LOG-FORMAT", 0,100"Set log format, valid"101" options are: no-msg-id and with-msg-id, [default: \"with-msg-id\"]"},102{"log-buf-size", ARGP_LOG_BUF_SIZE, "LOG-BUF-SIZE", 0,103"Set logging "104"buffer size, [default: 5]"},105{"log-flush-timeout", ARGP_LOG_FLUSH_TIMEOUT, "LOG-FLUSH-TIMEOUT", 0,106"Set log flush timeout, [default: 2 minutes]"},107
108{0, 0, 0, 0, "Advanced Options:"},109{"volfile-server-port", ARGP_VOLFILE_SERVER_PORT_KEY, "PORT", 0,110"Listening port number of volfile server"},111{"volfile-server-transport", ARGP_VOLFILE_SERVER_TRANSPORT_KEY, "TRANSPORT",1120, "Transport type to get volfile from server [default: socket]"},113{"volfile-id", ARGP_VOLFILE_ID_KEY, "KEY", 0,114"'key' of the volfile to be fetched from server"},115{"pid-file", ARGP_PID_FILE_KEY, "PIDFILE", 0, "File to use as pid file"},116{"socket-file", ARGP_SOCK_FILE_KEY, "SOCKFILE", 0,117"File to use as unix-socket"},118{"no-daemon", ARGP_NO_DAEMON_KEY, 0, 0, "Run in foreground"},119{"run-id", ARGP_RUN_ID_KEY, "RUN-ID", OPTION_HIDDEN,120"Run ID for the process, used by scripts to keep track of process "121"they started, defaults to none"},122{"debug", ARGP_DEBUG_KEY, 0, 0,123"Run in debug mode. This option sets --no-daemon, --log-level "124"to DEBUG and --log-file to console"},125{"volume-name", ARGP_VOLUME_NAME_KEY, "XLATOR-NAME", 0,126"Translator name to be used for MOUNT-POINT [default: top most volume "127"definition in VOLFILE]"},128{"xlator-option", ARGP_XLATOR_OPTION_KEY, "XLATOR-NAME.OPTION=VALUE", 0,129"Add/override an option for a translator in volume file with specified"130" value"},131{"read-only", ARGP_READ_ONLY_KEY, 0, 0,132"Mount the filesystem in 'read-only' mode"},133{"acl", ARGP_ACL_KEY, 0, 0, "Mount the filesystem with POSIX ACL support"},134{"selinux", ARGP_SELINUX_KEY, 0, 0,135"Enable SELinux label (extended attributes) support on inodes"},136{"capability", ARGP_CAPABILITY_KEY, 0, 0,137"Enable Capability (extended attributes) support on inodes"},138{"subdir-mount", ARGP_SUBDIR_MOUNT_KEY, "SUBDIR-PATH", 0,139"Mount subdirectory given [default: NULL]"},140
141{"print-netgroups", ARGP_PRINT_NETGROUPS, "NETGROUP-FILE", 0,142"Validate the netgroups file and print it out"},143{"print-exports", ARGP_PRINT_EXPORTS, "EXPORTS-FILE", 0,144"Validate the exports file and print it out"},145{"print-xlatordir", ARGP_PRINT_XLATORDIR_KEY, 0, OPTION_ARG_OPTIONAL,146"Print xlator directory path"},147{"print-statedumpdir", ARGP_PRINT_STATEDUMPDIR_KEY, 0, OPTION_ARG_OPTIONAL,148"Print directory path in which statedumps shall be generated"},149{"print-logdir", ARGP_PRINT_LOGDIR_KEY, 0, OPTION_ARG_OPTIONAL,150"Print path of default log directory"},151{"print-libexecdir", ARGP_PRINT_LIBEXECDIR_KEY, 0, OPTION_ARG_OPTIONAL,152"Print path of default libexec directory"},153
154{"volfile-max-fetch-attempts", ARGP_VOLFILE_MAX_FETCH_ATTEMPTS, "0",155OPTION_HIDDEN, "Maximum number of attempts to fetch the volfile"},156{"aux-gfid-mount", ARGP_AUX_GFID_MOUNT_KEY, 0, 0,157"Enable access to filesystem through gfid directly"},158{"enable-ino32", ARGP_INODE32_KEY, "BOOL", OPTION_ARG_OPTIONAL,159"Use 32-bit inodes when mounting to workaround broken applications"160"that don't support 64-bit inodes"},161{"worm", ARGP_WORM_KEY, 0, 0, "Mount the filesystem in 'worm' mode"},162{"mac-compat", ARGP_MAC_COMPAT_KEY, "BOOL", OPTION_ARG_OPTIONAL,163"Provide stubs for attributes needed for seamless operation on Macs "164#ifdef GF_DARWIN_HOST_OS165"[default: \"on\" on client side, else \"off\"]"166#else167"[default: \"off\"]"168#endif169},170{"brick-name", ARGP_BRICK_NAME_KEY, "BRICK-NAME", OPTION_HIDDEN,171"Brick name to be registered with Gluster portmapper"},172{"brick-port", ARGP_BRICK_PORT_KEY, "BRICK-PORT", OPTION_HIDDEN,173"Brick Port to be registered with Gluster portmapper"},174{"fopen-keep-cache", ARGP_FOPEN_KEEP_CACHE_KEY, "BOOL", OPTION_ARG_OPTIONAL,175"Do not purge the cache on file open [default: false]"},176{"global-timer-wheel", ARGP_GLOBAL_TIMER_WHEEL, "BOOL", OPTION_ARG_OPTIONAL,177"Instantiate process global timer-wheel"},178{"thin-client", ARGP_THIN_CLIENT_KEY, 0, 0,179"Enables thin mount and connects via gfproxyd daemon"},180{"global-threading", ARGP_GLOBAL_THREADING_KEY, "BOOL", OPTION_ARG_OPTIONAL,181"Use the global thread pool instead of io-threads"},182{0, 0, 0, 0, "Fuse options:"},183{"direct-io-mode", ARGP_DIRECT_IO_MODE_KEY, "BOOL|auto",184OPTION_ARG_OPTIONAL, "Specify direct I/O strategy [default: \"auto\"]"},185{"entry-timeout", ARGP_ENTRY_TIMEOUT_KEY, "SECONDS", 0,186"Set entry timeout to SECONDS in fuse kernel module [default: 1]"},187{"negative-timeout", ARGP_NEGATIVE_TIMEOUT_KEY, "SECONDS", 0,188"Set negative timeout to SECONDS in fuse kernel module [default: 0]"},189{"attribute-timeout", ARGP_ATTRIBUTE_TIMEOUT_KEY, "SECONDS", 0,190"Set attribute timeout to SECONDS for inodes in fuse kernel module "191"[default: 1]"},192{"gid-timeout", ARGP_GID_TIMEOUT_KEY, "SECONDS", 0,193"Set auxiliary group list timeout to SECONDS for fuse translator "194"[default: 300]"},195{"resolve-gids", ARGP_RESOLVE_GIDS_KEY, 0, 0,196"Resolve all auxiliary groups in fuse translator (max 32 otherwise)"},197{"lru-limit", ARGP_FUSE_LRU_LIMIT_KEY, "N", 0,198"Set fuse module's limit for number of inodes kept in LRU list to N "199"[default: 65536]"},200{"inode-table-size", ARGP_FUSE_INODE_TABLESIZE_KEY, "N", 0,201"Set the inode hash table size to N - this must be a power of 2 and "202"will be rounded up if not [default: 65536]"},203{"invalidate-limit", ARGP_FUSE_INVALIDATE_LIMIT_KEY, "N", 0,204"Suspend inode invalidations implied by 'lru-limit' if the number of "205"outstanding invalidations reaches N"},206{"background-qlen", ARGP_FUSE_BACKGROUND_QLEN_KEY, "N", 0,207"Set fuse module's background queue length to N "208"[default: 64]"},209{"congestion-threshold", ARGP_FUSE_CONGESTION_THRESHOLD_KEY, "N", 0,210"Set fuse module's congestion threshold to N "211"[default: 48]"},212#ifdef GF_LINUX_HOST_OS213{"oom-score-adj", ARGP_OOM_SCORE_ADJ_KEY, "INTEGER", 0,214"Set oom_score_adj value for process"215"[default: 0]"},216#endif217{"client-pid", ARGP_CLIENT_PID_KEY, "PID", OPTION_HIDDEN,218"client will authenticate itself with process id PID to server"},219{"no-root-squash", ARGP_FUSE_NO_ROOT_SQUASH_KEY, "BOOL",220OPTION_ARG_OPTIONAL,221"disable/enable root squashing for the trusted "222"client"},223{"user-map-root", ARGP_USER_MAP_ROOT_KEY, "USER", OPTION_HIDDEN,224"replace USER with root in messages"},225{"dump-fuse", ARGP_DUMP_FUSE_KEY, "PATH", 0, "Dump fuse traffic to PATH"},226{"volfile-check", ARGP_VOLFILE_CHECK_KEY, 0, 0,227"Enable strict volume file checking"},228{"no-mem-accounting", ARGP_MEM_ACCOUNTING_KEY, 0, OPTION_HIDDEN,229"disable internal memory accounting"},230{"fuse-mountopts", ARGP_FUSE_MOUNTOPTS_KEY, "OPTIONS", OPTION_HIDDEN,231"Extra mount options to pass to FUSE"},232{"use-readdirp", ARGP_FUSE_USE_READDIRP_KEY, "BOOL", OPTION_ARG_OPTIONAL,233"Use readdirp mode in fuse kernel module"234" [default: \"yes\"]"},235{"secure-mgmt", ARGP_SECURE_MGMT_KEY, "BOOL", OPTION_ARG_OPTIONAL,236"Override default for secure (SSL) management connections"},237{"localtime-logging", ARGP_LOCALTIME_LOGGING_KEY, 0, 0,238"Enable localtime logging"},239{"process-name", ARGP_PROCESS_NAME_KEY, "PROCESS-NAME", OPTION_HIDDEN,240"option to specify the process type"},241{"event-history", ARGP_FUSE_EVENT_HISTORY_KEY, "BOOL", OPTION_ARG_OPTIONAL,242"disable/enable fuse event-history"},243{"reader-thread-count", ARGP_READER_THREAD_COUNT_KEY, "INTEGER",244OPTION_ARG_OPTIONAL, "set fuse reader thread count"},245{"kernel-writeback-cache", ARGP_KERNEL_WRITEBACK_CACHE_KEY, "BOOL",246OPTION_ARG_OPTIONAL, "enable fuse in-kernel writeback cache"},247{"attr-times-granularity", ARGP_ATTR_TIMES_GRANULARITY_KEY, "NS",248OPTION_ARG_OPTIONAL,249"declare supported granularity of file attribute"250" times in nanoseconds"},251{"fuse-flush-handle-interrupt", ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY,252"BOOL", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,253"handle interrupt in fuse FLUSH handler"},254{"fuse-setlk-handle-interrupt", ARGP_FUSE_SETLK_HANDLE_INTERRUPT_KEY,255"BOOL", OPTION_ARG_OPTIONAL, "handle interrupt in fuse SETLK handler"},256{"auto-invalidation", ARGP_FUSE_AUTO_INVAL_KEY, "BOOL", OPTION_ARG_OPTIONAL,257"controls whether fuse-kernel can auto-invalidate "258"attribute, dentry and page-cache. "259"Disable this only if same files/directories are not accessed across "260"two different mounts concurrently [default: \"on\"]"},261{"fuse-dev-eperm-ratelimit-ns", ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY,262"OPTIONS", OPTION_HIDDEN,263"rate limit reading from fuse device upon EPERM failure"},264{"fs-display-name", ARGP_FUSE_DISPLAY_NAME_KEY, "DISPLAY-NAME",265OPTION_HIDDEN,266"Filesystem display name, shown with mount point (as source). Used with "267"commands like 'mount', 'df', etc."},268{"brick-mux", ARGP_BRICK_MUX_KEY, 0, 0, "Enable brick mux. "},269{"io-engine", ARGP_IO_ENGINE_KEY, "ENGINE", OPTION_ARG_OPTIONAL,270"force utilization of the given I/O ENGINE"},271{"fuse-handle-copy_file_range", ARGP_FUSE_HANDLE_COPY_FILE_RANGE, "BOOL",272OPTION_ARG_OPTIONAL | OPTION_HIDDEN,273"enable the handler of the FUSE_COPY_FILE_RANGE message"},274{0, 0, 0, 0, "Miscellaneous Options:"},275{2760,277}};278
279static struct argp argp = {gf_options, parse_opts, argp_doc, gf_doc};280
281static void282glusterfs_pidfile_cleanup(glusterfs_ctx_t *ctx)283{
284cmd_args_t *cmd_args = NULL;285
286cmd_args = &ctx->cmd_args;287
288if (!ctx->pidfp)289return;290
291gf_msg_trace("glusterfsd", 0, "pidfile %s cleanup", cmd_args->pid_file);292
293if (ctx->cmd_args.pid_file) {294GF_FREE(ctx->cmd_args.pid_file);295ctx->cmd_args.pid_file = NULL;296}297
298lockf(fileno(ctx->pidfp), F_ULOCK, 0);299fclose(ctx->pidfp);300ctx->pidfp = NULL;301}
302
303#define DICT_SET_VAL(method, dict, key, val, msgid) \304if (method(dict, key, val)) { \305gf_smsg("glusterfsd", GF_LOG_ERROR, 0, msgid, "key=%s", key); \306goto err; \307}308
309static int310set_fuse_mount_options(glusterfs_ctx_t *ctx, dict_t *options)311{
312int ret = 0;313cmd_args_t *cmd_args = NULL;314char *mount_point = NULL;315char cwd[PATH_MAX] = {3160,317};318
319cmd_args = &ctx->cmd_args;320
321/* Check if mount-point is absolute path,322* if not convert to absolute path by concatenating with CWD
323*/
324if (cmd_args->mount_point[0] != '/') {325if (getcwd(cwd, PATH_MAX) != NULL) {326ret = gf_asprintf(&mount_point, "%s/%s", cwd,327cmd_args->mount_point);328if (ret == -1) {329gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_1,330"gf_asprintf failed", NULL);331goto err;332}333} else {334gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_2,335"getcwd failed", NULL);336goto err;337}338
339} else {340mount_point = gf_strdup(cmd_args->mount_point);341}342DICT_SET_VAL(dict_set_dynstr_sizen, options, ZR_MOUNTPOINT_OPT, mount_point,343glusterfsd_msg_3);344
345if (cmd_args->fuse_attribute_timeout >= 0) {346DICT_SET_VAL(dict_set_double, options, ZR_ATTR_TIMEOUT_OPT,347cmd_args->fuse_attribute_timeout, glusterfsd_msg_3);348}349
350if (cmd_args->fuse_entry_timeout >= 0) {351DICT_SET_VAL(dict_set_double, options, ZR_ENTRY_TIMEOUT_OPT,352cmd_args->fuse_entry_timeout, glusterfsd_msg_3);353}354
355if (cmd_args->fuse_negative_timeout >= 0) {356DICT_SET_VAL(dict_set_double, options, ZR_NEGATIVE_TIMEOUT_OPT,357cmd_args->fuse_negative_timeout, glusterfsd_msg_3);358}359
360if (cmd_args->client_pid_set) {361DICT_SET_VAL(dict_set_int32_sizen, options, "client-pid",362cmd_args->client_pid, glusterfsd_msg_3);363}364
365if (cmd_args->uid_map_root) {366DICT_SET_VAL(dict_set_int32_sizen, options, "uid-map-root",367cmd_args->uid_map_root, glusterfsd_msg_3);368}369
370if (cmd_args->volfile_check) {371DICT_SET_VAL(dict_set_int32_sizen, options, ZR_STRICT_VOLFILE_CHECK,372cmd_args->volfile_check, glusterfsd_msg_3);373}374
375if (cmd_args->dump_fuse) {376DICT_SET_VAL(dict_set_static_ptr, options, ZR_DUMP_FUSE,377cmd_args->dump_fuse, glusterfsd_msg_3);378}379
380if (cmd_args->acl) {381DICT_SET_VAL(dict_set_static_ptr, options, "acl", "on",382glusterfsd_msg_3);383}384
385if (cmd_args->selinux) {386DICT_SET_VAL(dict_set_static_ptr, options, "selinux", "on",387glusterfsd_msg_3);388}389
390if (cmd_args->capability) {391DICT_SET_VAL(dict_set_static_ptr, options, "capability", "on",392glusterfsd_msg_3);393}394
395if (cmd_args->aux_gfid_mount) {396DICT_SET_VAL(dict_set_static_ptr, options, "virtual-gfid-access", "on",397glusterfsd_msg_3);398}399
400if (cmd_args->enable_ino32) {401DICT_SET_VAL(dict_set_static_ptr, options, "enable-ino32", "on",402glusterfsd_msg_3);403}404
405if (cmd_args->read_only) {406DICT_SET_VAL(dict_set_static_ptr, options, "read-only", "on",407glusterfsd_msg_3);408}409
410switch (cmd_args->fopen_keep_cache) {411case GF_OPTION_ENABLE:412
413DICT_SET_VAL(dict_set_static_ptr, options, "fopen-keep-cache", "on",414glusterfsd_msg_3);415break;416case GF_OPTION_DISABLE:417DICT_SET_VAL(dict_set_static_ptr, options, "fopen-keep-cache",418"off", glusterfsd_msg_3);419break;420default:421gf_msg_debug("glusterfsd", 0, "fopen-keep-cache mode %d",422cmd_args->fopen_keep_cache);423break;424}425
426if (cmd_args->gid_timeout_set) {427DICT_SET_VAL(dict_set_int32_sizen, options, "gid-timeout",428cmd_args->gid_timeout, glusterfsd_msg_3);429}430
431if (cmd_args->resolve_gids) {432DICT_SET_VAL(dict_set_static_ptr, options, "resolve-gids", "on",433glusterfsd_msg_3);434}435
436if (cmd_args->lru_limit >= 0) {437DICT_SET_VAL(dict_set_int32_sizen, options, "lru-limit",438cmd_args->lru_limit, glusterfsd_msg_3);439}440
441if (cmd_args->inode_table_size >= 0) {442DICT_SET_VAL(dict_set_int32_sizen, options, "inode-table-size",443cmd_args->inode_table_size, glusterfsd_msg_3);444}445
446if (cmd_args->invalidate_limit >= 0) {447DICT_SET_VAL(dict_set_int32_sizen, options, "invalidate-limit",448cmd_args->invalidate_limit, glusterfsd_msg_3);449}450
451if (cmd_args->background_qlen) {452DICT_SET_VAL(dict_set_int32_sizen, options, "background-qlen",453cmd_args->background_qlen, glusterfsd_msg_3);454}455if (cmd_args->congestion_threshold) {456DICT_SET_VAL(dict_set_int32_sizen, options, "congestion-threshold",457cmd_args->congestion_threshold, glusterfsd_msg_3);458}459
460switch (cmd_args->fuse_direct_io_mode) {461case GF_OPTION_DISABLE: /* disable */462DICT_SET_VAL(dict_set_static_ptr, options, ZR_DIRECT_IO_OPT,463"disable", glusterfsd_msg_3);464break;465case GF_OPTION_ENABLE: /* enable */466DICT_SET_VAL(dict_set_static_ptr, options, ZR_DIRECT_IO_OPT,467"enable", glusterfsd_msg_3);468break;469default:470gf_msg_debug("glusterfsd", 0, "fuse direct io type %d",471cmd_args->fuse_direct_io_mode);472break;473}474
475switch (cmd_args->no_root_squash) {476case GF_OPTION_ENABLE: /* enable */477DICT_SET_VAL(dict_set_static_ptr, options, "no-root-squash",478"enable", glusterfsd_msg_3);479break;480default:481DICT_SET_VAL(dict_set_static_ptr, options, "no-root-squash",482"disable", glusterfsd_msg_3);483gf_msg_debug("glusterfsd", 0, "fuse no-root-squash mode %d",484cmd_args->no_root_squash);485break;486}487
488if (!cmd_args->no_daemon_mode) {489DICT_SET_VAL(dict_set_static_ptr, options, "sync-to-mount", "enable",490glusterfsd_msg_3);491}492
493if (cmd_args->use_readdirp) {494DICT_SET_VAL(dict_set_static_ptr, options, "use-readdirp",495cmd_args->use_readdirp, glusterfsd_msg_3);496}497if (cmd_args->event_history) {498ret = dict_set_str(options, "event-history", cmd_args->event_history);499DICT_SET_VAL(dict_set_static_ptr, options, "event-history",500cmd_args->event_history, glusterfsd_msg_3);501}502if (cmd_args->thin_client) {503DICT_SET_VAL(dict_set_static_ptr, options, "thin-client", "on",504glusterfsd_msg_3);505}506if (cmd_args->reader_thread_count) {507DICT_SET_VAL(dict_set_uint32, options, "reader-thread-count",508cmd_args->reader_thread_count, glusterfsd_msg_3);509}510
511DICT_SET_VAL(dict_set_uint32, options, "auto-invalidation",512cmd_args->fuse_auto_inval, glusterfsd_msg_3);513
514switch (cmd_args->kernel_writeback_cache) {515case GF_OPTION_ENABLE:516DICT_SET_VAL(dict_set_static_ptr, options, "kernel-writeback-cache",517"on", glusterfsd_msg_3);518break;519case GF_OPTION_DISABLE:520DICT_SET_VAL(dict_set_static_ptr, options, "kernel-writeback-cache",521"off", glusterfsd_msg_3);522break;523default:524gf_msg_debug("glusterfsd", 0, "kernel-writeback-cache mode %d",525cmd_args->kernel_writeback_cache);526break;527}528if (cmd_args->attr_times_granularity) {529DICT_SET_VAL(dict_set_uint32, options, "attr-times-granularity",530cmd_args->attr_times_granularity, glusterfsd_msg_3);531}532switch (cmd_args->fuse_flush_handle_interrupt) {533case GF_OPTION_ENABLE:534DICT_SET_VAL(dict_set_static_ptr, options, "flush-handle-interrupt",535"on", glusterfsd_msg_3);536break;537case GF_OPTION_DISABLE:538DICT_SET_VAL(dict_set_static_ptr, options, "flush-handle-interrupt",539"off", glusterfsd_msg_3);540break;541default:542gf_msg_debug("glusterfsd", 0, "fuse-flush-handle-interrupt mode %d",543cmd_args->fuse_flush_handle_interrupt);544break;545}546if (cmd_args->global_threading) {547DICT_SET_VAL(dict_set_static_ptr, options, "global-threading", "on",548glusterfsd_msg_3);549}550if (cmd_args->fuse_dev_eperm_ratelimit_ns) {551DICT_SET_VAL(dict_set_uint32, options, "fuse-dev-eperm-ratelimit-ns",552cmd_args->fuse_dev_eperm_ratelimit_ns, glusterfsd_msg_3);553}554switch (cmd_args->fuse_handle_copy_file_range) {555case GF_OPTION_ENABLE:556DICT_SET_VAL(dict_set_static_ptr, options, "handle-copy_file_range",557"on", glusterfsd_msg_3);558break;559case GF_OPTION_DISABLE:560DICT_SET_VAL(dict_set_static_ptr, options, "handle-copy_file_range",561"off", glusterfsd_msg_3);562break;563default:564gf_msg_debug("glusterfsd", 0, "fuse-handle-copy_file_range mode %d",565cmd_args->fuse_handle_copy_file_range);566break;567}568
569if (cmd_args->fs_display_name) {570DICT_SET_VAL(dict_set_dynstr, options, "fs-display-name",571cmd_args->fs_display_name, glusterfsd_msg_3);572}573
574if (cmd_args->io_engine != NULL) {575DICT_SET_VAL(dict_set_static_ptr, options, "io-engine",576cmd_args->io_engine, glusterfsd_msg_3);577}578
579switch (cmd_args->fuse_setlk_handle_interrupt) {580case GF_OPTION_ENABLE:581ret = dict_set_static_ptr(options, "setlk-handle-interrupt", "on");582if (ret < 0) {583gf_msg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4,584"failed to set dict value for key "585"setlk-handle-interrupt");586goto err;587}588break;589case GF_OPTION_DISABLE:590ret = dict_set_static_ptr(options, "setlk-handle-interrupt", "off");591if (ret < 0) {592gf_msg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4,593"failed to set dict value for key "594"setlk-handle-interrupt");595goto err;596}597break;598case GF_OPTION_DEFERRED: /* default */599default:600gf_msg_debug("glusterfsd", 0, "fuse-setlk-handle-interrupt mode %d",601cmd_args->fuse_setlk_handle_interrupt);602break;603}604
605ret = 0;606err:607return ret;608}
609
610static int611create_fuse_mount(glusterfs_ctx_t *ctx)612{
613int ret = 0;614cmd_args_t *cmd_args = NULL;615xlator_t *root = NULL;616
617cmd_args = &ctx->cmd_args;618if (!cmd_args->mount_point) {619gf_msg_trace("glusterfsd", 0,620"mount point not found, not a client process");621return 0;622}623
624if (ctx->process_mode != GF_CLIENT_PROCESS) {625gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_7, NULL);626return -1;627}628
629root = GF_CALLOC(1, sizeof(*root), gfd_mt_xlator_t);630if (!root)631goto err;632
633root->name = gf_strdup("fuse");634if (!root->name)635goto err;636
637if (xlator_set_type(root, "mount/fuse") == -1) {638gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_8,639"MOUNT-POINT=%s", cmd_args->mount_point, NULL);640goto err;641}642
643root->ctx = ctx;644root->options = dict_new();645if (!root->options)646goto err;647
648ret = set_fuse_mount_options(ctx, root->options);649if (ret)650goto err;651
652if (cmd_args->fuse_mountopts) {653ret = dict_set_static_ptr(root->options, ZR_FUSE_MOUNTOPTS,654cmd_args->fuse_mountopts);655if (ret < 0) {656gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_3,657ZR_FUSE_MOUNTOPTS, NULL);658goto err;659}660}661
662ret = xlator_init(root);663if (ret) {664gf_msg_debug("glusterfsd", 0, "failed to initialize fuse translator");665goto err;666}667
668ctx->root = root;669
670return 0;671
672err:673if (root) {674xlator_destroy(root);675}676
677return 1;678}
679
680static int681gf_remember_backup_volfile_server(char *arg)682{
683glusterfs_ctx_t *ctx = NULL;684cmd_args_t *cmd_args = NULL;685int ret = -1;686
687ctx = glusterfsd_ctx;688if (!ctx)689goto out;690cmd_args = &ctx->cmd_args;691
692if (!cmd_args)693goto out;694
695ret = gf_set_volfile_server_common(696cmd_args, arg, GF_DEFAULT_VOLFILE_TRANSPORT, GF_DEFAULT_BASE_PORT);697if (ret) {698gf_log("glusterfs", GF_LOG_ERROR, "failed to set volfile server: %s",699strerror(errno));700}701out:702return ret;703}
704
705static int706gf_remember_xlator_option(char *arg)707{
708glusterfs_ctx_t *ctx = NULL;709cmd_args_t *cmd_args = NULL;710xlator_cmdline_option_t *option = NULL;711int ret = -1;712char *dot = NULL;713char *equals = NULL;714
715ctx = glusterfsd_ctx;716cmd_args = &ctx->cmd_args;717
718option = GF_CALLOC(1, sizeof(xlator_cmdline_option_t),719gfd_mt_xlator_cmdline_option_t);720if (!option)721goto out;722
723INIT_LIST_HEAD(&option->cmd_args);724
725dot = strchr(arg, '.');726if (!dot) {727gf_smsg("", GF_LOG_WARNING, 0, glusterfsd_msg_10, "arg=%s", arg, NULL);728goto out;729}730
731option->volume = GF_MALLOC((dot - arg) + 1, gfd_mt_char);732if (!option->volume)733goto out;734
735strncpy(option->volume, arg, (dot - arg));736option->volume[(dot - arg)] = '\0';737
738equals = strchr(arg, '=');739if (!equals) {740gf_smsg("", GF_LOG_WARNING, 0, glusterfsd_msg_10, "arg=%s", arg, NULL);741goto out;742}743
744option->key = GF_MALLOC((equals - dot) + 1, gfd_mt_char);745if (!option->key)746goto out;747
748strncpy(option->key, dot + 1, (equals - dot - 1));749option->key[(equals - dot - 1)] = '\0';750
751if (!*(equals + 1)) {752gf_smsg("", GF_LOG_WARNING, 0, glusterfsd_msg_10, "arg=%s", arg, NULL);753goto out;754}755
756option->value = gf_strdup(equals + 1);757
758list_add(&option->cmd_args, &cmd_args->xlator_options);759
760ret = 0;761out:762if (ret == -1) {763if (option) {764GF_FREE(option->volume);765GF_FREE(option->key);766GF_FREE(option->value);767
768GF_FREE(option);769}770}771
772return ret;773}
774
775#ifdef GF_LINUX_HOST_OS776static struct oom_api_info {777char *oom_api_file;778int32_t oom_min;779int32_t oom_max;780} oom_api_info[] = {781{"/proc/self/oom_score_adj", OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX},782{"/proc/self/oom_adj", OOM_DISABLE, OOM_ADJUST_MAX},783{NULL, 0, 0}};784
785static struct oom_api_info *786get_oom_api_info(void)787{
788struct oom_api_info *api = NULL;789
790for (api = oom_api_info; api->oom_api_file; api++) {791if (sys_access(api->oom_api_file, F_OK) != -1) {792return api;793}794}795
796return NULL;797}
798#endif799
800static error_t801parse_opts(int key, char *arg, struct argp_state *state)802{
803cmd_args_t *cmd_args = NULL;804uint32_t n = 0;805#ifdef GF_LINUX_HOST_OS806int32_t k = 0;807struct oom_api_info *api = NULL;808#endif809double d = 0.0;810gf_boolean_t b = _gf_false;811char *tmp_str = NULL;812char *port_str = NULL;813struct passwd *pw = NULL;814int ret = 0;815
816cmd_args = state->input;817
818switch (key) {819case ARGP_VOLFILE_SERVER_KEY:820gf_remember_backup_volfile_server(arg);821
822break;823
824case ARGP_READ_ONLY_KEY:825cmd_args->read_only = 1;826break;827
828case ARGP_ACL_KEY:829cmd_args->acl = 1;830gf_remember_xlator_option("*-md-cache.cache-posix-acl=true");831break;832
833case ARGP_SELINUX_KEY:834cmd_args->selinux = 1;835gf_remember_xlator_option("*-md-cache.cache-selinux=true");836break;837
838case ARGP_CAPABILITY_KEY:839cmd_args->capability = 1;840break;841
842case ARGP_AUX_GFID_MOUNT_KEY:843cmd_args->aux_gfid_mount = 1;844break;845
846case ARGP_INODE32_KEY:847cmd_args->enable_ino32 = 1;848break;849
850case ARGP_WORM_KEY:851cmd_args->worm = 1;852break;853
854case ARGP_PRINT_NETGROUPS:855cmd_args->print_netgroups = arg;856break;857
858case ARGP_PRINT_EXPORTS:859cmd_args->print_exports = arg;860break;861
862case ARGP_PRINT_XLATORDIR_KEY:863cmd_args->print_xlatordir = _gf_true;864break;865
866case ARGP_PRINT_STATEDUMPDIR_KEY:867cmd_args->print_statedumpdir = _gf_true;868break;869
870case ARGP_PRINT_LOGDIR_KEY:871cmd_args->print_logdir = _gf_true;872break;873
874case ARGP_PRINT_LIBEXECDIR_KEY:875cmd_args->print_libexecdir = _gf_true;876break;877
878case ARGP_MAC_COMPAT_KEY:879if (!arg)880arg = "on";881
882if (gf_string2boolean(arg, &b) == 0) {883cmd_args->mac_compat = b;884
885break;886}887
888argp_failure(state, -1, 0, "invalid value \"%s\" for mac-compat",889arg);890break;891
892case ARGP_VOLUME_FILE_KEY:893GF_FREE(cmd_args->volfile);894
895if (arg[0] != '/') {896char pwd[PATH_MAX];897if (!getcwd(pwd, PATH_MAX)) {898argp_failure(state, -1, errno,899"getcwd failed with error no %d", errno);900break;901}902gf_asprintf(&cmd_args->volfile, "%s/%s", pwd, arg);903} else {904cmd_args->volfile = gf_strdup(arg);905}906
907break;908
909case ARGP_LOG_LEVEL_KEY:910if (strcasecmp(arg, ARGP_LOG_LEVEL_NONE_OPTION) == 0) {911cmd_args->log_level = GF_LOG_NONE;912break;913}914if (strcasecmp(arg, ARGP_LOG_LEVEL_CRITICAL_OPTION) == 0) {915cmd_args->log_level = GF_LOG_CRITICAL;916break;917}918if (strcasecmp(arg, ARGP_LOG_LEVEL_ERROR_OPTION) == 0) {919cmd_args->log_level = GF_LOG_ERROR;920break;921}922if (strcasecmp(arg, ARGP_LOG_LEVEL_WARNING_OPTION) == 0) {923cmd_args->log_level = GF_LOG_WARNING;924break;925}926if (strcasecmp(arg, ARGP_LOG_LEVEL_INFO_OPTION) == 0) {927cmd_args->log_level = GF_LOG_INFO;928break;929}930if (strcasecmp(arg, ARGP_LOG_LEVEL_DEBUG_OPTION) == 0) {931cmd_args->log_level = GF_LOG_DEBUG;932break;933}934if (strcasecmp(arg, ARGP_LOG_LEVEL_TRACE_OPTION) == 0) {935cmd_args->log_level = GF_LOG_TRACE;936break;937}938
939argp_failure(state, -1, 0, "unknown log level %s", arg);940break;941
942case ARGP_LOG_FILE_KEY:943cmd_args->log_file = gf_strdup(arg);944break;945
946case ARGP_VOLFILE_SERVER_PORT_KEY:947n = 0;948
949if (gf_string2uint_base10(arg, &n) == 0) {950cmd_args->volfile_server_port = n;951break;952}953
954argp_failure(state, -1, 0, "unknown volfile server port %s", arg);955break;956
957case ARGP_VOLFILE_SERVER_TRANSPORT_KEY:958cmd_args->volfile_server_transport = gf_strdup(arg);959break;960
961case ARGP_VOLFILE_ID_KEY:962cmd_args->volfile_id = gf_strdup(arg);963break;964
965case ARGP_THIN_CLIENT_KEY:966cmd_args->thin_client = _gf_true;967break;968
969case ARGP_BRICK_MUX_KEY:970cmd_args->brick_mux = _gf_true;971break;972
973case ARGP_PID_FILE_KEY:974cmd_args->pid_file = gf_strdup(arg);975break;976
977case ARGP_SOCK_FILE_KEY:978cmd_args->sock_file = gf_strdup(arg);979break;980
981case ARGP_NO_DAEMON_KEY:982cmd_args->no_daemon_mode = ENABLE_NO_DAEMON_MODE;983break;984
985case ARGP_RUN_ID_KEY:986cmd_args->run_id = gf_strdup(arg);987break;988
989case ARGP_DEBUG_KEY:990cmd_args->debug_mode = ENABLE_DEBUG_MODE;991break;992case ARGP_VOLFILE_MAX_FETCH_ATTEMPTS:993cmd_args->max_connect_attempts = 1;994break;995
996case ARGP_DIRECT_IO_MODE_KEY:997if (!arg)998arg = "on";999
1000if (gf_string2boolean(arg, &b) == 0) {1001cmd_args->fuse_direct_io_mode = b;1002
1003break;1004}1005
1006if (strcmp(arg, "auto") == 0)1007break;1008
1009argp_failure(state, -1, 0, "unknown direct I/O mode setting \"%s\"",1010arg);1011break;1012
1013case ARGP_FUSE_NO_ROOT_SQUASH_KEY:1014cmd_args->no_root_squash = _gf_true;1015break;1016
1017case ARGP_ENTRY_TIMEOUT_KEY:1018d = 0.0;1019
1020gf_string2double(arg, &d);1021if (!(d < 0.0)) {1022cmd_args->fuse_entry_timeout = d;1023break;1024}1025
1026argp_failure(state, -1, 0, "unknown entry timeout %s", arg);1027break;1028
1029case ARGP_NEGATIVE_TIMEOUT_KEY:1030d = 0.0;1031
1032ret = gf_string2double(arg, &d);1033if ((ret == 0) && !(d < 0.0)) {1034cmd_args->fuse_negative_timeout = d;1035break;1036}1037
1038argp_failure(state, -1, 0, "unknown negative timeout %s", arg);1039break;1040
1041case ARGP_ATTRIBUTE_TIMEOUT_KEY:1042d = 0.0;1043
1044gf_string2double(arg, &d);1045if (!(d < 0.0)) {1046cmd_args->fuse_attribute_timeout = d;1047break;1048}1049
1050argp_failure(state, -1, 0, "unknown attribute timeout %s", arg);1051break;1052
1053case ARGP_CLIENT_PID_KEY:1054if (gf_string2int(arg, &cmd_args->client_pid) == 0) {1055cmd_args->client_pid_set = 1;1056break;1057}1058
1059argp_failure(state, -1, 0, "unknown client pid %s", arg);1060break;1061
1062case ARGP_USER_MAP_ROOT_KEY:1063pw = getpwnam(arg);1064if (pw)1065cmd_args->uid_map_root = pw->pw_uid;1066else1067argp_failure(state, -1, 0, "user %s does not exist", arg);1068break;1069
1070case ARGP_VOLFILE_CHECK_KEY:1071cmd_args->volfile_check = 1;1072break;1073
1074case ARGP_VOLUME_NAME_KEY:1075cmd_args->volume_name = gf_strdup(arg);1076break;1077
1078case ARGP_XLATOR_OPTION_KEY:1079if (gf_remember_xlator_option(arg))1080argp_failure(state, -1, 0, "invalid xlator option %s", arg);1081
1082break;1083
1084case ARGP_KEY_NO_ARGS:1085break;1086
1087case ARGP_KEY_ARG:1088if (state->arg_num >= 1)1089argp_usage(state);1090cmd_args->mount_point = gf_strdup(arg);1091break;1092
1093case ARGP_DUMP_FUSE_KEY:1094cmd_args->dump_fuse = gf_strdup(arg);1095break;1096case ARGP_BRICK_NAME_KEY:1097cmd_args->brick_name = gf_strdup(arg);1098break;1099case ARGP_BRICK_PORT_KEY:1100n = 0;1101
1102if (arg != NULL) {1103port_str = strtok_r(arg, ",", &tmp_str);1104if (gf_string2uint_base10(port_str, &n) == 0) {1105cmd_args->brick_port = n;1106port_str = strtok_r(NULL, ",", &tmp_str);1107if (port_str) {1108if (gf_string2uint_base10(port_str, &n) == 0) {1109cmd_args->brick_port2 = n;1110break;1111}1112argp_failure(state, -1, 0,1113"wrong brick (listen) port %s", arg);1114}1115break;1116}1117}1118
1119argp_failure(state, -1, 0, "unknown brick (listen) port %s", arg);1120break;1121
1122case ARGP_MEM_ACCOUNTING_KEY:1123/* TODO: it should have got handled much earlier */1124// gf_mem_acct_enable_set (THIS->ctx);1125break;1126
1127case ARGP_FOPEN_KEEP_CACHE_KEY:1128if (!arg)1129arg = "on";1130
1131if (gf_string2boolean(arg, &b) == 0) {1132cmd_args->fopen_keep_cache = b;1133
1134break;1135}1136
1137argp_failure(state, -1, 0, "unknown cache setting \"%s\"", arg);1138
1139break;1140
1141case ARGP_GID_TIMEOUT_KEY:1142if (!gf_string2int(arg, &cmd_args->gid_timeout)) {1143cmd_args->gid_timeout_set = _gf_true;1144break;1145}1146
1147argp_failure(state, -1, 0, "unknown group list timeout %s", arg);1148break;1149
1150case ARGP_RESOLVE_GIDS_KEY:1151cmd_args->resolve_gids = 1;1152break;1153
1154case ARGP_FUSE_LRU_LIMIT_KEY:1155if (!gf_string2int32(arg, &cmd_args->lru_limit))1156break;1157
1158argp_failure(state, -1, 0, "unknown LRU limit option %s", arg);1159break;1160
1161case ARGP_FUSE_INODE_TABLESIZE_KEY:1162if (!gf_string2int32(arg, &cmd_args->inode_table_size))1163break;1164
1165argp_failure(state, -1, 0, "unknown inode table size option %s",1166arg);1167break;1168
1169case ARGP_FUSE_INVALIDATE_LIMIT_KEY:1170if (!gf_string2int32(arg, &cmd_args->invalidate_limit))1171break;1172
1173argp_failure(state, -1, 0, "unknown invalidate limit option %s",1174arg);1175break;1176
1177case ARGP_FUSE_BACKGROUND_QLEN_KEY:1178if (!gf_string2int(arg, &cmd_args->background_qlen))1179break;1180
1181argp_failure(state, -1, 0, "unknown background qlen option %s",1182arg);1183break;1184case ARGP_FUSE_CONGESTION_THRESHOLD_KEY:1185if (!gf_string2int(arg, &cmd_args->congestion_threshold))1186break;1187
1188argp_failure(state, -1, 0, "unknown congestion threshold option %s",1189arg);1190break;1191
1192#ifdef GF_LINUX_HOST_OS1193case ARGP_OOM_SCORE_ADJ_KEY:1194k = 0;1195
1196api = get_oom_api_info();1197if (!api)1198goto no_oom_api;1199
1200if (gf_string2int(arg, &k) == 0 && k >= api->oom_min &&1201k <= api->oom_max) {1202cmd_args->oom_score_adj = gf_strdup(arg);1203break;1204}1205
1206argp_failure(state, -1, 0, "unknown oom_score_adj value %s", arg);1207
1208no_oom_api:1209break;1210#endif1211
1212case ARGP_FUSE_MOUNTOPTS_KEY:1213cmd_args->fuse_mountopts = gf_strdup(arg);1214break;1215
1216case ARGP_FUSE_USE_READDIRP_KEY:1217if (!arg)1218arg = "yes";1219
1220if (gf_string2boolean(arg, &b) == 0) {1221if (b) {1222cmd_args->use_readdirp = "yes";1223} else {1224cmd_args->use_readdirp = "no";1225}1226
1227break;1228}1229
1230argp_failure(state, -1, 0, "unknown use-readdirp setting \"%s\"",1231arg);1232break;1233
1234case ARGP_LOGGER:1235if (strcasecmp(arg, GF_LOGGER_GLUSTER_LOG) == 0)1236cmd_args->logger = gf_logger_glusterlog;1237else if (strcasecmp(arg, GF_LOGGER_SYSLOG) == 0)1238cmd_args->logger = gf_logger_syslog;1239else1240argp_failure(state, -1, 0, "unknown logger %s", arg);1241
1242break;1243
1244case ARGP_LOG_FORMAT:1245if (strcasecmp(arg, GF_LOG_FORMAT_NO_MSG_ID) == 0)1246cmd_args->log_format = gf_logformat_traditional;1247else if (strcasecmp(arg, GF_LOG_FORMAT_WITH_MSG_ID) == 0)1248cmd_args->log_format = gf_logformat_withmsgid;1249else1250argp_failure(state, -1, 0, "unknown log format %s", arg);1251
1252break;1253
1254case ARGP_LOG_BUF_SIZE:1255if (gf_string2uint32(arg, &cmd_args->log_buf_size)) {1256argp_failure(state, -1, 0, "unknown log buf size option %s",1257arg);1258} else if (cmd_args->log_buf_size > GF_LOG_LRU_BUFSIZE_MAX) {1259argp_failure(state, -1, 0,1260"Invalid log buf size %s. "1261"Valid range: [" GF_LOG_LRU_BUFSIZE_MIN_STR1262"," GF_LOG_LRU_BUFSIZE_MAX_STR "]",1263arg);1264}1265
1266break;1267
1268case ARGP_LOG_FLUSH_TIMEOUT:1269if (gf_string2uint32(arg, &cmd_args->log_flush_timeout)) {1270argp_failure(state, -1, 0,1271"unknown log flush timeout option %s", arg);1272} else if ((cmd_args->log_flush_timeout <1273GF_LOG_FLUSH_TIMEOUT_MIN) ||1274(cmd_args->log_flush_timeout >1275GF_LOG_FLUSH_TIMEOUT_MAX)) {1276argp_failure(state, -1, 0,1277"Invalid log flush timeout %s. "1278"Valid range: [" GF_LOG_FLUSH_TIMEOUT_MIN_STR1279"," GF_LOG_FLUSH_TIMEOUT_MAX_STR "]",1280arg);1281}1282
1283break;1284
1285case ARGP_SECURE_MGMT_KEY:1286if (!arg)1287arg = "yes";1288
1289if (gf_string2boolean(arg, &b) == 0) {1290cmd_args->secure_mgmt = b ? 1 : 0;1291break;1292}1293
1294argp_failure(state, -1, 0, "unknown secure-mgmt setting \"%s\"",1295arg);1296break;1297
1298case ARGP_LOCALTIME_LOGGING_KEY:1299cmd_args->localtime_logging = 1;1300break;1301case ARGP_PROCESS_NAME_KEY:1302cmd_args->process_name = gf_strdup(arg);1303break;1304case ARGP_SUBDIR_MOUNT_KEY:1305if (arg[0] != '/') {1306argp_failure(state, -1, 0, "expect '/%s', provided just \"%s\"",1307arg, arg);1308break;1309}1310cmd_args->subdir_mount = gf_strdup(arg);1311break;1312case ARGP_FUSE_EVENT_HISTORY_KEY:1313if (!arg)1314arg = "no";1315
1316if (gf_string2boolean(arg, &b) == 0) {1317if (b) {1318cmd_args->event_history = "yes";1319} else {1320cmd_args->event_history = "no";1321}1322
1323break;1324}1325
1326argp_failure(state, -1, 0, "unknown event-history setting \"%s\"",1327arg);1328break;1329case ARGP_READER_THREAD_COUNT_KEY:1330if (gf_string2uint32(arg, &cmd_args->reader_thread_count)) {1331argp_failure(state, -1, 0,1332"unknown reader thread count option %s", arg);1333} else if ((cmd_args->reader_thread_count < 1) ||1334(cmd_args->reader_thread_count > 64)) {1335argp_failure(state, -1, 0,1336"Invalid reader thread count %s. "1337"Valid range: [\"1, 64\"]",1338arg);1339}1340
1341break;1342
1343case ARGP_KERNEL_WRITEBACK_CACHE_KEY:1344if (!arg)1345arg = "yes";1346
1347if (gf_string2boolean(arg, &b) == 0) {1348cmd_args->kernel_writeback_cache = b;1349
1350break;1351}1352
1353argp_failure(state, -1, 0,1354"unknown kernel writeback cache setting \"%s\"", arg);1355break;1356case ARGP_ATTR_TIMES_GRANULARITY_KEY:1357if (gf_string2uint32(arg, &cmd_args->attr_times_granularity)) {1358argp_failure(state, -1, 0,1359"unknown attribute times granularity option %s",1360arg);1361} else if (cmd_args->attr_times_granularity > 1000000000) {1362argp_failure(state, -1, 0,1363"Invalid attribute times granularity value %s. "1364"Valid range: [\"0, 1000000000\"]",1365arg);1366}1367
1368break;1369
1370case ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY:1371if (!arg)1372arg = "yes";1373
1374if (gf_string2boolean(arg, &b) == 0) {1375cmd_args->fuse_flush_handle_interrupt = b;1376
1377break;1378}1379
1380argp_failure(state, -1, 0,1381"unknown fuse flush handle interrupt setting \"%s\"",1382arg);1383break;1384
1385case ARGP_FUSE_AUTO_INVAL_KEY:1386if (!arg)1387arg = "yes";1388
1389if (gf_string2boolean(arg, &b) == 0) {1390cmd_args->fuse_auto_inval = b;1391break;1392}1393
1394break;1395
1396case ARGP_GLOBAL_THREADING_KEY:1397if (!arg || (*arg == 0)) {1398arg = "yes";1399}1400
1401if (gf_string2boolean(arg, &b) == 0) {1402cmd_args->global_threading = b;1403break;1404}1405
1406argp_failure(state, -1, 0,1407"Invalid value for global threading \"%s\"", arg);1408break;1409
1410case ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY:1411if (gf_string2uint32(arg, &cmd_args->fuse_dev_eperm_ratelimit_ns)) {1412argp_failure(state, -1, 0,1413"Non-numerical value for "1414"'fuse-dev-eperm-ratelimit-ns' option %s",1415arg);1416} else if (cmd_args->fuse_dev_eperm_ratelimit_ns > 1000000000) {1417argp_failure(state, -1, 0,1418"Invalid 'fuse-dev-eperm-ratelimit-ns' value %s. "1419"Valid range: [\"0, 1000000000\"]",1420arg);1421}1422
1423break;1424
1425case ARGP_FUSE_DISPLAY_NAME_KEY:1426cmd_args->fs_display_name = gf_strdup(arg);1427break;1428
1429case ARGP_IO_ENGINE_KEY:1430cmd_args->io_engine = gf_strdup(arg);1431if (cmd_args->io_engine == NULL) {1432argp_failure(state, -1, 0,1433"Failed to allocate memory for "1434"io-engine");1435}1436break;1437
1438case ARGP_FUSE_SETLK_HANDLE_INTERRUPT_KEY:1439if (!arg)1440arg = "yes";1441
1442if (gf_string2boolean(arg, &b) == 0) {1443cmd_args->fuse_setlk_handle_interrupt = b;1444
1445break;1446}1447
1448argp_failure(state, -1, 0,1449"unknown fuse setlk handle interrupt setting \"%s\"",1450arg);1451break;1452case ARGP_FUSE_HANDLE_COPY_FILE_RANGE:1453if (!arg)1454arg = "yes";1455
1456if (gf_string2boolean(arg, &b) == 0) {1457cmd_args->fuse_handle_copy_file_range = b;1458
1459break;1460}1461
1462argp_failure(state, -1, 0,1463"unknown fuse handle copy_file_range setting \"%s\"",1464arg);1465break;1466}1467return 0;1468}
1469
1470void
1471cleanup_and_exit(int signum)1472{
1473glusterfs_ctx_t *ctx = NULL;1474xlator_t *trav = NULL;1475xlator_t *top;1476xlator_t *victim;1477xlator_list_t **trav_p;1478
1479ctx = glusterfsd_ctx;1480
1481if (!ctx)1482return;1483
1484/* To take or not to take the mutex here and in the other1485* signal handler - gf_print_trace() - is the big question here.
1486*
1487* Taking mutex in signal handler would mean that if the process
1488* receives a fatal signal while another thread is holding
1489* ctx->log.log_buf_lock to perhaps log a message in _gf_msg_internal(),
1490* the offending thread hangs on the mutex lock forever without letting
1491* the process exit.
1492*
1493* On the other hand. not taking the mutex in signal handler would cause
1494* it to modify the lru_list of buffered log messages in a racy manner,
1495* corrupt the list and potentially give rise to an unending
1496* cascade of SIGSEGVs and other re-entrancy issues.
1497*/
1498
1499gf_log_disable_suppression_before_exit(ctx);1500
1501gf_msg_callingfn("", GF_LOG_WARNING, 0, glusterfsd_msg_32,1502"received signum (%d), shutting down", signum);1503
1504if (ctx->cleanup_started)1505return;1506pthread_mutex_lock(&ctx->cleanup_lock);1507{1508ctx->cleanup_started = 1;1509
1510/* signout should be sent to all the bricks in case brick mux is enabled1511* and multiple brick instances are attached to this process
1512*/
1513if (ctx->active) {1514top = ctx->active->first;1515for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) {1516victim = (*trav_p)->xlator;1517rpc_clnt_mgmt_pmap_signout(ctx, victim->name);1518}1519} else {1520rpc_clnt_mgmt_pmap_signout(ctx, NULL);1521}1522
1523/* below part is a racy code where the rpcsvc object is freed.1524* But in another thread (epoll thread), upon poll error in the
1525* socket the transports are cleaned up where again rpcsvc object
1526* is accessed (which is already freed by the below function).
1527* Since the process is about to be killed don't execute the function
1528* below.
1529*/
1530/* if (ctx->listener) { */1531/* (void) glusterfs_listener_stop (ctx); */1532/* } */1533
1534/* Call fini() of FUSE xlator first:1535* so there are no more requests coming and
1536* 'umount' of mount point is done properly */
1537trav = ctx->root;1538if (trav && trav->fini) {1539THIS = trav;1540trav->fini(trav);1541}1542
1543glusterfs_pidfile_cleanup(ctx);1544
1545#if 01546/* TODO: Properly do cleanup_and_exit(), with synchronization */1547if (ctx->mgmt) {1548/* cleanup the saved-frames before last unref */1549rpc_clnt_connection_cleanup (&ctx->mgmt->conn);1550rpc_clnt_unref (ctx->mgmt);1551}1552#endif1553
1554trav = NULL;1555
1556/* previously we were releasing the cleanup mutex lock before the1557process exit. As we are releasing the cleanup mutex lock, before
1558the process can exit some other thread which is blocked on
1559cleanup mutex lock is acquiring the cleanup mutex lock and
1560trying to acquire some resources which are already freed as a
1561part of cleanup. To avoid this, we are exiting the process without
1562releasing the cleanup mutex lock. This will not cause any lock
1563related issues as the process which acquired the lock is going down
1564*/
1565/* NOTE: Only the least significant 8 bits i.e (signum & 255)1566will be available to parent process on calling exit() */
1567exit(abs(signum));1568}1569}
1570
1571static FILE *1572get_volfp(glusterfs_ctx_t *ctx)1573{
1574cmd_args_t *cmd_args = NULL;1575FILE *specfp = NULL;1576
1577cmd_args = &ctx->cmd_args;1578
1579if ((specfp = fopen(cmd_args->volfile, "r")) == NULL) {1580gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_9,1581"volume_file=%s", cmd_args->volfile, NULL);1582return NULL;1583}1584
1585gf_msg_debug("glusterfsd", 0, "loading volume file %s", cmd_args->volfile);1586
1587return specfp;1588}
1589
1590static int1591volfile_init(glusterfs_ctx_t *ctx)1592{
1593int ret = -1;1594char *volfile = NULL;1595gf_volfile_t *volfile_obj = NULL;1596gf_volfile_t *volfile_tmp = NULL;1597struct stat stbuf = {15980,1599};1600char sha256_hash[SHA256_DIGEST_LENGTH] = {16010,1602};1603
1604cmd_args_t *cmd_args = &ctx->cmd_args;1605FILE *fp = get_volfp(ctx);1606if (!fp) {1607gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_28, NULL);1608goto out;1609}1610ret = sys_stat(cmd_args->volfile, &stbuf);1611if (IS_ERROR(ret)) {1612gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_9,1613"volume_file=%s", cmd_args->volfile, NULL);1614goto out;1615}1616
1617volfile = GF_MALLOC(stbuf.st_size, gf_common_mt_char);1618if (!volfile) {1619gf_smsg("glusterfsd", GF_LOG_ERROR, ENOMEM, glusterfsd_msg_9,1620"volume_file=%s", cmd_args->volfile, NULL);1621ret = -1;1622goto out;1623}1624ret = fread(volfile, stbuf.st_size, 1, fp);1625if (IS_ERROR(ret)) {1626gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_9,1627"volume_file=%s", cmd_args->volfile, NULL);1628goto out;1629}1630glusterfs_compute_sha256((const unsigned char *)volfile, stbuf.st_size,1631sha256_hash);1632LOCK(&ctx->volfile_lock);1633{1634list_for_each_entry(volfile_obj, &ctx->volfile_list, volfile_list)1635{1636if (!memcmp(sha256_hash, volfile_obj->volfile_checksum,1637sizeof(volfile_obj->volfile_checksum))) {1638UNLOCK(&ctx->volfile_lock);1639ret = 0;1640gf_smsg(THIS->name, GF_LOG_INFO, 0, glusterfsd_msg_40, NULL);1641goto out;1642}1643volfile_tmp = volfile_obj;1644break;1645}1646}1647UNLOCK(&ctx->volfile_lock);1648
1649/* Check if only options have changed. No need to reload the1650* volfile if topology hasn't changed.
1651* glusterfs_volfile_reconfigure returns 3 possible return states
1652* return 0 =======> reconfiguration of options has succeeded
1653* return 1 =======> the graph has to be reconstructed and all
1654* the xlators should be inited return -1(or -ve) =======> Some Internal
1655* Error occurred during the operation
1656*/
1657
1658if (volfile_tmp) {1659ret = glusterfs_volfile_reconfigure(fp, ctx);1660if (ret == 0) {1661gf_msg_debug("glusterfsd-mgmt", 0,1662"No need to re-load volfile, reconfigure done");1663memcpy(volfile_tmp->volfile_checksum, sha256_hash,1664sizeof(volfile_tmp->volfile_checksum));1665goto out;1666} else {1667gf_msg("glusterfsd-mgmt", GF_LOG_INFO, 0, 0,1668"reconfigure failed, continuing with init");1669}1670} else {1671gf_msg("glusterfsd-mgmt", GF_LOG_INFO, 0, 0,1672"volume not found, continuing with init");1673}1674
1675ret = glusterfs_process_volfp(ctx, fp);1676fp = NULL; /* this is freed inside the function (both success & failure) */1677if (ret)1678goto out;1679
1680LOCK(&ctx->volfile_lock);1681{1682if (!volfile_tmp) {1683volfile_tmp = GF_CALLOC(1, sizeof(gf_volfile_t),1684gf_common_volfile_t);1685if (!volfile_tmp) {1686ret = -1;1687goto out;1688}1689
1690INIT_LIST_HEAD(&volfile_tmp->volfile_list);1691volfile_tmp->graph = ctx->active;1692list_add(&volfile_tmp->volfile_list, &ctx->volfile_list);1693snprintf(volfile_tmp->vol_id, sizeof(volfile_tmp->vol_id), "%s",1694cmd_args->volfile_id);1695}1696memcpy(volfile_tmp->volfile_checksum, sha256_hash,1697sizeof(volfile_tmp->volfile_checksum));1698}1699UNLOCK(&ctx->volfile_lock);1700
1701ret = 0;1702out:1703if (fp)1704fclose(fp);1705
1706if (volfile)1707GF_FREE(volfile);1708return ret;1709}
1710
1711static void1712reincarnate(int signum)1713{
1714int ret = 0;1715glusterfs_ctx_t *ctx = NULL;1716cmd_args_t *cmd_args = NULL;1717
1718ctx = glusterfsd_ctx;1719cmd_args = &ctx->cmd_args;1720
1721gf_msg_trace("gluster", 0, "received reincarnate request (sig:HUP)");1722
1723if (cmd_args->volfile_server) {1724gf_smsg("glusterfsd", GF_LOG_INFO, 0, glusterfsd_msg_11, NULL);1725ret = glusterfs_volfile_fetch(ctx);1726} else {1727ret = volfile_init(ctx);1728}1729
1730/* Also, SIGHUP should do logrotate */1731gf_log_logrotate(1);1732
1733if (ret < 0)1734gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_12, NULL);1735
1736/* Notify all xlators */1737if (ctx->active)1738xlator_notify(ctx->active->top, GF_EVENT_SIGHUP, NULL);1739
1740return;1741}
1742
1743void
1744emancipate(glusterfs_ctx_t *ctx, int ret)1745{
1746/* break free from the parent */1747if (ctx->daemon_pipe[1] != -1) {1748sys_write(ctx->daemon_pipe[1], (void *)&ret, sizeof(ret));1749sys_close(ctx->daemon_pipe[1]);1750ctx->daemon_pipe[1] = -1;1751}1752}
1753
1754static uint8_t1755gf_get_process_mode(char *exec_name)1756{
1757char *dup_execname = NULL, *base = NULL;1758uint8_t ret = 0;1759
1760dup_execname = gf_strdup(exec_name);1761base = basename(dup_execname);1762
1763if (!strncmp(base, "glusterfsd", 10)) {1764ret = GF_SERVER_PROCESS;1765} else if (!strncmp(base, "glusterd", 8)) {1766ret = GF_GLUSTERD_PROCESS;1767} else {1768ret = GF_CLIENT_PROCESS;1769}1770
1771GF_FREE(dup_execname);1772
1773return ret;1774}
1775
1776static int1777glusterfs_ctx_defaults_init(glusterfs_ctx_t *ctx)1778{
1779cmd_args_t *cmd_args = NULL;1780struct rlimit lim = {17810,1782};1783int ret = -1;1784
1785if (!ctx)1786return ret;1787
1788ret = xlator_mem_acct_init(THIS, gfd_mt_end);1789if (ret != 0) {1790gf_smsg(THIS->name, GF_LOG_CRITICAL, 0, glusterfsd_msg_34, NULL);1791return ret;1792}1793
1794/* reset ret to -1 so that we don't need to explicitly1795* set it in all error paths before "goto err"
1796*/
1797ret = -1;1798
1799/* monitoring should be enabled by default */1800ctx->measure_latency = true;1801
1802ctx->process_uuid = generate_glusterfs_ctx_id();1803if (!ctx->process_uuid) {1804gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_13, NULL);1805goto out;1806}1807
1808ctx->page_size = 128 * GF_UNIT_KB;1809
1810ctx->iobuf_pool = iobuf_pool_new();1811if (!ctx->iobuf_pool) {1812gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "iobuf", NULL);1813goto out;1814}1815
1816ctx->event_pool = gf_event_pool_new(DEFAULT_EVENT_POOL_SIZE,1817STARTING_EVENT_THREADS);1818if (!ctx->event_pool) {1819gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "event", NULL);1820goto out;1821}1822
1823ctx->pool = GF_CALLOC(1, sizeof(call_pool_t), gfd_mt_call_pool_t);1824if (!ctx->pool) {1825gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "call", NULL);1826goto out;1827}1828
1829INIT_LIST_HEAD(&ctx->pool->all_frames);1830LOCK_INIT(&ctx->pool->lock);1831
1832/* frame_mem_pool size 112 * 4k */1833ctx->pool->frame_mem_pool = mem_pool_new(call_frame_t, 4096);1834if (!ctx->pool->frame_mem_pool) {1835gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "frame", NULL);1836goto out;1837}1838/* stack_mem_pool size 256 * 1024 */1839ctx->pool->stack_mem_pool = mem_pool_new(call_stack_t, 1024);1840if (!ctx->pool->stack_mem_pool) {1841gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "stack", NULL);1842goto out;1843}1844
1845ctx->dict_pool = mem_pool_new(dict_t, GF_MEMPOOL_COUNT_OF_DICT_T);1846if (!ctx->dict_pool)1847goto out;1848
1849ctx->dict_data_pool = mem_pool_new(data_t, GF_MEMPOOL_COUNT_OF_DATA_T);1850if (!ctx->dict_data_pool)1851goto out;1852
1853ctx->logbuf_pool = mem_pool_new(log_buf_t, GF_MEMPOOL_COUNT_OF_LRU_BUF_T);1854if (!ctx->logbuf_pool)1855goto out;1856
1857pthread_mutex_init(&ctx->notify_lock, NULL);1858pthread_mutex_init(&ctx->cleanup_lock, NULL);1859pthread_cond_init(&ctx->notify_cond, NULL);1860
1861ctx->clienttable = gf_clienttable_alloc();1862if (!ctx->clienttable)1863goto out;1864
1865cmd_args = &ctx->cmd_args;1866
1867/* parsing command line arguments */1868cmd_args->log_level = DEFAULT_LOG_LEVEL;1869cmd_args->logger = gf_logger_glusterlog;1870cmd_args->log_format = gf_logformat_withmsgid;1871cmd_args->log_buf_size = GF_LOG_LRU_BUFSIZE_DEFAULT;1872cmd_args->log_flush_timeout = GF_LOG_FLUSH_TIMEOUT_DEFAULT;1873
1874cmd_args->mac_compat = GF_OPTION_DISABLE;1875#ifdef GF_DARWIN_HOST_OS1876/* On Darwin machines, O_APPEND is not handled,1877* which may corrupt the data
1878*/
1879cmd_args->fuse_direct_io_mode = GF_OPTION_DISABLE;1880#else1881cmd_args->fuse_direct_io_mode = GF_OPTION_DEFERRED;1882#endif1883cmd_args->fuse_attribute_timeout = -1;1884cmd_args->fuse_entry_timeout = -1;1885cmd_args->fopen_keep_cache = GF_OPTION_DEFERRED;1886cmd_args->kernel_writeback_cache = GF_OPTION_DEFERRED;1887cmd_args->fuse_flush_handle_interrupt = GF_OPTION_DEFERRED;1888cmd_args->fuse_setlk_handle_interrupt = GF_OPTION_DEFERRED;1889
1890if (ctx->mem_acct_enable)1891cmd_args->mem_acct = 1;1892
1893INIT_LIST_HEAD(&cmd_args->xlator_options);1894INIT_LIST_HEAD(&cmd_args->volfile_servers);1895ctx->pxl_count = 0;1896ctx->diskxl_count = 0;1897pthread_mutex_init(&ctx->fd_lock, NULL);1898pthread_cond_init(&ctx->fd_cond, NULL);1899INIT_LIST_HEAD(&ctx->janitor_fds);1900pthread_mutex_init(&ctx->xl_lock, NULL);1901pthread_cond_init(&ctx->xl_cond, NULL);1902INIT_LIST_HEAD(&ctx->diskth_xl);1903
1904lim.rlim_cur = RLIM_INFINITY;1905lim.rlim_max = RLIM_INFINITY;1906setrlimit(RLIMIT_CORE, &lim);1907
1908ret = 0;1909out:1910
1911if (ret) {1912if (ctx->pool) {1913mem_pool_destroy(ctx->pool->frame_mem_pool);1914mem_pool_destroy(ctx->pool->stack_mem_pool);1915}1916GF_FREE(ctx->pool);1917mem_pool_destroy(ctx->dict_pool);1918mem_pool_destroy(ctx->dict_data_pool);1919mem_pool_destroy(ctx->logbuf_pool);1920}1921
1922return ret;1923}
1924
1925static int1926gf_set_log_ident(cmd_args_t *cmd_args)1927{
1928int ret = 0;1929char *ptr = NULL;1930
1931if (cmd_args->log_file == NULL) {1932/* no ident source */1933return 0;1934}1935
1936/* TODO: Some idents would look like, etc-glusterfs-glusterd.vol, which1937* seems ugly and can be bettered? */
1938/* just get the filename as the ident */1939if (NULL != (ptr = strrchr(cmd_args->log_file, '/'))) {1940ret = gf_asprintf(&cmd_args->log_ident, "%s", ptr + 1);1941} else {1942ret = gf_asprintf(&cmd_args->log_ident, "%s", cmd_args->log_file);1943}1944
1945if (ret > 0)1946ret = 0;1947else1948return ret;1949
1950/* remove .log suffix */1951if (NULL != (ptr = strrchr(cmd_args->log_ident, '.'))) {1952if (strcmp(ptr, ".log") == 0) {1953ptr[0] = '\0';1954}1955}1956
1957return ret;1958}
1959
1960static int1961logging_init(glusterfs_ctx_t *ctx, const char *progpath)1962{
1963cmd_args_t *cmd_args = NULL;1964int ret = 0;1965
1966cmd_args = &ctx->cmd_args;1967
1968if (cmd_args->log_file == NULL) {1969ret = gf_set_log_file_path(cmd_args, ctx);1970if (ret == -1) {1971fprintf(stderr,1972"ERROR: failed to set the log file "1973"path\n");1974return -1;1975}1976}1977
1978if (cmd_args->log_ident == NULL) {1979ret = gf_set_log_ident(cmd_args);1980if (ret == -1) {1981fprintf(stderr,1982"ERROR: failed to set the log "1983"identity\n");1984return -1;1985}1986}1987
1988/* finish log set parameters before init */1989ctx->log.loglevel = cmd_args->log_level;1990
1991ctx->log.localtime = cmd_args->localtime_logging;1992
1993ctx->log.logger = cmd_args->logger;1994
1995ctx->log.logformat = cmd_args->log_format;1996
1997gf_log_set_log_buf_size(ctx, cmd_args->log_buf_size);1998
1999ctx->log.timeout = cmd_args->log_flush_timeout;2000
2001if (gf_log_init(ctx, cmd_args->log_file, cmd_args->log_ident) == -1) {2002fprintf(stderr, "ERROR: failed to open logfile %s\n",2003cmd_args->log_file);2004return -1;2005}2006
2007/* At this point, all the logging related parameters are initialised2008* except for the log flush timer, which will be injected post fork(2)
2009* in daemonize() . During this time, any log message that is logged
2010* will be kept buffered. And if the list that holds these messages
2011* overflows, then the same lru policy is used to drive out the least
2012* recently used message and displace it with the message just logged.
2013*/
2014
2015return 0;2016}
2017
2018static void2019gf_check_and_set_mem_acct(int argc, char *argv[])2020{
2021int i = 0;2022
2023for (i = 0; i < argc; i++) {2024if (strcmp(argv[i], "--no-mem-accounting") == 0) {2025gf_global_mem_acct_enable_set(0);2026break;2027}2028}2029}
2030#ifdef BUILD_GNFS2031/**
2032* print_exports_file - Print out & verify the syntax
2033* of the exports file specified
2034* in the parameter.
2035*
2036* @exports_file : Path of the exports file to print & verify
2037*
2038* @return : success: 0 when successfully parsed
2039* failure: 1 when failed to parse one or more lines
2040* -1 when other critical errors (dlopen () etc)
2041* Critical errors are treated differently than parse errors. Critical
2042* errors terminate the program immediately here and print out different
2043* error messages. Hence there are different return values.
2044*/
2045static int2046print_exports_file(const char *exports_file)2047{
2048void *libhandle = NULL;2049char *libpathfull = NULL;2050struct exports_file *file = NULL;2051int ret = 0;2052
2053int (*exp_file_parse)(const char *filepath, struct exports_file **expfile,2054struct mount3_state *ms) = NULL;2055void (*exp_file_print)(const struct exports_file *file) = NULL;2056void (*exp_file_deinit)(struct exports_file * ptr) = NULL;2057
2058/* XLATORDIR passed through a -D flag to GCC */2059ret = gf_asprintf(&libpathfull, "%s/%s/server.so", XLATORDIR, "nfs");2060if (ret < 0) {2061gf_log("glusterfs", GF_LOG_CRITICAL, "asprintf () failed.");2062ret = -1;2063goto out;2064}2065
2066/* Load up the library */2067libhandle = dlopen(libpathfull, RTLD_NOW);2068if (!libhandle) {2069gf_log("glusterfs", GF_LOG_CRITICAL,2070"Error loading NFS server library : "2071"%s\n",2072dlerror());2073ret = -1;2074goto out;2075}2076
2077/* Load up the function */2078exp_file_parse = dlsym(libhandle, "exp_file_parse");2079if (!exp_file_parse) {2080gf_log("glusterfs", GF_LOG_CRITICAL,2081"Error finding function exp_file_parse "2082"in symbol.");2083ret = -1;2084goto out;2085}2086
2087/* Parse the file */2088ret = exp_file_parse(exports_file, &file, NULL);2089if (ret < 0) {2090ret = 1; /* This means we failed to parse */2091goto out;2092}2093
2094/* Load up the function */2095exp_file_print = dlsym(libhandle, "exp_file_print");2096if (!exp_file_print) {2097gf_log("glusterfs", GF_LOG_CRITICAL,2098"Error finding function exp_file_print in symbol.");2099ret = -1;2100goto out;2101}2102
2103/* Print it out to screen */2104exp_file_print(file);2105
2106/* Load up the function */2107exp_file_deinit = dlsym(libhandle, "exp_file_deinit");2108if (!exp_file_deinit) {2109gf_log("glusterfs", GF_LOG_CRITICAL,2110"Error finding function exp_file_deinit in lib.");2111ret = -1;2112goto out;2113}2114
2115/* Free the file */2116exp_file_deinit(file);2117
2118out:2119if (libhandle)2120dlclose(libhandle);2121GF_FREE(libpathfull);2122return ret;2123}
2124
2125/**
2126* print_netgroups_file - Print out & verify the syntax
2127* of the netgroups file specified
2128* in the parameter.
2129*
2130* @netgroups_file : Path of the netgroups file to print & verify
2131* @return : success: 0 when successfully parsed
2132* failure: 1 when failed to parse one more more lines
2133* -1 when other critical errors (dlopen () etc)
2134*
2135* We have multiple returns here because for critical errors, we abort
2136* operations immediately and exit. For example, if we can't load the
2137* NFS server library, then we have a real bad problem so we don't continue.
2138* Or if we cannot allocate anymore memory, we don't want to continue. Also,
2139* we want to print out a different error messages based on the ret value.
2140*/
2141static int2142print_netgroups_file(const char *netgroups_file)2143{
2144void *libhandle = NULL;2145char *libpathfull = NULL;2146struct netgroups_file *file = NULL;2147int ret = 0;2148
2149struct netgroups_file *(*ng_file_parse)(const char *file_path) = NULL;2150void (*ng_file_print)(const struct netgroups_file *file) = NULL;2151void (*ng_file_deinit)(struct netgroups_file * ptr) = NULL;2152
2153/* XLATORDIR passed through a -D flag to GCC */2154ret = gf_asprintf(&libpathfull, "%s/%s/server.so", XLATORDIR, "nfs");2155if (ret < 0) {2156gf_log("glusterfs", GF_LOG_CRITICAL, "asprintf () failed.");2157ret = -1;2158goto out;2159}2160/* Load up the library */2161libhandle = dlopen(libpathfull, RTLD_NOW);2162if (!libhandle) {2163gf_log("glusterfs", GF_LOG_CRITICAL,2164"Error loading NFS server library : %s\n", dlerror());2165ret = -1;2166goto out;2167}2168
2169/* Load up the function */2170ng_file_parse = dlsym(libhandle, "ng_file_parse");2171if (!ng_file_parse) {2172gf_log("glusterfs", GF_LOG_CRITICAL,2173"Error finding function ng_file_parse in symbol.");2174ret = -1;2175goto out;2176}2177
2178/* Parse the file */2179file = ng_file_parse(netgroups_file);2180if (!file) {2181ret = 1; /* This means we failed to parse */2182goto out;2183}2184
2185/* Load up the function */2186ng_file_print = dlsym(libhandle, "ng_file_print");2187if (!ng_file_print) {2188gf_log("glusterfs", GF_LOG_CRITICAL,2189"Error finding function ng_file_print in symbol.");2190ret = -1;2191goto out;2192}2193
2194/* Print it out to screen */2195ng_file_print(file);2196
2197/* Load up the function */2198ng_file_deinit = dlsym(libhandle, "ng_file_deinit");2199if (!ng_file_deinit) {2200gf_log("glusterfs", GF_LOG_CRITICAL,2201"Error finding function ng_file_deinit in lib.");2202ret = -1;2203goto out;2204}2205
2206/* Free the file */2207ng_file_deinit(file);2208
2209out:2210if (libhandle)2211dlclose(libhandle);2212GF_FREE(libpathfull);2213return ret;2214}
2215
2216#endif2217
2218static int2219parse_cmdline(int argc, char *argv[], glusterfs_ctx_t *ctx)2220{
2221int process_mode = 0;2222int ret = 0;2223struct stat stbuf = {22240,2225};2226char timestr[GF_TIMESTR_SIZE];2227char tmp_logfile[1024] = {0};2228char *tmp_logfile_dyn = NULL;2229char *tmp_logfilebase = NULL;2230cmd_args_t *cmd_args = NULL;2231int len = 0;2232char *thin_volfileid = NULL;2233
2234cmd_args = &ctx->cmd_args;2235
2236/* Do this before argp_parse so it can be overridden. */2237if (sys_access(SECURE_ACCESS_FILE, F_OK) == 0) {2238cmd_args->secure_mgmt = 1;2239ctx->ssl_cert_depth = glusterfs_read_secure_access_file();2240}2241
2242/* Need to set lru_limit to below 0 to indicate there was nothing2243specified. This is needed as 0 is a valid option, and may not be
2244default value. */
2245cmd_args->lru_limit = -1;2246
2247argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, cmd_args);2248
2249if (cmd_args->print_xlatordir || cmd_args->print_statedumpdir ||2250cmd_args->print_logdir || cmd_args->print_libexecdir) {2251/* Just print, nothing else to do */2252goto out;2253}2254
2255if (cmd_args->print_netgroups) {2256/* When this option is set we don't want to do anything else2257* except for printing & verifying the netgroups file.
2258*/
2259ret = 0;2260goto out;2261}2262
2263if (cmd_args->print_exports) {2264/* When this option is set we don't want to do anything else2265* except for printing & verifying the exports file.
2266*/
2267ret = 0;2268goto out;2269}2270
2271ctx->secure_mgmt = cmd_args->secure_mgmt;2272
2273if (ENABLE_DEBUG_MODE == cmd_args->debug_mode) {2274cmd_args->log_level = GF_LOG_DEBUG;2275cmd_args->log_file = gf_strdup("/dev/stderr");2276cmd_args->no_daemon_mode = ENABLE_NO_DAEMON_MODE;2277}2278
2279process_mode = gf_get_process_mode(argv[0]);2280ctx->process_mode = process_mode;2281
2282if (cmd_args->process_name) {2283ctx->cmd_args.process_name = cmd_args->process_name;2284}2285/* Make sure after the parsing cli, if '--volfile-server' option is2286given, then '--volfile-id' is mandatory */
2287if (cmd_args->volfile_server && !cmd_args->volfile_id) {2288gf_smsg("glusterfs", GF_LOG_CRITICAL, 0, glusterfsd_msg_15, NULL);2289ret = -1;2290goto out;2291}2292
2293if ((cmd_args->volfile_server == NULL) && (cmd_args->volfile == NULL)) {2294if (process_mode == GF_SERVER_PROCESS)2295cmd_args->volfile = gf_strdup(DEFAULT_SERVER_VOLFILE);2296else if (process_mode == GF_GLUSTERD_PROCESS)2297cmd_args->volfile = gf_strdup(DEFAULT_GLUSTERD_VOLFILE);2298else2299cmd_args->volfile = gf_strdup(DEFAULT_CLIENT_VOLFILE);2300
2301/* Check if the volfile exists, if not give usage output2302and exit */
2303ret = sys_stat(cmd_args->volfile, &stbuf);2304if (ret) {2305gf_smsg("glusterfs", GF_LOG_CRITICAL, errno, glusterfsd_msg_16,2306NULL);2307/* argp_usage (argp.) */2308fprintf(stderr, "USAGE: %s [options] [mountpoint]\n", argv[0]);2309goto out;2310}2311}2312
2313if (cmd_args->thin_client) {2314len = strlen(cmd_args->volfile_id) + SLEN("gfproxy-client/");2315thin_volfileid = GF_MALLOC(len + 1, gf_common_mt_char);2316snprintf(thin_volfileid, len + 1, "gfproxy-client/%s",2317cmd_args->volfile_id);2318GF_FREE(cmd_args->volfile_id);2319cmd_args->volfile_id = thin_volfileid;2320}2321
2322if (cmd_args->run_id) {2323ret = sys_lstat(cmd_args->log_file, &stbuf);2324/* If its /dev/null, or /dev/stdout, /dev/stderr,2325* let it use the same, no need to alter
2326*/
2327if (((ret == 0) &&2328(S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))) ||2329(ret == -1)) {2330/* Have separate logfile per run. */2331gf_time_fmt_FT(timestr, sizeof timestr, gf_time());2332sprintf(tmp_logfile, "%s.%s.%d", cmd_args->log_file, timestr,2333getpid());2334
2335/* Create symlink to actual log file */2336sys_unlink(cmd_args->log_file);2337
2338tmp_logfile_dyn = gf_strdup(tmp_logfile);2339tmp_logfilebase = basename(tmp_logfile_dyn);2340ret = sys_symlink(tmp_logfilebase, cmd_args->log_file);2341if (ret == -1) {2342fprintf(stderr, "ERROR: symlink of logfile failed\n");2343goto out;2344}2345
2346GF_FREE(cmd_args->log_file);2347cmd_args->log_file = gf_strdup(tmp_logfile);2348
2349GF_FREE(tmp_logfile_dyn);2350}2351}2352
2353/*2354This option was made obsolete but parsing it for backward
2355compatibility with third party applications
2356*/
2357if (cmd_args->max_connect_attempts) {2358gf_smsg("glusterfs", GF_LOG_WARNING, 0, glusterfsd_msg_33, NULL);2359}2360
2361#ifdef GF_DARWIN_HOST_OS2362if (cmd_args->mount_point)2363cmd_args->mac_compat = GF_OPTION_DEFERRED;2364#endif2365
2366ret = 0;2367out:2368return ret;2369}
2370
2371static int2372glusterfs_pidfile_setup(glusterfs_ctx_t *ctx)2373{
2374cmd_args_t *cmd_args = NULL;2375int ret = -1;2376FILE *pidfp = NULL;2377
2378cmd_args = &ctx->cmd_args;2379
2380if (!cmd_args->pid_file)2381return 0;2382
2383pidfp = fopen(cmd_args->pid_file, "a+");2384if (!pidfp) {2385gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_17,2386"pidfile=%s", cmd_args->pid_file, NULL);2387goto out;2388}2389
2390ctx->pidfp = pidfp;2391
2392ret = 0;2393out:2394
2395return ret;2396}
2397
2398static int2399glusterfs_pidfile_update(glusterfs_ctx_t *ctx, pid_t pid)2400{
2401cmd_args_t *cmd_args = NULL;2402int ret = 0;2403FILE *pidfp = NULL;2404
2405cmd_args = &ctx->cmd_args;2406
2407pidfp = ctx->pidfp;2408if (!pidfp)2409return 0;2410
2411ret = lockf(fileno(pidfp), F_TLOCK, 0);2412if (ret) {2413gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_18,2414"pidfile=%s", cmd_args->pid_file, NULL);2415return ret;2416}2417
2418ret = sys_ftruncate(fileno(pidfp), 0);2419if (ret) {2420gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_20,2421"pidfile=%s", cmd_args->pid_file, NULL);2422return ret;2423}2424
2425ret = fprintf(pidfp, "%d\n", pid);2426if (ret <= 0) {2427gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_21,2428"pidfile=%s", cmd_args->pid_file, NULL);2429return ret;2430}2431
2432ret = fflush(pidfp);2433if (ret) {2434gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_21,2435"pidfile=%s", cmd_args->pid_file, NULL);2436return ret;2437}2438
2439gf_msg_debug("glusterfsd", 0, "pidfile %s updated with pid %d",2440cmd_args->pid_file, pid);2441
2442return 0;2443}
2444
2445static void *2446glusterfs_sigwaiter(void *arg)2447{
2448sigset_t set;2449int ret = 0;2450int sig = 0;2451char *file = NULL;2452
2453sigemptyset(&set);2454sigaddset(&set, SIGINT); /* cleanup_and_exit */2455sigaddset(&set, SIGTERM); /* cleanup_and_exit */2456sigaddset(&set, SIGHUP); /* reincarnate */2457sigaddset(&set, SIGUSR1); /* gf_proc_dump_info */2458sigaddset(&set, SIGUSR2);2459
2460for (;;) {2461ret = sigwait(&set, &sig);2462if (ret)2463continue;2464
2465switch (sig) {2466case SIGINT:2467case SIGTERM:2468cleanup_and_exit(sig);2469break;2470case SIGHUP:2471reincarnate(sig);2472break;2473case SIGUSR1:2474gf_proc_dump_info(sig, glusterfsd_ctx);2475break;2476case SIGUSR2:2477file = gf_monitor_metrics(glusterfsd_ctx);2478
2479/* Nothing needed to be done here */2480GF_FREE(file);2481
2482break;2483default:2484
2485break;2486}2487}2488
2489return NULL;2490}
2491
2492static void2493glusterfsd_print_trace(int signum)2494{
2495gf_print_trace(signum, glusterfsd_ctx);2496}
2497
2498static int2499glusterfs_signals_setup(glusterfs_ctx_t *ctx)2500{
2501sigset_t set;2502int ret = 0;2503
2504sigemptyset(&set);2505
2506/* common setting for all threads */2507signal(SIGSEGV, glusterfsd_print_trace);2508signal(SIGABRT, glusterfsd_print_trace);2509signal(SIGILL, glusterfsd_print_trace);2510signal(SIGTRAP, glusterfsd_print_trace);2511signal(SIGFPE, glusterfsd_print_trace);2512signal(SIGBUS, glusterfsd_print_trace);2513signal(SIGINT, cleanup_and_exit);2514signal(SIGPIPE, SIG_IGN);2515
2516/* block these signals from non-sigwaiter threads */2517sigaddset(&set, SIGTERM); /* cleanup_and_exit */2518sigaddset(&set, SIGHUP); /* reincarnate */2519sigaddset(&set, SIGUSR1); /* gf_proc_dump_info */2520sigaddset(&set, SIGUSR2);2521
2522/* Signals needed for asynchronous framework. */2523sigaddset(&set, GF_ASYNC_SIGQUEUE);2524sigaddset(&set, GF_ASYNC_SIGCTRL);2525
2526ret = pthread_sigmask(SIG_BLOCK, &set, NULL);2527if (ret) {2528gf_smsg("glusterfsd", GF_LOG_WARNING, errno, glusterfsd_msg_22, NULL);2529return ret;2530}2531
2532ret = gf_thread_create(&ctx->sigwaiter, NULL, glusterfs_sigwaiter,2533(void *)&set, "sigwait");2534if (ret) {2535/*2536TODO:
2537fallback to signals getting handled by other threads.
2538setup the signal handlers
2539*/
2540gf_smsg("glusterfsd", GF_LOG_WARNING, errno, glusterfsd_msg_23, NULL);2541return ret;2542}2543
2544return ret;2545}
2546
2547static int2548daemonize(glusterfs_ctx_t *ctx)2549{
2550int ret = -1;2551cmd_args_t *cmd_args = NULL;2552int cstatus = 0;2553int err = 1;2554int child_pid = 0;2555
2556cmd_args = &ctx->cmd_args;2557
2558ret = glusterfs_pidfile_setup(ctx);2559if (ret)2560goto out;2561
2562if (cmd_args->no_daemon_mode) {2563goto postfork;2564}2565
2566if (cmd_args->debug_mode)2567goto postfork;2568
2569ret = pipe(ctx->daemon_pipe);2570if (ret) {2571/* If pipe() fails, retain daemon_pipe[] = {-1, -1}2572and parent will just not wait for child status
2573*/
2574ctx->daemon_pipe[0] = -1;2575ctx->daemon_pipe[1] = -1;2576}2577
2578ret = os_daemon_return(0, 0);2579switch (ret) {2580case -1:2581if (ctx->daemon_pipe[0] != -1) {2582sys_close(ctx->daemon_pipe[0]);2583sys_close(ctx->daemon_pipe[1]);2584}2585
2586gf_smsg("daemonize", GF_LOG_ERROR, errno, glusterfsd_msg_24, NULL);2587goto out;2588case 0:2589/* child */2590/* close read */2591sys_close(ctx->daemon_pipe[0]);2592break;2593default:2594/* parent */2595/* close write */2596child_pid = ret;2597sys_close(ctx->daemon_pipe[1]);2598
2599if (ctx->mnt_pid > 0) {2600ret = waitpid(ctx->mnt_pid, &cstatus, 0);2601if (!(ret == ctx->mnt_pid)) {2602if (WIFEXITED(cstatus)) {2603err = WEXITSTATUS(cstatus);2604} else {2605err = cstatus;2606}2607gf_smsg("daemonize", GF_LOG_ERROR, 0, glusterfsd_msg_25,2608NULL);2609exit(err);2610}2611}2612sys_read(ctx->daemon_pipe[0], (void *)&err, sizeof(err));2613/* NOTE: Only the least significant 8 bits i.e (err & 255)2614will be available to parent process on calling exit() */
2615if (err)2616_exit(abs(err));2617
2618/* Update pid in parent only for glusterd process */2619if (ctx->process_mode == GF_GLUSTERD_PROCESS) {2620ret = glusterfs_pidfile_update(ctx, child_pid);2621if (ret)2622exit(1);2623}2624_exit(0);2625}2626
2627postfork:2628/* Update pid in child either process_mode is not belong to glusterd2629or process is spawned in no daemon mode
2630*/
2631if ((ctx->process_mode != GF_GLUSTERD_PROCESS) ||2632(cmd_args->no_daemon_mode)) {2633ret = glusterfs_pidfile_update(ctx, getpid());2634if (ret)2635goto out;2636}2637gf_log("glusterfs", GF_LOG_INFO, "Pid of current running process is %d",2638getpid());2639ret = gf_log_inject_timer_event(ctx);2640
2641glusterfs_signals_setup(ctx);2642out:2643return ret;2644}
2645
2646#ifdef GF_LINUX_HOST_OS2647static int2648set_oom_score_adj(glusterfs_ctx_t *ctx)2649{
2650int ret = -1;2651cmd_args_t *cmd_args = NULL;2652int fd = -1;2653size_t oom_score_len = 0;2654struct oom_api_info *api = NULL;2655
2656cmd_args = &ctx->cmd_args;2657
2658if (!cmd_args->oom_score_adj)2659goto success;2660
2661api = get_oom_api_info();2662if (!api)2663goto out;2664
2665fd = open(api->oom_api_file, O_WRONLY);2666if (fd < 0)2667goto out;2668
2669oom_score_len = strlen(cmd_args->oom_score_adj);2670if (sys_write(fd, cmd_args->oom_score_adj, oom_score_len) !=2671oom_score_len) {2672sys_close(fd);2673goto out;2674}2675
2676if (sys_close(fd) < 0)2677goto out;2678
2679success:2680ret = 0;2681
2682out:2683return ret;2684}
2685#endif2686
2687int
2688glusterfs_process_volfp(glusterfs_ctx_t *ctx, FILE *fp)2689{
2690glusterfs_graph_t *graph = NULL;2691int ret = -1;2692xlator_t *trav = NULL;2693
2694if (!ctx)2695return -1;2696
2697graph = glusterfs_graph_construct(fp);2698if (!graph) {2699gf_smsg("", GF_LOG_ERROR, 0, glusterfsd_msg_26, NULL);2700goto out;2701}2702
2703for (trav = graph->first; trav; trav = trav->next) {2704if (strcmp(trav->type, "mount/fuse") == 0) {2705gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_27, NULL);2706goto out;2707}2708}2709
2710xlator_t *xl = graph->first;2711if (xl && (strcmp(xl->type, "protocol/server") == 0)) {2712(void)copy_opts_to_child(xl, FIRST_CHILD(xl), "*auth*");2713}2714
2715ret = glusterfs_graph_prepare(graph, ctx, ctx->cmd_args.volume_name);2716if (ret) {2717goto out;2718}2719
2720ret = glusterfs_graph_activate(graph, ctx);2721
2722if (ret) {2723goto out;2724}2725
2726gf_log_dump_graph(fp, graph);2727
2728ret = 0;2729out:2730if (fp)2731fclose(fp);2732
2733if (ret) {2734/* TODO This code makes to generic for all graphs2735client as well as servers.For now it destroys
2736graph only for server-side xlators not for client-side
2737xlators, before destroying a graph call xlator fini for
2738xlators those call xlator_init to avoid leak
2739*/
2740if (graph) {2741xl = graph->first;2742if ((ctx->active != graph) &&2743(xl && !strcmp(xl->type, "protocol/server"))) {2744/* Take dict ref for every graph xlator to avoid dict leak2745at the time of graph destroying
2746*/
2747glusterfs_graph_fini(graph);2748glusterfs_graph_destroy(graph);2749}2750}2751
2752/* there is some error in setting up the first graph itself */2753if (!ctx->active) {2754emancipate(ctx, ret);2755cleanup_and_exit(ret);2756}2757}2758
2759return ret;2760}
2761
2762static int2763glusterfs_volumes_init(glusterfs_ctx_t *ctx)2764{
2765cmd_args_t *cmd_args = NULL;2766int ret = 0;2767
2768cmd_args = &ctx->cmd_args;2769
2770if (cmd_args->sock_file) {2771ret = glusterfs_listener_init(ctx);2772if (ret)2773goto out;2774}2775
2776if (cmd_args->volfile_server) {2777ret = glusterfs_mgmt_init(ctx);2778/* return, do not emancipate() yet */2779return ret;2780}2781
2782ret = volfile_init(ctx);2783out:2784emancipate(ctx, ret);2785return ret;2786}
2787
2788/* This is the only legal global pointer */
2789glusterfs_ctx_t *glusterfsd_ctx;2790
2791GF_IO_ASYNC(main_terminate, op, static)2792{
2793// glusterfs_ctx_destroy (ctx);2794gf_async_fini();2795
2796return 0;2797}
2798
2799GF_IO_ASYNC(main_start, op, static)2800{
2801int32_t res;2802
2803mem_pools_init();2804
2805/* TODO: gf_async support should be removed once the I/O framework2806* supports multithreaded I/O without io_uring. */
2807res = gf_async_init(global_ctx);2808if (res < 0) {2809goto out;2810}2811
2812#ifdef GF_LINUX_HOST_OS2813res = set_oom_score_adj(global_ctx);2814if (res)2815goto out;2816#endif2817
2818global_ctx->env = syncenv_new(0, 0, 0);2819if (!global_ctx->env) {2820gf_smsg("", GF_LOG_ERROR, 0, glusterfsd_msg_31, NULL);2821res = -1;2822goto out;2823}2824
2825if (!glusterfs_ctx_tw_get(global_ctx)) {2826res = -1;2827goto out;2828}2829
2830res = glusterfs_volumes_init(global_ctx);2831if (res)2832goto out;2833
2834return 0;2835
2836out:2837// glusterfs_ctx_destroy (global_ctx);2838gf_async_fini();2839
2840/* TODO: 'res' should be a negative error code instead of -1. */2841
2842return res;2843}
2844
2845int
2846main(int argc, char *argv[])2847{
2848gf_io_handlers_t main_handlers = {.setup = main_start,2849.cleanup = main_terminate};2850glusterfs_ctx_t *ctx = NULL;2851int ret = -1;2852char cmdlinestr[PATH_MAX] = {28530,2854};2855cmd_args_t *cmd = NULL;2856
2857gf_check_and_set_mem_acct(argc, argv);2858
2859ctx = glusterfs_ctx_new();2860if (!ctx) {2861gf_smsg("glusterfs", GF_LOG_CRITICAL, 0, glusterfsd_msg_29, NULL);2862return ENOMEM;2863}2864glusterfsd_ctx = ctx;2865
2866ret = glusterfs_globals_init(ctx);2867if (ret)2868return ret;2869
2870THIS->ctx = ctx;2871
2872ret = glusterfs_ctx_defaults_init(ctx);2873if (ret)2874goto out;2875
2876ret = parse_cmdline(argc, argv, ctx);2877if (ret)2878goto out;2879cmd = &ctx->cmd_args;2880
2881if (cmd->print_xlatordir) {2882/* XLATORDIR passed through a -D flag to GCC */2883printf("%s\n", XLATORDIR);2884goto out;2885}2886
2887if (cmd->print_statedumpdir) {2888printf("%s\n", DEFAULT_VAR_RUN_DIRECTORY);2889goto out;2890}2891
2892if (cmd->print_logdir) {2893printf("%s\n", DEFAULT_LOG_FILE_DIRECTORY);2894goto out;2895}2896
2897if (cmd->print_libexecdir) {2898printf("%s\n", LIBEXECDIR);2899goto out;2900}2901
2902#ifdef BUILD_GNFS2903if (cmd->print_netgroups) {2904/* If this option is set we want to print & verify the file,2905* set the return value (exit code in this case) and exit.
2906*/
2907ret = print_netgroups_file(cmd->print_netgroups);2908goto out;2909}2910
2911if (cmd->print_exports) {2912/* If this option is set we want to print & verify the file,2913* set the return value (exit code in this case)
2914* and exit.
2915*/
2916ret = print_exports_file(cmd->print_exports);2917goto out;2918}2919
2920#endif2921ret = logging_init(ctx, argv[0]);2922if (ret)2923goto out;2924
2925/* set brick_mux mode only for server process */2926if ((ctx->process_mode != GF_SERVER_PROCESS) && cmd->brick_mux) {2927gf_smsg("glusterfs", GF_LOG_CRITICAL, 0, glusterfsd_msg_43, NULL);2928goto out;2929}2930
2931/* log the version of glusterfs running here along with the actual2932command line options. */
2933{2934int i = 0;2935int pos = 0;2936int len = snprintf(cmdlinestr, sizeof(cmdlinestr), "%s", argv[0]);2937for (i = 1; (i < argc) && (len > 0); i++) {2938pos += len;2939len = snprintf(cmdlinestr + pos, sizeof(cmdlinestr) - pos, " %s",2940argv[i]);2941if ((len <= 0) || (len >= (sizeof(cmdlinestr) - pos))) {2942gf_smsg("glusterfs", GF_LOG_ERROR, 0, glusterfsd_msg_029, NULL);2943ret = -1;2944goto out;2945}2946}2947gf_smsg(argv[0], GF_LOG_INFO, 0, glusterfsd_msg_30, "arg=%s", argv[0],2948"version=%s", PACKAGE_VERSION, "cmdlinestr=%s", cmdlinestr,2949NULL);2950
2951ctx->cmdlinestr = gf_strdup(cmdlinestr);2952}2953
2954gf_proc_dump_init();2955
2956ret = create_fuse_mount(ctx);2957if (ret)2958goto out;2959
2960ret = daemonize(ctx);2961if (ret)2962goto out;2963
2964/* Before 'daemonize()' there are no threads started because they would2965* not be cloned into the child process and would die with the parent.
2966* After this point, there are several initialization functions that
2967* can start additional threads. Let's call them from inside the I/O
2968* framework context so that they can decide if a new thread is needed
2969* or use the I/O framework for the functionalities they need. */
2970ret = gf_io_run(cmd->io_engine, &main_handlers, NULL);2971
2972out:2973return ret;2974}
2975