"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.6/glusterfsd/src/glusterfsd.c" (20 Aug 2021, 83745 Bytes) of package /linux/misc/glusterfs-8.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glusterfsd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.5_vs_8.6.

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