glusterfs

Форк
0
/
glusterfsd.c 
2974 строки · 90.3 Кб
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 <sys/wait.h>
14
#include <dlfcn.h>
15
#include <pthread.h>
16
#include <errno.h>
17
#include <pwd.h>
18

19
#ifdef GF_LINUX_HOST_OS
20
#ifdef HAVE_LINUX_OOM_H
21
#include <linux/oom.h>
22
#else
23
#define OOM_SCORE_ADJ_MIN (-1000)
24
#define OOM_SCORE_ADJ_MAX 1000
25
#define OOM_DISABLE (-17)
26
#define OOM_ADJUST_MAX 15
27
#endif
28
#endif
29

30
#ifdef HAVE_MALLOC_H
31
#include <malloc.h>
32
#endif
33

34
#include <glusterfs/compat.h>
35
#include <glusterfs/logging.h>
36
#include "glusterfsd-messages.h"
37
#include <glusterfs/dict.h>
38
#include <glusterfs/list.h>
39
#include <glusterfs/timer.h>
40
#include <glusterfs/revision.h>
41
#include <glusterfs/gf-event.h>
42
#include <glusterfs/statedump.h>
43
#include <glusterfs/latency.h>
44
#include "glusterfsd-mem-types.h"
45
#include <glusterfs/syscall.h>
46
#include <glusterfs/syncop.h>
47
#include <glusterfs/client_t.h>
48
#include <glusterfs/monitoring.h>
49
#include <glusterfs/gf-io.h>
50
#include <glusterfs/daemon.h>
51

52
#include "glusterfsd.h"
53
#include "rpc-clnt.h"
54
#include "netgroups.h"
55
#include "exports.h"
56

57
/* using argp for command line parsing */
58
static char gf_doc[] = "";
59
static char argp_doc[] =
60
    "--volfile-server=SERVER [MOUNT-POINT]\n"
61
    "--volfile=VOLFILE [MOUNT-POINT]";
62
const char *argp_program_version =
63
    "" PACKAGE_NAME " " PACKAGE_VERSION
64
    "\nRepository revision: " GLUSTERFS_REPOSITORY_REVISION
65
    "\n"
66
    "Copyright (c) 2006-2016 Red Hat, Inc. "
67
    "<https://www.gluster.org/>\n"
68
    "GlusterFS comes with ABSOLUTELY NO WARRANTY.\n"
69
    "It is licensed to you under your choice of the GNU Lesser\n"
70
    "General Public License, version 3 or any later version (LGPLv3\n"
71
    "or later), or the GNU General Public License, version 2 (GPLv2),\n"
72
    "in all cases as published by the Free Software Foundation.";
73
const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
74

75
static error_t
76
parse_opts(int32_t key, char *arg, struct argp_state *_state);
77

78
static struct argp_option gf_options[] = {
79
    {0, 0, 0, 0, "Basic options:"},
80
    {"volfile-server", ARGP_VOLFILE_SERVER_KEY, "SERVER", 0,
81
     "Server to get the volume file from. Unix domain socket path when "
82
     "transport type 'unix'. This option overrides --volfile option"},
83
    {"volfile", ARGP_VOLUME_FILE_KEY, "VOLFILE", 0,
84
     "File to use as VOLUME_FILE"},
85
    {"spec-file", ARGP_VOLUME_FILE_KEY, "VOLFILE", OPTION_HIDDEN,
86
     "File to use as VOLUME FILE"},
87

88
    {"log-level", ARGP_LOG_LEVEL_KEY, "LOGLEVEL", 0,
89
     "Logging severity.  Valid options are DEBUG, INFO, WARNING, ERROR, "
90
     "CRITICAL, TRACE and NONE [default: INFO]"},
91
    {"log-file", ARGP_LOG_FILE_KEY, "LOGFILE", 0,
92
     "File to use for logging [default: " DEFAULT_LOG_FILE_DIRECTORY
93
     "/" PACKAGE_NAME ".log"
94
     "]"},
95
    {"logger", ARGP_LOGGER, "LOGGER", 0,
96
     "Set which logging sub-system to "
97
     "log to, valid options are: gluster-log and syslog, "
98
     "[default: \"gluster-log\"]"},
99
    {"log-format", ARGP_LOG_FORMAT, "LOG-FORMAT", 0,
100
     "Set log format, valid"
101
     " options are: no-msg-id and with-msg-id, [default: \"with-msg-id\"]"},
102
    {"log-buf-size", ARGP_LOG_BUF_SIZE, "LOG-BUF-SIZE", 0,
103
     "Set logging "
104
     "buffer size, [default: 5]"},
105
    {"log-flush-timeout", ARGP_LOG_FLUSH_TIMEOUT, "LOG-FLUSH-TIMEOUT", 0,
106
     "Set log flush timeout, [default: 2 minutes]"},
107

108
    {0, 0, 0, 0, "Advanced Options:"},
109
    {"volfile-server-port", ARGP_VOLFILE_SERVER_PORT_KEY, "PORT", 0,
110
     "Listening port number of volfile server"},
111
    {"volfile-server-transport", ARGP_VOLFILE_SERVER_TRANSPORT_KEY, "TRANSPORT",
112
     0, "Transport type to get volfile from server [default: socket]"},
113
    {"volfile-id", ARGP_VOLFILE_ID_KEY, "KEY", 0,
114
     "'key' of the volfile to be fetched from server"},
115
    {"pid-file", ARGP_PID_FILE_KEY, "PIDFILE", 0, "File to use as pid file"},
116
    {"socket-file", ARGP_SOCK_FILE_KEY, "SOCKFILE", 0,
117
     "File to use as unix-socket"},
118
    {"no-daemon", ARGP_NO_DAEMON_KEY, 0, 0, "Run in foreground"},
119
    {"run-id", ARGP_RUN_ID_KEY, "RUN-ID", OPTION_HIDDEN,
120
     "Run ID for the process, used by scripts to keep track of process "
121
     "they started, defaults to none"},
122
    {"debug", ARGP_DEBUG_KEY, 0, 0,
123
     "Run in debug mode.  This option sets --no-daemon, --log-level "
124
     "to DEBUG and --log-file to console"},
125
    {"volume-name", ARGP_VOLUME_NAME_KEY, "XLATOR-NAME", 0,
126
     "Translator name to be used for MOUNT-POINT [default: top most volume "
127
     "definition in VOLFILE]"},
128
    {"xlator-option", ARGP_XLATOR_OPTION_KEY, "XLATOR-NAME.OPTION=VALUE", 0,
129
     "Add/override an option for a translator in volume file with specified"
130
     " value"},
131
    {"read-only", ARGP_READ_ONLY_KEY, 0, 0,
132
     "Mount the filesystem in 'read-only' mode"},
133
    {"acl", ARGP_ACL_KEY, 0, 0, "Mount the filesystem with POSIX ACL support"},
134
    {"selinux", ARGP_SELINUX_KEY, 0, 0,
135
     "Enable SELinux label (extended attributes) support on inodes"},
136
    {"capability", ARGP_CAPABILITY_KEY, 0, 0,
137
     "Enable Capability (extended attributes) support on inodes"},
138
    {"subdir-mount", ARGP_SUBDIR_MOUNT_KEY, "SUBDIR-PATH", 0,
139
     "Mount subdirectory given [default: NULL]"},
140

141
    {"print-netgroups", ARGP_PRINT_NETGROUPS, "NETGROUP-FILE", 0,
142
     "Validate the netgroups file and print it out"},
143
    {"print-exports", ARGP_PRINT_EXPORTS, "EXPORTS-FILE", 0,
144
     "Validate the exports file and print it out"},
145
    {"print-xlatordir", ARGP_PRINT_XLATORDIR_KEY, 0, OPTION_ARG_OPTIONAL,
146
     "Print xlator directory path"},
147
    {"print-statedumpdir", ARGP_PRINT_STATEDUMPDIR_KEY, 0, OPTION_ARG_OPTIONAL,
148
     "Print directory path in which statedumps shall be generated"},
149
    {"print-logdir", ARGP_PRINT_LOGDIR_KEY, 0, OPTION_ARG_OPTIONAL,
150
     "Print path of default log directory"},
151
    {"print-libexecdir", ARGP_PRINT_LIBEXECDIR_KEY, 0, OPTION_ARG_OPTIONAL,
152
     "Print path of default libexec directory"},
153

154
    {"volfile-max-fetch-attempts", ARGP_VOLFILE_MAX_FETCH_ATTEMPTS, "0",
155
     OPTION_HIDDEN, "Maximum number of attempts to fetch the volfile"},
156
    {"aux-gfid-mount", ARGP_AUX_GFID_MOUNT_KEY, 0, 0,
157
     "Enable access to filesystem through gfid directly"},
158
    {"enable-ino32", ARGP_INODE32_KEY, "BOOL", OPTION_ARG_OPTIONAL,
159
     "Use 32-bit inodes when mounting to workaround broken applications"
160
     "that don't support 64-bit inodes"},
161
    {"worm", ARGP_WORM_KEY, 0, 0, "Mount the filesystem in 'worm' mode"},
162
    {"mac-compat", ARGP_MAC_COMPAT_KEY, "BOOL", OPTION_ARG_OPTIONAL,
163
     "Provide stubs for attributes needed for seamless operation on Macs "
164
#ifdef GF_DARWIN_HOST_OS
165
     "[default: \"on\" on client side, else \"off\"]"
166
#else
167
     "[default: \"off\"]"
168
#endif
169
    },
170
    {"brick-name", ARGP_BRICK_NAME_KEY, "BRICK-NAME", OPTION_HIDDEN,
171
     "Brick name to be registered with Gluster portmapper"},
172
    {"brick-port", ARGP_BRICK_PORT_KEY, "BRICK-PORT", OPTION_HIDDEN,
173
     "Brick Port to be registered with Gluster portmapper"},
174
    {"fopen-keep-cache", ARGP_FOPEN_KEEP_CACHE_KEY, "BOOL", OPTION_ARG_OPTIONAL,
175
     "Do not purge the cache on file open [default: false]"},
176
    {"global-timer-wheel", ARGP_GLOBAL_TIMER_WHEEL, "BOOL", OPTION_ARG_OPTIONAL,
177
     "Instantiate process global timer-wheel"},
178
    {"thin-client", ARGP_THIN_CLIENT_KEY, 0, 0,
179
     "Enables thin mount and connects via gfproxyd daemon"},
180
    {"global-threading", ARGP_GLOBAL_THREADING_KEY, "BOOL", OPTION_ARG_OPTIONAL,
181
     "Use the global thread pool instead of io-threads"},
182
    {0, 0, 0, 0, "Fuse options:"},
183
    {"direct-io-mode", ARGP_DIRECT_IO_MODE_KEY, "BOOL|auto",
184
     OPTION_ARG_OPTIONAL, "Specify direct I/O strategy [default: \"auto\"]"},
185
    {"entry-timeout", ARGP_ENTRY_TIMEOUT_KEY, "SECONDS", 0,
186
     "Set entry timeout to SECONDS in fuse kernel module [default: 1]"},
187
    {"negative-timeout", ARGP_NEGATIVE_TIMEOUT_KEY, "SECONDS", 0,
188
     "Set negative timeout to SECONDS in fuse kernel module [default: 0]"},
189
    {"attribute-timeout", ARGP_ATTRIBUTE_TIMEOUT_KEY, "SECONDS", 0,
190
     "Set attribute timeout to SECONDS for inodes in fuse kernel module "
191
     "[default: 1]"},
192
    {"gid-timeout", ARGP_GID_TIMEOUT_KEY, "SECONDS", 0,
193
     "Set auxiliary group list timeout to SECONDS for fuse translator "
194
     "[default: 300]"},
195
    {"resolve-gids", ARGP_RESOLVE_GIDS_KEY, 0, 0,
196
     "Resolve all auxiliary groups in fuse translator (max 32 otherwise)"},
197
    {"lru-limit", ARGP_FUSE_LRU_LIMIT_KEY, "N", 0,
198
     "Set fuse module's limit for number of inodes kept in LRU list to N "
199
     "[default: 65536]"},
200
    {"inode-table-size", ARGP_FUSE_INODE_TABLESIZE_KEY, "N", 0,
201
     "Set the inode hash table size to N - this must be a power of 2 and "
202
     "will be rounded up if not [default: 65536]"},
203
    {"invalidate-limit", ARGP_FUSE_INVALIDATE_LIMIT_KEY, "N", 0,
204
     "Suspend inode invalidations implied by 'lru-limit' if the number of "
205
     "outstanding invalidations reaches N"},
206
    {"background-qlen", ARGP_FUSE_BACKGROUND_QLEN_KEY, "N", 0,
207
     "Set fuse module's background queue length to N "
208
     "[default: 64]"},
209
    {"congestion-threshold", ARGP_FUSE_CONGESTION_THRESHOLD_KEY, "N", 0,
210
     "Set fuse module's congestion threshold to N "
211
     "[default: 48]"},
212
#ifdef GF_LINUX_HOST_OS
213
    {"oom-score-adj", ARGP_OOM_SCORE_ADJ_KEY, "INTEGER", 0,
214
     "Set oom_score_adj value for process"
215
     "[default: 0]"},
216
#endif
217
    {"client-pid", ARGP_CLIENT_PID_KEY, "PID", OPTION_HIDDEN,
218
     "client will authenticate itself with process id PID to server"},
219
    {"no-root-squash", ARGP_FUSE_NO_ROOT_SQUASH_KEY, "BOOL",
220
     OPTION_ARG_OPTIONAL,
221
     "disable/enable root squashing for the trusted "
222
     "client"},
223
    {"user-map-root", ARGP_USER_MAP_ROOT_KEY, "USER", OPTION_HIDDEN,
224
     "replace USER with root in messages"},
225
    {"dump-fuse", ARGP_DUMP_FUSE_KEY, "PATH", 0, "Dump fuse traffic to PATH"},
226
    {"volfile-check", ARGP_VOLFILE_CHECK_KEY, 0, 0,
227
     "Enable strict volume file checking"},
228
    {"no-mem-accounting", ARGP_MEM_ACCOUNTING_KEY, 0, OPTION_HIDDEN,
229
     "disable internal memory accounting"},
230
    {"fuse-mountopts", ARGP_FUSE_MOUNTOPTS_KEY, "OPTIONS", OPTION_HIDDEN,
231
     "Extra mount options to pass to FUSE"},
232
    {"use-readdirp", ARGP_FUSE_USE_READDIRP_KEY, "BOOL", OPTION_ARG_OPTIONAL,
233
     "Use readdirp mode in fuse kernel module"
234
     " [default: \"yes\"]"},
235
    {"secure-mgmt", ARGP_SECURE_MGMT_KEY, "BOOL", OPTION_ARG_OPTIONAL,
236
     "Override default for secure (SSL) management connections"},
237
    {"localtime-logging", ARGP_LOCALTIME_LOGGING_KEY, 0, 0,
238
     "Enable localtime logging"},
239
    {"process-name", ARGP_PROCESS_NAME_KEY, "PROCESS-NAME", OPTION_HIDDEN,
240
     "option to specify the process type"},
241
    {"event-history", ARGP_FUSE_EVENT_HISTORY_KEY, "BOOL", OPTION_ARG_OPTIONAL,
242
     "disable/enable fuse event-history"},
243
    {"reader-thread-count", ARGP_READER_THREAD_COUNT_KEY, "INTEGER",
244
     OPTION_ARG_OPTIONAL, "set fuse reader thread count"},
245
    {"kernel-writeback-cache", ARGP_KERNEL_WRITEBACK_CACHE_KEY, "BOOL",
246
     OPTION_ARG_OPTIONAL, "enable fuse in-kernel writeback cache"},
247
    {"attr-times-granularity", ARGP_ATTR_TIMES_GRANULARITY_KEY, "NS",
248
     OPTION_ARG_OPTIONAL,
249
     "declare supported granularity of file attribute"
250
     " times in nanoseconds"},
251
    {"fuse-flush-handle-interrupt", ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY,
252
     "BOOL", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
253
     "handle interrupt in fuse FLUSH handler"},
254
    {"fuse-setlk-handle-interrupt", ARGP_FUSE_SETLK_HANDLE_INTERRUPT_KEY,
255
     "BOOL", OPTION_ARG_OPTIONAL, "handle interrupt in fuse SETLK handler"},
256
    {"auto-invalidation", ARGP_FUSE_AUTO_INVAL_KEY, "BOOL", OPTION_ARG_OPTIONAL,
257
     "controls whether fuse-kernel can auto-invalidate "
258
     "attribute, dentry and page-cache. "
259
     "Disable this only if same files/directories are not accessed across "
260
     "two different mounts concurrently [default: \"on\"]"},
261
    {"fuse-dev-eperm-ratelimit-ns", ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY,
262
     "OPTIONS", OPTION_HIDDEN,
263
     "rate limit reading from fuse device upon EPERM failure"},
264
    {"fs-display-name", ARGP_FUSE_DISPLAY_NAME_KEY, "DISPLAY-NAME",
265
     OPTION_HIDDEN,
266
     "Filesystem display name, shown with mount point (as source). Used with "
267
     "commands like 'mount', 'df', etc."},
268
    {"brick-mux", ARGP_BRICK_MUX_KEY, 0, 0, "Enable brick mux. "},
269
    {"io-engine", ARGP_IO_ENGINE_KEY, "ENGINE", OPTION_ARG_OPTIONAL,
270
     "force utilization of the given I/O ENGINE"},
271
    {"fuse-handle-copy_file_range", ARGP_FUSE_HANDLE_COPY_FILE_RANGE, "BOOL",
272
     OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
273
     "enable the handler of the FUSE_COPY_FILE_RANGE message"},
274
    {0, 0, 0, 0, "Miscellaneous Options:"},
275
    {
276
        0,
277
    }};
278

279
static struct argp argp = {gf_options, parse_opts, argp_doc, gf_doc};
280

281
static void
282
glusterfs_pidfile_cleanup(glusterfs_ctx_t *ctx)
283
{
284
    cmd_args_t *cmd_args = NULL;
285

286
    cmd_args = &ctx->cmd_args;
287

288
    if (!ctx->pidfp)
289
        return;
290

291
    gf_msg_trace("glusterfsd", 0, "pidfile %s cleanup", cmd_args->pid_file);
292

293
    if (ctx->cmd_args.pid_file) {
294
        GF_FREE(ctx->cmd_args.pid_file);
295
        ctx->cmd_args.pid_file = NULL;
296
    }
297

298
    lockf(fileno(ctx->pidfp), F_ULOCK, 0);
299
    fclose(ctx->pidfp);
300
    ctx->pidfp = NULL;
301
}
302

303
#define DICT_SET_VAL(method, dict, key, val, msgid)                            \
304
    if (method(dict, key, val)) {                                              \
305
        gf_smsg("glusterfsd", GF_LOG_ERROR, 0, msgid, "key=%s", key);          \
306
        goto err;                                                              \
307
    }
308

309
static int
310
set_fuse_mount_options(glusterfs_ctx_t *ctx, dict_t *options)
311
{
312
    int ret = 0;
313
    cmd_args_t *cmd_args = NULL;
314
    char *mount_point = NULL;
315
    char cwd[PATH_MAX] = {
316
        0,
317
    };
318

319
    cmd_args = &ctx->cmd_args;
320

321
    /* Check if mount-point is absolute path,
322
     * if not convert to absolute path by concatenating with CWD
323
     */
324
    if (cmd_args->mount_point[0] != '/') {
325
        if (getcwd(cwd, PATH_MAX) != NULL) {
326
            ret = gf_asprintf(&mount_point, "%s/%s", cwd,
327
                              cmd_args->mount_point);
328
            if (ret == -1) {
329
                gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_1,
330
                        "gf_asprintf failed", NULL);
331
                goto err;
332
            }
333
        } else {
334
            gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_2,
335
                    "getcwd failed", NULL);
336
            goto err;
337
        }
338

339
    } else {
340
        mount_point = gf_strdup(cmd_args->mount_point);
341
    }
342
    DICT_SET_VAL(dict_set_dynstr_sizen, options, ZR_MOUNTPOINT_OPT, mount_point,
343
                 glusterfsd_msg_3);
344

345
    if (cmd_args->fuse_attribute_timeout >= 0) {
346
        DICT_SET_VAL(dict_set_double, options, ZR_ATTR_TIMEOUT_OPT,
347
                     cmd_args->fuse_attribute_timeout, glusterfsd_msg_3);
348
    }
349

350
    if (cmd_args->fuse_entry_timeout >= 0) {
351
        DICT_SET_VAL(dict_set_double, options, ZR_ENTRY_TIMEOUT_OPT,
352
                     cmd_args->fuse_entry_timeout, glusterfsd_msg_3);
353
    }
354

355
    if (cmd_args->fuse_negative_timeout >= 0) {
356
        DICT_SET_VAL(dict_set_double, options, ZR_NEGATIVE_TIMEOUT_OPT,
357
                     cmd_args->fuse_negative_timeout, glusterfsd_msg_3);
358
    }
359

360
    if (cmd_args->client_pid_set) {
361
        DICT_SET_VAL(dict_set_int32_sizen, options, "client-pid",
362
                     cmd_args->client_pid, glusterfsd_msg_3);
363
    }
364

365
    if (cmd_args->uid_map_root) {
366
        DICT_SET_VAL(dict_set_int32_sizen, options, "uid-map-root",
367
                     cmd_args->uid_map_root, glusterfsd_msg_3);
368
    }
369

370
    if (cmd_args->volfile_check) {
371
        DICT_SET_VAL(dict_set_int32_sizen, options, ZR_STRICT_VOLFILE_CHECK,
372
                     cmd_args->volfile_check, glusterfsd_msg_3);
373
    }
374

375
    if (cmd_args->dump_fuse) {
376
        DICT_SET_VAL(dict_set_static_ptr, options, ZR_DUMP_FUSE,
377
                     cmd_args->dump_fuse, glusterfsd_msg_3);
378
    }
379

380
    if (cmd_args->acl) {
381
        DICT_SET_VAL(dict_set_static_ptr, options, "acl", "on",
382
                     glusterfsd_msg_3);
383
    }
384

385
    if (cmd_args->selinux) {
386
        DICT_SET_VAL(dict_set_static_ptr, options, "selinux", "on",
387
                     glusterfsd_msg_3);
388
    }
389

390
    if (cmd_args->capability) {
391
        DICT_SET_VAL(dict_set_static_ptr, options, "capability", "on",
392
                     glusterfsd_msg_3);
393
    }
394

395
    if (cmd_args->aux_gfid_mount) {
396
        DICT_SET_VAL(dict_set_static_ptr, options, "virtual-gfid-access", "on",
397
                     glusterfsd_msg_3);
398
    }
399

400
    if (cmd_args->enable_ino32) {
401
        DICT_SET_VAL(dict_set_static_ptr, options, "enable-ino32", "on",
402
                     glusterfsd_msg_3);
403
    }
404

405
    if (cmd_args->read_only) {
406
        DICT_SET_VAL(dict_set_static_ptr, options, "read-only", "on",
407
                     glusterfsd_msg_3);
408
    }
409

410
    switch (cmd_args->fopen_keep_cache) {
411
        case GF_OPTION_ENABLE:
412

413
            DICT_SET_VAL(dict_set_static_ptr, options, "fopen-keep-cache", "on",
414
                         glusterfsd_msg_3);
415
            break;
416
        case GF_OPTION_DISABLE:
417
            DICT_SET_VAL(dict_set_static_ptr, options, "fopen-keep-cache",
418
                         "off", glusterfsd_msg_3);
419
            break;
420
        default:
421
            gf_msg_debug("glusterfsd", 0, "fopen-keep-cache mode %d",
422
                         cmd_args->fopen_keep_cache);
423
            break;
424
    }
425

426
    if (cmd_args->gid_timeout_set) {
427
        DICT_SET_VAL(dict_set_int32_sizen, options, "gid-timeout",
428
                     cmd_args->gid_timeout, glusterfsd_msg_3);
429
    }
430

431
    if (cmd_args->resolve_gids) {
432
        DICT_SET_VAL(dict_set_static_ptr, options, "resolve-gids", "on",
433
                     glusterfsd_msg_3);
434
    }
435

436
    if (cmd_args->lru_limit >= 0) {
437
        DICT_SET_VAL(dict_set_int32_sizen, options, "lru-limit",
438
                     cmd_args->lru_limit, glusterfsd_msg_3);
439
    }
440

441
    if (cmd_args->inode_table_size >= 0) {
442
        DICT_SET_VAL(dict_set_int32_sizen, options, "inode-table-size",
443
                     cmd_args->inode_table_size, glusterfsd_msg_3);
444
    }
445

446
    if (cmd_args->invalidate_limit >= 0) {
447
        DICT_SET_VAL(dict_set_int32_sizen, options, "invalidate-limit",
448
                     cmd_args->invalidate_limit, glusterfsd_msg_3);
449
    }
450

451
    if (cmd_args->background_qlen) {
452
        DICT_SET_VAL(dict_set_int32_sizen, options, "background-qlen",
453
                     cmd_args->background_qlen, glusterfsd_msg_3);
454
    }
455
    if (cmd_args->congestion_threshold) {
456
        DICT_SET_VAL(dict_set_int32_sizen, options, "congestion-threshold",
457
                     cmd_args->congestion_threshold, glusterfsd_msg_3);
458
    }
459

460
    switch (cmd_args->fuse_direct_io_mode) {
461
        case GF_OPTION_DISABLE: /* disable */
462
            DICT_SET_VAL(dict_set_static_ptr, options, ZR_DIRECT_IO_OPT,
463
                         "disable", glusterfsd_msg_3);
464
            break;
465
        case GF_OPTION_ENABLE: /* enable */
466
            DICT_SET_VAL(dict_set_static_ptr, options, ZR_DIRECT_IO_OPT,
467
                         "enable", glusterfsd_msg_3);
468
            break;
469
        default:
470
            gf_msg_debug("glusterfsd", 0, "fuse direct io type %d",
471
                         cmd_args->fuse_direct_io_mode);
472
            break;
473
    }
474

475
    switch (cmd_args->no_root_squash) {
476
        case GF_OPTION_ENABLE: /* enable */
477
            DICT_SET_VAL(dict_set_static_ptr, options, "no-root-squash",
478
                         "enable", glusterfsd_msg_3);
479
            break;
480
        default:
481
            DICT_SET_VAL(dict_set_static_ptr, options, "no-root-squash",
482
                         "disable", glusterfsd_msg_3);
483
            gf_msg_debug("glusterfsd", 0, "fuse no-root-squash mode %d",
484
                         cmd_args->no_root_squash);
485
            break;
486
    }
487

488
    if (!cmd_args->no_daemon_mode) {
489
        DICT_SET_VAL(dict_set_static_ptr, options, "sync-to-mount", "enable",
490
                     glusterfsd_msg_3);
491
    }
492

493
    if (cmd_args->use_readdirp) {
494
        DICT_SET_VAL(dict_set_static_ptr, options, "use-readdirp",
495
                     cmd_args->use_readdirp, glusterfsd_msg_3);
496
    }
497
    if (cmd_args->event_history) {
498
        ret = dict_set_str(options, "event-history", cmd_args->event_history);
499
        DICT_SET_VAL(dict_set_static_ptr, options, "event-history",
500
                     cmd_args->event_history, glusterfsd_msg_3);
501
    }
502
    if (cmd_args->thin_client) {
503
        DICT_SET_VAL(dict_set_static_ptr, options, "thin-client", "on",
504
                     glusterfsd_msg_3);
505
    }
506
    if (cmd_args->reader_thread_count) {
507
        DICT_SET_VAL(dict_set_uint32, options, "reader-thread-count",
508
                     cmd_args->reader_thread_count, glusterfsd_msg_3);
509
    }
510

511
    DICT_SET_VAL(dict_set_uint32, options, "auto-invalidation",
512
                 cmd_args->fuse_auto_inval, glusterfsd_msg_3);
513

514
    switch (cmd_args->kernel_writeback_cache) {
515
        case GF_OPTION_ENABLE:
516
            DICT_SET_VAL(dict_set_static_ptr, options, "kernel-writeback-cache",
517
                         "on", glusterfsd_msg_3);
518
            break;
519
        case GF_OPTION_DISABLE:
520
            DICT_SET_VAL(dict_set_static_ptr, options, "kernel-writeback-cache",
521
                         "off", glusterfsd_msg_3);
522
            break;
523
        default:
524
            gf_msg_debug("glusterfsd", 0, "kernel-writeback-cache mode %d",
525
                         cmd_args->kernel_writeback_cache);
526
            break;
527
    }
528
    if (cmd_args->attr_times_granularity) {
529
        DICT_SET_VAL(dict_set_uint32, options, "attr-times-granularity",
530
                     cmd_args->attr_times_granularity, glusterfsd_msg_3);
531
    }
532
    switch (cmd_args->fuse_flush_handle_interrupt) {
533
        case GF_OPTION_ENABLE:
534
            DICT_SET_VAL(dict_set_static_ptr, options, "flush-handle-interrupt",
535
                         "on", glusterfsd_msg_3);
536
            break;
537
        case GF_OPTION_DISABLE:
538
            DICT_SET_VAL(dict_set_static_ptr, options, "flush-handle-interrupt",
539
                         "off", glusterfsd_msg_3);
540
            break;
541
        default:
542
            gf_msg_debug("glusterfsd", 0, "fuse-flush-handle-interrupt mode %d",
543
                         cmd_args->fuse_flush_handle_interrupt);
544
            break;
545
    }
546
    if (cmd_args->global_threading) {
547
        DICT_SET_VAL(dict_set_static_ptr, options, "global-threading", "on",
548
                     glusterfsd_msg_3);
549
    }
550
    if (cmd_args->fuse_dev_eperm_ratelimit_ns) {
551
        DICT_SET_VAL(dict_set_uint32, options, "fuse-dev-eperm-ratelimit-ns",
552
                     cmd_args->fuse_dev_eperm_ratelimit_ns, glusterfsd_msg_3);
553
    }
554
    switch (cmd_args->fuse_handle_copy_file_range) {
555
        case GF_OPTION_ENABLE:
556
            DICT_SET_VAL(dict_set_static_ptr, options, "handle-copy_file_range",
557
                         "on", glusterfsd_msg_3);
558
            break;
559
        case GF_OPTION_DISABLE:
560
            DICT_SET_VAL(dict_set_static_ptr, options, "handle-copy_file_range",
561
                         "off", glusterfsd_msg_3);
562
            break;
563
        default:
564
            gf_msg_debug("glusterfsd", 0, "fuse-handle-copy_file_range mode %d",
565
                         cmd_args->fuse_handle_copy_file_range);
566
            break;
567
    }
568

569
    if (cmd_args->fs_display_name) {
570
        DICT_SET_VAL(dict_set_dynstr, options, "fs-display-name",
571
                     cmd_args->fs_display_name, glusterfsd_msg_3);
572
    }
573

574
    if (cmd_args->io_engine != NULL) {
575
        DICT_SET_VAL(dict_set_static_ptr, options, "io-engine",
576
                     cmd_args->io_engine, glusterfsd_msg_3);
577
    }
578

579
    switch (cmd_args->fuse_setlk_handle_interrupt) {
580
        case GF_OPTION_ENABLE:
581
            ret = dict_set_static_ptr(options, "setlk-handle-interrupt", "on");
582
            if (ret < 0) {
583
                gf_msg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4,
584
                       "failed to set dict value for key "
585
                       "setlk-handle-interrupt");
586
                goto err;
587
            }
588
            break;
589
        case GF_OPTION_DISABLE:
590
            ret = dict_set_static_ptr(options, "setlk-handle-interrupt", "off");
591
            if (ret < 0) {
592
                gf_msg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4,
593
                       "failed to set dict value for key "
594
                       "setlk-handle-interrupt");
595
                goto err;
596
            }
597
            break;
598
        case GF_OPTION_DEFERRED: /* default */
599
        default:
600
            gf_msg_debug("glusterfsd", 0, "fuse-setlk-handle-interrupt mode %d",
601
                         cmd_args->fuse_setlk_handle_interrupt);
602
            break;
603
    }
604

605
    ret = 0;
606
err:
607
    return ret;
608
}
609

610
static int
611
create_fuse_mount(glusterfs_ctx_t *ctx)
612
{
613
    int ret = 0;
614
    cmd_args_t *cmd_args = NULL;
615
    xlator_t *root = NULL;
616

617
    cmd_args = &ctx->cmd_args;
618
    if (!cmd_args->mount_point) {
619
        gf_msg_trace("glusterfsd", 0,
620
                     "mount point not found, not a client process");
621
        return 0;
622
    }
623

624
    if (ctx->process_mode != GF_CLIENT_PROCESS) {
625
        gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_7, NULL);
626
        return -1;
627
    }
628

629
    root = GF_CALLOC(1, sizeof(*root), gfd_mt_xlator_t);
630
    if (!root)
631
        goto err;
632

633
    root->name = gf_strdup("fuse");
634
    if (!root->name)
635
        goto err;
636

637
    if (xlator_set_type(root, "mount/fuse") == -1) {
638
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_8,
639
                "MOUNT-POINT=%s", cmd_args->mount_point, NULL);
640
        goto err;
641
    }
642

643
    root->ctx = ctx;
644
    root->options = dict_new();
645
    if (!root->options)
646
        goto err;
647

648
    ret = set_fuse_mount_options(ctx, root->options);
649
    if (ret)
650
        goto err;
651

652
    if (cmd_args->fuse_mountopts) {
653
        ret = dict_set_static_ptr(root->options, ZR_FUSE_MOUNTOPTS,
654
                                  cmd_args->fuse_mountopts);
655
        if (ret < 0) {
656
            gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_3,
657
                    ZR_FUSE_MOUNTOPTS, NULL);
658
            goto err;
659
        }
660
    }
661

662
    ret = xlator_init(root);
663
    if (ret) {
664
        gf_msg_debug("glusterfsd", 0, "failed to initialize fuse translator");
665
        goto err;
666
    }
667

668
    ctx->root = root;
669

670
    return 0;
671

672
err:
673
    if (root) {
674
        xlator_destroy(root);
675
    }
676

677
    return 1;
678
}
679

680
static int
681
gf_remember_backup_volfile_server(char *arg)
682
{
683
    glusterfs_ctx_t *ctx = NULL;
684
    cmd_args_t *cmd_args = NULL;
685
    int ret = -1;
686

687
    ctx = glusterfsd_ctx;
688
    if (!ctx)
689
        goto out;
690
    cmd_args = &ctx->cmd_args;
691

692
    if (!cmd_args)
693
        goto out;
694

695
    ret = gf_set_volfile_server_common(
696
        cmd_args, arg, GF_DEFAULT_VOLFILE_TRANSPORT, GF_DEFAULT_BASE_PORT);
697
    if (ret) {
698
        gf_log("glusterfs", GF_LOG_ERROR, "failed to set volfile server: %s",
699
               strerror(errno));
700
    }
701
out:
702
    return ret;
703
}
704

705
static int
706
gf_remember_xlator_option(char *arg)
707
{
708
    glusterfs_ctx_t *ctx = NULL;
709
    cmd_args_t *cmd_args = NULL;
710
    xlator_cmdline_option_t *option = NULL;
711
    int ret = -1;
712
    char *dot = NULL;
713
    char *equals = NULL;
714

715
    ctx = glusterfsd_ctx;
716
    cmd_args = &ctx->cmd_args;
717

718
    option = GF_CALLOC(1, sizeof(xlator_cmdline_option_t),
719
                       gfd_mt_xlator_cmdline_option_t);
720
    if (!option)
721
        goto out;
722

723
    INIT_LIST_HEAD(&option->cmd_args);
724

725
    dot = strchr(arg, '.');
726
    if (!dot) {
727
        gf_smsg("", GF_LOG_WARNING, 0, glusterfsd_msg_10, "arg=%s", arg, NULL);
728
        goto out;
729
    }
730

731
    option->volume = GF_MALLOC((dot - arg) + 1, gfd_mt_char);
732
    if (!option->volume)
733
        goto out;
734

735
    strncpy(option->volume, arg, (dot - arg));
736
    option->volume[(dot - arg)] = '\0';
737

738
    equals = strchr(arg, '=');
739
    if (!equals) {
740
        gf_smsg("", GF_LOG_WARNING, 0, glusterfsd_msg_10, "arg=%s", arg, NULL);
741
        goto out;
742
    }
743

744
    option->key = GF_MALLOC((equals - dot) + 1, gfd_mt_char);
745
    if (!option->key)
746
        goto out;
747

748
    strncpy(option->key, dot + 1, (equals - dot - 1));
749
    option->key[(equals - dot - 1)] = '\0';
750

751
    if (!*(equals + 1)) {
752
        gf_smsg("", GF_LOG_WARNING, 0, glusterfsd_msg_10, "arg=%s", arg, NULL);
753
        goto out;
754
    }
755

756
    option->value = gf_strdup(equals + 1);
757

758
    list_add(&option->cmd_args, &cmd_args->xlator_options);
759

760
    ret = 0;
761
out:
762
    if (ret == -1) {
763
        if (option) {
764
            GF_FREE(option->volume);
765
            GF_FREE(option->key);
766
            GF_FREE(option->value);
767

768
            GF_FREE(option);
769
        }
770
    }
771

772
    return ret;
773
}
774

775
#ifdef GF_LINUX_HOST_OS
776
static struct oom_api_info {
777
    char *oom_api_file;
778
    int32_t oom_min;
779
    int32_t oom_max;
780
} oom_api_info[] = {
781
    {"/proc/self/oom_score_adj", OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX},
782
    {"/proc/self/oom_adj", OOM_DISABLE, OOM_ADJUST_MAX},
783
    {NULL, 0, 0}};
784

785
static struct oom_api_info *
786
get_oom_api_info(void)
787
{
788
    struct oom_api_info *api = NULL;
789

790
    for (api = oom_api_info; api->oom_api_file; api++) {
791
        if (sys_access(api->oom_api_file, F_OK) != -1) {
792
            return api;
793
        }
794
    }
795

796
    return NULL;
797
}
798
#endif
799

800
static error_t
801
parse_opts(int key, char *arg, struct argp_state *state)
802
{
803
    cmd_args_t *cmd_args = NULL;
804
    uint32_t n = 0;
805
#ifdef GF_LINUX_HOST_OS
806
    int32_t k = 0;
807
    struct oom_api_info *api = NULL;
808
#endif
809
    double d = 0.0;
810
    gf_boolean_t b = _gf_false;
811
    char *tmp_str = NULL;
812
    char *port_str = NULL;
813
    struct passwd *pw = NULL;
814
    int ret = 0;
815

816
    cmd_args = state->input;
817

818
    switch (key) {
819
        case ARGP_VOLFILE_SERVER_KEY:
820
            gf_remember_backup_volfile_server(arg);
821

822
            break;
823

824
        case ARGP_READ_ONLY_KEY:
825
            cmd_args->read_only = 1;
826
            break;
827

828
        case ARGP_ACL_KEY:
829
            cmd_args->acl = 1;
830
            gf_remember_xlator_option("*-md-cache.cache-posix-acl=true");
831
            break;
832

833
        case ARGP_SELINUX_KEY:
834
            cmd_args->selinux = 1;
835
            gf_remember_xlator_option("*-md-cache.cache-selinux=true");
836
            break;
837

838
        case ARGP_CAPABILITY_KEY:
839
            cmd_args->capability = 1;
840
            break;
841

842
        case ARGP_AUX_GFID_MOUNT_KEY:
843
            cmd_args->aux_gfid_mount = 1;
844
            break;
845

846
        case ARGP_INODE32_KEY:
847
            cmd_args->enable_ino32 = 1;
848
            break;
849

850
        case ARGP_WORM_KEY:
851
            cmd_args->worm = 1;
852
            break;
853

854
        case ARGP_PRINT_NETGROUPS:
855
            cmd_args->print_netgroups = arg;
856
            break;
857

858
        case ARGP_PRINT_EXPORTS:
859
            cmd_args->print_exports = arg;
860
            break;
861

862
        case ARGP_PRINT_XLATORDIR_KEY:
863
            cmd_args->print_xlatordir = _gf_true;
864
            break;
865

866
        case ARGP_PRINT_STATEDUMPDIR_KEY:
867
            cmd_args->print_statedumpdir = _gf_true;
868
            break;
869

870
        case ARGP_PRINT_LOGDIR_KEY:
871
            cmd_args->print_logdir = _gf_true;
872
            break;
873

874
        case ARGP_PRINT_LIBEXECDIR_KEY:
875
            cmd_args->print_libexecdir = _gf_true;
876
            break;
877

878
        case ARGP_MAC_COMPAT_KEY:
879
            if (!arg)
880
                arg = "on";
881

882
            if (gf_string2boolean(arg, &b) == 0) {
883
                cmd_args->mac_compat = b;
884

885
                break;
886
            }
887

888
            argp_failure(state, -1, 0, "invalid value \"%s\" for mac-compat",
889
                         arg);
890
            break;
891

892
        case ARGP_VOLUME_FILE_KEY:
893
            GF_FREE(cmd_args->volfile);
894

895
            if (arg[0] != '/') {
896
                char pwd[PATH_MAX];
897
                if (!getcwd(pwd, PATH_MAX)) {
898
                    argp_failure(state, -1, errno,
899
                                 "getcwd failed with error no %d", errno);
900
                    break;
901
                }
902
                gf_asprintf(&cmd_args->volfile, "%s/%s", pwd, arg);
903
            } else {
904
                cmd_args->volfile = gf_strdup(arg);
905
            }
906

907
            break;
908

909
        case ARGP_LOG_LEVEL_KEY:
910
            if (strcasecmp(arg, ARGP_LOG_LEVEL_NONE_OPTION) == 0) {
911
                cmd_args->log_level = GF_LOG_NONE;
912
                break;
913
            }
914
            if (strcasecmp(arg, ARGP_LOG_LEVEL_CRITICAL_OPTION) == 0) {
915
                cmd_args->log_level = GF_LOG_CRITICAL;
916
                break;
917
            }
918
            if (strcasecmp(arg, ARGP_LOG_LEVEL_ERROR_OPTION) == 0) {
919
                cmd_args->log_level = GF_LOG_ERROR;
920
                break;
921
            }
922
            if (strcasecmp(arg, ARGP_LOG_LEVEL_WARNING_OPTION) == 0) {
923
                cmd_args->log_level = GF_LOG_WARNING;
924
                break;
925
            }
926
            if (strcasecmp(arg, ARGP_LOG_LEVEL_INFO_OPTION) == 0) {
927
                cmd_args->log_level = GF_LOG_INFO;
928
                break;
929
            }
930
            if (strcasecmp(arg, ARGP_LOG_LEVEL_DEBUG_OPTION) == 0) {
931
                cmd_args->log_level = GF_LOG_DEBUG;
932
                break;
933
            }
934
            if (strcasecmp(arg, ARGP_LOG_LEVEL_TRACE_OPTION) == 0) {
935
                cmd_args->log_level = GF_LOG_TRACE;
936
                break;
937
            }
938

939
            argp_failure(state, -1, 0, "unknown log level %s", arg);
940
            break;
941

942
        case ARGP_LOG_FILE_KEY:
943
            cmd_args->log_file = gf_strdup(arg);
944
            break;
945

946
        case ARGP_VOLFILE_SERVER_PORT_KEY:
947
            n = 0;
948

949
            if (gf_string2uint_base10(arg, &n) == 0) {
950
                cmd_args->volfile_server_port = n;
951
                break;
952
            }
953

954
            argp_failure(state, -1, 0, "unknown volfile server port %s", arg);
955
            break;
956

957
        case ARGP_VOLFILE_SERVER_TRANSPORT_KEY:
958
            cmd_args->volfile_server_transport = gf_strdup(arg);
959
            break;
960

961
        case ARGP_VOLFILE_ID_KEY:
962
            cmd_args->volfile_id = gf_strdup(arg);
963
            break;
964

965
        case ARGP_THIN_CLIENT_KEY:
966
            cmd_args->thin_client = _gf_true;
967
            break;
968

969
        case ARGP_BRICK_MUX_KEY:
970
            cmd_args->brick_mux = _gf_true;
971
            break;
972

973
        case ARGP_PID_FILE_KEY:
974
            cmd_args->pid_file = gf_strdup(arg);
975
            break;
976

977
        case ARGP_SOCK_FILE_KEY:
978
            cmd_args->sock_file = gf_strdup(arg);
979
            break;
980

981
        case ARGP_NO_DAEMON_KEY:
982
            cmd_args->no_daemon_mode = ENABLE_NO_DAEMON_MODE;
983
            break;
984

985
        case ARGP_RUN_ID_KEY:
986
            cmd_args->run_id = gf_strdup(arg);
987
            break;
988

989
        case ARGP_DEBUG_KEY:
990
            cmd_args->debug_mode = ENABLE_DEBUG_MODE;
991
            break;
992
        case ARGP_VOLFILE_MAX_FETCH_ATTEMPTS:
993
            cmd_args->max_connect_attempts = 1;
994
            break;
995

996
        case ARGP_DIRECT_IO_MODE_KEY:
997
            if (!arg)
998
                arg = "on";
999

1000
            if (gf_string2boolean(arg, &b) == 0) {
1001
                cmd_args->fuse_direct_io_mode = b;
1002

1003
                break;
1004
            }
1005

1006
            if (strcmp(arg, "auto") == 0)
1007
                break;
1008

1009
            argp_failure(state, -1, 0, "unknown direct I/O mode setting \"%s\"",
1010
                         arg);
1011
            break;
1012

1013
        case ARGP_FUSE_NO_ROOT_SQUASH_KEY:
1014
            cmd_args->no_root_squash = _gf_true;
1015
            break;
1016

1017
        case ARGP_ENTRY_TIMEOUT_KEY:
1018
            d = 0.0;
1019

1020
            gf_string2double(arg, &d);
1021
            if (!(d < 0.0)) {
1022
                cmd_args->fuse_entry_timeout = d;
1023
                break;
1024
            }
1025

1026
            argp_failure(state, -1, 0, "unknown entry timeout %s", arg);
1027
            break;
1028

1029
        case ARGP_NEGATIVE_TIMEOUT_KEY:
1030
            d = 0.0;
1031

1032
            ret = gf_string2double(arg, &d);
1033
            if ((ret == 0) && !(d < 0.0)) {
1034
                cmd_args->fuse_negative_timeout = d;
1035
                break;
1036
            }
1037

1038
            argp_failure(state, -1, 0, "unknown negative timeout %s", arg);
1039
            break;
1040

1041
        case ARGP_ATTRIBUTE_TIMEOUT_KEY:
1042
            d = 0.0;
1043

1044
            gf_string2double(arg, &d);
1045
            if (!(d < 0.0)) {
1046
                cmd_args->fuse_attribute_timeout = d;
1047
                break;
1048
            }
1049

1050
            argp_failure(state, -1, 0, "unknown attribute timeout %s", arg);
1051
            break;
1052

1053
        case ARGP_CLIENT_PID_KEY:
1054
            if (gf_string2int(arg, &cmd_args->client_pid) == 0) {
1055
                cmd_args->client_pid_set = 1;
1056
                break;
1057
            }
1058

1059
            argp_failure(state, -1, 0, "unknown client pid %s", arg);
1060
            break;
1061

1062
        case ARGP_USER_MAP_ROOT_KEY:
1063
            pw = getpwnam(arg);
1064
            if (pw)
1065
                cmd_args->uid_map_root = pw->pw_uid;
1066
            else
1067
                argp_failure(state, -1, 0, "user %s does not exist", arg);
1068
            break;
1069

1070
        case ARGP_VOLFILE_CHECK_KEY:
1071
            cmd_args->volfile_check = 1;
1072
            break;
1073

1074
        case ARGP_VOLUME_NAME_KEY:
1075
            cmd_args->volume_name = gf_strdup(arg);
1076
            break;
1077

1078
        case ARGP_XLATOR_OPTION_KEY:
1079
            if (gf_remember_xlator_option(arg))
1080
                argp_failure(state, -1, 0, "invalid xlator option  %s", arg);
1081

1082
            break;
1083

1084
        case ARGP_KEY_NO_ARGS:
1085
            break;
1086

1087
        case ARGP_KEY_ARG:
1088
            if (state->arg_num >= 1)
1089
                argp_usage(state);
1090
            cmd_args->mount_point = gf_strdup(arg);
1091
            break;
1092

1093
        case ARGP_DUMP_FUSE_KEY:
1094
            cmd_args->dump_fuse = gf_strdup(arg);
1095
            break;
1096
        case ARGP_BRICK_NAME_KEY:
1097
            cmd_args->brick_name = gf_strdup(arg);
1098
            break;
1099
        case ARGP_BRICK_PORT_KEY:
1100
            n = 0;
1101

1102
            if (arg != NULL) {
1103
                port_str = strtok_r(arg, ",", &tmp_str);
1104
                if (gf_string2uint_base10(port_str, &n) == 0) {
1105
                    cmd_args->brick_port = n;
1106
                    port_str = strtok_r(NULL, ",", &tmp_str);
1107
                    if (port_str) {
1108
                        if (gf_string2uint_base10(port_str, &n) == 0) {
1109
                            cmd_args->brick_port2 = n;
1110
                            break;
1111
                        }
1112
                        argp_failure(state, -1, 0,
1113
                                     "wrong brick (listen) port %s", arg);
1114
                    }
1115
                    break;
1116
                }
1117
            }
1118

1119
            argp_failure(state, -1, 0, "unknown brick (listen) port %s", arg);
1120
            break;
1121

1122
        case ARGP_MEM_ACCOUNTING_KEY:
1123
            /* TODO: it should have got handled much earlier */
1124
            // gf_mem_acct_enable_set (THIS->ctx);
1125
            break;
1126

1127
        case ARGP_FOPEN_KEEP_CACHE_KEY:
1128
            if (!arg)
1129
                arg = "on";
1130

1131
            if (gf_string2boolean(arg, &b) == 0) {
1132
                cmd_args->fopen_keep_cache = b;
1133

1134
                break;
1135
            }
1136

1137
            argp_failure(state, -1, 0, "unknown cache setting \"%s\"", arg);
1138

1139
            break;
1140

1141
        case ARGP_GID_TIMEOUT_KEY:
1142
            if (!gf_string2int(arg, &cmd_args->gid_timeout)) {
1143
                cmd_args->gid_timeout_set = _gf_true;
1144
                break;
1145
            }
1146

1147
            argp_failure(state, -1, 0, "unknown group list timeout %s", arg);
1148
            break;
1149

1150
        case ARGP_RESOLVE_GIDS_KEY:
1151
            cmd_args->resolve_gids = 1;
1152
            break;
1153

1154
        case ARGP_FUSE_LRU_LIMIT_KEY:
1155
            if (!gf_string2int32(arg, &cmd_args->lru_limit))
1156
                break;
1157

1158
            argp_failure(state, -1, 0, "unknown LRU limit option %s", arg);
1159
            break;
1160

1161
        case ARGP_FUSE_INODE_TABLESIZE_KEY:
1162
            if (!gf_string2int32(arg, &cmd_args->inode_table_size))
1163
                break;
1164

1165
            argp_failure(state, -1, 0, "unknown inode table size option %s",
1166
                         arg);
1167
            break;
1168

1169
        case ARGP_FUSE_INVALIDATE_LIMIT_KEY:
1170
            if (!gf_string2int32(arg, &cmd_args->invalidate_limit))
1171
                break;
1172

1173
            argp_failure(state, -1, 0, "unknown invalidate limit option %s",
1174
                         arg);
1175
            break;
1176

1177
        case ARGP_FUSE_BACKGROUND_QLEN_KEY:
1178
            if (!gf_string2int(arg, &cmd_args->background_qlen))
1179
                break;
1180

1181
            argp_failure(state, -1, 0, "unknown background qlen option %s",
1182
                         arg);
1183
            break;
1184
        case ARGP_FUSE_CONGESTION_THRESHOLD_KEY:
1185
            if (!gf_string2int(arg, &cmd_args->congestion_threshold))
1186
                break;
1187

1188
            argp_failure(state, -1, 0, "unknown congestion threshold option %s",
1189
                         arg);
1190
            break;
1191

1192
#ifdef GF_LINUX_HOST_OS
1193
        case ARGP_OOM_SCORE_ADJ_KEY:
1194
            k = 0;
1195

1196
            api = get_oom_api_info();
1197
            if (!api)
1198
                goto no_oom_api;
1199

1200
            if (gf_string2int(arg, &k) == 0 && k >= api->oom_min &&
1201
                k <= api->oom_max) {
1202
                cmd_args->oom_score_adj = gf_strdup(arg);
1203
                break;
1204
            }
1205

1206
            argp_failure(state, -1, 0, "unknown oom_score_adj value %s", arg);
1207

1208
        no_oom_api:
1209
            break;
1210
#endif
1211

1212
        case ARGP_FUSE_MOUNTOPTS_KEY:
1213
            cmd_args->fuse_mountopts = gf_strdup(arg);
1214
            break;
1215

1216
        case ARGP_FUSE_USE_READDIRP_KEY:
1217
            if (!arg)
1218
                arg = "yes";
1219

1220
            if (gf_string2boolean(arg, &b) == 0) {
1221
                if (b) {
1222
                    cmd_args->use_readdirp = "yes";
1223
                } else {
1224
                    cmd_args->use_readdirp = "no";
1225
                }
1226

1227
                break;
1228
            }
1229

1230
            argp_failure(state, -1, 0, "unknown use-readdirp setting \"%s\"",
1231
                         arg);
1232
            break;
1233

1234
        case ARGP_LOGGER:
1235
            if (strcasecmp(arg, GF_LOGGER_GLUSTER_LOG) == 0)
1236
                cmd_args->logger = gf_logger_glusterlog;
1237
            else if (strcasecmp(arg, GF_LOGGER_SYSLOG) == 0)
1238
                cmd_args->logger = gf_logger_syslog;
1239
            else
1240
                argp_failure(state, -1, 0, "unknown logger %s", arg);
1241

1242
            break;
1243

1244
        case ARGP_LOG_FORMAT:
1245
            if (strcasecmp(arg, GF_LOG_FORMAT_NO_MSG_ID) == 0)
1246
                cmd_args->log_format = gf_logformat_traditional;
1247
            else if (strcasecmp(arg, GF_LOG_FORMAT_WITH_MSG_ID) == 0)
1248
                cmd_args->log_format = gf_logformat_withmsgid;
1249
            else
1250
                argp_failure(state, -1, 0, "unknown log format %s", arg);
1251

1252
            break;
1253

1254
        case ARGP_LOG_BUF_SIZE:
1255
            if (gf_string2uint32(arg, &cmd_args->log_buf_size)) {
1256
                argp_failure(state, -1, 0, "unknown log buf size option %s",
1257
                             arg);
1258
            } else if (cmd_args->log_buf_size > GF_LOG_LRU_BUFSIZE_MAX) {
1259
                argp_failure(state, -1, 0,
1260
                             "Invalid log buf size %s. "
1261
                             "Valid range: [" GF_LOG_LRU_BUFSIZE_MIN_STR
1262
                             "," GF_LOG_LRU_BUFSIZE_MAX_STR "]",
1263
                             arg);
1264
            }
1265

1266
            break;
1267

1268
        case ARGP_LOG_FLUSH_TIMEOUT:
1269
            if (gf_string2uint32(arg, &cmd_args->log_flush_timeout)) {
1270
                argp_failure(state, -1, 0,
1271
                             "unknown log flush timeout option %s", arg);
1272
            } else if ((cmd_args->log_flush_timeout <
1273
                        GF_LOG_FLUSH_TIMEOUT_MIN) ||
1274
                       (cmd_args->log_flush_timeout >
1275
                        GF_LOG_FLUSH_TIMEOUT_MAX)) {
1276
                argp_failure(state, -1, 0,
1277
                             "Invalid log flush timeout %s. "
1278
                             "Valid range: [" GF_LOG_FLUSH_TIMEOUT_MIN_STR
1279
                             "," GF_LOG_FLUSH_TIMEOUT_MAX_STR "]",
1280
                             arg);
1281
            }
1282

1283
            break;
1284

1285
        case ARGP_SECURE_MGMT_KEY:
1286
            if (!arg)
1287
                arg = "yes";
1288

1289
            if (gf_string2boolean(arg, &b) == 0) {
1290
                cmd_args->secure_mgmt = b ? 1 : 0;
1291
                break;
1292
            }
1293

1294
            argp_failure(state, -1, 0, "unknown secure-mgmt setting \"%s\"",
1295
                         arg);
1296
            break;
1297

1298
        case ARGP_LOCALTIME_LOGGING_KEY:
1299
            cmd_args->localtime_logging = 1;
1300
            break;
1301
        case ARGP_PROCESS_NAME_KEY:
1302
            cmd_args->process_name = gf_strdup(arg);
1303
            break;
1304
        case ARGP_SUBDIR_MOUNT_KEY:
1305
            if (arg[0] != '/') {
1306
                argp_failure(state, -1, 0, "expect '/%s', provided just \"%s\"",
1307
                             arg, arg);
1308
                break;
1309
            }
1310
            cmd_args->subdir_mount = gf_strdup(arg);
1311
            break;
1312
        case ARGP_FUSE_EVENT_HISTORY_KEY:
1313
            if (!arg)
1314
                arg = "no";
1315

1316
            if (gf_string2boolean(arg, &b) == 0) {
1317
                if (b) {
1318
                    cmd_args->event_history = "yes";
1319
                } else {
1320
                    cmd_args->event_history = "no";
1321
                }
1322

1323
                break;
1324
            }
1325

1326
            argp_failure(state, -1, 0, "unknown event-history setting \"%s\"",
1327
                         arg);
1328
            break;
1329
        case ARGP_READER_THREAD_COUNT_KEY:
1330
            if (gf_string2uint32(arg, &cmd_args->reader_thread_count)) {
1331
                argp_failure(state, -1, 0,
1332
                             "unknown reader thread count option %s", arg);
1333
            } else if ((cmd_args->reader_thread_count < 1) ||
1334
                       (cmd_args->reader_thread_count > 64)) {
1335
                argp_failure(state, -1, 0,
1336
                             "Invalid reader thread count %s. "
1337
                             "Valid range: [\"1, 64\"]",
1338
                             arg);
1339
            }
1340

1341
            break;
1342

1343
        case ARGP_KERNEL_WRITEBACK_CACHE_KEY:
1344
            if (!arg)
1345
                arg = "yes";
1346

1347
            if (gf_string2boolean(arg, &b) == 0) {
1348
                cmd_args->kernel_writeback_cache = b;
1349

1350
                break;
1351
            }
1352

1353
            argp_failure(state, -1, 0,
1354
                         "unknown kernel writeback cache setting \"%s\"", arg);
1355
            break;
1356
        case ARGP_ATTR_TIMES_GRANULARITY_KEY:
1357
            if (gf_string2uint32(arg, &cmd_args->attr_times_granularity)) {
1358
                argp_failure(state, -1, 0,
1359
                             "unknown attribute times granularity option %s",
1360
                             arg);
1361
            } else if (cmd_args->attr_times_granularity > 1000000000) {
1362
                argp_failure(state, -1, 0,
1363
                             "Invalid attribute times granularity value %s. "
1364
                             "Valid range: [\"0, 1000000000\"]",
1365
                             arg);
1366
            }
1367

1368
            break;
1369

1370
        case ARGP_FUSE_FLUSH_HANDLE_INTERRUPT_KEY:
1371
            if (!arg)
1372
                arg = "yes";
1373

1374
            if (gf_string2boolean(arg, &b) == 0) {
1375
                cmd_args->fuse_flush_handle_interrupt = b;
1376

1377
                break;
1378
            }
1379

1380
            argp_failure(state, -1, 0,
1381
                         "unknown fuse flush handle interrupt setting \"%s\"",
1382
                         arg);
1383
            break;
1384

1385
        case ARGP_FUSE_AUTO_INVAL_KEY:
1386
            if (!arg)
1387
                arg = "yes";
1388

1389
            if (gf_string2boolean(arg, &b) == 0) {
1390
                cmd_args->fuse_auto_inval = b;
1391
                break;
1392
            }
1393

1394
            break;
1395

1396
        case ARGP_GLOBAL_THREADING_KEY:
1397
            if (!arg || (*arg == 0)) {
1398
                arg = "yes";
1399
            }
1400

1401
            if (gf_string2boolean(arg, &b) == 0) {
1402
                cmd_args->global_threading = b;
1403
                break;
1404
            }
1405

1406
            argp_failure(state, -1, 0,
1407
                         "Invalid value for global threading \"%s\"", arg);
1408
            break;
1409

1410
        case ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY:
1411
            if (gf_string2uint32(arg, &cmd_args->fuse_dev_eperm_ratelimit_ns)) {
1412
                argp_failure(state, -1, 0,
1413
                             "Non-numerical value for "
1414
                             "'fuse-dev-eperm-ratelimit-ns' option %s",
1415
                             arg);
1416
            } else if (cmd_args->fuse_dev_eperm_ratelimit_ns > 1000000000) {
1417
                argp_failure(state, -1, 0,
1418
                             "Invalid 'fuse-dev-eperm-ratelimit-ns' value %s. "
1419
                             "Valid range: [\"0, 1000000000\"]",
1420
                             arg);
1421
            }
1422

1423
            break;
1424

1425
        case ARGP_FUSE_DISPLAY_NAME_KEY:
1426
            cmd_args->fs_display_name = gf_strdup(arg);
1427
            break;
1428

1429
        case ARGP_IO_ENGINE_KEY:
1430
            cmd_args->io_engine = gf_strdup(arg);
1431
            if (cmd_args->io_engine == NULL) {
1432
                argp_failure(state, -1, 0,
1433
                             "Failed to allocate memory for "
1434
                             "io-engine");
1435
            }
1436
            break;
1437

1438
        case ARGP_FUSE_SETLK_HANDLE_INTERRUPT_KEY:
1439
            if (!arg)
1440
                arg = "yes";
1441

1442
            if (gf_string2boolean(arg, &b) == 0) {
1443
                cmd_args->fuse_setlk_handle_interrupt = b;
1444

1445
                break;
1446
            }
1447

1448
            argp_failure(state, -1, 0,
1449
                         "unknown fuse setlk handle interrupt setting \"%s\"",
1450
                         arg);
1451
            break;
1452
        case ARGP_FUSE_HANDLE_COPY_FILE_RANGE:
1453
            if (!arg)
1454
                arg = "yes";
1455

1456
            if (gf_string2boolean(arg, &b) == 0) {
1457
                cmd_args->fuse_handle_copy_file_range = b;
1458

1459
                break;
1460
            }
1461

1462
            argp_failure(state, -1, 0,
1463
                         "unknown fuse handle copy_file_range setting \"%s\"",
1464
                         arg);
1465
            break;
1466
    }
1467
    return 0;
1468
}
1469

1470
void
1471
cleanup_and_exit(int signum)
1472
{
1473
    glusterfs_ctx_t *ctx = NULL;
1474
    xlator_t *trav = NULL;
1475
    xlator_t *top;
1476
    xlator_t *victim;
1477
    xlator_list_t **trav_p;
1478

1479
    ctx = glusterfsd_ctx;
1480

1481
    if (!ctx)
1482
        return;
1483

1484
    /* To take or not to take the mutex here and in the other
1485
     * signal handler - gf_print_trace() - is the big question here.
1486
     *
1487
     * Taking mutex in signal handler would mean that if the process
1488
     * receives a fatal signal while another thread is holding
1489
     * ctx->log.log_buf_lock to perhaps log a message in _gf_msg_internal(),
1490
     * the offending thread hangs on the mutex lock forever without letting
1491
     * the process exit.
1492
     *
1493
     * On the other hand. not taking the mutex in signal handler would cause
1494
     * it to modify the lru_list of buffered log messages in a racy manner,
1495
     * corrupt the list and potentially give rise to an unending
1496
     * cascade of SIGSEGVs and other re-entrancy issues.
1497
     */
1498

1499
    gf_log_disable_suppression_before_exit(ctx);
1500

1501
    gf_msg_callingfn("", GF_LOG_WARNING, 0, glusterfsd_msg_32,
1502
                     "received signum (%d), shutting down", signum);
1503

1504
    if (ctx->cleanup_started)
1505
        return;
1506
    pthread_mutex_lock(&ctx->cleanup_lock);
1507
    {
1508
        ctx->cleanup_started = 1;
1509

1510
        /* signout should be sent to all the bricks in case brick mux is enabled
1511
         * and multiple brick instances are attached to this process
1512
         */
1513
        if (ctx->active) {
1514
            top = ctx->active->first;
1515
            for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) {
1516
                victim = (*trav_p)->xlator;
1517
                rpc_clnt_mgmt_pmap_signout(ctx, victim->name);
1518
            }
1519
        } else {
1520
            rpc_clnt_mgmt_pmap_signout(ctx, NULL);
1521
        }
1522

1523
        /* below part is a racy code where the rpcsvc object is freed.
1524
         * But in another thread (epoll thread), upon poll error in the
1525
         * socket the transports are cleaned up where again rpcsvc object
1526
         * is accessed (which is already freed by the below function).
1527
         * Since the process is about to be killed don't execute the function
1528
         * below.
1529
         */
1530
        /* if (ctx->listener) { */
1531
        /*         (void) glusterfs_listener_stop (ctx); */
1532
        /* } */
1533

1534
        /* Call fini() of FUSE xlator first:
1535
         * so there are no more requests coming and
1536
         * 'umount' of mount point is done properly */
1537
        trav = ctx->root;
1538
        if (trav && trav->fini) {
1539
            THIS = trav;
1540
            trav->fini(trav);
1541
        }
1542

1543
        glusterfs_pidfile_cleanup(ctx);
1544

1545
#if 0
1546
        /* TODO: Properly do cleanup_and_exit(), with synchronization */
1547
        if (ctx->mgmt) {
1548
                /* cleanup the saved-frames before last unref */
1549
                rpc_clnt_connection_cleanup (&ctx->mgmt->conn);
1550
                rpc_clnt_unref (ctx->mgmt);
1551
        }
1552
#endif
1553

1554
        trav = NULL;
1555

1556
        /* previously we were releasing the cleanup mutex lock before the
1557
           process exit. As we are releasing the cleanup mutex lock, before
1558
           the process can exit some other thread which is blocked on
1559
           cleanup mutex lock is acquiring the cleanup mutex lock and
1560
           trying to acquire some resources which are already freed as a
1561
           part of cleanup. To avoid this, we are exiting the process without
1562
           releasing the cleanup mutex lock. This will not cause any lock
1563
           related issues as the process which acquired the lock is going down
1564
         */
1565
        /* NOTE: Only the least significant 8 bits i.e (signum & 255)
1566
           will be available to parent process on calling exit() */
1567
        exit(abs(signum));
1568
    }
1569
}
1570

1571
static FILE *
1572
get_volfp(glusterfs_ctx_t *ctx)
1573
{
1574
    cmd_args_t *cmd_args = NULL;
1575
    FILE *specfp = NULL;
1576

1577
    cmd_args = &ctx->cmd_args;
1578

1579
    if ((specfp = fopen(cmd_args->volfile, "r")) == NULL) {
1580
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_9,
1581
                "volume_file=%s", cmd_args->volfile, NULL);
1582
        return NULL;
1583
    }
1584

1585
    gf_msg_debug("glusterfsd", 0, "loading volume file %s", cmd_args->volfile);
1586

1587
    return specfp;
1588
}
1589

1590
static int
1591
volfile_init(glusterfs_ctx_t *ctx)
1592
{
1593
    int ret = -1;
1594
    char *volfile = NULL;
1595
    gf_volfile_t *volfile_obj = NULL;
1596
    gf_volfile_t *volfile_tmp = NULL;
1597
    struct stat stbuf = {
1598
        0,
1599
    };
1600
    char sha256_hash[SHA256_DIGEST_LENGTH] = {
1601
        0,
1602
    };
1603

1604
    cmd_args_t *cmd_args = &ctx->cmd_args;
1605
    FILE *fp = get_volfp(ctx);
1606
    if (!fp) {
1607
        gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_28, NULL);
1608
        goto out;
1609
    }
1610
    ret = sys_stat(cmd_args->volfile, &stbuf);
1611
    if (IS_ERROR(ret)) {
1612
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_9,
1613
                "volume_file=%s", cmd_args->volfile, NULL);
1614
        goto out;
1615
    }
1616

1617
    volfile = GF_MALLOC(stbuf.st_size, gf_common_mt_char);
1618
    if (!volfile) {
1619
        gf_smsg("glusterfsd", GF_LOG_ERROR, ENOMEM, glusterfsd_msg_9,
1620
                "volume_file=%s", cmd_args->volfile, NULL);
1621
        ret = -1;
1622
        goto out;
1623
    }
1624
    ret = fread(volfile, stbuf.st_size, 1, fp);
1625
    if (IS_ERROR(ret)) {
1626
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_9,
1627
                "volume_file=%s", cmd_args->volfile, NULL);
1628
        goto out;
1629
    }
1630
    glusterfs_compute_sha256((const unsigned char *)volfile, stbuf.st_size,
1631
                             sha256_hash);
1632
    LOCK(&ctx->volfile_lock);
1633
    {
1634
        list_for_each_entry(volfile_obj, &ctx->volfile_list, volfile_list)
1635
        {
1636
            if (!memcmp(sha256_hash, volfile_obj->volfile_checksum,
1637
                        sizeof(volfile_obj->volfile_checksum))) {
1638
                UNLOCK(&ctx->volfile_lock);
1639
                ret = 0;
1640
                gf_smsg(THIS->name, GF_LOG_INFO, 0, glusterfsd_msg_40, NULL);
1641
                goto out;
1642
            }
1643
            volfile_tmp = volfile_obj;
1644
            break;
1645
        }
1646
    }
1647
    UNLOCK(&ctx->volfile_lock);
1648

1649
    /*  Check if only options have changed. No need to reload the
1650
     *  volfile if topology hasn't changed.
1651
     *  glusterfs_volfile_reconfigure returns 3 possible return states
1652
     *  return 0          =======> reconfiguration of options has succeeded
1653
     *  return 1          =======> the graph has to be reconstructed and all
1654
     * the xlators should be inited return -1(or -ve) =======> Some Internal
1655
     * Error occurred during the operation
1656
     */
1657

1658
    if (volfile_tmp) {
1659
        ret = glusterfs_volfile_reconfigure(fp, ctx);
1660
        if (ret == 0) {
1661
            gf_msg_debug("glusterfsd-mgmt", 0,
1662
                         "No need to re-load volfile, reconfigure done");
1663
            memcpy(volfile_tmp->volfile_checksum, sha256_hash,
1664
                   sizeof(volfile_tmp->volfile_checksum));
1665
            goto out;
1666
        } else {
1667
            gf_msg("glusterfsd-mgmt", GF_LOG_INFO, 0, 0,
1668
                   "reconfigure failed, continuing with init");
1669
        }
1670
    } else {
1671
        gf_msg("glusterfsd-mgmt", GF_LOG_INFO, 0, 0,
1672
               "volume not found, continuing with init");
1673
    }
1674

1675
    ret = glusterfs_process_volfp(ctx, fp);
1676
    fp = NULL; /* this is freed inside the function (both success & failure) */
1677
    if (ret)
1678
        goto out;
1679

1680
    LOCK(&ctx->volfile_lock);
1681
    {
1682
        if (!volfile_tmp) {
1683
            volfile_tmp = GF_CALLOC(1, sizeof(gf_volfile_t),
1684
                                    gf_common_volfile_t);
1685
            if (!volfile_tmp) {
1686
                ret = -1;
1687
                goto out;
1688
            }
1689

1690
            INIT_LIST_HEAD(&volfile_tmp->volfile_list);
1691
            volfile_tmp->graph = ctx->active;
1692
            list_add(&volfile_tmp->volfile_list, &ctx->volfile_list);
1693
            snprintf(volfile_tmp->vol_id, sizeof(volfile_tmp->vol_id), "%s",
1694
                     cmd_args->volfile_id);
1695
        }
1696
        memcpy(volfile_tmp->volfile_checksum, sha256_hash,
1697
               sizeof(volfile_tmp->volfile_checksum));
1698
    }
1699
    UNLOCK(&ctx->volfile_lock);
1700

1701
    ret = 0;
1702
out:
1703
    if (fp)
1704
        fclose(fp);
1705

1706
    if (volfile)
1707
        GF_FREE(volfile);
1708
    return ret;
1709
}
1710

1711
static void
1712
reincarnate(int signum)
1713
{
1714
    int ret = 0;
1715
    glusterfs_ctx_t *ctx = NULL;
1716
    cmd_args_t *cmd_args = NULL;
1717

1718
    ctx = glusterfsd_ctx;
1719
    cmd_args = &ctx->cmd_args;
1720

1721
    gf_msg_trace("gluster", 0, "received reincarnate request (sig:HUP)");
1722

1723
    if (cmd_args->volfile_server) {
1724
        gf_smsg("glusterfsd", GF_LOG_INFO, 0, glusterfsd_msg_11, NULL);
1725
        ret = glusterfs_volfile_fetch(ctx);
1726
    } else {
1727
        ret = volfile_init(ctx);
1728
    }
1729

1730
    /* Also, SIGHUP should do logrotate */
1731
    gf_log_logrotate(1);
1732

1733
    if (ret < 0)
1734
        gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_12, NULL);
1735

1736
    /* Notify all xlators */
1737
    if (ctx->active)
1738
        xlator_notify(ctx->active->top, GF_EVENT_SIGHUP, NULL);
1739

1740
    return;
1741
}
1742

1743
void
1744
emancipate(glusterfs_ctx_t *ctx, int ret)
1745
{
1746
    /* break free from the parent */
1747
    if (ctx->daemon_pipe[1] != -1) {
1748
        sys_write(ctx->daemon_pipe[1], (void *)&ret, sizeof(ret));
1749
        sys_close(ctx->daemon_pipe[1]);
1750
        ctx->daemon_pipe[1] = -1;
1751
    }
1752
}
1753

1754
static uint8_t
1755
gf_get_process_mode(char *exec_name)
1756
{
1757
    char *dup_execname = NULL, *base = NULL;
1758
    uint8_t ret = 0;
1759

1760
    dup_execname = gf_strdup(exec_name);
1761
    base = basename(dup_execname);
1762

1763
    if (!strncmp(base, "glusterfsd", 10)) {
1764
        ret = GF_SERVER_PROCESS;
1765
    } else if (!strncmp(base, "glusterd", 8)) {
1766
        ret = GF_GLUSTERD_PROCESS;
1767
    } else {
1768
        ret = GF_CLIENT_PROCESS;
1769
    }
1770

1771
    GF_FREE(dup_execname);
1772

1773
    return ret;
1774
}
1775

1776
static int
1777
glusterfs_ctx_defaults_init(glusterfs_ctx_t *ctx)
1778
{
1779
    cmd_args_t *cmd_args = NULL;
1780
    struct rlimit lim = {
1781
        0,
1782
    };
1783
    int ret = -1;
1784

1785
    if (!ctx)
1786
        return ret;
1787

1788
    ret = xlator_mem_acct_init(THIS, gfd_mt_end);
1789
    if (ret != 0) {
1790
        gf_smsg(THIS->name, GF_LOG_CRITICAL, 0, glusterfsd_msg_34, NULL);
1791
        return ret;
1792
    }
1793

1794
    /* reset ret to -1 so that we don't need to explicitly
1795
     * set it in all error paths before "goto err"
1796
     */
1797
    ret = -1;
1798

1799
    /* monitoring should be enabled by default */
1800
    ctx->measure_latency = true;
1801

1802
    ctx->process_uuid = generate_glusterfs_ctx_id();
1803
    if (!ctx->process_uuid) {
1804
        gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_13, NULL);
1805
        goto out;
1806
    }
1807

1808
    ctx->page_size = 128 * GF_UNIT_KB;
1809

1810
    ctx->iobuf_pool = iobuf_pool_new();
1811
    if (!ctx->iobuf_pool) {
1812
        gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "iobuf", NULL);
1813
        goto out;
1814
    }
1815

1816
    ctx->event_pool = gf_event_pool_new(DEFAULT_EVENT_POOL_SIZE,
1817
                                        STARTING_EVENT_THREADS);
1818
    if (!ctx->event_pool) {
1819
        gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "event", NULL);
1820
        goto out;
1821
    }
1822

1823
    ctx->pool = GF_CALLOC(1, sizeof(call_pool_t), gfd_mt_call_pool_t);
1824
    if (!ctx->pool) {
1825
        gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "call", NULL);
1826
        goto out;
1827
    }
1828

1829
    INIT_LIST_HEAD(&ctx->pool->all_frames);
1830
    LOCK_INIT(&ctx->pool->lock);
1831

1832
    /* frame_mem_pool size 112 * 4k */
1833
    ctx->pool->frame_mem_pool = mem_pool_new(call_frame_t, 4096);
1834
    if (!ctx->pool->frame_mem_pool) {
1835
        gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "frame", NULL);
1836
        goto out;
1837
    }
1838
    /* stack_mem_pool size 256 * 1024 */
1839
    ctx->pool->stack_mem_pool = mem_pool_new(call_stack_t, 1024);
1840
    if (!ctx->pool->stack_mem_pool) {
1841
        gf_smsg("", GF_LOG_CRITICAL, 0, glusterfsd_msg_14, "stack", NULL);
1842
        goto out;
1843
    }
1844

1845
    ctx->dict_pool = mem_pool_new(dict_t, GF_MEMPOOL_COUNT_OF_DICT_T);
1846
    if (!ctx->dict_pool)
1847
        goto out;
1848

1849
    ctx->dict_data_pool = mem_pool_new(data_t, GF_MEMPOOL_COUNT_OF_DATA_T);
1850
    if (!ctx->dict_data_pool)
1851
        goto out;
1852

1853
    ctx->logbuf_pool = mem_pool_new(log_buf_t, GF_MEMPOOL_COUNT_OF_LRU_BUF_T);
1854
    if (!ctx->logbuf_pool)
1855
        goto out;
1856

1857
    pthread_mutex_init(&ctx->notify_lock, NULL);
1858
    pthread_mutex_init(&ctx->cleanup_lock, NULL);
1859
    pthread_cond_init(&ctx->notify_cond, NULL);
1860

1861
    ctx->clienttable = gf_clienttable_alloc();
1862
    if (!ctx->clienttable)
1863
        goto out;
1864

1865
    cmd_args = &ctx->cmd_args;
1866

1867
    /* parsing command line arguments */
1868
    cmd_args->log_level = DEFAULT_LOG_LEVEL;
1869
    cmd_args->logger = gf_logger_glusterlog;
1870
    cmd_args->log_format = gf_logformat_withmsgid;
1871
    cmd_args->log_buf_size = GF_LOG_LRU_BUFSIZE_DEFAULT;
1872
    cmd_args->log_flush_timeout = GF_LOG_FLUSH_TIMEOUT_DEFAULT;
1873

1874
    cmd_args->mac_compat = GF_OPTION_DISABLE;
1875
#ifdef GF_DARWIN_HOST_OS
1876
    /* On Darwin machines, O_APPEND is not handled,
1877
     * which may corrupt the data
1878
     */
1879
    cmd_args->fuse_direct_io_mode = GF_OPTION_DISABLE;
1880
#else
1881
    cmd_args->fuse_direct_io_mode = GF_OPTION_DEFERRED;
1882
#endif
1883
    cmd_args->fuse_attribute_timeout = -1;
1884
    cmd_args->fuse_entry_timeout = -1;
1885
    cmd_args->fopen_keep_cache = GF_OPTION_DEFERRED;
1886
    cmd_args->kernel_writeback_cache = GF_OPTION_DEFERRED;
1887
    cmd_args->fuse_flush_handle_interrupt = GF_OPTION_DEFERRED;
1888
    cmd_args->fuse_setlk_handle_interrupt = GF_OPTION_DEFERRED;
1889

1890
    if (ctx->mem_acct_enable)
1891
        cmd_args->mem_acct = 1;
1892

1893
    INIT_LIST_HEAD(&cmd_args->xlator_options);
1894
    INIT_LIST_HEAD(&cmd_args->volfile_servers);
1895
    ctx->pxl_count = 0;
1896
    ctx->diskxl_count = 0;
1897
    pthread_mutex_init(&ctx->fd_lock, NULL);
1898
    pthread_cond_init(&ctx->fd_cond, NULL);
1899
    INIT_LIST_HEAD(&ctx->janitor_fds);
1900
    pthread_mutex_init(&ctx->xl_lock, NULL);
1901
    pthread_cond_init(&ctx->xl_cond, NULL);
1902
    INIT_LIST_HEAD(&ctx->diskth_xl);
1903

1904
    lim.rlim_cur = RLIM_INFINITY;
1905
    lim.rlim_max = RLIM_INFINITY;
1906
    setrlimit(RLIMIT_CORE, &lim);
1907

1908
    ret = 0;
1909
out:
1910

1911
    if (ret) {
1912
        if (ctx->pool) {
1913
            mem_pool_destroy(ctx->pool->frame_mem_pool);
1914
            mem_pool_destroy(ctx->pool->stack_mem_pool);
1915
        }
1916
        GF_FREE(ctx->pool);
1917
        mem_pool_destroy(ctx->dict_pool);
1918
        mem_pool_destroy(ctx->dict_data_pool);
1919
        mem_pool_destroy(ctx->logbuf_pool);
1920
    }
1921

1922
    return ret;
1923
}
1924

1925
static int
1926
gf_set_log_ident(cmd_args_t *cmd_args)
1927
{
1928
    int ret = 0;
1929
    char *ptr = NULL;
1930

1931
    if (cmd_args->log_file == NULL) {
1932
        /* no ident source */
1933
        return 0;
1934
    }
1935

1936
    /* TODO: Some idents would look like, etc-glusterfs-glusterd.vol, which
1937
     * seems ugly and can be bettered? */
1938
    /* just get the filename as the ident */
1939
    if (NULL != (ptr = strrchr(cmd_args->log_file, '/'))) {
1940
        ret = gf_asprintf(&cmd_args->log_ident, "%s", ptr + 1);
1941
    } else {
1942
        ret = gf_asprintf(&cmd_args->log_ident, "%s", cmd_args->log_file);
1943
    }
1944

1945
    if (ret > 0)
1946
        ret = 0;
1947
    else
1948
        return ret;
1949

1950
    /* remove .log suffix */
1951
    if (NULL != (ptr = strrchr(cmd_args->log_ident, '.'))) {
1952
        if (strcmp(ptr, ".log") == 0) {
1953
            ptr[0] = '\0';
1954
        }
1955
    }
1956

1957
    return ret;
1958
}
1959

1960
static int
1961
logging_init(glusterfs_ctx_t *ctx, const char *progpath)
1962
{
1963
    cmd_args_t *cmd_args = NULL;
1964
    int ret = 0;
1965

1966
    cmd_args = &ctx->cmd_args;
1967

1968
    if (cmd_args->log_file == NULL) {
1969
        ret = gf_set_log_file_path(cmd_args, ctx);
1970
        if (ret == -1) {
1971
            fprintf(stderr,
1972
                    "ERROR: failed to set the log file "
1973
                    "path\n");
1974
            return -1;
1975
        }
1976
    }
1977

1978
    if (cmd_args->log_ident == NULL) {
1979
        ret = gf_set_log_ident(cmd_args);
1980
        if (ret == -1) {
1981
            fprintf(stderr,
1982
                    "ERROR: failed to set the log "
1983
                    "identity\n");
1984
            return -1;
1985
        }
1986
    }
1987

1988
    /* finish log set parameters before init */
1989
    ctx->log.loglevel = cmd_args->log_level;
1990

1991
    ctx->log.localtime = cmd_args->localtime_logging;
1992

1993
    ctx->log.logger = cmd_args->logger;
1994

1995
    ctx->log.logformat = cmd_args->log_format;
1996

1997
    gf_log_set_log_buf_size(ctx, cmd_args->log_buf_size);
1998

1999
    ctx->log.timeout = cmd_args->log_flush_timeout;
2000

2001
    if (gf_log_init(ctx, cmd_args->log_file, cmd_args->log_ident) == -1) {
2002
        fprintf(stderr, "ERROR: failed to open logfile %s\n",
2003
                cmd_args->log_file);
2004
        return -1;
2005
    }
2006

2007
    /* At this point, all the logging related parameters are initialised
2008
     * except for the log flush timer, which will be injected post fork(2)
2009
     * in daemonize() . During this time, any log message that is logged
2010
     * will be kept buffered. And if the list that holds these messages
2011
     * overflows, then the same lru policy is used to drive out the least
2012
     * recently used message and displace it with the message just logged.
2013
     */
2014

2015
    return 0;
2016
}
2017

2018
static void
2019
gf_check_and_set_mem_acct(int argc, char *argv[])
2020
{
2021
    int i = 0;
2022

2023
    for (i = 0; i < argc; i++) {
2024
        if (strcmp(argv[i], "--no-mem-accounting") == 0) {
2025
            gf_global_mem_acct_enable_set(0);
2026
            break;
2027
        }
2028
    }
2029
}
2030
#ifdef BUILD_GNFS
2031
/**
2032
 * print_exports_file - Print out & verify the syntax
2033
 *                      of the exports file specified
2034
 *                      in the parameter.
2035
 *
2036
 * @exports_file : Path of the exports file to print & verify
2037
 *
2038
 * @return : success: 0 when successfully parsed
2039
 *           failure: 1 when failed to parse one or more lines
2040
 *                   -1 when other critical errors (dlopen () etc)
2041
 * Critical errors are treated differently than parse errors. Critical
2042
 * errors terminate the program immediately here and print out different
2043
 * error messages. Hence there are different return values.
2044
 */
2045
static int
2046
print_exports_file(const char *exports_file)
2047
{
2048
    void *libhandle = NULL;
2049
    char *libpathfull = NULL;
2050
    struct exports_file *file = NULL;
2051
    int ret = 0;
2052

2053
    int (*exp_file_parse)(const char *filepath, struct exports_file **expfile,
2054
                          struct mount3_state *ms) = NULL;
2055
    void (*exp_file_print)(const struct exports_file *file) = NULL;
2056
    void (*exp_file_deinit)(struct exports_file * ptr) = NULL;
2057

2058
    /* XLATORDIR passed through a -D flag to GCC */
2059
    ret = gf_asprintf(&libpathfull, "%s/%s/server.so", XLATORDIR, "nfs");
2060
    if (ret < 0) {
2061
        gf_log("glusterfs", GF_LOG_CRITICAL, "asprintf () failed.");
2062
        ret = -1;
2063
        goto out;
2064
    }
2065

2066
    /* Load up the library */
2067
    libhandle = dlopen(libpathfull, RTLD_NOW);
2068
    if (!libhandle) {
2069
        gf_log("glusterfs", GF_LOG_CRITICAL,
2070
               "Error loading NFS server library : "
2071
               "%s\n",
2072
               dlerror());
2073
        ret = -1;
2074
        goto out;
2075
    }
2076

2077
    /* Load up the function */
2078
    exp_file_parse = dlsym(libhandle, "exp_file_parse");
2079
    if (!exp_file_parse) {
2080
        gf_log("glusterfs", GF_LOG_CRITICAL,
2081
               "Error finding function exp_file_parse "
2082
               "in symbol.");
2083
        ret = -1;
2084
        goto out;
2085
    }
2086

2087
    /* Parse the file */
2088
    ret = exp_file_parse(exports_file, &file, NULL);
2089
    if (ret < 0) {
2090
        ret = 1; /* This means we failed to parse */
2091
        goto out;
2092
    }
2093

2094
    /* Load up the function */
2095
    exp_file_print = dlsym(libhandle, "exp_file_print");
2096
    if (!exp_file_print) {
2097
        gf_log("glusterfs", GF_LOG_CRITICAL,
2098
               "Error finding function exp_file_print in symbol.");
2099
        ret = -1;
2100
        goto out;
2101
    }
2102

2103
    /* Print it out to screen */
2104
    exp_file_print(file);
2105

2106
    /* Load up the function */
2107
    exp_file_deinit = dlsym(libhandle, "exp_file_deinit");
2108
    if (!exp_file_deinit) {
2109
        gf_log("glusterfs", GF_LOG_CRITICAL,
2110
               "Error finding function exp_file_deinit in lib.");
2111
        ret = -1;
2112
        goto out;
2113
    }
2114

2115
    /* Free the file */
2116
    exp_file_deinit(file);
2117

2118
out:
2119
    if (libhandle)
2120
        dlclose(libhandle);
2121
    GF_FREE(libpathfull);
2122
    return ret;
2123
}
2124

2125
/**
2126
 * print_netgroups_file - Print out & verify the syntax
2127
 *                        of the netgroups file specified
2128
 *                        in the parameter.
2129
 *
2130
 * @netgroups_file : Path of the netgroups file to print & verify
2131
 * @return : success: 0 when successfully parsed
2132
 *           failure: 1 when failed to parse one more more lines
2133
 *                   -1 when other critical errors (dlopen () etc)
2134
 *
2135
 * We have multiple returns here because for critical errors, we abort
2136
 * operations immediately and exit. For example, if we can't load the
2137
 * NFS server library, then we have a real bad problem so we don't continue.
2138
 * Or if we cannot allocate anymore memory, we don't want to continue. Also,
2139
 * we want to print out a different error messages based on the ret value.
2140
 */
2141
static int
2142
print_netgroups_file(const char *netgroups_file)
2143
{
2144
    void *libhandle = NULL;
2145
    char *libpathfull = NULL;
2146
    struct netgroups_file *file = NULL;
2147
    int ret = 0;
2148

2149
    struct netgroups_file *(*ng_file_parse)(const char *file_path) = NULL;
2150
    void (*ng_file_print)(const struct netgroups_file *file) = NULL;
2151
    void (*ng_file_deinit)(struct netgroups_file * ptr) = NULL;
2152

2153
    /* XLATORDIR passed through a -D flag to GCC */
2154
    ret = gf_asprintf(&libpathfull, "%s/%s/server.so", XLATORDIR, "nfs");
2155
    if (ret < 0) {
2156
        gf_log("glusterfs", GF_LOG_CRITICAL, "asprintf () failed.");
2157
        ret = -1;
2158
        goto out;
2159
    }
2160
    /* Load up the library */
2161
    libhandle = dlopen(libpathfull, RTLD_NOW);
2162
    if (!libhandle) {
2163
        gf_log("glusterfs", GF_LOG_CRITICAL,
2164
               "Error loading NFS server library : %s\n", dlerror());
2165
        ret = -1;
2166
        goto out;
2167
    }
2168

2169
    /* Load up the function */
2170
    ng_file_parse = dlsym(libhandle, "ng_file_parse");
2171
    if (!ng_file_parse) {
2172
        gf_log("glusterfs", GF_LOG_CRITICAL,
2173
               "Error finding function ng_file_parse in symbol.");
2174
        ret = -1;
2175
        goto out;
2176
    }
2177

2178
    /* Parse the file */
2179
    file = ng_file_parse(netgroups_file);
2180
    if (!file) {
2181
        ret = 1; /* This means we failed to parse */
2182
        goto out;
2183
    }
2184

2185
    /* Load up the function */
2186
    ng_file_print = dlsym(libhandle, "ng_file_print");
2187
    if (!ng_file_print) {
2188
        gf_log("glusterfs", GF_LOG_CRITICAL,
2189
               "Error finding function ng_file_print in symbol.");
2190
        ret = -1;
2191
        goto out;
2192
    }
2193

2194
    /* Print it out to screen */
2195
    ng_file_print(file);
2196

2197
    /* Load up the function */
2198
    ng_file_deinit = dlsym(libhandle, "ng_file_deinit");
2199
    if (!ng_file_deinit) {
2200
        gf_log("glusterfs", GF_LOG_CRITICAL,
2201
               "Error finding function ng_file_deinit in lib.");
2202
        ret = -1;
2203
        goto out;
2204
    }
2205

2206
    /* Free the file */
2207
    ng_file_deinit(file);
2208

2209
out:
2210
    if (libhandle)
2211
        dlclose(libhandle);
2212
    GF_FREE(libpathfull);
2213
    return ret;
2214
}
2215

2216
#endif
2217

2218
static int
2219
parse_cmdline(int argc, char *argv[], glusterfs_ctx_t *ctx)
2220
{
2221
    int process_mode = 0;
2222
    int ret = 0;
2223
    struct stat stbuf = {
2224
        0,
2225
    };
2226
    char timestr[GF_TIMESTR_SIZE];
2227
    char tmp_logfile[1024] = {0};
2228
    char *tmp_logfile_dyn = NULL;
2229
    char *tmp_logfilebase = NULL;
2230
    cmd_args_t *cmd_args = NULL;
2231
    int len = 0;
2232
    char *thin_volfileid = NULL;
2233

2234
    cmd_args = &ctx->cmd_args;
2235

2236
    /* Do this before argp_parse so it can be overridden. */
2237
    if (sys_access(SECURE_ACCESS_FILE, F_OK) == 0) {
2238
        cmd_args->secure_mgmt = 1;
2239
        ctx->ssl_cert_depth = glusterfs_read_secure_access_file();
2240
    }
2241

2242
    /* Need to set lru_limit to below 0 to indicate there was nothing
2243
       specified. This is needed as 0 is a valid option, and may not be
2244
       default value. */
2245
    cmd_args->lru_limit = -1;
2246

2247
    argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, cmd_args);
2248

2249
    if (cmd_args->print_xlatordir || cmd_args->print_statedumpdir ||
2250
        cmd_args->print_logdir || cmd_args->print_libexecdir) {
2251
        /* Just print, nothing else to do */
2252
        goto out;
2253
    }
2254

2255
    if (cmd_args->print_netgroups) {
2256
        /* When this option is set we don't want to do anything else
2257
         * except for printing & verifying the netgroups file.
2258
         */
2259
        ret = 0;
2260
        goto out;
2261
    }
2262

2263
    if (cmd_args->print_exports) {
2264
        /* When this option is set we don't want to do anything else
2265
         * except for printing & verifying the exports file.
2266
         */
2267
        ret = 0;
2268
        goto out;
2269
    }
2270

2271
    ctx->secure_mgmt = cmd_args->secure_mgmt;
2272

2273
    if (ENABLE_DEBUG_MODE == cmd_args->debug_mode) {
2274
        cmd_args->log_level = GF_LOG_DEBUG;
2275
        cmd_args->log_file = gf_strdup("/dev/stderr");
2276
        cmd_args->no_daemon_mode = ENABLE_NO_DAEMON_MODE;
2277
    }
2278

2279
    process_mode = gf_get_process_mode(argv[0]);
2280
    ctx->process_mode = process_mode;
2281

2282
    if (cmd_args->process_name) {
2283
        ctx->cmd_args.process_name = cmd_args->process_name;
2284
    }
2285
    /* Make sure after the parsing cli, if '--volfile-server' option is
2286
       given, then '--volfile-id' is mandatory */
2287
    if (cmd_args->volfile_server && !cmd_args->volfile_id) {
2288
        gf_smsg("glusterfs", GF_LOG_CRITICAL, 0, glusterfsd_msg_15, NULL);
2289
        ret = -1;
2290
        goto out;
2291
    }
2292

2293
    if ((cmd_args->volfile_server == NULL) && (cmd_args->volfile == NULL)) {
2294
        if (process_mode == GF_SERVER_PROCESS)
2295
            cmd_args->volfile = gf_strdup(DEFAULT_SERVER_VOLFILE);
2296
        else if (process_mode == GF_GLUSTERD_PROCESS)
2297
            cmd_args->volfile = gf_strdup(DEFAULT_GLUSTERD_VOLFILE);
2298
        else
2299
            cmd_args->volfile = gf_strdup(DEFAULT_CLIENT_VOLFILE);
2300

2301
        /* Check if the volfile exists, if not give usage output
2302
           and exit */
2303
        ret = sys_stat(cmd_args->volfile, &stbuf);
2304
        if (ret) {
2305
            gf_smsg("glusterfs", GF_LOG_CRITICAL, errno, glusterfsd_msg_16,
2306
                    NULL);
2307
            /* argp_usage (argp.) */
2308
            fprintf(stderr, "USAGE: %s [options] [mountpoint]\n", argv[0]);
2309
            goto out;
2310
        }
2311
    }
2312

2313
    if (cmd_args->thin_client) {
2314
        len = strlen(cmd_args->volfile_id) + SLEN("gfproxy-client/");
2315
        thin_volfileid = GF_MALLOC(len + 1, gf_common_mt_char);
2316
        snprintf(thin_volfileid, len + 1, "gfproxy-client/%s",
2317
                 cmd_args->volfile_id);
2318
        GF_FREE(cmd_args->volfile_id);
2319
        cmd_args->volfile_id = thin_volfileid;
2320
    }
2321

2322
    if (cmd_args->run_id) {
2323
        ret = sys_lstat(cmd_args->log_file, &stbuf);
2324
        /* If its /dev/null, or /dev/stdout, /dev/stderr,
2325
         * let it use the same, no need to alter
2326
         */
2327
        if (((ret == 0) &&
2328
             (S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))) ||
2329
            (ret == -1)) {
2330
            /* Have separate logfile per run. */
2331
            gf_time_fmt_FT(timestr, sizeof timestr, gf_time());
2332
            sprintf(tmp_logfile, "%s.%s.%d", cmd_args->log_file, timestr,
2333
                    getpid());
2334

2335
            /* Create symlink to actual log file */
2336
            sys_unlink(cmd_args->log_file);
2337

2338
            tmp_logfile_dyn = gf_strdup(tmp_logfile);
2339
            tmp_logfilebase = basename(tmp_logfile_dyn);
2340
            ret = sys_symlink(tmp_logfilebase, cmd_args->log_file);
2341
            if (ret == -1) {
2342
                fprintf(stderr, "ERROR: symlink of logfile failed\n");
2343
                goto out;
2344
            }
2345

2346
            GF_FREE(cmd_args->log_file);
2347
            cmd_args->log_file = gf_strdup(tmp_logfile);
2348

2349
            GF_FREE(tmp_logfile_dyn);
2350
        }
2351
    }
2352

2353
    /*
2354
       This option was made obsolete but parsing it for backward
2355
       compatibility with third party applications
2356
     */
2357
    if (cmd_args->max_connect_attempts) {
2358
        gf_smsg("glusterfs", GF_LOG_WARNING, 0, glusterfsd_msg_33, NULL);
2359
    }
2360

2361
#ifdef GF_DARWIN_HOST_OS
2362
    if (cmd_args->mount_point)
2363
        cmd_args->mac_compat = GF_OPTION_DEFERRED;
2364
#endif
2365

2366
    ret = 0;
2367
out:
2368
    return ret;
2369
}
2370

2371
static int
2372
glusterfs_pidfile_setup(glusterfs_ctx_t *ctx)
2373
{
2374
    cmd_args_t *cmd_args = NULL;
2375
    int ret = -1;
2376
    FILE *pidfp = NULL;
2377

2378
    cmd_args = &ctx->cmd_args;
2379

2380
    if (!cmd_args->pid_file)
2381
        return 0;
2382

2383
    pidfp = fopen(cmd_args->pid_file, "a+");
2384
    if (!pidfp) {
2385
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_17,
2386
                "pidfile=%s", cmd_args->pid_file, NULL);
2387
        goto out;
2388
    }
2389

2390
    ctx->pidfp = pidfp;
2391

2392
    ret = 0;
2393
out:
2394

2395
    return ret;
2396
}
2397

2398
static int
2399
glusterfs_pidfile_update(glusterfs_ctx_t *ctx, pid_t pid)
2400
{
2401
    cmd_args_t *cmd_args = NULL;
2402
    int ret = 0;
2403
    FILE *pidfp = NULL;
2404

2405
    cmd_args = &ctx->cmd_args;
2406

2407
    pidfp = ctx->pidfp;
2408
    if (!pidfp)
2409
        return 0;
2410

2411
    ret = lockf(fileno(pidfp), F_TLOCK, 0);
2412
    if (ret) {
2413
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_18,
2414
                "pidfile=%s", cmd_args->pid_file, NULL);
2415
        return ret;
2416
    }
2417

2418
    ret = sys_ftruncate(fileno(pidfp), 0);
2419
    if (ret) {
2420
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_20,
2421
                "pidfile=%s", cmd_args->pid_file, NULL);
2422
        return ret;
2423
    }
2424

2425
    ret = fprintf(pidfp, "%d\n", pid);
2426
    if (ret <= 0) {
2427
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_21,
2428
                "pidfile=%s", cmd_args->pid_file, NULL);
2429
        return ret;
2430
    }
2431

2432
    ret = fflush(pidfp);
2433
    if (ret) {
2434
        gf_smsg("glusterfsd", GF_LOG_ERROR, errno, glusterfsd_msg_21,
2435
                "pidfile=%s", cmd_args->pid_file, NULL);
2436
        return ret;
2437
    }
2438

2439
    gf_msg_debug("glusterfsd", 0, "pidfile %s updated with pid %d",
2440
                 cmd_args->pid_file, pid);
2441

2442
    return 0;
2443
}
2444

2445
static void *
2446
glusterfs_sigwaiter(void *arg)
2447
{
2448
    sigset_t set;
2449
    int ret = 0;
2450
    int sig = 0;
2451
    char *file = NULL;
2452

2453
    sigemptyset(&set);
2454
    sigaddset(&set, SIGINT);  /* cleanup_and_exit */
2455
    sigaddset(&set, SIGTERM); /* cleanup_and_exit */
2456
    sigaddset(&set, SIGHUP);  /* reincarnate */
2457
    sigaddset(&set, SIGUSR1); /* gf_proc_dump_info */
2458
    sigaddset(&set, SIGUSR2);
2459

2460
    for (;;) {
2461
        ret = sigwait(&set, &sig);
2462
        if (ret)
2463
            continue;
2464

2465
        switch (sig) {
2466
            case SIGINT:
2467
            case SIGTERM:
2468
                cleanup_and_exit(sig);
2469
                break;
2470
            case SIGHUP:
2471
                reincarnate(sig);
2472
                break;
2473
            case SIGUSR1:
2474
                gf_proc_dump_info(sig, glusterfsd_ctx);
2475
                break;
2476
            case SIGUSR2:
2477
                file = gf_monitor_metrics(glusterfsd_ctx);
2478

2479
                /* Nothing needed to be done here */
2480
                GF_FREE(file);
2481

2482
                break;
2483
            default:
2484

2485
                break;
2486
        }
2487
    }
2488

2489
    return NULL;
2490
}
2491

2492
static void
2493
glusterfsd_print_trace(int signum)
2494
{
2495
    gf_print_trace(signum, glusterfsd_ctx);
2496
}
2497

2498
static int
2499
glusterfs_signals_setup(glusterfs_ctx_t *ctx)
2500
{
2501
    sigset_t set;
2502
    int ret = 0;
2503

2504
    sigemptyset(&set);
2505

2506
    /* common setting for all threads */
2507
    signal(SIGSEGV, glusterfsd_print_trace);
2508
    signal(SIGABRT, glusterfsd_print_trace);
2509
    signal(SIGILL, glusterfsd_print_trace);
2510
    signal(SIGTRAP, glusterfsd_print_trace);
2511
    signal(SIGFPE, glusterfsd_print_trace);
2512
    signal(SIGBUS, glusterfsd_print_trace);
2513
    signal(SIGINT, cleanup_and_exit);
2514
    signal(SIGPIPE, SIG_IGN);
2515

2516
    /* block these signals from non-sigwaiter threads */
2517
    sigaddset(&set, SIGTERM); /* cleanup_and_exit */
2518
    sigaddset(&set, SIGHUP);  /* reincarnate */
2519
    sigaddset(&set, SIGUSR1); /* gf_proc_dump_info */
2520
    sigaddset(&set, SIGUSR2);
2521

2522
    /* Signals needed for asynchronous framework. */
2523
    sigaddset(&set, GF_ASYNC_SIGQUEUE);
2524
    sigaddset(&set, GF_ASYNC_SIGCTRL);
2525

2526
    ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
2527
    if (ret) {
2528
        gf_smsg("glusterfsd", GF_LOG_WARNING, errno, glusterfsd_msg_22, NULL);
2529
        return ret;
2530
    }
2531

2532
    ret = gf_thread_create(&ctx->sigwaiter, NULL, glusterfs_sigwaiter,
2533
                           (void *)&set, "sigwait");
2534
    if (ret) {
2535
        /*
2536
          TODO:
2537
          fallback to signals getting handled by other threads.
2538
          setup the signal handlers
2539
        */
2540
        gf_smsg("glusterfsd", GF_LOG_WARNING, errno, glusterfsd_msg_23, NULL);
2541
        return ret;
2542
    }
2543

2544
    return ret;
2545
}
2546

2547
static int
2548
daemonize(glusterfs_ctx_t *ctx)
2549
{
2550
    int ret = -1;
2551
    cmd_args_t *cmd_args = NULL;
2552
    int cstatus = 0;
2553
    int err = 1;
2554
    int child_pid = 0;
2555

2556
    cmd_args = &ctx->cmd_args;
2557

2558
    ret = glusterfs_pidfile_setup(ctx);
2559
    if (ret)
2560
        goto out;
2561

2562
    if (cmd_args->no_daemon_mode) {
2563
        goto postfork;
2564
    }
2565

2566
    if (cmd_args->debug_mode)
2567
        goto postfork;
2568

2569
    ret = pipe(ctx->daemon_pipe);
2570
    if (ret) {
2571
        /* If pipe() fails, retain daemon_pipe[] = {-1, -1}
2572
           and parent will just not wait for child status
2573
        */
2574
        ctx->daemon_pipe[0] = -1;
2575
        ctx->daemon_pipe[1] = -1;
2576
    }
2577

2578
    ret = os_daemon_return(0, 0);
2579
    switch (ret) {
2580
        case -1:
2581
            if (ctx->daemon_pipe[0] != -1) {
2582
                sys_close(ctx->daemon_pipe[0]);
2583
                sys_close(ctx->daemon_pipe[1]);
2584
            }
2585

2586
            gf_smsg("daemonize", GF_LOG_ERROR, errno, glusterfsd_msg_24, NULL);
2587
            goto out;
2588
        case 0:
2589
            /* child */
2590
            /* close read */
2591
            sys_close(ctx->daemon_pipe[0]);
2592
            break;
2593
        default:
2594
            /* parent */
2595
            /* close write */
2596
            child_pid = ret;
2597
            sys_close(ctx->daemon_pipe[1]);
2598

2599
            if (ctx->mnt_pid > 0) {
2600
                ret = waitpid(ctx->mnt_pid, &cstatus, 0);
2601
                if (!(ret == ctx->mnt_pid)) {
2602
                    if (WIFEXITED(cstatus)) {
2603
                        err = WEXITSTATUS(cstatus);
2604
                    } else {
2605
                        err = cstatus;
2606
                    }
2607
                    gf_smsg("daemonize", GF_LOG_ERROR, 0, glusterfsd_msg_25,
2608
                            NULL);
2609
                    exit(err);
2610
                }
2611
            }
2612
            sys_read(ctx->daemon_pipe[0], (void *)&err, sizeof(err));
2613
            /* NOTE: Only the least significant 8 bits i.e (err & 255)
2614
               will be available to parent process on calling exit() */
2615
            if (err)
2616
                _exit(abs(err));
2617

2618
            /* Update pid in parent only for glusterd process */
2619
            if (ctx->process_mode == GF_GLUSTERD_PROCESS) {
2620
                ret = glusterfs_pidfile_update(ctx, child_pid);
2621
                if (ret)
2622
                    exit(1);
2623
            }
2624
            _exit(0);
2625
    }
2626

2627
postfork:
2628
    /* Update pid in child either process_mode is not belong to glusterd
2629
       or process is spawned in no daemon mode
2630
    */
2631
    if ((ctx->process_mode != GF_GLUSTERD_PROCESS) ||
2632
        (cmd_args->no_daemon_mode)) {
2633
        ret = glusterfs_pidfile_update(ctx, getpid());
2634
        if (ret)
2635
            goto out;
2636
    }
2637
    gf_log("glusterfs", GF_LOG_INFO, "Pid of current running process is %d",
2638
           getpid());
2639
    ret = gf_log_inject_timer_event(ctx);
2640

2641
    glusterfs_signals_setup(ctx);
2642
out:
2643
    return ret;
2644
}
2645

2646
#ifdef GF_LINUX_HOST_OS
2647
static int
2648
set_oom_score_adj(glusterfs_ctx_t *ctx)
2649
{
2650
    int ret = -1;
2651
    cmd_args_t *cmd_args = NULL;
2652
    int fd = -1;
2653
    size_t oom_score_len = 0;
2654
    struct oom_api_info *api = NULL;
2655

2656
    cmd_args = &ctx->cmd_args;
2657

2658
    if (!cmd_args->oom_score_adj)
2659
        goto success;
2660

2661
    api = get_oom_api_info();
2662
    if (!api)
2663
        goto out;
2664

2665
    fd = open(api->oom_api_file, O_WRONLY);
2666
    if (fd < 0)
2667
        goto out;
2668

2669
    oom_score_len = strlen(cmd_args->oom_score_adj);
2670
    if (sys_write(fd, cmd_args->oom_score_adj, oom_score_len) !=
2671
        oom_score_len) {
2672
        sys_close(fd);
2673
        goto out;
2674
    }
2675

2676
    if (sys_close(fd) < 0)
2677
        goto out;
2678

2679
success:
2680
    ret = 0;
2681

2682
out:
2683
    return ret;
2684
}
2685
#endif
2686

2687
int
2688
glusterfs_process_volfp(glusterfs_ctx_t *ctx, FILE *fp)
2689
{
2690
    glusterfs_graph_t *graph = NULL;
2691
    int ret = -1;
2692
    xlator_t *trav = NULL;
2693

2694
    if (!ctx)
2695
        return -1;
2696

2697
    graph = glusterfs_graph_construct(fp);
2698
    if (!graph) {
2699
        gf_smsg("", GF_LOG_ERROR, 0, glusterfsd_msg_26, NULL);
2700
        goto out;
2701
    }
2702

2703
    for (trav = graph->first; trav; trav = trav->next) {
2704
        if (strcmp(trav->type, "mount/fuse") == 0) {
2705
            gf_smsg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_27, NULL);
2706
            goto out;
2707
        }
2708
    }
2709

2710
    xlator_t *xl = graph->first;
2711
    if (xl && (strcmp(xl->type, "protocol/server") == 0)) {
2712
        (void)copy_opts_to_child(xl, FIRST_CHILD(xl), "*auth*");
2713
    }
2714

2715
    ret = glusterfs_graph_prepare(graph, ctx, ctx->cmd_args.volume_name);
2716
    if (ret) {
2717
        goto out;
2718
    }
2719

2720
    ret = glusterfs_graph_activate(graph, ctx);
2721

2722
    if (ret) {
2723
        goto out;
2724
    }
2725

2726
    gf_log_dump_graph(fp, graph);
2727

2728
    ret = 0;
2729
out:
2730
    if (fp)
2731
        fclose(fp);
2732

2733
    if (ret) {
2734
        /* TODO This code makes to generic for all graphs
2735
           client as well as servers.For now it destroys
2736
           graph only for server-side xlators not for client-side
2737
           xlators, before destroying a graph call xlator fini for
2738
           xlators those call xlator_init to avoid leak
2739
        */
2740
        if (graph) {
2741
            xl = graph->first;
2742
            if ((ctx->active != graph) &&
2743
                (xl && !strcmp(xl->type, "protocol/server"))) {
2744
                /* Take dict ref for every graph xlator to avoid dict leak
2745
                   at the time of graph destroying
2746
                */
2747
                glusterfs_graph_fini(graph);
2748
                glusterfs_graph_destroy(graph);
2749
            }
2750
        }
2751

2752
        /* there is some error in setting up the first graph itself */
2753
        if (!ctx->active) {
2754
            emancipate(ctx, ret);
2755
            cleanup_and_exit(ret);
2756
        }
2757
    }
2758

2759
    return ret;
2760
}
2761

2762
static int
2763
glusterfs_volumes_init(glusterfs_ctx_t *ctx)
2764
{
2765
    cmd_args_t *cmd_args = NULL;
2766
    int ret = 0;
2767

2768
    cmd_args = &ctx->cmd_args;
2769

2770
    if (cmd_args->sock_file) {
2771
        ret = glusterfs_listener_init(ctx);
2772
        if (ret)
2773
            goto out;
2774
    }
2775

2776
    if (cmd_args->volfile_server) {
2777
        ret = glusterfs_mgmt_init(ctx);
2778
        /* return, do not emancipate() yet */
2779
        return ret;
2780
    }
2781

2782
    ret = volfile_init(ctx);
2783
out:
2784
    emancipate(ctx, ret);
2785
    return ret;
2786
}
2787

2788
/* This is the only legal global pointer  */
2789
glusterfs_ctx_t *glusterfsd_ctx;
2790

2791
GF_IO_ASYNC(main_terminate, op, static)
2792
{
2793
    //    glusterfs_ctx_destroy (ctx);
2794
    gf_async_fini();
2795

2796
    return 0;
2797
}
2798

2799
GF_IO_ASYNC(main_start, op, static)
2800
{
2801
    int32_t res;
2802

2803
    mem_pools_init();
2804

2805
    /* TODO: gf_async support should be removed once the I/O framework
2806
     *       supports multithreaded I/O without io_uring. */
2807
    res = gf_async_init(global_ctx);
2808
    if (res < 0) {
2809
        goto out;
2810
    }
2811

2812
#ifdef GF_LINUX_HOST_OS
2813
    res = set_oom_score_adj(global_ctx);
2814
    if (res)
2815
        goto out;
2816
#endif
2817

2818
    global_ctx->env = syncenv_new(0, 0, 0);
2819
    if (!global_ctx->env) {
2820
        gf_smsg("", GF_LOG_ERROR, 0, glusterfsd_msg_31, NULL);
2821
        res = -1;
2822
        goto out;
2823
    }
2824

2825
    if (!glusterfs_ctx_tw_get(global_ctx)) {
2826
        res = -1;
2827
        goto out;
2828
    }
2829

2830
    res = glusterfs_volumes_init(global_ctx);
2831
    if (res)
2832
        goto out;
2833

2834
    return 0;
2835

2836
out:
2837
    //    glusterfs_ctx_destroy (global_ctx);
2838
    gf_async_fini();
2839

2840
    /* TODO: 'res' should be a negative error code instead of -1. */
2841

2842
    return res;
2843
}
2844

2845
int
2846
main(int argc, char *argv[])
2847
{
2848
    gf_io_handlers_t main_handlers = {.setup = main_start,
2849
                                      .cleanup = main_terminate};
2850
    glusterfs_ctx_t *ctx = NULL;
2851
    int ret = -1;
2852
    char cmdlinestr[PATH_MAX] = {
2853
        0,
2854
    };
2855
    cmd_args_t *cmd = NULL;
2856

2857
    gf_check_and_set_mem_acct(argc, argv);
2858

2859
    ctx = glusterfs_ctx_new();
2860
    if (!ctx) {
2861
        gf_smsg("glusterfs", GF_LOG_CRITICAL, 0, glusterfsd_msg_29, NULL);
2862
        return ENOMEM;
2863
    }
2864
    glusterfsd_ctx = ctx;
2865

2866
    ret = glusterfs_globals_init(ctx);
2867
    if (ret)
2868
        return ret;
2869

2870
    THIS->ctx = ctx;
2871

2872
    ret = glusterfs_ctx_defaults_init(ctx);
2873
    if (ret)
2874
        goto out;
2875

2876
    ret = parse_cmdline(argc, argv, ctx);
2877
    if (ret)
2878
        goto out;
2879
    cmd = &ctx->cmd_args;
2880

2881
    if (cmd->print_xlatordir) {
2882
        /* XLATORDIR passed through a -D flag to GCC */
2883
        printf("%s\n", XLATORDIR);
2884
        goto out;
2885
    }
2886

2887
    if (cmd->print_statedumpdir) {
2888
        printf("%s\n", DEFAULT_VAR_RUN_DIRECTORY);
2889
        goto out;
2890
    }
2891

2892
    if (cmd->print_logdir) {
2893
        printf("%s\n", DEFAULT_LOG_FILE_DIRECTORY);
2894
        goto out;
2895
    }
2896

2897
    if (cmd->print_libexecdir) {
2898
        printf("%s\n", LIBEXECDIR);
2899
        goto out;
2900
    }
2901

2902
#ifdef BUILD_GNFS
2903
    if (cmd->print_netgroups) {
2904
        /* If this option is set we want to print & verify the file,
2905
         * set the return value (exit code in this case) and exit.
2906
         */
2907
        ret = print_netgroups_file(cmd->print_netgroups);
2908
        goto out;
2909
    }
2910

2911
    if (cmd->print_exports) {
2912
        /* If this option is set we want to print & verify the file,
2913
         * set the return value (exit code in this case)
2914
         * and exit.
2915
         */
2916
        ret = print_exports_file(cmd->print_exports);
2917
        goto out;
2918
    }
2919

2920
#endif
2921
    ret = logging_init(ctx, argv[0]);
2922
    if (ret)
2923
        goto out;
2924

2925
    /* set brick_mux mode only for server process */
2926
    if ((ctx->process_mode != GF_SERVER_PROCESS) && cmd->brick_mux) {
2927
        gf_smsg("glusterfs", GF_LOG_CRITICAL, 0, glusterfsd_msg_43, NULL);
2928
        goto out;
2929
    }
2930

2931
    /* log the version of glusterfs running here along with the actual
2932
       command line options. */
2933
    {
2934
        int i = 0;
2935
        int pos = 0;
2936
        int len = snprintf(cmdlinestr, sizeof(cmdlinestr), "%s", argv[0]);
2937
        for (i = 1; (i < argc) && (len > 0); i++) {
2938
            pos += len;
2939
            len = snprintf(cmdlinestr + pos, sizeof(cmdlinestr) - pos, " %s",
2940
                           argv[i]);
2941
            if ((len <= 0) || (len >= (sizeof(cmdlinestr) - pos))) {
2942
                gf_smsg("glusterfs", GF_LOG_ERROR, 0, glusterfsd_msg_029, NULL);
2943
                ret = -1;
2944
                goto out;
2945
            }
2946
        }
2947
        gf_smsg(argv[0], GF_LOG_INFO, 0, glusterfsd_msg_30, "arg=%s", argv[0],
2948
                "version=%s", PACKAGE_VERSION, "cmdlinestr=%s", cmdlinestr,
2949
                NULL);
2950

2951
        ctx->cmdlinestr = gf_strdup(cmdlinestr);
2952
    }
2953

2954
    gf_proc_dump_init();
2955

2956
    ret = create_fuse_mount(ctx);
2957
    if (ret)
2958
        goto out;
2959

2960
    ret = daemonize(ctx);
2961
    if (ret)
2962
        goto out;
2963

2964
    /* Before 'daemonize()' there are no threads started because they would
2965
     * not be cloned into the child process and would die with the parent.
2966
     * After this point, there are several initialization functions that
2967
     * can start additional threads. Let's call them from inside the I/O
2968
     * framework context so that they can decide if a new thread is needed
2969
     * or use the I/O framework for the functionalities they need. */
2970
    ret = gf_io_run(cmd->io_engine, &main_handlers, NULL);
2971

2972
out:
2973
    return ret;
2974
}
2975

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.