Blame xlators/storage/posix/src/posix-common.c

Packit Service e080da
/*
Packit Service e080da
   Copyright (c) 2006-2017 Red Hat, Inc. <http://www.redhat.com>
Packit Service e080da
   This file is part of GlusterFS.
Packit Service e080da
Packit Service e080da
   This file is licensed to you under your choice of the GNU Lesser
Packit Service e080da
   General Public License, version 3 or any later version (LGPLv3 or
Packit Service e080da
   later), or the GNU General Public License, version 2 (GPLv2), in all
Packit Service e080da
   cases as published by the Free Software Foundation.
Packit Service e080da
*/
Packit Service e080da
#define __XOPEN_SOURCE 500
Packit Service e080da
Packit Service e080da
/* for SEEK_HOLE and SEEK_DATA */
Packit Service e080da
#ifndef _GNU_SOURCE
Packit Service e080da
#define _GNU_SOURCE
Packit Service e080da
#endif
Packit Service e080da
Packit Service e080da
#include <openssl/md5.h>
Packit Service e080da
#include <stdint.h>
Packit Service e080da
#include <sys/time.h>
Packit Service e080da
#include <sys/resource.h>
Packit Service e080da
#include <errno.h>
Packit Service e080da
#include <libgen.h>
Packit Service e080da
#include <pthread.h>
Packit Service e080da
#include <ftw.h>
Packit Service e080da
#include <sys/stat.h>
Packit Service e080da
#include <signal.h>
Packit Service e080da
#include <sys/uio.h>
Packit Service e080da
#include <unistd.h>
Packit Service e080da
#include <ftw.h>
Packit Service e080da
Packit Service e080da
#ifndef GF_BSD_HOST_OS
Packit Service e080da
#include <alloca.h>
Packit Service e080da
#endif /* GF_BSD_HOST_OS */
Packit Service e080da
Packit Service e080da
#ifdef HAVE_LINKAT
Packit Service e080da
#include <fcntl.h>
Packit Service e080da
#endif /* HAVE_LINKAT */
Packit Service e080da
Packit Service e080da
#include <glusterfs/glusterfs.h>
Packit Service e080da
#include <glusterfs/checksum.h>
Packit Service e080da
#include <glusterfs/dict.h>
Packit Service e080da
#include <glusterfs/logging.h>
Packit Service e080da
#include "posix.h"
Packit Service e080da
#include "posix-inode-handle.h"
Packit Service e080da
#include <glusterfs/xlator.h>
Packit Service e080da
#include <glusterfs/defaults.h>
Packit Service e080da
#include <glusterfs/common-utils.h>
Packit Service e080da
#include <glusterfs/compat-errno.h>
Packit Service e080da
#include <glusterfs/compat.h>
Packit Service e080da
#include <glusterfs/byte-order.h>
Packit Service e080da
#include <glusterfs/syscall.h>
Packit Service e080da
#include <glusterfs/statedump.h>
Packit Service e080da
#include <glusterfs/locking.h>
Packit Service e080da
#include <glusterfs/timer.h>
Packit Service e080da
#include "glusterfs3-xdr.h"
Packit Service e080da
#include <glusterfs/hashfn.h>
Packit Service e080da
#include "posix-aio.h"
Packit Service e080da
#include <glusterfs/glusterfs-acl.h>
Packit Service e080da
#include "posix-messages.h"
Packit Service e080da
#include <glusterfs/events.h>
Packit Service e080da
#include "posix-gfid-path.h"
Packit Service e080da
#include <glusterfs/compat-uuid.h>
Packit Service e080da
#include "timer-wheel.h"
Packit Service e080da
Packit Service e080da
extern char *marker_xattrs[];
Packit Service e080da
#define ALIGN_SIZE 4096
Packit Service e080da
Packit Service e080da
#undef HAVE_SET_FSID
Packit Service e080da
#ifdef HAVE_SET_FSID
Packit Service e080da
Packit Service e080da
#define DECLARE_OLD_FS_ID_VAR                                                  \
Packit Service e080da
    uid_t old_fsuid;                                                           \
Packit Service e080da
    gid_t old_fsgid;
Packit Service e080da
Packit Service e080da
#define SET_FS_ID(uid, gid)                                                    \
Packit Service e080da
    do {                                                                       \
Packit Service e080da
        old_fsuid = setfsuid(uid);                                             \
Packit Service e080da
        old_fsgid = setfsgid(gid);                                             \
Packit Service e080da
    } while (0)
Packit Service e080da
Packit Service e080da
#define SET_TO_OLD_FS_ID()                                                     \
Packit Service e080da
    do {                                                                       \
Packit Service e080da
        setfsuid(old_fsuid);                                                   \
Packit Service e080da
        setfsgid(old_fsgid);                                                   \
Packit Service e080da
    } while (0)
Packit Service e080da
Packit Service e080da
#else
Packit Service e080da
Packit Service e080da
#define DECLARE_OLD_FS_ID_VAR
Packit Service e080da
#define SET_FS_ID(uid, gid)
Packit Service e080da
#define SET_TO_OLD_FS_ID()
Packit Service e080da
Packit Service e080da
#endif
Packit Service e080da
Packit Service e080da
/* Setting microseconds or nanoseconds depending on what's supported:
Packit Service e080da
   The passed in `tv` can be
Packit Service e080da
       struct timespec
Packit Service e080da
   if supported (better, because it supports nanosecond resolution) or
Packit Service e080da
       struct timeval
Packit Service e080da
   otherwise. */
Packit Service e080da
#if HAVE_UTIMENSAT
Packit Service e080da
#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) tv.tv_nsec = nanosecs
Packit Service e080da
#else
Packit Service e080da
#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs)                        \
Packit Service e080da
    tv.tv_usec = nanosecs / 1000
Packit Service e080da
#endif
Packit Service e080da
Packit Service e080da
int32_t
Packit Service e080da
posix_priv(xlator_t *this)
Packit Service e080da
{
Packit Service e080da
    struct posix_private *priv = NULL;
Packit Service e080da
    char key_prefix[GF_DUMP_MAX_BUF_LEN];
Packit Service e080da
Packit Service e080da
    (void)snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s", this->type,
Packit Service e080da
                   this->name);
Packit Service e080da
    gf_proc_dump_add_section("%s", key_prefix);
Packit Service e080da
Packit Service e080da
    if (!this)
Packit Service e080da
        return 0;
Packit Service e080da
Packit Service e080da
    priv = this->private;
Packit Service e080da
Packit Service e080da
    if (!priv)
Packit Service e080da
        return 0;
Packit Service e080da
Packit Service e080da
    gf_proc_dump_write("base_path", "%s", priv->base_path);
Packit Service e080da
    gf_proc_dump_write("base_path_length", "%d", priv->base_path_length);
Packit Service e080da
    gf_proc_dump_write("max_read", "%" PRId64, GF_ATOMIC_GET(priv->read_value));
Packit Service e080da
    gf_proc_dump_write("max_write", "%" PRId64,
Packit Service e080da
                       GF_ATOMIC_GET(priv->write_value));
Packit Service e080da
    gf_proc_dump_write("nr_files", "%" PRId64, GF_ATOMIC_GET(priv->nr_files));
Packit Service e080da
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
int32_t
Packit Service e080da
posix_inode(xlator_t *this)
Packit Service e080da
{
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
/**
Packit Service e080da
 * notify - when parent sends PARENT_UP, send CHILD_UP event from here
Packit Service e080da
 */
Packit Service e080da
int32_t
Packit Service e080da
posix_notify(xlator_t *this, int32_t event, void *data, ...)
Packit Service e080da
{
Packit Service e080da
    xlator_t *victim = data;
Packit Service 173fb3
    struct posix_private *priv = this->private;
Packit Service 173fb3
    int ret = 0;
Packit Service 173fb3
    struct timespec sleep_till = {
Packit Service 173fb3
        0,
Packit Service 173fb3
    };
Packit Service e080da
Packit Service e080da
    switch (event) {
Packit Service e080da
        case GF_EVENT_PARENT_UP: {
Packit Service 173fb3
            /* the parent that posix xlator is up */
Packit Service e080da
            default_notify(this, GF_EVENT_CHILD_UP, data);
Packit Service e080da
        } break;
Packit Service e080da
Packit Service e080da
        case GF_EVENT_PARENT_DOWN: {
Packit Service e080da
            if (!victim->cleanup_starting)
Packit Service e080da
                break;
Packit Service e080da
            gf_log(this->name, GF_LOG_INFO, "Sending CHILD_DOWN for brick %s",
Packit Service e080da
                   victim->name);
Packit Service 173fb3
Packit Service 173fb3
            if (priv->janitor) {
Packit Service 173fb3
                pthread_mutex_lock(&priv->janitor_mutex);
Packit Service 173fb3
                {
Packit Service 173fb3
                    priv->janitor_task_stop = _gf_true;
Packit Service 173fb3
                    ret = gf_tw_del_timer(this->ctx->tw->timer_wheel,
Packit Service 173fb3
                                          priv->janitor);
Packit Service 173fb3
                    if (!ret) {
Packit Service 173fb3
                        clock_gettime(CLOCK_REALTIME, &sleep_till);
Packit Service 173fb3
                        sleep_till.tv_sec += 1;
Packit Service 173fb3
                        /* Wait to set janitor_task flag to _gf_false by
Packit Service 173fb3
                         * janitor_task_done */
Packit Service 173fb3
                        while (priv->janitor_task_stop) {
Packit Service 173fb3
                            (void)pthread_cond_timedwait(&priv->janitor_cond,
Packit Service 173fb3
                                                         &priv->janitor_mutex,
Packit Service 173fb3
                                                         &sleep_till);
Packit Service 173fb3
                            clock_gettime(CLOCK_REALTIME, &sleep_till);
Packit Service 173fb3
                            sleep_till.tv_sec += 1;
Packit Service 173fb3
                        }
Packit Service 173fb3
                    }
Packit Service 173fb3
                }
Packit Service 173fb3
                pthread_mutex_unlock(&priv->janitor_mutex);
Packit Service 173fb3
                GF_FREE(priv->janitor);
Packit Service 173fb3
            }
Packit Service 173fb3
            priv->janitor = NULL;
Packit Service e080da
            default_notify(this->parents->xlator, GF_EVENT_CHILD_DOWN, data);
Packit Service e080da
        } break;
Packit Service e080da
        default:
Packit Service e080da
            /* */
Packit Service e080da
            break;
Packit Service e080da
    }
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
int32_t
Packit Service e080da
mem_acct_init(xlator_t *this)
Packit Service e080da
{
Packit Service e080da
    int ret = -1;
Packit Service e080da
Packit Service e080da
    if (!this)
Packit Service e080da
        return ret;
Packit Service e080da
Packit Service e080da
    ret = xlator_mem_acct_init(this, gf_posix_mt_end + 1);
Packit Service e080da
Packit Service e080da
    if (ret != 0) {
Packit Service e080da
        return ret;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    return ret;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
static int
Packit Service e080da
posix_set_owner(xlator_t *this, uid_t uid, gid_t gid)
Packit Service e080da
{
Packit Service e080da
    struct posix_private *priv = NULL;
Packit Service e080da
    int ret = -1;
Packit Service e080da
    struct stat st = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
Packit Service e080da
    priv = this->private;
Packit Service e080da
Packit Service e080da
    ret = sys_lstat(priv->base_path, &st);
Packit Service e080da
    if (ret) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_DIR_OPERATION_FAILED,
Packit Service e080da
               "Failed to stat "
Packit Service e080da
               "brick path %s",
Packit Service e080da
               priv->base_path);
Packit Service e080da
        return ret;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    if ((uid == -1 || st.st_uid == uid) && (gid == -1 || st.st_gid == gid))
Packit Service e080da
        return 0;
Packit Service e080da
Packit Service e080da
    ret = sys_chown(priv->base_path, uid, gid);
Packit Service e080da
    if (ret)
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_DIR_OPERATION_FAILED,
Packit Service e080da
               "Failed to set uid/gid for"
Packit Service e080da
               " brick path %s",
Packit Service e080da
               priv->base_path);
Packit Service e080da
Packit Service e080da
    return ret;
Packit Service e080da
}
Packit Service e080da
static int
Packit Service e080da
set_gfid2path_separator(struct posix_private *priv, const char *str)
Packit Service e080da
{
Packit Service e080da
    int str_len = 0;
Packit Service e080da
Packit Service e080da
    str_len = strlen(str);
Packit Service e080da
    if (str_len > 0 && str_len < 8) {
Packit Service e080da
        strcpy(priv->gfid2path_sep, str);
Packit Service e080da
        return 0;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    return -1;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
static int
Packit Service e080da
set_batch_fsync_mode(struct posix_private *priv, const char *str)
Packit Service e080da
{
Packit Service e080da
    if (strcmp(str, "none") == 0)
Packit Service e080da
        priv->batch_fsync_mode = BATCH_NONE;
Packit Service e080da
    else if (strcmp(str, "syncfs") == 0)
Packit Service e080da
        priv->batch_fsync_mode = BATCH_SYNCFS;
Packit Service e080da
    else if (strcmp(str, "syncfs-single-fsync") == 0)
Packit Service e080da
        priv->batch_fsync_mode = BATCH_SYNCFS_SINGLE_FSYNC;
Packit Service e080da
    else if (strcmp(str, "syncfs-reverse-fsync") == 0)
Packit Service e080da
        priv->batch_fsync_mode = BATCH_SYNCFS_REVERSE_FSYNC;
Packit Service e080da
    else if (strcmp(str, "reverse-fsync") == 0)
Packit Service e080da
        priv->batch_fsync_mode = BATCH_REVERSE_FSYNC;
Packit Service e080da
    else
Packit Service e080da
        return -1;
Packit Service e080da
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
#ifdef GF_DARWIN_HOST_OS
Packit Service e080da
static int
Packit Service e080da
set_xattr_user_namespace_mode(struct posix_private *priv, const char *str)
Packit Service e080da
{
Packit Service e080da
    if (strcmp(str, "none") == 0)
Packit Service e080da
        priv->xattr_user_namespace = XATTR_NONE;
Packit Service e080da
    else if (strcmp(str, "strip") == 0)
Packit Service e080da
        priv->xattr_user_namespace = XATTR_STRIP;
Packit Service e080da
    else if (strcmp(str, "append") == 0)
Packit Service e080da
        priv->xattr_user_namespace = XATTR_APPEND;
Packit Service e080da
    else if (strcmp(str, "both") == 0)
Packit Service e080da
        priv->xattr_user_namespace = XATTR_BOTH;
Packit Service e080da
    else
Packit Service e080da
        return -1;
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
#endif
Packit Service e080da
Packit Service e080da
int
Packit Service e080da
posix_reconfigure(xlator_t *this, dict_t *options)
Packit Service e080da
{
Packit Service e080da
    int ret = -1;
Packit Service e080da
    struct posix_private *priv = NULL;
Packit Service e080da
    int32_t uid = -1;
Packit Service e080da
    int32_t gid = -1;
Packit Service e080da
    char *batch_fsync_mode_str = NULL;
Packit Service e080da
    char *gfid2path_sep = NULL;
Packit Service e080da
    int32_t force_create_mode = -1;
Packit Service e080da
    int32_t force_directory_mode = -1;
Packit Service e080da
    int32_t create_mask = -1;
Packit Service e080da
    int32_t create_directory_mask = -1;
Packit Service e080da
Packit Service e080da
    priv = this->private;
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("brick-uid", uid, options, int32, out);
Packit Service e080da
    GF_OPTION_RECONF("brick-gid", gid, options, int32, out);
Packit Service e080da
    if (uid != -1 || gid != -1)
Packit Service e080da
        posix_set_owner(this, uid, gid);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("batch-fsync-delay-usec", priv->batch_fsync_delay_usec,
Packit Service e080da
                     options, uint32, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("batch-fsync-mode", batch_fsync_mode_str, options, str,
Packit Service e080da
                     out);
Packit Service e080da
Packit Service e080da
    if (set_batch_fsync_mode(priv, batch_fsync_mode_str) != 0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT,
Packit Service e080da
               "Unknown mode string: %s", batch_fsync_mode_str);
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("gfid2path-separator", gfid2path_sep, options, str, out);
Packit Service e080da
    if (set_gfid2path_separator(priv, gfid2path_sep) != 0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT,
Packit Service e080da
               "Length of separator exceeds 7: %s", gfid2path_sep);
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
#ifdef GF_DARWIN_HOST_OS
Packit Service e080da
Packit Service e080da
    char *xattr_user_namespace_mode_str = NULL;
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("xattr-user-namespace-mode", xattr_user_namespace_mode_str,
Packit Service e080da
                     options, str, out);
Packit Service e080da
Packit Service e080da
    if (set_xattr_user_namespace_mode(priv, xattr_user_namespace_mode_str) !=
Packit Service e080da
        0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_UNKNOWN_ARGUMENT,
Packit Service e080da
               "Unknown xattr user namespace mode string: %s",
Packit Service e080da
               xattr_user_namespace_mode_str);
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
#endif
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("linux-aio", priv->aio_configured, options, bool, out);
Packit Service e080da
Packit Service e080da
    if (priv->aio_configured)
Packit Service e080da
        posix_aio_on(this);
Packit Service e080da
    else
Packit Service e080da
        posix_aio_off(this);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("update-link-count-parent", priv->update_pgfid_nlinks,
Packit Service e080da
                     options, bool, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("gfid2path", priv->gfid2path, options, bool, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("node-uuid-pathinfo", priv->node_uuid_pathinfo, options,
Packit Service e080da
                     bool, out);
Packit Service e080da
Packit Service e080da
    if (priv->node_uuid_pathinfo && (gf_uuid_is_null(priv->glusterd_uuid))) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_INFO, 0, P_MSG_UUID_NULL,
Packit Service e080da
               "glusterd uuid is NULL, pathinfo xattr would"
Packit Service e080da
               " fallback to <hostname>:<export>");
Packit Service e080da
    }
Packit Service e080da
Packit Service 173fb3
    GF_OPTION_RECONF("reserve", priv->disk_reserve, options, percent_or_size,
Packit Service 173fb3
                     out);
Packit Service 173fb3
    /* option can be any one of percent or bytes */
Packit Service 173fb3
    priv->disk_unit = 0;
Packit Service 173fb3
    if (priv->disk_reserve < 100.0)
Packit Service 173fb3
        priv->disk_unit = 'p';
Packit Service 173fb3
Packit Service e080da
    if (priv->disk_reserve) {
Packit Service e080da
        ret = posix_spawn_disk_space_check_thread(this);
Packit Service 173fb3
        if (ret) {
Packit Service 173fb3
            gf_msg(this->name, GF_LOG_INFO, 0, P_MSG_DISK_SPACE_CHECK_FAILED,
Packit Service 173fb3
                   "Getting disk space check from thread failed");
Packit Service e080da
            goto out;
Packit Service 173fb3
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("health-check-interval", priv->health_check_interval,
Packit Service e080da
                     options, uint32, out);
Packit Service e080da
    GF_OPTION_RECONF("health-check-timeout", priv->health_check_timeout,
Packit Service e080da
                     options, uint32, out);
Packit Service e080da
    if (priv->health_check_interval) {
Packit Service e080da
        ret = posix_spawn_health_check_thread(this);
Packit Service e080da
        if (ret)
Packit Service e080da
            goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("shared-brick-count", priv->shared_brick_count, options,
Packit Service e080da
                     int32, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("disable-landfill-purge", priv->disable_landfill_purge,
Packit Service e080da
                     options, bool, out);
Packit Service e080da
    if (priv->disable_landfill_purge) {
Packit Service e080da
        gf_log(this->name, GF_LOG_WARNING,
Packit Service e080da
               "Janitor WILL NOT purge the landfill directory. "
Packit Service e080da
               "Your landfill directory"
Packit Service e080da
               " may fill up this brick.");
Packit Service e080da
    } else {
Packit Service e080da
        gf_msg_debug(this->name, 0,
Packit Service e080da
                     "Janitor will purge the landfill "
Packit Service e080da
                     "directory, which is default behavior");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("force-create-mode", force_create_mode, options, int32,
Packit Service e080da
                     out);
Packit Service e080da
    priv->force_create_mode = force_create_mode;
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("force-directory-mode", force_directory_mode, options,
Packit Service e080da
                     int32, out);
Packit Service e080da
    priv->force_directory_mode = force_directory_mode;
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("create-mask", create_mask, options, int32, out);
Packit Service e080da
    priv->create_mask = create_mask;
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("create-directory-mask", create_directory_mask, options,
Packit Service e080da
                     int32, out);
Packit Service e080da
    priv->create_directory_mask = create_directory_mask;
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("max-hardlinks", priv->max_hardlinks, options, uint32,
Packit Service e080da
                     out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("fips-mode-rchecksum", priv->fips_mode_rchecksum, options,
Packit Service e080da
                     bool, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_RECONF("ctime", priv->ctime, options, bool, out);
Packit Service e080da
Packit Service e080da
    ret = 0;
Packit Service e080da
out:
Packit Service e080da
    return ret;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
int32_t
Packit Service e080da
posix_delete_unlink_entry(const char *fpath, const struct stat *sb,
Packit Service e080da
                          int typeflag, struct FTW *ftwbuf)
Packit Service e080da
{
Packit Service e080da
    int ret = 0;
Packit Service e080da
Packit Service e080da
    if (!fpath)
Packit Service e080da
        goto out;
Packit Service e080da
Packit Service e080da
    switch (typeflag) {
Packit Service e080da
        case FTW_SL:
Packit Service e080da
        case FTW_NS:
Packit Service e080da
        case FTW_F:
Packit Service e080da
        case FTW_SLN:
Packit Service e080da
            ret = sys_unlink(fpath);
Packit Service e080da
            break;
Packit Service e080da
        case FTW_D:
Packit Service e080da
        case FTW_DP:
Packit Service e080da
        case FTW_DNR:
Packit Service e080da
            if (ftwbuf->level != 0) {
Packit Service e080da
                ret = sys_rmdir(fpath);
Packit Service e080da
            }
Packit Service e080da
            break;
Packit Service e080da
        default:
Packit Service e080da
            break;
Packit Service e080da
    }
Packit Service e080da
    if (ret) {
Packit Service e080da
        gf_msg("posix_delete_unlink_entry", GF_LOG_WARNING, errno,
Packit Service e080da
               P_MSG_HANDLE_CREATE,
Packit Service e080da
               "Deletion of entries %s failed"
Packit Service e080da
               "Please delete it manually",
Packit Service e080da
               fpath);
Packit Service e080da
    }
Packit Service e080da
out:
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
int32_t
Packit Service e080da
posix_delete_unlink(const char *unlink_path)
Packit Service e080da
{
Packit Service e080da
    int ret = -1;
Packit Service e080da
    int flags = 0;
Packit Service e080da
Packit Service e080da
    flags |= (FTW_DEPTH | FTW_PHYS);
Packit Service e080da
Packit Service e080da
    ret = nftw(unlink_path, posix_delete_unlink_entry, 2, flags);
Packit Service e080da
    if (ret) {
Packit Service e080da
        gf_msg("posix_delete_unlink", GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE,
Packit Service e080da
               "Deleting files from  %s failed", unlink_path);
Packit Service e080da
    }
Packit Service e080da
    return ret;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
int32_t
Packit Service e080da
posix_create_unlink_dir(xlator_t *this)
Packit Service e080da
{
Packit Service e080da
    struct posix_private *priv = NULL;
Packit Service e080da
    struct stat stbuf;
Packit Service e080da
    int ret = -1;
Packit Service e080da
    uuid_t gfid = {0};
Packit Service e080da
    char gfid_str[64] = {0};
Packit Service e080da
    char unlink_path[PATH_MAX] = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
    char landfill_path[PATH_MAX] = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
Packit Service e080da
    priv = this->private;
Packit Service e080da
Packit Service e080da
    (void)snprintf(unlink_path, sizeof(unlink_path), "%s/%s", priv->base_path,
Packit Service e080da
                   GF_UNLINK_PATH);
Packit Service e080da
Packit Service e080da
    gf_uuid_generate(gfid);
Packit Service e080da
    uuid_utoa_r(gfid, gfid_str);
Packit Service e080da
Packit Service e080da
    (void)snprintf(landfill_path, sizeof(landfill_path), "%s/%s/%s",
Packit Service e080da
                   priv->base_path, GF_LANDFILL_PATH, gfid_str);
Packit Service e080da
Packit Service e080da
    ret = sys_stat(unlink_path, &stbuf);
Packit Service e080da
    switch (ret) {
Packit Service e080da
        case -1:
Packit Service e080da
            if (errno != ENOENT) {
Packit Service e080da
                gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE,
Packit Service e080da
                       "Checking for %s failed", unlink_path);
Packit Service e080da
                return -1;
Packit Service e080da
            }
Packit Service e080da
            break;
Packit Service e080da
        case 0:
Packit Service e080da
            if (!S_ISDIR(stbuf.st_mode)) {
Packit Service e080da
                gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE,
Packit Service e080da
                       "Not a directory: %s", unlink_path);
Packit Service e080da
                return -1;
Packit Service e080da
            }
Packit Service e080da
            ret = posix_delete_unlink(unlink_path);
Packit Service e080da
            return 0;
Packit Service e080da
        default:
Packit Service e080da
            break;
Packit Service e080da
    }
Packit Service e080da
    ret = sys_mkdir(unlink_path, 0600);
Packit Service e080da
    if (ret) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE,
Packit Service e080da
               "Creating directory %s failed", unlink_path);
Packit Service e080da
        return -1;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    return 0;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
/**
Packit Service e080da
 * init -
Packit Service e080da
 */
Packit Service e080da
int
Packit Service e080da
posix_init(xlator_t *this)
Packit Service e080da
{
Packit Service e080da
    struct posix_private *_private = NULL;
Packit Service e080da
    data_t *dir_data = NULL;
Packit Service e080da
    data_t *tmp_data = NULL;
Packit Service e080da
    struct stat buf = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
    gf_boolean_t tmp_bool = 0;
Packit Service e080da
    int ret = 0;
Packit Service e080da
    int op_ret = -1;
Packit Service e080da
    int op_errno = 0;
Packit Service e080da
    ssize_t size = -1;
Packit Service e080da
    uuid_t old_uuid = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
    uuid_t dict_uuid = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
    uuid_t gfid = {
Packit Service e080da
        0,
Packit Service e080da
    };
Packit Service e080da
    uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
Packit Service e080da
    char *guuid = NULL;
Packit Service e080da
    int32_t uid = -1;
Packit Service e080da
    int32_t gid = -1;
Packit Service e080da
    char *batch_fsync_mode_str;
Packit Service e080da
    char *gfid2path_sep = NULL;
Packit Service e080da
    int force_create = -1;
Packit Service e080da
    int force_directory = -1;
Packit Service e080da
    int create_mask = -1;
Packit Service e080da
    int create_directory_mask = -1;
Packit Service e080da
Packit Service e080da
    dir_data = dict_get(this->options, "directory");
Packit Service e080da
Packit Service e080da
    if (this->children) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_CRITICAL, 0, P_MSG_SUBVOLUME_ERROR,
Packit Service e080da
               "FATAL: storage/posix cannot have subvolumes");
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    if (!this->parents) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_VOLUME_DANGLING,
Packit Service e080da
               "Volume is dangling. Please check the volume file.");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    if (!dir_data) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_CRITICAL, 0, P_MSG_EXPORT_DIR_MISSING,
Packit Service e080da
               "Export directory not specified in volume file.");
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    umask(000);  // umask `masking' is done at the client side
Packit Service e080da
Packit Service e080da
    /* Check whether the specified directory exists, if not log it. */
Packit Service e080da
    op_ret = sys_stat(dir_data->data, &buf;;
Packit Service e080da
    if ((op_ret != 0) || !S_ISDIR(buf.st_mode)) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_DIR_OPERATION_FAILED,
Packit Service e080da
               "Directory '%s' doesn't exist, exiting.", dir_data->data);
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    _private = GF_CALLOC(1, sizeof(*_private), gf_posix_mt_posix_private);
Packit Service e080da
    if (!_private) {
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    _private->base_path = gf_strdup(dir_data->data);
Packit Service e080da
    _private->base_path_length = strlen(_private->base_path);
Packit Service e080da
Packit Service e080da
    ret = dict_get_str(this->options, "hostname", &_private->hostname);
Packit Service e080da
    if (ret) {
Packit Service e080da
        _private->hostname = GF_CALLOC(256, sizeof(char), gf_common_mt_char);
Packit Service e080da
        if (!_private->hostname) {
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
        ret = gethostname(_private->hostname, 256);
Packit Service e080da
        if (ret < 0) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HOSTNAME_MISSING,
Packit Service e080da
                   "could not find hostname ");
Packit Service e080da
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    /* Check for Extended attribute support, if not present, log it */
Packit Service e080da
    op_ret = sys_lsetxattr(dir_data->data, "trusted.glusterfs.test", "working",
Packit Service e080da
                           8, 0);
Packit Service e080da
    if (op_ret != -1) {
Packit Service e080da
        ret = sys_lremovexattr(dir_data->data, "trusted.glusterfs.test");
Packit Service e080da
        if (ret) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_DEBUG, errno, P_MSG_INVALID_OPTION,
Packit Service e080da
                   "failed to remove xattr: "
Packit Service e080da
                   "trusted.glusterfs.test");
Packit Service e080da
        }
Packit Service e080da
    } else {
Packit Service e080da
        tmp_data = dict_get(this->options, "mandate-attribute");
Packit Service e080da
        if (tmp_data) {
Packit Service e080da
            if (gf_string2boolean(tmp_data->data, &tmp_bool) == -1) {
Packit Service e080da
                gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_OPTION,
Packit Service e080da
                       "wrong option provided for key "
Packit Service e080da
                       "\"mandate-attribute\"");
Packit Service e080da
                ret = -1;
Packit Service e080da
                goto out;
Packit Service e080da
            }
Packit Service e080da
            if (!tmp_bool) {
Packit Service e080da
                gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_XATTR_NOTSUP,
Packit Service e080da
                       "Extended attribute not supported, "
Packit Service e080da
                       "starting as per option");
Packit Service e080da
            } else {
Packit Service e080da
                gf_msg(this->name, GF_LOG_CRITICAL, 0, P_MSG_XATTR_NOTSUP,
Packit Service e080da
                       "Extended attribute not supported, "
Packit Service e080da
                       "exiting.");
Packit Service e080da
                ret = -1;
Packit Service e080da
                goto out;
Packit Service e080da
            }
Packit Service e080da
        } else {
Packit Service e080da
            gf_msg(this->name, GF_LOG_CRITICAL, 0, P_MSG_XATTR_NOTSUP,
Packit Service e080da
                   "Extended attribute not supported, exiting.");
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    tmp_data = dict_get(this->options, "volume-id");
Packit Service e080da
    if (tmp_data) {
Packit Service e080da
        op_ret = gf_uuid_parse(tmp_data->data, dict_uuid);
Packit Service e080da
        if (op_ret < 0) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_VOLUME_ID,
Packit Service e080da
                   "wrong volume-id (%s) set"
Packit Service e080da
                   " in volume file",
Packit Service e080da
                   tmp_data->data);
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
        size = sys_lgetxattr(dir_data->data, "trusted.glusterfs.volume-id",
Packit Service e080da
                             old_uuid, 16);
Packit Service e080da
        if (size == 16) {
Packit Service e080da
            if (gf_uuid_compare(old_uuid, dict_uuid)) {
Packit Service e080da
                gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_VOLUME_ID,
Packit Service e080da
                       "mismatching volume-id (%s) received. "
Packit Service e080da
                       "already is a part of volume %s ",
Packit Service e080da
                       tmp_data->data, uuid_utoa(old_uuid));
Packit Service e080da
                gf_event(EVENT_POSIX_ALREADY_PART_OF_VOLUME,
Packit Service e080da
                         "volume-id=%s;brick=%s:%s", uuid_utoa(old_uuid),
Packit Service e080da
                         _private->hostname, _private->base_path);
Packit Service e080da
                ret = -1;
Packit Service e080da
                goto out;
Packit Service e080da
            }
Packit Service e080da
        } else if ((size == -1) && (errno == ENODATA || errno == ENOATTR)) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_VOLUME_ID_ABSENT,
Packit Service e080da
                   "Extended attribute trusted.glusterfs."
Packit Service e080da
                   "volume-id is absent");
Packit Service e080da
            gf_event(EVENT_POSIX_BRICK_NOT_IN_VOLUME, "brick=%s:%s",
Packit Service e080da
                     _private->hostname, _private->base_path);
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
Packit Service e080da
        } else if ((size == -1) && (errno != ENODATA) && (errno != ENOATTR)) {
Packit Service e080da
            /* Wrong 'volume-id' is set, it should be error */
Packit Service e080da
            gf_event(EVENT_POSIX_BRICK_VERIFICATION_FAILED, "brick=%s:%s",
Packit Service e080da
                     _private->hostname, _private->base_path);
Packit Service e080da
            gf_msg(this->name, GF_LOG_WARNING, errno,
Packit Service e080da
                   P_MSG_VOLUME_ID_FETCH_FAILED,
Packit Service e080da
                   "%s: failed to fetch volume-id", dir_data->data);
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
        } else {
Packit Service e080da
            ret = -1;
Packit Service e080da
            gf_event(EVENT_POSIX_BRICK_VERIFICATION_FAILED, "brick=%s:%s",
Packit Service e080da
                     _private->hostname, _private->base_path);
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_VOLUME_ID_FETCH_FAILED,
Packit Service e080da
                   "failed to fetch proper volume id from export");
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    /* Now check if the export directory has some other 'gfid',
Packit Service e080da
       other than that of root '/' */
Packit Service e080da
    size = sys_lgetxattr(dir_data->data, "trusted.gfid", gfid, 16);
Packit Service e080da
    if (size == 16) {
Packit Service e080da
        if (!__is_root_gfid(gfid)) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GFID_SET_FAILED,
Packit Service e080da
                   "%s: gfid (%s) is not that of glusterfs '/' ",
Packit Service e080da
                   dir_data->data, uuid_utoa(gfid));
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
    } else if (size != -1) {
Packit Service e080da
        /* Wrong 'gfid' is set, it should be error */
Packit Service e080da
        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GFID_SET_FAILED,
Packit Service e080da
               "%s: wrong value set as gfid", dir_data->data);
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    } else if ((size == -1) && (errno != ENODATA) && (errno != ENOATTR)) {
Packit Service e080da
        /* Wrong 'gfid' is set, it should be error */
Packit Service e080da
        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GFID_SET_FAILED,
Packit Service e080da
               "%s: failed to fetch gfid", dir_data->data);
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    } else {
Packit Service e080da
        /* First time volume, set the GFID */
Packit Service e080da
        size = sys_lsetxattr(dir_data->data, "trusted.gfid", rootgfid, 16,
Packit Service e080da
                             XATTR_CREATE);
Packit Service e080da
        if (size == -1) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_GFID_SET_FAILED,
Packit Service e080da
                   "%s: failed to set gfid", dir_data->data);
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    ret = 0;
Packit Service e080da
Packit Service e080da
    size = sys_lgetxattr(dir_data->data, POSIX_ACL_ACCESS_XATTR, NULL, 0);
Packit Service e080da
    if ((size < 0) && (errno == ENOTSUP)) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_ACL_NOTSUP,
Packit Service e080da
               "Posix access control list is not supported.");
Packit Service e080da
        gf_event(EVENT_POSIX_ACL_NOT_SUPPORTED, "brick=%s:%s",
Packit Service e080da
                 _private->hostname, _private->base_path);
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    /*
Packit Service e080da
     * _XOPEN_PATH_MAX is the longest file path len we MUST
Packit Service e080da
     * support according to POSIX standard. When prepended
Packit Service e080da
     * by the brick base path it may exceed backed filesystem
Packit Service e080da
     * capacity (which MAY be bigger than _XOPEN_PATH_MAX). If
Packit Service e080da
     * this is the case, chdir() to the brick base path and
Packit Service e080da
     * use relative paths when they are too long. See also
Packit Service e080da
     * MAKE_REAL_PATH in posix-handle.h
Packit Service e080da
     */
Packit Service e080da
    _private->path_max = pathconf(_private->base_path, _PC_PATH_MAX);
Packit Service e080da
    if (_private->path_max != -1 &&
Packit Service e080da
        _XOPEN_PATH_MAX + _private->base_path_length > _private->path_max) {
Packit Service e080da
        ret = chdir(_private->base_path);
Packit Service e080da
        if (ret) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_BASEPATH_CHDIR_FAILED,
Packit Service e080da
                   "chdir() to \"%s\" failed", _private->base_path);
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
#ifdef __NetBSD__
Packit Service e080da
        /*
Packit Service e080da
         * At least on NetBSD, the chdir() above uncovers a
Packit Service e080da
         * race condition which cause file lookup to fail
Packit Service e080da
         * with ENODATA for a few seconds. The volume quickly
Packit Service e080da
         * reaches a sane state, but regression tests are fast
Packit Service e080da
         * enough to choke on it. The reason is obscure (as
Packit Service e080da
         * often with race conditions), but sleeping here for
Packit Service e080da
         * a second seems to workaround the problem.
Packit Service e080da
         */
Packit Service e080da
        sleep(1);
Packit Service e080da
#endif
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    LOCK_INIT(&_private->lock);
Packit Service e080da
    GF_ATOMIC_INIT(_private->nr_files, 0);
Packit Service e080da
    GF_ATOMIC_INIT(_private->read_value, 0);
Packit Service e080da
    GF_ATOMIC_INIT(_private->write_value, 0);
Packit Service e080da
Packit Service e080da
    _private->export_statfs = 1;
Packit Service e080da
    tmp_data = dict_get(this->options, "export-statfs-size");
Packit Service e080da
    if (tmp_data) {
Packit Service e080da
        if (gf_string2boolean(tmp_data->data, &_private->export_statfs) == -1) {
Packit Service e080da
            ret = -1;
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_OPTION_VAL,
Packit Service e080da
                   "'export-statfs-size' takes only boolean "
Packit Service e080da
                   "options");
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
        if (!_private->export_statfs)
Packit Service e080da
            gf_msg_debug(this->name, 0, "'statfs()' returns dummy size");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    _private->background_unlink = 0;
Packit Service e080da
    tmp_data = dict_get(this->options, "background-unlink");
Packit Service e080da
    if (tmp_data) {
Packit Service e080da
        if (gf_string2boolean(tmp_data->data, &_private->background_unlink) ==
Packit Service e080da
            -1) {
Packit Service e080da
            ret = -1;
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_OPTION_VAL,
Packit Service e080da
                   "'background-unlink'"
Packit Service e080da
                   " takes only boolean options");
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
Packit Service e080da
        if (_private->background_unlink)
Packit Service e080da
            gf_msg_debug(this->name, 0,
Packit Service e080da
                         "unlinks will be performed in background");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    tmp_data = dict_get(this->options, "o-direct");
Packit Service e080da
    if (tmp_data) {
Packit Service e080da
        if (gf_string2boolean(tmp_data->data, &_private->o_direct) == -1) {
Packit Service e080da
            ret = -1;
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_OPTION_VAL,
Packit Service e080da
                   "wrong option provided for 'o-direct'");
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
        if (_private->o_direct)
Packit Service e080da
            gf_msg_debug(this->name, 0,
Packit Service e080da
                         "o-direct mode is enabled"
Packit Service e080da
                         " (O_DIRECT for every open)");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    tmp_data = dict_get(this->options, "update-link-count-parent");
Packit Service e080da
    if (tmp_data) {
Packit Service e080da
        if (gf_string2boolean(tmp_data->data, &_private->update_pgfid_nlinks) ==
Packit Service e080da
            -1) {
Packit Service e080da
            ret = -1;
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_OPTION,
Packit Service e080da
                   "wrong value provided "
Packit Service e080da
                   "for 'update-link-count-parent'");
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
        if (_private->update_pgfid_nlinks)
Packit Service e080da
            gf_msg_debug(this->name, 0,
Packit Service e080da
                         "update-link-count-parent"
Packit Service e080da
                         " is enabled. Thus for each file an "
Packit Service e080da
                         "extended attribute representing the "
Packit Service e080da
                         "number of hardlinks for that file "
Packit Service e080da
                         "within the same parent directory is"
Packit Service e080da
                         " set.");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    ret = dict_get_str(this->options, "glusterd-uuid", &guuid);
Packit Service e080da
    if (!ret) {
Packit Service e080da
        if (gf_uuid_parse(guuid, _private->glusterd_uuid))
Packit Service e080da
            gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_INVALID_NODE_UUID,
Packit Service e080da
                   "Cannot parse "
Packit Service e080da
                   "glusterd (node) UUID, node-uuid xattr "
Packit Service e080da
                   "request would return - \"No such attribute\"");
Packit Service e080da
    } else {
Packit Service e080da
        gf_msg_debug(this->name, 0,
Packit Service e080da
                     "No glusterd (node) UUID passed -"
Packit Service e080da
                     " node-uuid xattr request will return \"No such"
Packit Service e080da
                     " attribute\"");
Packit Service e080da
    }
Packit Service e080da
    ret = 0;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("janitor-sleep-duration", _private->janitor_sleep_duration,
Packit Service e080da
                   int32, out);
Packit Service e080da
Packit Service e080da
    /* performing open dir on brick dir locks the brick dir
Packit Service e080da
     * and prevents it from being unmounted
Packit Service e080da
     */
Packit Service e080da
    _private->mount_lock = sys_opendir(dir_data->data);
Packit Service e080da
    if (!_private->mount_lock) {
Packit Service e080da
        ret = -1;
Packit Service e080da
        op_errno = errno;
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_DIR_OPERATION_FAILED,
Packit Service e080da
               "Could not lock brick directory (%s)", strerror(op_errno));
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
#ifndef GF_DARWIN_HOST_OS
Packit Service e080da
    {
Packit Service e080da
        struct rlimit lim;
Packit Service e080da
        lim.rlim_cur = 1048576;
Packit Service e080da
        lim.rlim_max = 1048576;
Packit Service e080da
Packit Service e080da
        if (setrlimit(RLIMIT_NOFILE, &lim) == -1) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SET_ULIMIT_FAILED,
Packit Service e080da
                   "Failed to set 'ulimit -n "
Packit Service e080da
                   " 1048576'");
Packit Service e080da
            lim.rlim_cur = 65536;
Packit Service e080da
            lim.rlim_max = 65536;
Packit Service e080da
Packit Service e080da
            if (setrlimit(RLIMIT_NOFILE, &lim) == -1) {
Packit Service e080da
                gf_msg(this->name, GF_LOG_WARNING, errno,
Packit Service e080da
                       P_MSG_SET_FILE_MAX_FAILED,
Packit Service e080da
                       "Failed to set maximum allowed open "
Packit Service e080da
                       "file descriptors to 64k");
Packit Service e080da
            } else {
Packit Service e080da
                gf_msg(this->name, GF_LOG_INFO, 0, P_MSG_MAX_FILE_OPEN,
Packit Service e080da
                       "Maximum allowed "
Packit Service e080da
                       "open file descriptors set to 65536");
Packit Service e080da
            }
Packit Service e080da
        }
Packit Service e080da
    }
Packit Service e080da
#endif
Packit Service e080da
    _private->shared_brick_count = 1;
Packit Service e080da
    ret = dict_get_int32(this->options, "shared-brick-count",
Packit Service e080da
                         &_private->shared_brick_count);
Packit Service e080da
    if (ret == -1) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_OPTION_VAL,
Packit Service e080da
               "'shared-brick-count' takes only integer "
Packit Service e080da
               "values");
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    this->private = (void *)_private;
Packit Service e080da
Packit Service e080da
    op_ret = posix_handle_init(this);
Packit Service e080da
    if (op_ret == -1) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE,
Packit Service e080da
               "Posix handle setup failed");
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    op_ret = posix_handle_trash_init(this);
Packit Service e080da
    if (op_ret < 0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE_TRASH,
Packit Service e080da
               "Posix landfill setup failed");
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    op_ret = posix_create_unlink_dir(this);
Packit Service e080da
    if (op_ret == -1) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE,
Packit Service e080da
               "Creation of unlink directory failed");
Packit Service e080da
        ret = -1;
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    _private->aio_init_done = _gf_false;
Packit Service e080da
    _private->aio_capable = _gf_false;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("brick-uid", uid, int32, out);
Packit Service e080da
    GF_OPTION_INIT("brick-gid", gid, int32, out);
Packit Service e080da
    if (uid != -1 || gid != -1)
Packit Service e080da
        posix_set_owner(this, uid, gid);
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("linux-aio", _private->aio_configured, bool, out);
Packit Service e080da
Packit Service e080da
    if (_private->aio_configured) {
Packit Service e080da
        op_ret = posix_aio_on(this);
Packit Service e080da
Packit Service e080da
        if (op_ret == -1) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_POSIX_AIO,
Packit Service e080da
                   "Posix AIO init failed");
Packit Service e080da
            ret = -1;
Packit Service e080da
            goto out;
Packit Service e080da
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("node-uuid-pathinfo", _private->node_uuid_pathinfo, bool,
Packit Service e080da
                   out);
Packit Service e080da
    if (_private->node_uuid_pathinfo &&
Packit Service e080da
        (gf_uuid_is_null(_private->glusterd_uuid))) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_INFO, 0, P_MSG_UUID_NULL,
Packit Service e080da
               "glusterd uuid is NULL, pathinfo xattr would"
Packit Service e080da
               " fallback to <hostname>:<export>");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    _private->disk_space_check_active = _gf_false;
Packit Service e080da
    _private->disk_space_full = 0;
Packit Service 173fb3
Packit Service 173fb3
    GF_OPTION_INIT("reserve", _private->disk_reserve, percent_or_size, out);
Packit Service 173fb3
Packit Service 173fb3
    /* option can be any one of percent or bytes */
Packit Service 173fb3
    _private->disk_unit = 0;
Packit Service 173fb3
    if (_private->disk_reserve < 100.0)
Packit Service 173fb3
        _private->disk_unit = 'p';
Packit Service 173fb3
Packit Service e080da
    if (_private->disk_reserve) {
Packit Service e080da
        ret = posix_spawn_disk_space_check_thread(this);
Packit Service 173fb3
        if (ret) {
Packit Service 173fb3
            gf_msg(this->name, GF_LOG_INFO, 0, P_MSG_DISK_SPACE_CHECK_FAILED,
Packit Service 173fb3
                   "Getting disk space check from thread failed ");
Packit Service e080da
            goto out;
Packit Service 173fb3
        }
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    _private->health_check_active = _gf_false;
Packit Service e080da
    GF_OPTION_INIT("health-check-interval", _private->health_check_interval,
Packit Service e080da
                   uint32, out);
Packit Service e080da
    GF_OPTION_INIT("health-check-timeout", _private->health_check_timeout,
Packit Service e080da
                   uint32, out);
Packit Service e080da
    if (_private->health_check_interval) {
Packit Service e080da
        ret = posix_spawn_health_check_thread(this);
Packit Service e080da
        if (ret)
Packit Service e080da
            goto out;
Packit Service e080da
    }
Packit Service e080da
    posix_janitor_timer_start(this);
Packit Service e080da
Packit Service e080da
    pthread_mutex_init(&_private->fsync_mutex, NULL);
Packit Service e080da
    pthread_cond_init(&_private->fsync_cond, NULL);
Packit Service 173fb3
    pthread_mutex_init(&_private->janitor_mutex, NULL);
Packit Service 173fb3
    pthread_cond_init(&_private->janitor_cond, NULL);
Packit Service e080da
    INIT_LIST_HEAD(&_private->fsyncs);
Packit Service e080da
    ret = posix_spawn_ctx_janitor_thread(this);
Packit Service e080da
    if (ret)
Packit Service e080da
        goto out;
Packit Service e080da
Packit Service e080da
    ret = gf_thread_create(&_private->fsyncer, NULL, posix_fsyncer, this,
Packit Service e080da
                           "posixfsy");
Packit Service e080da
    if (ret) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, errno,
Packit Service e080da
               P_MSG_FSYNCER_THREAD_CREATE_FAILED,
Packit Service e080da
               "fsyncer thread creation failed");
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("batch-fsync-mode", batch_fsync_mode_str, str, out);
Packit Service e080da
Packit Service e080da
    if (set_batch_fsync_mode(_private, batch_fsync_mode_str) != 0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT,
Packit Service e080da
               "Unknown mode string: %s", batch_fsync_mode_str);
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("gfid2path", _private->gfid2path, bool, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("gfid2path-separator", gfid2path_sep, str, out);
Packit Service e080da
    if (set_gfid2path_separator(_private, gfid2path_sep) != 0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT,
Packit Service e080da
               "Length of separator exceeds 7: %s", gfid2path_sep);
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
#ifdef GF_DARWIN_HOST_OS
Packit Service e080da
Packit Service e080da
    char *xattr_user_namespace_mode_str = NULL;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("xattr-user-namespace-mode", xattr_user_namespace_mode_str,
Packit Service e080da
                   str, out);
Packit Service e080da
Packit Service e080da
    if (set_xattr_user_namespace_mode(_private,
Packit Service e080da
                                      xattr_user_namespace_mode_str) != 0) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT,
Packit Service e080da
               "Unknown xattr user namespace mode string: %s",
Packit Service e080da
               xattr_user_namespace_mode_str);
Packit Service e080da
        goto out;
Packit Service e080da
    }
Packit Service e080da
#endif
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("batch-fsync-delay-usec", _private->batch_fsync_delay_usec,
Packit Service e080da
                   uint32, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("disable-landfill-purge", _private->disable_landfill_purge,
Packit Service e080da
                   bool, out);
Packit Service e080da
    if (_private->disable_landfill_purge) {
Packit Service e080da
        gf_msg(this->name, GF_LOG_WARNING, 0, 0,
Packit Service e080da
               "Janitor WILL NOT purge the landfill directory. "
Packit Service e080da
               "Your landfill directory"
Packit Service e080da
               " may fill up this brick.");
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("force-create-mode", force_create, int32, out);
Packit Service e080da
    _private->force_create_mode = force_create;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("force-directory-mode", force_directory, int32, out);
Packit Service e080da
    _private->force_directory_mode = force_directory;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("create-mask", create_mask, int32, out);
Packit Service e080da
    _private->create_mask = create_mask;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("create-directory-mask", create_directory_mask, int32, out);
Packit Service e080da
    _private->create_directory_mask = create_directory_mask;
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("max-hardlinks", _private->max_hardlinks, uint32, out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("fips-mode-rchecksum", _private->fips_mode_rchecksum, bool,
Packit Service e080da
                   out);
Packit Service e080da
Packit Service e080da
    GF_OPTION_INIT("ctime", _private->ctime, bool, out);
Packit Service e080da
out:
Packit Service e080da
    if (ret) {
Packit Service e080da
        if (_private) {
Packit Service e080da
            GF_FREE(_private->base_path);
Packit Service e080da
Packit Service e080da
            GF_FREE(_private->hostname);
Packit Service e080da
Packit Service e080da
            GF_FREE(_private->trash_path);
Packit Service e080da
Packit Service e080da
            GF_FREE(_private);
Packit Service e080da
        }
Packit Service e080da
Packit Service e080da
        this->private = NULL;
Packit Service e080da
    }
Packit Service e080da
    return ret;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
void
Packit Service e080da
posix_fini(xlator_t *this)
Packit Service e080da
{
Packit Service e080da
    struct posix_private *priv = this->private;
Packit Service e080da
    gf_boolean_t health_check = _gf_false;
Packit Service e080da
    int ret = 0;
Packit Service e080da
Packit Service e080da
    if (!priv)
Packit Service e080da
        return;
Packit Service e080da
    LOCK(&priv->lock);
Packit Service e080da
    {
Packit Service e080da
        health_check = priv->health_check_active;
Packit Service e080da
        priv->health_check_active = _gf_false;
Packit Service e080da
    }
Packit Service e080da
    UNLOCK(&priv->lock);
Packit Service e080da
Packit Service e080da
    if (health_check) {
Packit Service e080da
        (void)gf_thread_cleanup_xint(priv->health_check);
Packit Service e080da
        priv->health_check = 0;
Packit Service e080da
    }
Packit Service e080da
Packit Service e080da
    if (priv->disk_space_check) {
Packit Service e080da
        priv->disk_space_check_active = _gf_false;
Packit Service e080da
        (void)gf_thread_cleanup_xint(priv->disk_space_check);
Packit Service e080da
        priv->disk_space_check = 0;
Packit Service e080da
    }
Packit Service 173fb3
Packit Service e080da
    if (priv->janitor) {
Packit Service e080da
        /*TODO: Make sure the synctask is also complete */
Packit Service e080da
        ret = gf_tw_del_timer(this->ctx->tw->timer_wheel, priv->janitor);
Packit Service e080da
        if (ret < 0) {
Packit Service e080da
            gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_TIMER_DELETE_FAILED,
Packit Service e080da
                   "Failed to delete janitor timer");
Packit Service e080da
        }
Packit Service 173fb3
        GF_FREE(priv->janitor);
Packit Service e080da
        priv->janitor = NULL;
Packit Service e080da
    }
Packit Service 173fb3
Packit Service e080da
    if (priv->fsyncer) {
Packit Service e080da
        (void)gf_thread_cleanup_xint(priv->fsyncer);
Packit Service e080da
        priv->fsyncer = 0;
Packit Service e080da
    }
Packit Service e080da
    /*unlock brick dir*/
Packit Service e080da
    if (priv->mount_lock)
Packit Service e080da
        (void)sys_closedir(priv->mount_lock);
Packit Service e080da
Packit Service e080da
    GF_FREE(priv->base_path);
Packit Service e080da
    LOCK_DESTROY(&priv->lock);
Packit Service e080da
    pthread_mutex_destroy(&priv->fsync_mutex);
Packit Service 173fb3
    pthread_cond_destroy(&priv->fsync_cond);
Packit Service 173fb3
    pthread_mutex_destroy(&priv->janitor_mutex);
Packit Service 173fb3
    pthread_cond_destroy(&priv->janitor_cond);
Packit Service e080da
    GF_FREE(priv->hostname);
Packit Service e080da
    GF_FREE(priv->trash_path);
Packit Service e080da
    GF_FREE(priv);
Packit Service e080da
    this->private = NULL;
Packit Service e080da
Packit Service e080da
    return;
Packit Service e080da
}
Packit Service e080da
Packit Service e080da
struct volume_options posix_options[] = {
Packit Service e080da
    {.key = {"o-direct"}, .type = GF_OPTION_TYPE_BOOL},
Packit Service e080da
    {.key = {"directory"},
Packit Service e080da
     .type = GF_OPTION_TYPE_PATH,
Packit Service e080da
     .default_value = "{{brick.path}}"},
Packit Service e080da
    {.key = {"hostname"}, .type = GF_OPTION_TYPE_ANY},
Packit Service e080da
    {.key = {"export-statfs-size"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
     .default_value = "on"},
Packit Service e080da
    {.key = {"mandate-attribute"}, .type = GF_OPTION_TYPE_BOOL},
Packit Service e080da
    {.key = {"background-unlink"}, .type = GF_OPTION_TYPE_BOOL},
Packit Service e080da
    {.key = {"janitor-sleep-duration"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 1,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .default_value = "10",
Packit Service e080da
     .description = "Interval (in seconds) between times the internal "
Packit Service e080da
                    "'landfill' directory is emptied."},
Packit Service e080da
    {.key = {"volume-id"},
Packit Service e080da
     .type = GF_OPTION_TYPE_ANY,
Packit Service e080da
     .default_value = "{{brick.volumeid}}"},
Packit Service e080da
    {.key = {"glusterd-uuid"}, .type = GF_OPTION_TYPE_STR},
Packit Service e080da
    {.key = {"linux-aio"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
     .default_value = "off",
Packit Service e080da
     .description = "Support for native Linux AIO",
Packit Service e080da
     .op_version = {1},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"brick-uid"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = -1,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .default_value = "-1",
Packit Service e080da
     .description = "Support for setting uid of brick's owner",
Packit Service e080da
     .op_version = {1},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"brick-gid"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = -1,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .default_value = "-1",
Packit Service e080da
     .description = "Support for setting gid of brick's owner",
Packit Service e080da
     .op_version = {1},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"node-uuid-pathinfo"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
     .default_value = "off",
Packit Service e080da
     .description = "return glusterd's node-uuid in pathinfo xattr"
Packit Service e080da
                    " string instead of hostname",
Packit Service e080da
     .op_version = {3},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"health-check-interval"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0,
Packit Service e080da
     .default_value = "30",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .description = "Interval in seconds for a filesystem health check, "
Packit Service e080da
                    "set to 0 to disable",
Packit Service e080da
     .op_version = {3},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"health-check-timeout"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0,
Packit Service 173fb3
     .default_value = "20",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .description =
Packit Service e080da
         "Interval in seconds to wait aio_write finish for health check, "
Packit Service e080da
         "set to 0 to disable",
Packit Service e080da
     .op_version = {GD_OP_VERSION_4_0_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"reserve"},
Packit Service 173fb3
     .type = GF_OPTION_TYPE_PERCENT_OR_SIZET,
Packit Service e080da
     .min = 0,
Packit Service e080da
     .default_value = "1",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service 173fb3
     .description = "Percentage/Size of disk space to be reserved."
Packit Service e080da
                    " Set to 0 to disable",
Packit Service e080da
     .op_version = {GD_OP_VERSION_3_13_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"batch-fsync-mode"},
Packit Service e080da
     .type = GF_OPTION_TYPE_STR,
Packit Service e080da
     .default_value = "reverse-fsync",
Packit Service e080da
     .description =
Packit Service e080da
         "Possible values:\n"
Packit Service e080da
         "\t- syncfs: Perform one syncfs() on behalf oa batch"
Packit Service e080da
         "of fsyncs.\n"
Packit Service e080da
         "\t- syncfs-single-fsync: Perform one syncfs() on behalf of a batch"
Packit Service e080da
         " of fsyncs and one fsync() per batch.\n"
Packit Service e080da
         "\t- syncfs-reverse-fsync: Perform one syncfs() on behalf of a batch"
Packit Service e080da
         " of fsyncs and fsync() each file in the batch in reverse order.\n"
Packit Service e080da
         " in reverse order.\n"
Packit Service e080da
         "\t- reverse-fsync: Perform fsync() of each file in the batch in"
Packit Service e080da
         " reverse order.",
Packit Service e080da
     .op_version = {3},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"batch-fsync-delay-usec"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .default_value = "0",
Packit Service e080da
     .description = "Num of usecs to wait for aggregating fsync"
Packit Service e080da
                    " requests",
Packit Service e080da
     .op_version = {3},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"update-link-count-parent"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
     .default_value = "off",
Packit Service e080da
     .description = "Enable placeholders for gfid to path conversion",
Packit Service 173fb3
     .op_version = {GD_OP_VERSION_RHS_3_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
    {.key = {"gfid2path"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
#ifdef __NetBSD__
Packit Service e080da
     /*
Packit Service e080da
      * NetBSD storage of extended attributes for UFS1 badly
Packit Service e080da
      * scales when the list of extended attributes names rises.
Packit Service e080da
      * This option can add as many extended attributes names
Packit Service e080da
      * as we have files, hence we keep it disabled for performance
Packit Service e080da
      * sake.
Packit Service e080da
      */
Packit Service e080da
     .default_value = "off",
Packit Service e080da
#else
Packit Service e080da
     .default_value = "on",
Packit Service e080da
#endif
Packit Service e080da
     .description = "Enable logging metadata for gfid to path conversion",
Packit Service e080da
     .op_version = {GD_OP_VERSION_3_12_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE},
Packit Service e080da
    {.key = {"gfid2path-separator"},
Packit Service e080da
     .type = GF_OPTION_TYPE_STR,
Packit Service e080da
     .default_value = ":",
Packit Service e080da
     .description = "Path separator for glusterfs.gfidtopath virt xattr",
Packit Service e080da
     .op_version = {GD_OP_VERSION_3_12_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
#if GF_DARWIN_HOST_OS
Packit Service e080da
    {.key = {"xattr-user-namespace-mode"},
Packit Service e080da
     .type = GF_OPTION_TYPE_STR,
Packit Service e080da
     .default_value = "none",
Packit Service e080da
     .description =
Packit Service e080da
         "Option to control XATTR user namespace on the raw filesystem: "
Packit Service e080da
         "\t- None: Will use the user namespace, so files will be exchangeable "
Packit Service e080da
         "with Linux.\n"
Packit Service e080da
         " The raw filesystem will not be compatible with OS X Finder.\n"
Packit Service e080da
         "\t- Strip: Will strip the user namespace before setting. The raw "
Packit Service e080da
         "filesystem will work in OS X.\n",
Packit Service 173fb3
     .op_version = {GD_OP_VERSION_RHS_3_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC},
Packit Service e080da
#endif
Packit Service e080da
    {
Packit Service e080da
        .key = {"shared-brick-count"},
Packit Service e080da
        .type = GF_OPTION_TYPE_INT,
Packit Service e080da
        .default_value = "1",
Packit Service e080da
        .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC,
Packit Service e080da
        .description =
Packit Service e080da
            "Number of bricks sharing the same backend export."
Packit Service e080da
            " Useful for displaying the proper usable size through statvfs() "
Packit Service e080da
            "call (df command)",
Packit Service e080da
    },
Packit Service e080da
    {
Packit Service e080da
        .key = {"disable-landfill-purge"},
Packit Service e080da
        .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
        .default_value = "off",
Packit Service e080da
        .description = "Disable glusterfs/landfill purges. "
Packit Service e080da
                       "WARNING: This can fill up a brick.",
Packit Service e080da
        .op_version = {GD_OP_VERSION_4_0_0},
Packit Service e080da
        .tags = {"diagnosis"},
Packit Service e080da
    },
Packit Service e080da
    {.key = {"force-create-mode"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0000,
Packit Service e080da
     .max = 0777,
Packit Service e080da
     .default_value = "0000",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MAX,
Packit Service e080da
     .description = "Mode bit permission that will always be set on a file."},
Packit Service e080da
    {.key = {"force-directory-mode"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0000,
Packit Service e080da
     .max = 0777,
Packit Service e080da
     .default_value = "0000",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MAX,
Packit Service e080da
     .description = "Mode bit permission that will be always set on directory"},
Packit Service e080da
    {.key = {"create-mask"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0000,
Packit Service e080da
     .max = 0777,
Packit Service e080da
     .default_value = "0777",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MAX,
Packit Service e080da
     .description = "Any bit not set here will be removed from the"
Packit Service e080da
                    "modes set on a file when it is created"},
Packit Service e080da
    {.key = {"create-directory-mask"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0000,
Packit Service e080da
     .max = 0777,
Packit Service e080da
     .default_value = "0777",
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MAX,
Packit Service e080da
     .description = "Any bit not set here will be removed from the"
Packit Service e080da
                    "modes set on a directory when it is created"},
Packit Service e080da
    {.key = {"max-hardlinks"},
Packit Service e080da
     .type = GF_OPTION_TYPE_INT,
Packit Service e080da
     .min = 0,
Packit Service e080da
     .default_value = "100",
Packit Service e080da
     .op_version = {GD_OP_VERSION_4_0_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC,
Packit Service e080da
     .tags = {"posix"},
Packit Service e080da
     .validate = GF_OPT_VALIDATE_MIN,
Packit Service e080da
     .description = "max number of hardlinks allowed on any one inode.\n"
Packit Service e080da
                    "0 is unlimited, 1 prevents any hardlinking at all."},
Packit Service e080da
    {.key = {"fips-mode-rchecksum"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service e080da
     .default_value = "off",
Packit Service e080da
     .op_version = {GD_OP_VERSION_4_0_0},
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE,
Packit Service e080da
     .tags = {"posix"},
Packit Service e080da
     .description = "If enabled, posix_rchecksum uses the FIPS compliant"
Packit Service e080da
                    "SHA256 checksum. MD5 otherwise."},
Packit Service e080da
    {.key = {"ctime"},
Packit Service e080da
     .type = GF_OPTION_TYPE_BOOL,
Packit Service 173fb3
     .default_value = "off",
Packit Service e080da
     .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC,
Packit Service e080da
     .op_version = {GD_OP_VERSION_4_1_0},
Packit Service e080da
     .tags = {"ctime"},
Packit Service e080da
     .description =
Packit Service e080da
         "When this option is enabled, time attributes (ctime,mtime,atime) "
Packit Service e080da
         "are stored in xattr to keep it consistent across replica and "
Packit Service e080da
         "distribute set. The time attributes stored at the backend are "
Packit Service e080da
         "not considered "},
Packit Service e080da
    {.key = {NULL}},
Packit Service e080da
};