diff options
| author | ShyamsundarR <srangana@redhat.com> | 2017-11-28 18:51:00 -0500 | 
|---|---|---|
| committer | ShyamsundarR <srangana@redhat.com> | 2017-12-02 13:56:19 -0500 | 
| commit | 8a0b115b20cfa2dd3c5a9e22a8244c9c2f03e17b (patch) | |
| tree | e0dc5088e9931d4d2cff442e8a780da0ff7caa15 /xlators/storage/posix/src | |
| parent | 09cb795587772b60ba102f4369ab3f4501cdc01a (diff) | |
posix: Reorganize posix xlator to prepare for reuse with rio
1. Split out entry and inode/fd based FOPs into
separate files from posix.c
2. Split out common routines (init, fini, reconf,
and such) into its own file, from posix.c
3. Retain just the method assignments in posix.c
(such that posix2 for RIO can assign its own methods in
the future for entry operations and such)
4. Based on the split in (1) and (2) split out
posix-handle.h into 2 files, such that macros that are
needed for inode ops are in one and rest are in the other
If the split is done as above, posix2 can compile with
its own entry ops, and hence not compile, the entry ops
as split in (1) above.
The split described in (4) can again help posix2 to
define its own macros to make entry and inode handles,
thus not impact existing POSIX xlator code.
Noted problems
- There are path references in certain cases where
quota is used (in the xattr FOPs), and thus will fail
on reuse in posix2, this needs to be handled when we
get there.
- posix_init does set root GFID on the brick root,
and this is incorrect for posix2, again will need
handling later when posix2 evolves based on this
code (other init checks seem fine on current inspection)
Merge of experimental branch patches with the following
gerrit change-IDs
> Change-Id: I965ce6dffe70a62c697f790f3438559520e0af20
> Change-Id: I089a4d9cf470c2f9c121611e8ef18dea92b2be70
> Change-Id: I2cec103f6ba8f3084443f3066bcc70b2f5ecb49a
Fixes gluster/glusterfs#327
Change-Id: I0ccfa78559a7c5a68f5e861e144cf856f5c9e19c
Signed-off-by: ShyamsundarR <srangana@redhat.com>
Diffstat (limited to 'xlators/storage/posix/src')
| -rw-r--r-- | xlators/storage/posix/src/Makefile.am | 5 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-common.c | 1326 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-entry-ops.c | 2125 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 3 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.h | 108 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 35 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-inode-fd-ops.c | 4975 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-inode-handle.h | 106 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 8242 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.h | 243 | 
10 files changed, 8830 insertions, 8338 deletions
diff --git a/xlators/storage/posix/src/Makefile.am b/xlators/storage/posix/src/Makefile.am index 8ec460578b5..17ea98016c9 100644 --- a/xlators/storage/posix/src/Makefile.am +++ b/xlators/storage/posix/src/Makefile.am @@ -5,12 +5,13 @@ xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/storage  posix_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS)  posix_la_SOURCES = posix.c posix-helpers.c posix-handle.c posix-aio.c \ -	posix-gfid-path.c +	posix-gfid-path.c posix-entry-ops.c posix-inode-fd-ops.c \ +        posix-common.c  posix_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(LIBAIO) \  	$(ACL_LIBS)  noinst_HEADERS = posix.h posix-mem-types.h posix-handle.h posix-aio.h \ -	posix-messages.h posix-gfid-path.h +	posix-messages.h posix-gfid-path.h posix-inode-handle.h  AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \  	-I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src \ diff --git a/xlators/storage/posix/src/posix-common.c b/xlators/storage/posix/src/posix-common.c new file mode 100644 index 00000000000..011bef8a720 --- /dev/null +++ b/xlators/storage/posix/src/posix-common.c @@ -0,0 +1,1326 @@ +/* +   Copyright (c) 2006-2017 Red Hat, Inc. <http://www.redhat.com> +   This file is part of GlusterFS. + +   This file is licensed to you under your choice of the GNU Lesser +   General Public License, version 3 or any later version (LGPLv3 or +   later), or the GNU General Public License, version 2 (GPLv2), in all +   cases as published by the Free Software Foundation. +*/ +#define __XOPEN_SOURCE 500 + +/* for SEEK_HOLE and SEEK_DATA */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <openssl/md5.h> +#include <stdint.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <errno.h> +#include <libgen.h> +#include <pthread.h> +#include <ftw.h> +#include <sys/stat.h> +#include <signal.h> +#include <sys/uio.h> +#include <unistd.h> +#include <ftw.h> + +#ifndef GF_BSD_HOST_OS +#include <alloca.h> +#endif /* GF_BSD_HOST_OS */ + +#ifdef HAVE_LINKAT +#include <fcntl.h> +#endif /* HAVE_LINKAT */ + +#include "glusterfs.h" +#include "checksum.h" +#include "dict.h" +#include "logging.h" +#include "posix.h" +#include "posix-inode-handle.h" +#include "xlator.h" +#include "defaults.h" +#include "common-utils.h" +#include "compat-errno.h" +#include "compat.h" +#include "byte-order.h" +#include "syscall.h" +#include "statedump.h" +#include "locking.h" +#include "timer.h" +#include "glusterfs3-xdr.h" +#include "hashfn.h" +#include "posix-aio.h" +#include "glusterfs-acl.h" +#include "posix-messages.h" +#include "events.h" +#include "posix-gfid-path.h" +#include "compat-uuid.h" + +extern char *marker_xattrs[]; +#define ALIGN_SIZE 4096 + +#undef HAVE_SET_FSID +#ifdef HAVE_SET_FSID + +#define DECLARE_OLD_FS_ID_VAR uid_t old_fsuid; gid_t old_fsgid; + +#define SET_FS_ID(uid, gid) do {                \ +                old_fsuid = setfsuid (uid);     \ +                old_fsgid = setfsgid (gid);     \ +        } while (0) + +#define SET_TO_OLD_FS_ID() do {                 \ +                setfsuid (old_fsuid);           \ +                setfsgid (old_fsgid);           \ +        } while (0) + +#else + +#define DECLARE_OLD_FS_ID_VAR +#define SET_FS_ID(uid, gid) +#define SET_TO_OLD_FS_ID() + +#endif + +/* Setting microseconds or nanoseconds depending on what's supported: +   The passed in `tv` can be +       struct timespec +   if supported (better, because it supports nanosecond resolution) or +       struct timeval +   otherwise. */ +#if HAVE_UTIMENSAT +#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ +        tv.tv_nsec = nanosecs +#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ +        (sys_utimensat (AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW)) +#else +#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ +        tv.tv_usec = nanosecs / 1000 +#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ +        (lutimes (path, tv)) +#endif + +int32_t +posix_priv (xlator_t *this) +{ +        struct posix_private *priv = NULL; +        char  key_prefix[GF_DUMP_MAX_BUF_LEN]; + +        (void) snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s", +                        this->type, this->name); +        gf_proc_dump_add_section(key_prefix); + +        if (!this) +                return 0; + +        priv = this->private; + +        if (!priv) +                return 0; + +        gf_proc_dump_write("base_path", "%s", priv->base_path); +        gf_proc_dump_write("base_path_length", "%d", priv->base_path_length); +        gf_proc_dump_write("max_read", "%d", priv->read_value); +        gf_proc_dump_write("max_write", "%d", priv->write_value); +        gf_proc_dump_write("nr_files", "%ld", priv->nr_files); + +        return 0; +} + +int32_t +posix_inode (xlator_t *this) +{ +        return 0; +} + +/** + * notify - when parent sends PARENT_UP, send CHILD_UP event from here + */ +int32_t +posix_notify (xlator_t *this, +        int32_t event, +        void *data, +        ...) +{ +        struct posix_private *priv = NULL; + +        priv = this->private; +        switch (event) +        { +        case GF_EVENT_PARENT_UP: +        { +                /* Tell the parent that posix xlator is up */ +                default_notify (this, GF_EVENT_CHILD_UP, data); +        } +        break; +        case GF_EVENT_CLEANUP: +                if (priv->health_check) { +                        priv->health_check_active = _gf_false; +                        pthread_cancel (priv->health_check); +                        priv->health_check = 0; +                } +                if (priv->disk_space_check) { +                        priv->disk_space_check_active = _gf_false; +                        pthread_cancel (priv->disk_space_check); +                        priv->disk_space_check = 0; +                } +                if (priv->janitor) { +                        (void) gf_thread_cleanup_xint (priv->janitor); +                        priv->janitor = 0; +                } +                if (priv->fsyncer) { +                        (void) gf_thread_cleanup_xint (priv->fsyncer); +                        priv->fsyncer = 0; +                } +                if (priv->mount_lock) { +                        (void) sys_closedir (priv->mount_lock); +                        priv->mount_lock = NULL; +                } + +        break; +        default: +                /* */ +                break; +        } +        return 0; +} + +int32_t +mem_acct_init (xlator_t *this) +{ +        int     ret = -1; + +        if (!this) +                return ret; + +        ret = xlator_mem_acct_init (this, gf_posix_mt_end + 1); + +        if (ret != 0) { +                return ret; +        } + +        return ret; +} + +static int +posix_set_owner (xlator_t *this, uid_t uid, gid_t gid) +{ +        struct posix_private *priv = NULL; +        int                   ret  = -1; +        struct stat st = {0,}; + +        priv = this->private; + +        ret = sys_lstat (priv->base_path, &st); +        if (ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_DIR_OPERATION_FAILED, "Failed to stat " +                        "brick path %s", +                        priv->base_path); +                return ret; +        } + +        if ((uid == -1 || st.st_uid == uid) && +            (gid == -1 || st.st_gid == gid)) +                return 0; + +        ret = sys_chown (priv->base_path, uid, gid); +        if (ret) +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_DIR_OPERATION_FAILED, "Failed to set uid/gid for" +                        " brick path %s", priv->base_path); + +        return ret; +} +static int +set_gfid2path_separator (struct posix_private *priv, const char *str) +{ +        int str_len = 0; + +        str_len = strlen(str); +        if (str_len > 0 && str_len < 8) { +                strcpy (priv->gfid2path_sep, str); +                return 0; +        } + +        return -1; +} + +static int +set_batch_fsync_mode (struct posix_private *priv, const char *str) +{ +        if (strcmp (str, "none") == 0) +                priv->batch_fsync_mode = BATCH_NONE; +        else if (strcmp (str, "syncfs") == 0) +                priv->batch_fsync_mode = BATCH_SYNCFS; +        else if (strcmp (str, "syncfs-single-fsync") == 0) +                priv->batch_fsync_mode = BATCH_SYNCFS_SINGLE_FSYNC; +        else if (strcmp (str, "syncfs-reverse-fsync") == 0) +                priv->batch_fsync_mode = BATCH_SYNCFS_REVERSE_FSYNC; +        else if (strcmp (str, "reverse-fsync") == 0) +                priv->batch_fsync_mode = BATCH_REVERSE_FSYNC; +        else +                return -1; + +        return 0; +} + +#ifdef GF_DARWIN_HOST_OS +static int +set_xattr_user_namespace_mode (struct posix_private *priv, const char *str) +{ +        if (strcmp (str, "none") == 0) +                priv->xattr_user_namespace = XATTR_NONE; +        else if (strcmp (str, "strip") == 0) +                priv->xattr_user_namespace = XATTR_STRIP; +        else if (strcmp (str, "append") == 0) +                priv->xattr_user_namespace = XATTR_APPEND; +        else if (strcmp (str, "both") == 0) +                priv->xattr_user_namespace = XATTR_BOTH; +        else +                return -1; +        return 0; +} +#endif + +int +posix_reconfigure (xlator_t *this, dict_t *options) +{ +        int                   ret = -1; +        struct posix_private *priv = NULL; +        int32_t               uid = -1; +        int32_t               gid = -1; +        char                 *batch_fsync_mode_str = NULL; +        char                 *gfid2path_sep = NULL; +        int32_t              force_create_mode = -1; +        int32_t              force_directory_mode = -1; +        int32_t              create_mask = -1; +        int32_t              create_directory_mask = -1; + +        priv = this->private; + +        GF_OPTION_RECONF ("brick-uid", uid, options, int32, out); +        GF_OPTION_RECONF ("brick-gid", gid, options, int32, out); +        if (uid != -1 || gid != -1) +                posix_set_owner (this, uid, gid); + +        GF_OPTION_RECONF ("batch-fsync-delay-usec", priv->batch_fsync_delay_usec, +                          options, uint32, out); + +        GF_OPTION_RECONF ("batch-fsync-mode", batch_fsync_mode_str, +                          options, str, out); + +        if (set_batch_fsync_mode (priv, batch_fsync_mode_str) != 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, +                        "Unknown mode string: %s", batch_fsync_mode_str); +                goto out; +        } + +        GF_OPTION_RECONF ("gfid2path-separator", gfid2path_sep, options, +                          str, out); +        if (set_gfid2path_separator (priv, gfid2path_sep) != 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, +                        "Length of separator exceeds 7: %s", gfid2path_sep); +                goto out; +        } + +#ifdef GF_DARWIN_HOST_OS + +        char   *xattr_user_namespace_mode_str = NULL; + +        GF_OPTION_RECONF ("xattr-user-namespace-mode", xattr_user_namespace_mode_str, +                          options, str, out); + +        if (set_xattr_user_namespace_mode (priv, xattr_user_namespace_mode_str) != 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_UNKNOWN_ARGUMENT, +                        "Unknown xattr user namespace mode string: %s", +                        xattr_user_namespace_mode_str); +                goto out; +        } + +#endif + +        GF_OPTION_RECONF ("linux-aio", priv->aio_configured, +                          options, bool, out); + +        if (priv->aio_configured) +                posix_aio_on (this); +        else +                posix_aio_off (this); + +        GF_OPTION_RECONF ("update-link-count-parent", priv->update_pgfid_nlinks, +                          options, bool, out); + +        GF_OPTION_RECONF ("gfid2path", priv->gfid2path, +                          options, bool, out); + +        GF_OPTION_RECONF ("node-uuid-pathinfo", priv->node_uuid_pathinfo, +                          options, bool, out); + +        if (priv->node_uuid_pathinfo && +                        (gf_uuid_is_null (priv->glusterd_uuid))) { +                gf_msg (this->name, GF_LOG_INFO, 0, P_MSG_UUID_NULL, +                        "glusterd uuid is NULL, pathinfo xattr would" +                        " fallback to <hostname>:<export>"); +        } + +        GF_OPTION_RECONF ("reserve", priv->disk_reserve, +                          options, uint32, out); +        if (priv->disk_reserve) +                posix_spawn_disk_space_check_thread (this); + +        GF_OPTION_RECONF ("health-check-interval", priv->health_check_interval, +                          options, uint32, out); +        GF_OPTION_RECONF ("health-check-timeout", priv->health_check_timeout, +                          options, uint32, out); +        posix_spawn_health_check_thread (this); + +        GF_OPTION_RECONF ("shared-brick-count", priv->shared_brick_count, +                          options, int32, out); +        GF_OPTION_RECONF ("force-create-mode", force_create_mode, +                          options, int32, out); +        priv->force_create_mode = force_create_mode; + +        GF_OPTION_RECONF ("force-directory-mode", force_directory_mode, +                          options, int32, out); +        priv->force_directory_mode = force_directory_mode; + +        GF_OPTION_RECONF ("create-mask", create_mask, +                          options, int32, out); +        priv->create_mask = create_mask; + +        GF_OPTION_RECONF ("create-directory-mask", create_directory_mask, +                          options, int32, out); +        priv->create_directory_mask = create_directory_mask; + +        ret = 0; +out: +        return ret; +} + +int32_t +posix_delete_unlink_entry (const char *fpath, const struct stat *sb, +                   int typeflag, struct FTW *ftwbuf) { + +        int    ret = 0; + +        if (!fpath) +                goto out; + +        switch (typeflag) { +        case FTW_SL: +        case FTW_NS: +        case FTW_F: +        case FTW_SLN: +                ret = sys_unlink(fpath); +                break; +        case FTW_D: +        case FTW_DP: +        case FTW_DNR: +                if (ftwbuf->level != 0) { +                        ret = sys_rmdir(fpath); +                } +                break; +        default: +                break; +        } +        if (ret) { +                gf_msg ("posix_delete_unlink_entry", GF_LOG_WARNING, errno, +                        P_MSG_HANDLE_CREATE, +                        "Deletion of entries %s failed" +                        "Please delete it manually", +                        fpath); +        } +out: +        return 0; +} + +int32_t +posix_delete_unlink (const char *unlink_path) { + +        int    ret = -1; +        int    flags = 0; + +        flags |= (FTW_DEPTH | FTW_PHYS); + +        ret = nftw(unlink_path, posix_delete_unlink_entry, 2, flags); +        if (ret) { +                gf_msg ("posix_delete_unlink", GF_LOG_ERROR, 0, +                        P_MSG_HANDLE_CREATE, +                        "Deleting files from  %s failed", +                        unlink_path); +        } +        return ret; +} + +int32_t +posix_create_unlink_dir (xlator_t *this) { + +        struct posix_private *priv = NULL; +        struct stat           stbuf; +        int                   ret = -1; +        uuid_t                gfid = {0}; +        char                  gfid_str[64] = {0}; +        char                  unlink_path[PATH_MAX] = {0,}; +        char                  landfill_path[PATH_MAX] = {0,}; + +        priv = this->private; + +        (void) snprintf (unlink_path, sizeof(unlink_path), "%s/%s", +                         priv->base_path, GF_UNLINK_PATH); + +        gf_uuid_generate (gfid); +        uuid_utoa_r (gfid, gfid_str); + +        (void) snprintf (landfill_path, sizeof(landfill_path), "%s/%s/%s", +                         priv->base_path, GF_LANDFILL_PATH, gfid_str); + +        ret = sys_stat (unlink_path, &stbuf); +        switch (ret) { +        case -1: +                if (errno != ENOENT) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_HANDLE_CREATE, +                                "Checking for %s failed", +                                unlink_path); +                        return -1; +                } +                break; +        case 0: +                if (!S_ISDIR (stbuf.st_mode)) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_HANDLE_CREATE, +                                "Not a directory: %s", +                                unlink_path); +                        return -1; +                } +                ret = posix_delete_unlink (unlink_path); +                return 0; +        default: +                break; +        } +        ret = sys_mkdir (unlink_path, 0600); +        if (ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_HANDLE_CREATE, +                        "Creating directory %s failed", +                        unlink_path); +                return -1; +        } + +        return 0; +} + +/** + * init - + */ +int +posix_init (xlator_t *this) +{ +        struct posix_private *_private      = NULL; +        data_t               *dir_data      = NULL; +        data_t               *tmp_data      = NULL; +        struct stat           buf           = {0,}; +        gf_boolean_t          tmp_bool      = 0; +        int                   ret           = 0; +        int                   op_ret        = -1; +        int                   op_errno      = 0; +        ssize_t               size          = -1; +        uuid_t                old_uuid      = {0,}; +        uuid_t                dict_uuid     = {0,}; +        uuid_t                gfid          = {0,}; +        uuid_t                rootgfid      = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; +        char                 *guuid         = NULL; +        int32_t               uid           = -1; +        int32_t               gid           = -1; +        char                 *batch_fsync_mode_str; +        char                 *gfid2path_sep = NULL; +        int                  force_create  = -1; +        int                  force_directory = -1; +        int                  create_mask  = -1; +        int                  create_directory_mask = -1; + +        dir_data = dict_get (this->options, "directory"); + +        if (this->children) { +                gf_msg (this->name, GF_LOG_CRITICAL, 0, P_MSG_SUBVOLUME_ERROR, +                        "FATAL: storage/posix cannot have subvolumes"); +                ret = -1; +                goto out; +        } + +        if (!this->parents) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_VOLUME_DANGLING, +                        "Volume is dangling. Please check the volume file."); +        } + +        if (!dir_data) { +                gf_msg (this->name, GF_LOG_CRITICAL, 0, +                        P_MSG_EXPORT_DIR_MISSING, +                        "Export directory not specified in volume file."); +                ret = -1; +                goto out; +        } + +        umask (000); // umask `masking' is done at the client side + +        /* Check whether the specified directory exists, if not log it. */ +        op_ret = sys_stat (dir_data->data, &buf); +        if ((op_ret != 0) || !S_ISDIR (buf.st_mode)) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_DIR_OPERATION_FAILED, +                        "Directory '%s' doesn't exist, exiting.", +                        dir_data->data); +                ret = -1; +                goto out; +        } + +        _private = GF_CALLOC (1, sizeof (*_private), +                              gf_posix_mt_posix_private); +        if (!_private) { +                ret = -1; +                goto out; +        } + +        _private->base_path = gf_strdup (dir_data->data); +        _private->base_path_length = strlen (_private->base_path); + +        ret = dict_get_str (this->options, "hostname", &_private->hostname); +        if (ret) { +                _private->hostname = GF_CALLOC (256, sizeof (char), +                                                gf_common_mt_char); +                if (!_private->hostname) { +                        goto out; +                } +                ret = gethostname (_private->hostname, 256); +                if (ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_HOSTNAME_MISSING, +                                "could not find hostname "); +                } +        } + +        /* Check for Extended attribute support, if not present, log it */ +        op_ret = sys_lsetxattr (dir_data->data, +                                "trusted.glusterfs.test", "working", 8, 0); +        if (op_ret != -1) { +                sys_lremovexattr (dir_data->data, "trusted.glusterfs.test"); +        } else { +                tmp_data = dict_get (this->options, +                                     "mandate-attribute"); +                if (tmp_data) { +                        if (gf_string2boolean (tmp_data->data, +                                               &tmp_bool) == -1) { +                                gf_msg (this->name, GF_LOG_ERROR, 0, +                                        P_MSG_INVALID_OPTION, +                                        "wrong option provided for key " +                                        "\"mandate-attribute\""); +                                ret = -1; +                                goto out; +                        } +                        if (!tmp_bool) { +                                gf_msg (this->name, GF_LOG_WARNING, 0, +                                        P_MSG_XATTR_NOTSUP, +                                        "Extended attribute not supported, " +                                        "starting as per option"); +                        } else { +                                gf_msg (this->name, GF_LOG_CRITICAL, 0, +                                        P_MSG_XATTR_NOTSUP, +                                        "Extended attribute not supported, " +                                        "exiting."); +                                ret = -1; +                                goto out; +                        } +                } else { +                        gf_msg (this->name, GF_LOG_CRITICAL, 0, +                                P_MSG_XATTR_NOTSUP, +                                "Extended attribute not supported, exiting."); +                        ret = -1; +                        goto out; +                } +        } + +        tmp_data = dict_get (this->options, "volume-id"); +        if (tmp_data) { +                op_ret = gf_uuid_parse (tmp_data->data, dict_uuid); +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_INVALID_VOLUME_ID, +                                "wrong volume-id (%s) set" +                                " in volume file", tmp_data->data); +                        ret = -1; +                        goto out; +                } +                size = sys_lgetxattr (dir_data->data, +                                      "trusted.glusterfs.volume-id", old_uuid, 16); +                if (size == 16) { +                        if (gf_uuid_compare (old_uuid, dict_uuid)) { +                                gf_msg (this->name, GF_LOG_ERROR, 0, +                                        P_MSG_INVALID_VOLUME_ID, +                                        "mismatching volume-id (%s) received. " +                                        "already is a part of volume %s ", +                                        tmp_data->data, uuid_utoa (old_uuid)); +                                gf_event (EVENT_POSIX_ALREADY_PART_OF_VOLUME, +                                        "volume-id=%s;brick=%s:%s", +                                        uuid_utoa (old_uuid), +                                       _private->hostname, _private->base_path); +                                ret = -1; +                                goto out; +                        } +                } else if ((size == -1) && +                           (errno == ENODATA || errno == ENOATTR)) { +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_VOLUME_ID_ABSENT, +                                        "Extended attribute trusted.glusterfs." +                                        "volume-id is absent"); +                                gf_event (EVENT_POSIX_BRICK_NOT_IN_VOLUME, +                                        "brick=%s:%s", +                                       _private->hostname, _private->base_path); +                                ret = -1; +                                goto out; + +                }  else if ((size == -1) && (errno != ENODATA) && +                            (errno != ENOATTR)) { +                        /* Wrong 'volume-id' is set, it should be error */ +                        gf_event (EVENT_POSIX_BRICK_VERIFICATION_FAILED, +                                "brick=%s:%s", +                                _private->hostname, _private->base_path); +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_VOLUME_ID_FETCH_FAILED, +                                "%s: failed to fetch volume-id", +                                dir_data->data); +                        ret = -1; +                        goto out; +                } else { +                        ret = -1; +                        gf_event (EVENT_POSIX_BRICK_VERIFICATION_FAILED, +                                "brick=%s:%s", +                                _private->hostname, _private->base_path); +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_VOLUME_ID_FETCH_FAILED, +                                "failed to fetch proper volume id from export"); +                        goto out; +                } +        } + +        /* Now check if the export directory has some other 'gfid', +           other than that of root '/' */ +        size = sys_lgetxattr (dir_data->data, "trusted.gfid", gfid, 16); +        if (size == 16) { +                if (!__is_root_gfid (gfid)) { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_GFID_SET_FAILED, +                                "%s: gfid (%s) is not that of glusterfs '/' ", +                                dir_data->data, uuid_utoa (gfid)); +                        ret = -1; +                        goto out; +                } +        } else if (size != -1) { +                /* Wrong 'gfid' is set, it should be error */ +                gf_msg (this->name, GF_LOG_WARNING, errno, +                        P_MSG_GFID_SET_FAILED, +                        "%s: wrong value set as gfid", +                        dir_data->data); +                ret = -1; +                goto out; +        } else if ((size == -1) && (errno != ENODATA) && +                   (errno != ENOATTR)) { +                /* Wrong 'gfid' is set, it should be error */ +                gf_msg (this->name, GF_LOG_WARNING, errno, +                        P_MSG_GFID_SET_FAILED, +                        "%s: failed to fetch gfid", +                        dir_data->data); +                ret = -1; +                goto out; +        } else { +                /* First time volume, set the GFID */ +                size = sys_lsetxattr (dir_data->data, "trusted.gfid", rootgfid, +                                     16, XATTR_CREATE); +                if (size == -1) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_GFID_SET_FAILED, +                                "%s: failed to set gfid", +                                dir_data->data); +                        ret = -1; +                        goto out; +                } +        } + +        ret = 0; + +        size = sys_lgetxattr (dir_data->data, POSIX_ACL_ACCESS_XATTR, +                              NULL, 0); +        if ((size < 0) && (errno == ENOTSUP)) { +                gf_msg (this->name, GF_LOG_WARNING, errno, +                        P_MSG_ACL_NOTSUP, +                        "Posix access control list is not supported."); +                gf_event (EVENT_POSIX_ACL_NOT_SUPPORTED, +                        "brick=%s:%s", _private->hostname, _private->base_path); +        } + +        /* +         * _XOPEN_PATH_MAX is the longest file path len we MUST +         * support according to POSIX standard. When prepended +         * by the brick base path it may exceed backed filesystem +         * capacity (which MAY be bigger than _XOPEN_PATH_MAX). If +         * this is the case, chdir() to the brick base path and +         * use relative paths when they are too long. See also +         * MAKE_REAL_PATH in posix-handle.h +          */ +        _private->path_max = pathconf(_private->base_path, _PC_PATH_MAX); +        if (_private->path_max != -1 && +            _XOPEN_PATH_MAX + _private->base_path_length > _private->path_max) { +                ret = chdir(_private->base_path); +                if (ret) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_BASEPATH_CHDIR_FAILED, +                                "chdir() to \"%s\" failed", +                                _private->base_path); +                        goto out; +                } +#ifdef __NetBSD__ +                /* +                 * At least on NetBSD, the chdir() above uncovers a +                 * race condition which cause file lookup to fail +                 * with ENODATA for a few seconds. The volume quickly +                 * reaches a sane state, but regression tests are fast +                 * enough to choke on it. The reason is obscure (as +                 * often with race conditions), but sleeping here for +                 * a second seems to workaround the problem. +                 */ +                sleep(1); +#endif +        } + + +        LOCK_INIT (&_private->lock); + +        _private->export_statfs = 1; +        tmp_data = dict_get (this->options, "export-statfs-size"); +        if (tmp_data) { +                if (gf_string2boolean (tmp_data->data, +                                       &_private->export_statfs) == -1) { +                        ret = -1; +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_INVALID_OPTION_VAL, +                                "'export-statfs-size' takes only boolean " +                                "options"); +                        goto out; +                } +                if (!_private->export_statfs) +                        gf_msg_debug (this->name, 0, +                                "'statfs()' returns dummy size"); +        } + +        _private->background_unlink = 0; +        tmp_data = dict_get (this->options, "background-unlink"); +        if (tmp_data) { +                if (gf_string2boolean (tmp_data->data, +                                       &_private->background_unlink) == -1) { +                        ret = -1; +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_INVALID_OPTION_VAL, "'background-unlink'" +                                " takes only boolean options"); +                        goto out; +                } + +                if (_private->background_unlink) +                        gf_msg_debug (this->name, 0, +                                "unlinks will be performed in background"); +        } + +        tmp_data = dict_get (this->options, "o-direct"); +        if (tmp_data) { +                if (gf_string2boolean (tmp_data->data, +                                       &_private->o_direct) == -1) { +                        ret = -1; +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_INVALID_OPTION_VAL, +                                "wrong option provided for 'o-direct'"); +                        goto out; +                } +                if (_private->o_direct) +                        gf_msg_debug (this->name, 0, "o-direct mode is enabled" +                                      " (O_DIRECT for every open)"); +        } + +        tmp_data = dict_get (this->options, "update-link-count-parent"); +        if (tmp_data) { +                if (gf_string2boolean (tmp_data->data, +                                       &_private->update_pgfid_nlinks) == -1) { +                        ret = -1; +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_INVALID_OPTION, "wrong value provided " +                                "for 'update-link-count-parent'"); +                        goto out; +                } +                if (_private->update_pgfid_nlinks) +                        gf_msg_debug (this->name, 0, "update-link-count-parent" +                                      " is enabled. Thus for each file an " +                                      "extended attribute representing the " +                                      "number of hardlinks for that file " +                                      "within the same parent directory is" +                                      " set."); +        } + +        ret = dict_get_str (this->options, "glusterd-uuid", &guuid); +        if (!ret) { +                if (gf_uuid_parse (guuid, _private->glusterd_uuid)) +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_INVALID_NODE_UUID, "Cannot parse " +                                "glusterd (node) UUID, node-uuid xattr " +                                "request would return - \"No such attribute\""); +        } else { +                gf_msg_debug (this->name, 0, "No glusterd (node) UUID passed -" +                              " node-uuid xattr request will return \"No such" +                              " attribute\""); +        } +        ret = 0; + +        GF_OPTION_INIT ("janitor-sleep-duration", +                        _private->janitor_sleep_duration, int32, out); + +        /* performing open dir on brick dir locks the brick dir +         * and prevents it from being unmounted +         */ +        _private->mount_lock = sys_opendir (dir_data->data); +        if (!_private->mount_lock) { +                ret = -1; +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, 0, +                        P_MSG_DIR_OPERATION_FAILED, +                        "Could not lock brick directory (%s)", +                        strerror (op_errno)); +                goto out; +        } +#ifndef GF_DARWIN_HOST_OS +        { +                struct rlimit lim; +                lim.rlim_cur = 1048576; +                lim.rlim_max = 1048576; + +                if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_SET_ULIMIT_FAILED, +                                "Failed to set 'ulimit -n " +                                " 1048576'"); +                        lim.rlim_cur = 65536; +                        lim.rlim_max = 65536; + +                        if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { +                                gf_msg (this->name, GF_LOG_WARNING, errno, +                                        P_MSG_SET_FILE_MAX_FAILED, +                                        "Failed to set maximum allowed open " +                                        "file descriptors to 64k"); +                        } +                        else { +                                gf_msg (this->name, GF_LOG_INFO, 0, +                                        P_MSG_MAX_FILE_OPEN, "Maximum allowed " +                                        "open file descriptors set to 65536"); +                        } +                } +        } +#endif +        _private->shared_brick_count = 1; +        ret = dict_get_int32 (this->options, "shared-brick-count", +                              &_private->shared_brick_count); +        if (ret == -1) { +                gf_msg (this->name, GF_LOG_ERROR, 0, +                        P_MSG_INVALID_OPTION_VAL, +                        "'shared-brick-count' takes only integer " +                        "values"); +                goto out; +        } + +        this->private = (void *)_private; + +        op_ret = posix_handle_init (this); +        if (op_ret == -1) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE, +                        "Posix handle setup failed"); +                ret = -1; +                goto out; +        } + +        op_ret = posix_handle_trash_init (this); +        if (op_ret < 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE_TRASH, +                        "Posix landfill setup failed"); +                ret = -1; +                goto out; +        } + +        op_ret = posix_create_unlink_dir (this); +        if (op_ret == -1) { +                gf_msg (this->name, GF_LOG_ERROR, 0, +                        P_MSG_HANDLE_CREATE, +                        "Creation of unlink directory failed"); +                ret = -1; +                goto out; +        } + +        _private->aio_init_done = _gf_false; +        _private->aio_capable = _gf_false; + +        GF_OPTION_INIT ("brick-uid", uid, int32, out); +        GF_OPTION_INIT ("brick-gid", gid, int32, out); +        if (uid != -1 || gid != -1) +                posix_set_owner (this, uid, gid); + +        GF_OPTION_INIT ("linux-aio", _private->aio_configured, bool, out); + +        if (_private->aio_configured) { +                op_ret = posix_aio_on (this); + +                if (op_ret == -1) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_POSIX_AIO, +                                "Posix AIO init failed"); +                        ret = -1; +                        goto out; +                } +        } + +        GF_OPTION_INIT ("node-uuid-pathinfo", +                        _private->node_uuid_pathinfo, bool, out); +        if (_private->node_uuid_pathinfo && +            (gf_uuid_is_null (_private->glusterd_uuid))) { +                        gf_msg (this->name, GF_LOG_INFO, 0, P_MSG_UUID_NULL, +                                "glusterd uuid is NULL, pathinfo xattr would" +                                " fallback to <hostname>:<export>"); +        } + +        _private->disk_space_check_active = _gf_false; +        _private->disk_space_full          = 0; +        GF_OPTION_INIT ("reserve", +                        _private->disk_reserve, uint32, out); +        if (_private->disk_reserve) +                posix_spawn_disk_space_check_thread (this); + +        _private->health_check_active = _gf_false; +        GF_OPTION_INIT ("health-check-interval", +                        _private->health_check_interval, uint32, out); +        GF_OPTION_INIT ("health-check-timeout", +                        _private->health_check_timeout, uint32, out); +        if (_private->health_check_interval) +                posix_spawn_health_check_thread (this); + +        pthread_mutex_init (&_private->janitor_lock, NULL); +        pthread_cond_init (&_private->janitor_cond, NULL); +        INIT_LIST_HEAD (&_private->janitor_fds); + +        posix_spawn_janitor_thread (this); + +        pthread_mutex_init (&_private->fsync_mutex, NULL); +        pthread_cond_init (&_private->fsync_cond, NULL); +        INIT_LIST_HEAD (&_private->fsyncs); + +        ret = gf_thread_create (&_private->fsyncer, NULL, posix_fsyncer, this, +                                "posixfsy"); +        if (ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_FSYNCER_THREAD_CREATE_FAILED, +                        "fsyncer thread creation failed"); +                goto out; +        } + +        GF_OPTION_INIT ("batch-fsync-mode", batch_fsync_mode_str, str, out); + +        if (set_batch_fsync_mode (_private, batch_fsync_mode_str) != 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, +                        "Unknown mode string: %s", batch_fsync_mode_str); +                goto out; +        } + +        GF_OPTION_INIT ("gfid2path", _private->gfid2path, bool, out); + +        GF_OPTION_INIT ("gfid2path-separator", gfid2path_sep, str, out); +        if (set_gfid2path_separator (_private, gfid2path_sep) != 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, +                        "Length of separator exceeds 7: %s", gfid2path_sep); +                goto out; +        } + +#ifdef GF_DARWIN_HOST_OS + +        char  *xattr_user_namespace_mode_str = NULL; + +        GF_OPTION_INIT ("xattr-user-namespace-mode", +                        xattr_user_namespace_mode_str, str, out); + +        if (set_xattr_user_namespace_mode (_private, +                                           xattr_user_namespace_mode_str) != 0) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, +                        "Unknown xattr user namespace mode string: %s", +                        xattr_user_namespace_mode_str); +                goto out; +        } +#endif + +        GF_OPTION_INIT ("batch-fsync-delay-usec", _private->batch_fsync_delay_usec, +                        uint32, out); +        GF_OPTION_INIT ("force-create-mode", force_create, int32, out); +        _private->force_create_mode = force_create; + +        GF_OPTION_INIT ("force-directory-mode", force_directory, int32, out); +        _private->force_directory_mode = force_directory; + +        GF_OPTION_INIT ("create-mask", +                        create_mask, int32, out); +        _private->create_mask = create_mask; + +        GF_OPTION_INIT ("create-directory-mask", +                        create_directory_mask, int32, out); +        _private->create_directory_mask = create_directory_mask; +out: +        if (ret) { +                if (_private) { +                        GF_FREE (_private->base_path); + +                        GF_FREE (_private->hostname); + +                        GF_FREE (_private->trash_path); + +                        GF_FREE (_private); +                } + +                this->private = NULL; +        } +        return ret; +} + +void +posix_fini (xlator_t *this) +{ +        struct posix_private *priv = this->private; +        if (!priv) +                return; +        this->private = NULL; +        /*unlock brick dir*/ +        if (priv->mount_lock) +                (void) sys_closedir (priv->mount_lock); + +        GF_FREE (priv->base_path); +        GF_FREE (priv->hostname); +        GF_FREE (priv->trash_path); +        GF_FREE (priv); + +        return; +} + +struct volume_options options[] = { +        { .key  = {"o-direct"}, +          .type = GF_OPTION_TYPE_BOOL }, +        { .key  = {"directory"}, +          .type = GF_OPTION_TYPE_PATH, +          .default_value = "{{brick.path}}" +        }, +        { .key  = {"hostname"}, +          .type = GF_OPTION_TYPE_ANY }, +        { .key  = {"export-statfs-size"}, +          .type = GF_OPTION_TYPE_BOOL }, +        { .key  = {"mandate-attribute"}, +          .type = GF_OPTION_TYPE_BOOL }, +        { .key  = {"background-unlink"}, +          .type = GF_OPTION_TYPE_BOOL }, +        { .key  = {"janitor-sleep-duration"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 1, +          .validate = GF_OPT_VALIDATE_MIN, +          .default_value = "10", +          .description = "Interval (in seconds) between times the internal " +                         "'landfill' directory is emptied." +        }, +        { .key  = {"volume-id"}, +          .type = GF_OPTION_TYPE_ANY, +          .default_value = "{{brick.volumeid}}" +        }, +        { .key  = {"glusterd-uuid"}, +          .type = GF_OPTION_TYPE_STR }, +        { +          .key  = {"linux-aio"}, +          .type = GF_OPTION_TYPE_BOOL, +          .default_value = "off", +          .description = "Support for native Linux AIO", +          .op_version = {1}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { +          .key = {"brick-uid"}, +          .type = GF_OPTION_TYPE_INT, +          .min = -1, +          .validate = GF_OPT_VALIDATE_MIN, +          .default_value = "-1", +          .description = "Support for setting uid of brick's owner", +          .op_version = {1}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { +          .key = {"brick-gid"}, +          .type = GF_OPTION_TYPE_INT, +          .min = -1, +          .validate = GF_OPT_VALIDATE_MIN, +          .default_value = "-1", +          .description = "Support for setting gid of brick's owner", +          .op_version = {1}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { .key = {"node-uuid-pathinfo"}, +          .type = GF_OPTION_TYPE_BOOL, +          .default_value = "off", +          .description = "return glusterd's node-uuid in pathinfo xattr" +                         " string instead of hostname", +          .op_version = {3}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { +          .key = {"health-check-interval"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0, +          .default_value = "30", +          .validate = GF_OPT_VALIDATE_MIN, +          .description = "Interval in seconds for a filesystem health check, " +                         "set to 0 to disable", +          .op_version = {3}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { +          .key = {"health-check-timeout"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0, +          .default_value = "10", +          .validate = GF_OPT_VALIDATE_MIN, +          .description = "Interval in seconds to wait aio_write finish for health check, " +                         "set to 0 to disable", +          .op_version = {GD_OP_VERSION_4_0_0}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { +          .key = {"reserve"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0, +          .default_value = "1", +          .validate = GF_OPT_VALIDATE_MIN, +          .description = "Percentage of disk space to be reserved." +           " Set to 0 to disable", +          .op_version = {GD_OP_VERSION_3_13_0}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { .key = {"batch-fsync-mode"}, +          .type = GF_OPTION_TYPE_STR, +          .default_value = "reverse-fsync", +          .description = "Possible values:\n" +          "\t- syncfs: Perform one syncfs() on behalf oa batch" +          "of fsyncs.\n" +          "\t- syncfs-single-fsync: Perform one syncfs() on behalf of a batch" +          " of fsyncs and one fsync() per batch.\n" +          "\t- syncfs-reverse-fsync: Preform one syncfs() on behalf of a batch" +          " of fsyncs and fsync() each file in the batch in reverse order.\n" +          " in reverse order.\n" +          "\t- reverse-fsync: Perform fsync() of each file in the batch in" +          " reverse order.", +          .op_version = {3}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { .key = {"batch-fsync-delay-usec"}, +          .type = GF_OPTION_TYPE_INT, +          .default_value = "0", +          .description = "Num of usecs to wait for aggregating fsync" +          " requests", +          .op_version = {3}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { .key = {"update-link-count-parent"}, +          .type = GF_OPTION_TYPE_BOOL, +          .default_value = "off", +          .description = "Enable placeholders for gfid to path conversion", +          .op_version = {GD_OP_VERSION_3_6_0}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +        { .key = {"gfid2path"}, +          .type = GF_OPTION_TYPE_BOOL, +#ifdef __NetBSD__ +          /* +           * NetBSD storage of extended attributes for UFS1 badly +           * scales when the list of extended attributes names rises. +           * This option can add as many extended attributes names +           * as we have files, hence we keep it disabled for performance +           * sake. +           */ +          .default_value = "off", +#else +          .default_value = "on", +#endif +          .description = "Enable logging metadata for gfid to path conversion", +          .op_version = {GD_OP_VERSION_3_12_0}, +          .flags = OPT_FLAG_SETTABLE +        }, +        { .key = {"gfid2path-separator"}, +          .type = GF_OPTION_TYPE_STR, +          .default_value = ":", +          .description = "Path separator for glusterfs.gfidtopath virt xattr", +          .op_version = {GD_OP_VERSION_3_12_0}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +#if GF_DARWIN_HOST_OS +        { .key = {"xattr-user-namespace-mode"}, +          .type = GF_OPTION_TYPE_STR, +          .default_value = "none", +          .description = "Option to control XATTR user namespace on the raw filesystem: " +          "\t- None: Will use the user namespace, so files will be exchangable with Linux.\n" +          " The raw filesystem will not be compatible with OS X Finder.\n" +          "\t- Strip: Will strip the user namespace before setting. The raw filesystem will work in OS X.\n", +          .op_version = {GD_OP_VERSION_3_6_0}, +          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC +        }, +#endif +        { .key  = {"shared-brick-count"}, +          .type = GF_OPTION_TYPE_INT, +          .default_value = "1", +          .description = "Number of bricks sharing the same backend export." +          " Useful for displaying the proper usable size through statvfs() " +          "call (df command)", +        }, +        { .key  = {"force-create-mode"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0000, +          .max = 0777, +          .default_value = "0000", +          .validate = GF_OPT_VALIDATE_MIN, +          .validate = GF_OPT_VALIDATE_MAX, +          .description = "Mode bit permission that will always be set on a file." +        }, +        { .key  = {"force-directory-mode"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0000, +          .max = 0777, +          .default_value = "0000", +          .validate = GF_OPT_VALIDATE_MIN, +          .validate = GF_OPT_VALIDATE_MAX, +          .description = "Mode bit permission that will be always set on directory" +        }, +        { .key  = {"create-mask"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0000, +          .max = 0777, +          .default_value = "0777", +          .validate = GF_OPT_VALIDATE_MIN, +          .validate = GF_OPT_VALIDATE_MAX, +          .description = "Any bit not set here will be removed from the" +          "modes set on a file when it is created" +        }, +        { .key  = {"create-directory-mask"}, +          .type = GF_OPTION_TYPE_INT, +          .min = 0000, +          .max = 0777, +          .default_value = "0777", +          .validate = GF_OPT_VALIDATE_MIN, +          .validate = GF_OPT_VALIDATE_MAX, +          .description = "Any bit not set here will be removed from the" +          "modes set on a directory when it is created" +        }, +        { .key  = {NULL} } +}; diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c new file mode 100644 index 00000000000..7a83eb3dfba --- /dev/null +++ b/xlators/storage/posix/src/posix-entry-ops.c @@ -0,0 +1,2125 @@ +/* +   Copyright (c) 2006-2017 Red Hat, Inc. <http://www.redhat.com> +   This file is part of GlusterFS. + +   This file is licensed to you under your choice of the GNU Lesser +   General Public License, version 3 or any later version (LGPLv3 or +   later), or the GNU General Public License, version 2 (GPLv2), in all +   cases as published by the Free Software Foundation. +*/ +#define __XOPEN_SOURCE 500 + +/* for SEEK_HOLE and SEEK_DATA */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <openssl/md5.h> +#include <stdint.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <errno.h> +#include <libgen.h> +#include <pthread.h> +#include <ftw.h> +#include <sys/stat.h> +#include <signal.h> +#include <sys/uio.h> +#include <unistd.h> +#include <ftw.h> + +#ifndef GF_BSD_HOST_OS +#include <alloca.h> +#endif /* GF_BSD_HOST_OS */ + +#ifdef HAVE_LINKAT +#include <fcntl.h> +#endif /* HAVE_LINKAT */ + +#include "glusterfs.h" +#include "checksum.h" +#include "dict.h" +#include "logging.h" +#include "posix.h" +#include "posix-handle.h" +#include "xlator.h" +#include "defaults.h" +#include "common-utils.h" +#include "compat-errno.h" +#include "compat.h" +#include "byte-order.h" +#include "syscall.h" +#include "statedump.h" +#include "locking.h" +#include "timer.h" +#include "glusterfs3-xdr.h" +#include "hashfn.h" +#include "posix-aio.h" +#include "glusterfs-acl.h" +#include "posix-messages.h" +#include "events.h" +#include "posix-gfid-path.h" +#include "compat-uuid.h" + +extern char *marker_xattrs[]; +#define ALIGN_SIZE 4096 + +#undef HAVE_SET_FSID +#ifdef HAVE_SET_FSID + +#define DECLARE_OLD_FS_ID_VAR uid_t old_fsuid; gid_t old_fsgid; + +#define SET_FS_ID(uid, gid) do {                \ +                old_fsuid = setfsuid (uid);     \ +                old_fsgid = setfsgid (gid);     \ +        } while (0) + +#define SET_TO_OLD_FS_ID() do {                 \ +                setfsuid (old_fsuid);           \ +                setfsgid (old_fsgid);           \ +        } while (0) + +#else + +#define DECLARE_OLD_FS_ID_VAR +#define SET_FS_ID(uid, gid) +#define SET_TO_OLD_FS_ID() + +#endif + +/* Setting microseconds or nanoseconds depending on what's supported: +   The passed in `tv` can be +       struct timespec +   if supported (better, because it supports nanosecond resolution) or +       struct timeval +   otherwise. */ +#if HAVE_UTIMENSAT +#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ +        tv.tv_nsec = nanosecs +#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ +        (sys_utimensat (AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW)) +#else +#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ +        tv.tv_usec = nanosecs / 1000 +#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ +        (lutimes (path, tv)) +#endif + +gf_boolean_t +posix_symlinks_match (xlator_t *this, loc_t *loc, uuid_t gfid) +{ +        struct posix_private *priv = NULL; +        char linkname_actual[PATH_MAX] = {0,}; +        char linkname_expected[PATH_MAX] = {0}; +        char *dir_handle = NULL; +        ssize_t len = 0; +        size_t handle_size = 0; +        gf_boolean_t ret = _gf_false; + +        priv = this->private; +        handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); +        dir_handle = alloca0 (handle_size); + +        snprintf (linkname_expected, handle_size, "../../%02x/%02x/%s/%s", +                  loc->pargfid[0], loc->pargfid[1], uuid_utoa (loc->pargfid), +                  loc->name); + +        MAKE_HANDLE_GFID_PATH (dir_handle, this, gfid, NULL); +        len = sys_readlink (dir_handle, linkname_actual, PATH_MAX); +        if (len < 0) +                goto out; +        linkname_actual[len] = '\0'; + +        if (!strncmp (linkname_actual, linkname_expected, handle_size)) +                ret = _gf_true; + +out: +        return ret; +} + +dict_t* +posix_dict_set_nlink (dict_t *req, dict_t *res, int32_t nlink) +{ +        int   ret  =  -1; + +        if (req == NULL || !dict_get (req, GF_REQUEST_LINK_COUNT_XDATA)) +                goto out; + +        if (res == NULL) +                res = dict_new (); +        if (res == NULL) +                goto out; + +        ret = dict_set_uint32 (res, GF_RESPONSE_LINK_COUNT_XDATA, nlink); +        if (ret == -1) +                gf_msg ("posix", GF_LOG_WARNING, 0, P_MSG_SET_XDATA_FAIL, +                        "Failed to set GF_RESPONSE_LINK_COUNT_XDATA"); +out: +        return res; +} + +/* Regular fops */ + +int32_t +posix_lookup (call_frame_t *frame, xlator_t *this, +              loc_t *loc, dict_t *xdata) +{ +        struct iatt buf                = {0, }; +        int32_t     op_ret             = -1; +        int32_t     entry_ret          = 0; +        int32_t     op_errno           = 0; +        dict_t *    xattr              = NULL; +        char *      real_path          = NULL; +        char *      par_path           = NULL; +        struct iatt postparent         = {0,}; +        int32_t     gfidless           = 0; +        char        *pgfid_xattr_key   = NULL; +        int32_t     nlink_samepgfid    = 0; +        struct  posix_private *priv    = NULL; +        posix_inode_ctx_t *ctx         = NULL; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        priv = this->private; + +        /* The Hidden directory should be for housekeeping purpose and it +           should not get any gfid on it */ +        if (__is_root_gfid (loc->pargfid) && loc->name +            && (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { +                gf_msg (this->name, GF_LOG_WARNING, EPERM, +                        P_MSG_LOOKUP_NOT_PERMITTED, "Lookup issued on %s," +                        " which is not permitted", GF_HIDDEN_PATH); +                op_errno = EPERM; +                op_ret = -1; +                goto out; +        } + +        op_ret = dict_get_int32 (xdata, GF_GFIDLESS_LOOKUP, &gfidless); +        op_ret = -1; +        if (gf_uuid_is_null (loc->pargfid) || (loc->name == NULL)) { +                /* nameless lookup */ +                MAKE_INODE_HANDLE (real_path, this, loc, &buf); +        } else { +                MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &buf); + +                if (gf_uuid_is_null (loc->inode->gfid)) { +                        op_ret = posix_gfid_heal (this, real_path, loc, xdata); +                        if (op_ret < 0) { +                                op_errno = -op_ret; +                                op_ret = -1; +                                goto out; +                        } +                        MAKE_ENTRY_HANDLE (real_path, par_path, this, +                                           loc, &buf); +                } +        } + +        op_errno = errno; + +        if (op_ret == -1) { +                if (op_errno != ENOENT) { +                        gf_msg (this->name, GF_LOG_WARNING, op_errno, +                                P_MSG_LSTAT_FAILED, +                                "lstat on %s failed", +                                real_path ? real_path : "null"); +                } + +                entry_ret = -1; +                goto parent; +        } + +        if (xdata && (op_ret == 0)) { +                xattr = posix_xattr_fill (this, real_path, loc, NULL, -1, xdata, +                                          &buf); +        } + +        if (priv->update_pgfid_nlinks) { +                if (!gf_uuid_is_null (loc->pargfid) && !IA_ISDIR (buf.ia_type)) { +                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, +                                              PGFID_XATTR_KEY_PREFIX, +                                              loc->pargfid); + +                        op_ret = posix_inode_ctx_get_all (loc->inode, this, +                                                          &ctx); +                        if (op_ret < 0) { +                                op_errno = ENOMEM; +                                goto out; +                        } + +                        pthread_mutex_lock (&ctx->pgfid_lock); +                        { +                                SET_PGFID_XATTR_IF_ABSENT (real_path, +                                                           pgfid_xattr_key, +                                                           nlink_samepgfid, +                                                           XATTR_CREATE, op_ret, +                                                           this, unlock); +                        } +unlock: +                        pthread_mutex_unlock (&ctx->pgfid_lock); +                } +        } + +parent: +        if (par_path) { +                op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_LSTAT_FAILED, "post-operation lstat on" +                                " parent %s failed", par_path); +                        if (op_errno == ENOENT) +                                /* If parent directory is missing in a lookup, +                                   errno should be ESTALE (bad handle) and not +                                   ENOENT (missing entry) +                                */ +                                op_errno = ESTALE; +                        goto out; +                } +        } + +        op_ret = entry_ret; +out: +        if (!op_ret && !gfidless && gf_uuid_is_null (buf.ia_gfid)) { +                gf_msg (this->name, GF_LOG_ERROR, ENODATA, P_MSG_NULL_GFID, +                        "buf->ia_gfid is null for " +                        "%s", (real_path) ? real_path: ""); +                op_ret = -1; +                op_errno = ENODATA; +        } + +        if (op_ret == 0) +                op_errno = 0; +        STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, +                             (loc)?loc->inode:NULL, &buf, xattr, &postparent); + +        if (xattr) +                dict_unref (xattr); + +        return 0; +} + +int +posix_mknod (call_frame_t *frame, xlator_t *this, +             loc_t *loc, mode_t mode, dev_t dev, mode_t umask, dict_t *xdata) +{ +        int                   tmp_fd          = 0; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_path       = 0; +        char                 *par_path        = 0; +        struct iatt           stbuf           = { 0, }; +        struct posix_private *priv            = NULL; +        gid_t                 gid             = 0; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        void *                uuid_req        = NULL; +        int32_t               nlink_samepgfid = 0; +        char                 *pgfid_xattr_key = NULL; +        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; +        gf_boolean_t          linked          = _gf_false; +        gf_loglevel_t         level           = GF_LOG_NONE; +        mode_t                mode_bit        = 0; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, +                                  out); +        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, NULL); + +        mode_bit = (priv->create_mask & mode) | priv->force_create_mode; +        mode = posix_override_umask (mode, mode_bit); + +        gid = frame->root->gid; + +        SET_FS_ID (frame->root->uid, gid); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); +        if (!real_path || !par_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent of %s failed", +                        real_path); +                goto out; +        } + +        if (preparent.ia_prot.sgid) { +                gid = preparent.ia_gid; +        } + +        /* Check if the 'gfid' already exists, because this mknod may be an +           internal call from distribute for creating 'linkfile', and that +           linkfile may be for a hardlinked file */ +        if (dict_get (xdata, GLUSTERFS_INTERNAL_FOP_KEY)) { +                dict_del (xdata, GLUSTERFS_INTERNAL_FOP_KEY); +                op_ret = dict_get_ptr (xdata, "gfid-req", &uuid_req); +                if (op_ret) { +                        gf_msg_debug (this->name, 0, "failed to get the gfid from " +                                "dict for %s", loc->path); +                        goto real_op; +                } +                op_ret = posix_create_link_if_gfid_exists (this, uuid_req, +                                                           real_path, +                                                           loc->inode->table); +                if (!op_ret) { +                        linked = _gf_true; +                        goto post_op; +                } +        } + +real_op: +#ifdef __NetBSD__ +        if (S_ISFIFO(mode)) +                op_ret = mkfifo (real_path, mode); +        else +#endif /* __NetBSD__ */ +        op_ret = sys_mknod (real_path, mode, dev); + +        if (op_ret == -1) { +                op_errno = errno; +                if ((op_errno == EINVAL) && S_ISREG (mode)) { +                        /* Over Darwin, mknod with (S_IFREG|mode) +                           doesn't work */ +                        tmp_fd = sys_creat (real_path, mode); +                        if (tmp_fd == -1) { +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_CREATE_FAILED, "create failed on" +                                        "%s", real_path); +                                goto out; +                        } +                        sys_close (tmp_fd); +                } else { +                        if (op_errno == EEXIST) +                                level = GF_LOG_DEBUG; +                        else +                                level = GF_LOG_ERROR; +                        gf_msg (this->name, level, errno, P_MSG_MKNOD_FAILED, +                                "mknod on %s failed", real_path); +                        goto out; +                } +        } + +        entry_created = _gf_true; + +#ifndef HAVE_SET_FSID +        op_ret = sys_lchown (real_path, frame->root->uid, gid); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LCHOWN_FAILED, +                        "lchown on %s failed", real_path); +                goto out; +        } +#endif + +post_op: +        op_ret = posix_acl_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_ACL_FAILED, +                        "setting ACLs on %s failed", real_path); +        } + +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                nlink_samepgfid = 1; + +                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, +                                 XATTR_CREATE, op_ret, this, ignore); +        } + +        if (priv->gfid2path) { +                posix_set_gfid2path_xattr (this, real_path, loc->pargfid, +                                           loc->name); +        } + +ignore: +        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); +        if (op_ret) { +                if (errno != EEXIST) +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_XATTR_FAILED, +                                "setting xattrs on %s failed", real_path); +                else +                        gf_msg_debug (this->name, 0, +                                      "setting xattrs on %s failed", real_path); +        } + +        if (!linked) { +                op_ret = posix_gfid_set (this, real_path, loc, xdata); +                if (op_ret) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, +                                "setting gfid on %s failed", real_path); +                } else { +                        gfid_set = _gf_true; +                } +        } + +        op_ret = posix_pstat (this, NULL, real_path, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_MKNOD_FAILED, +                        "mknod on %s failed", real_path); +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, +                             (loc)?loc->inode:NULL, &stbuf, &preparent, +                             &postparent, NULL); + +        if (op_ret < 0) { +                if (entry_created) { +                        if (S_ISREG (mode)) +                                sys_unlink (real_path); +                        else +                                sys_rmdir (real_path); +                } + +                if (gfid_set) +                        posix_gfid_unset (this, xdata); +        } + +        return 0; +} + +int +posix_mkdir (call_frame_t *frame, xlator_t *this, +             loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata) +{ +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_path       = NULL, *gfid_path = NULL; +        char                 *par_path        = NULL, *xattr_name = NULL; +        struct iatt           stbuf           = {0, }; +        struct posix_private *priv            = NULL; +        gid_t                 gid             = 0; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; +        void                 *uuid_req        = NULL; +        ssize_t               size            = 0; +        dict_t               *xdata_rsp       = NULL; +        void                 *disk_xattr      = NULL; +        data_t               *arg_data        = NULL; +        char          pgfid[GF_UUID_BUF_SIZE] = {0}; +        char                 value_buf[4096]  = {0,}; +        gf_boolean_t         have_val         = _gf_false; +        mode_t               mode_bit         = 0; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        /* The Hidden directory should be for housekeeping purpose and it +           should not get created from a user request */ +        if (__is_root_gfid (loc->pargfid) && +            (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { +                gf_msg (this->name, GF_LOG_WARNING, EPERM, +                        P_MSG_MKDIR_NOT_PERMITTED, "mkdir issued on %s, which" +                        "is not permitted", GF_HIDDEN_PATH); +                op_errno = EPERM; +                op_ret = -1; +                goto out; +        } + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, +                                  out); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, NULL); +        if (!real_path || !par_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        if (loc->parent) +                gf_uuid_unparse (loc->parent->gfid, pgfid); +        else +                gf_uuid_unparse (loc->pargfid, pgfid); + +        gid = frame->root->gid; + +        op_ret = posix_pstat (this, NULL, real_path, &stbuf); + +        SET_FS_ID (frame->root->uid, gid); + +        mode_bit = (priv->create_directory_mask & mode) +                   | priv->force_directory_mode; +        mode = posix_override_umask (mode, mode_bit); + +        if (xdata) { +                op_ret = dict_get_ptr (xdata, "gfid-req", &uuid_req); +                if (!op_ret && !gf_uuid_compare (stbuf.ia_gfid, uuid_req)) { +                        op_ret = -1; +                        op_errno = EEXIST; +                        goto out; +                } +        } + +        if (uuid_req && !gf_uuid_is_null (uuid_req)) { +                op_ret = posix_istat (this, uuid_req, NULL, &stbuf); +                if ((op_ret == 0) && IA_ISDIR (stbuf.ia_type)) { +                        size = posix_handle_path (this, uuid_req, NULL, NULL, +                                                  0); +                        if (size > 0) +                                gfid_path = alloca (size); + +                        if (gfid_path) +                                posix_handle_path (this, uuid_req, NULL, +                                                   gfid_path, size); + +                        if (frame->root->pid != GF_CLIENT_PID_SELF_HEALD) { +                                gf_msg (this->name, GF_LOG_WARNING, 0, +                                        P_MSG_DIR_OF_SAME_ID, "mkdir (%s): " +                                        "gfid (%s) is already associated with " +                                        "directory (%s). Hence, both " +                                        "directories will share same gfid and " +                                        "this can lead to inconsistencies.", +                                        loc->path, uuid_utoa (uuid_req), +                                        gfid_path ? gfid_path : "<NULL>"); + +                                gf_event (EVENT_POSIX_SAME_GFID, "gfid=%s;" +                                          "path=%s;newpath=%s;brick=%s:%s", +                                          uuid_utoa (uuid_req), +                                          gfid_path ? gfid_path : "<NULL>", +                                          loc->path, priv->hostname, +                                          priv->base_path); +                        } +                        if (!posix_symlinks_match (this, loc, uuid_req)) +                                /* For afr selfheal of dir renames, we need to +                                 * remove the old symlink in order for +                                 * posix_gfid_set to set the symlink to the +                                 * new dir.*/ +                                posix_handle_unset (this, stbuf.ia_gfid, NULL); +                } +        } else if (!uuid_req && frame->root->pid != GF_SERVER_PID_TRASH) { +                op_ret = -1; +                op_errno = EPERM; +                gf_msg_callingfn (this->name, GF_LOG_WARNING, op_errno, +                        P_MSG_NULL_GFID, "mkdir (%s): is issued without " +                        "gfid-req %p", loc->path, xdata); +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        if (preparent.ia_prot.sgid) { +                gid = preparent.ia_gid; +                mode |= S_ISGID; +        } + +        op_ret = dict_get_str (xdata, GF_PREOP_PARENT_KEY, &xattr_name); +        if (xattr_name != NULL) { +                arg_data = dict_get (xdata, xattr_name); +                if (arg_data) { +                        size = sys_lgetxattr (par_path, xattr_name, value_buf, +                                              sizeof(value_buf) - 1); +                        if (size >= 0) { +                                have_val = _gf_true; +                        } else { +                                if (errno == ERANGE) { +                                        gf_msg (this->name, GF_LOG_INFO, errno, +                                                P_MSG_PREOP_CHECK_FAILED, +                                                "mkdir (%s/%s): getxattr on key " +                                                "(%s) path (%s) failed due to " +                                                " buffer overflow", pgfid, +                                                loc->name, xattr_name, +                                                par_path); +                                        size = sys_lgetxattr (par_path, +                                                              xattr_name, NULL, +                                                              0); +                                } +                                if (size < 0) { +                                        op_ret = -1; +                                        op_errno = errno; +                                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                                P_MSG_PREOP_CHECK_FAILED, +                                                "mkdir (%s/%s): getxattr on key (%s)" +                                                " path (%s) failed ", pgfid, +                                                loc->name, xattr_name, +                                                par_path); +                                        goto out; +                                } +                        } +                        disk_xattr = alloca (size); +                        if (disk_xattr == NULL) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_PREOP_CHECK_FAILED, +                                        "mkdir (%s/%s): alloca failed during" +                                        " preop of mkdir (%s)", pgfid, +                                        loc->name, real_path); +                                goto out; +                        } +                        if (have_val) { +                                memcpy (disk_xattr, value_buf, size); +                        } else { +                                size = sys_lgetxattr (par_path, xattr_name, +                                                      disk_xattr, size); +                                if (size < 0) { +                                        op_errno = errno; +                                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                                P_MSG_PREOP_CHECK_FAILED, +                                                "mkdir (%s/%s): getxattr on " +                                                " key (%s) path (%s) failed " +                                                "(%s)", pgfid, loc->name, +                                                xattr_name, par_path, +                                                strerror (errno)); +                                        goto out; +                               } +                        } +                        if ((arg_data->len != size) +                            || (memcmp (arg_data->data, disk_xattr, size))) { +                                gf_msg (this->name, GF_LOG_INFO, EIO, +                                        P_MSG_PREOP_CHECK_FAILED, +                                        "mkdir (%s/%s): failing preop of " +                                        "mkdir (%s) as on-disk" +                                        " xattr value differs from argument " +                                        "value for key %s", pgfid, loc->name, +                                        real_path, xattr_name); +                                op_ret = -1; +                                op_errno = EIO; + +                                xdata_rsp = dict_new (); +                                if (xdata_rsp == NULL) { +                                        gf_msg (this->name, GF_LOG_ERROR, +                                                ENOMEM, +                                                P_MSG_PREOP_CHECK_FAILED, +                                                "mkdir (%s/%s):  " +                                                "dict allocation failed", pgfid, +                                                loc->name); +                                        op_errno = ENOMEM; +                                        goto out; +                                } + +                                op_errno = dict_set_int8 (xdata_rsp, +                                                          GF_PREOP_CHECK_FAILED, 1); +                                goto out; +                        } + +                        dict_del (xdata, xattr_name); +                } + +                dict_del (xdata, GF_PREOP_PARENT_KEY); +        } + +        op_ret = sys_mkdir (real_path, mode); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_MKDIR_FAILED, +                        "mkdir of %s failed", real_path); +                goto out; +        } + +        entry_created = _gf_true; + +#ifndef HAVE_SET_FSID +        op_ret = sys_chown (real_path, frame->root->uid, gid); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_CHOWN_FAILED, +                        "chown on %s failed", real_path); +                goto out; +        } +#endif +        op_ret = posix_acl_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACL_FAILED, +                        "setting ACLs on %s failed ", real_path); +        } + +        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, +                        "setting xattrs on %s failed", real_path); +        } + +        op_ret = posix_gfid_set (this, real_path, loc, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, +                        "setting gfid on %s failed", real_path); +        } else { +                gfid_set = _gf_true; +        } + +        op_ret = posix_pstat (this, NULL, real_path, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat on %s failed", real_path); +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent of %s failed", +                        real_path); +                goto out; +        } + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, +                             (loc)?loc->inode:NULL, &stbuf, &preparent, +                             &postparent, xdata_rsp); + +        if (op_ret < 0) { +                if (entry_created) +                        sys_rmdir (real_path); + +                if (gfid_set) +                        posix_gfid_unset (this, xdata); +        } + +        if (xdata_rsp) +                dict_unref (xdata_rsp); + +        return 0; +} + +int +posix_add_unlink_to_ctx (inode_t *inode, xlator_t *this, char *unlink_path) +{ +        uint64_t ctx = GF_UNLINK_FALSE; +        int ret = 0; + +        if (!unlink_path) { +                gf_msg (this->name, GF_LOG_ERROR, ENOMEM, +                        P_MSG_UNLINK_FAILED, +                        "Creation of unlink entry failed for gfid: %s", +                        unlink_path); +                ret = -1; +                goto out; +        } + +        ctx = GF_UNLINK_TRUE; +        ret = posix_inode_ctx_set_unlink_flag (inode, this, ctx); +        if (ret < 0) { +                goto out; +        } + +out: +        return ret; +} + +int32_t +posix_move_gfid_to_unlink (xlator_t *this, uuid_t gfid, loc_t *loc) +{ +        char *unlink_path = NULL; +        char *gfid_path = NULL; +        int ret = 0; +        struct posix_private    *priv_posix = NULL; + +        priv_posix = (struct posix_private *) this->private; + +        MAKE_HANDLE_GFID_PATH (gfid_path, this, gfid, NULL); + +        POSIX_GET_FILE_UNLINK_PATH (priv_posix->base_path, +                                    loc->inode->gfid, unlink_path); +        if (!unlink_path) { +                ret = -1; +                goto out; +        } +        gf_msg_debug (this->name, 0, +                      "Moving gfid: %s to unlink_path : %s", +                      gfid_path, unlink_path); +        ret = sys_rename (gfid_path, unlink_path); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_UNLINK_FAILED, +                        "Creation of unlink entry failed for gfid: %s", +                        unlink_path); +                goto out; +        } +        ret = posix_add_unlink_to_ctx (loc->inode, this, unlink_path); +        if (ret < 0) +                goto out; + +out: +        return ret; +} + +int32_t +posix_unlink_gfid_handle_and_entry (xlator_t *this, const char *real_path, +                                    struct iatt *stbuf, int32_t *op_errno, +                                    loc_t *loc, gf_boolean_t get_link_count, +                                    dict_t *rsp_dict) +{ +        int32_t                ret      = 0; +        struct iatt            prebuf   = {0,}; +        gf_boolean_t           locked   = _gf_false; + +        /*  Unlink the gfid_handle_first */ +        if (stbuf && stbuf->ia_nlink == 1) { + +                LOCK (&loc->inode->lock); + +                if (loc->inode->fd_count == 0) { +                        UNLOCK (&loc->inode->lock); +                        ret = posix_handle_unset (this, stbuf->ia_gfid, NULL); +                } else { +                        UNLOCK (&loc->inode->lock); +                        ret = posix_move_gfid_to_unlink (this, stbuf->ia_gfid, +                                                         loc); +                } +                if (ret) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_UNLINK_FAILED, "unlink of gfid handle " +                                "failed for path:%s with gfid %s", +                                real_path, uuid_utoa (stbuf->ia_gfid)); +                } +        } + +        if (get_link_count) { +                LOCK (&loc->inode->lock); +                locked = _gf_true; +                ret = posix_pstat (this, loc->gfid, real_path, &prebuf); +                if (ret) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_LSTAT_FAILED, "lstat on %s failed", +                                real_path); +                        goto err; +                } +        } + +        /* Unlink the actual file */ +        ret = sys_unlink (real_path); +        if (ret == -1) { +                if (op_errno) +                        *op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_UNLINK_FAILED, +                        "unlink of %s failed", real_path); +                goto err; +        } + +        if (locked) { +                UNLOCK (&loc->inode->lock); +                locked = _gf_false; +        } + +        ret = dict_set_uint32 (rsp_dict, GET_LINK_COUNT, prebuf.ia_nlink); +        if (ret) +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_SET_XDATA_FAIL, +                        "failed to set "GET_LINK_COUNT" for %s", real_path); + +        return 0; + +err: +        if (locked) { +                UNLOCK (&loc->inode->lock); +                locked = _gf_false; +        } +        return -1; +} + +gf_boolean_t +posix_skip_non_linkto_unlink (dict_t *xdata, loc_t *loc, char *key, +                              const char *linkto_xattr, struct iatt *stbuf, +                              const char *real_path) +{ +        gf_boolean_t     skip_unlink            = _gf_false; +        gf_boolean_t     is_dht_linkto_file     = _gf_false; +        int              unlink_if_linkto       = 0; +        ssize_t          xattr_size             = -1; +        int              op_ret                 = -1; + +        op_ret = dict_get_int32 (xdata, key, +                                 &unlink_if_linkto); + +        if (!op_ret && unlink_if_linkto) { + +                is_dht_linkto_file =  IS_DHT_LINKFILE_MODE (stbuf); +                if (!is_dht_linkto_file) +                        return _gf_true; + +                LOCK (&loc->inode->lock); + +                xattr_size = sys_lgetxattr (real_path, linkto_xattr, NULL, 0); + +                if (xattr_size <= 0) +                        skip_unlink = _gf_true; + +                UNLOCK (&loc->inode->lock); + +                gf_msg ("posix", GF_LOG_INFO, 0, P_MSG_XATTR_STATUS, +                        "linkto_xattr status: %"PRIu32" for %s", skip_unlink, +                        real_path); +        } +        return skip_unlink; + +} + +int32_t +posix_unlink (call_frame_t *frame, xlator_t *this, +              loc_t *loc, int xflag, dict_t *xdata) +{ +        int32_t                op_ret             = -1; +        int32_t                op_errno           = 0; +        char                   *real_path         = NULL; +        char                   *par_path          = NULL; +        int32_t                fd                 = -1; +        struct iatt            stbuf              = {0,}; +        struct iatt            postbuf            = {0,}; +        struct posix_private  *priv               = NULL; +        struct iatt            preparent          = {0,}; +        struct iatt            postparent         = {0,}; +        char                  *pgfid_xattr_key    = NULL; +        int32_t                nlink_samepgfid    = 0; +        int32_t                check_open_fd      = 0; +        int32_t                skip_unlink        = 0; +        int32_t                fdstat_requested   = 0; +        dict_t                *unwind_dict        = NULL; +        void                  *uuid               = NULL; +        char                   uuid_str[GF_UUID_BUF_SIZE] = {0}; +        char                   gfid_str[GF_UUID_BUF_SIZE] = {0}; +        gf_boolean_t           get_link_count     = _gf_false; +        posix_inode_ctx_t     *ctx                = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); +        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); +        if (!real_path || !par_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        priv = this->private; + +        op_ret = dict_get_ptr (xdata, TIER_LINKFILE_GFID, &uuid); + +        if (!op_ret && gf_uuid_compare (uuid, stbuf.ia_gfid)) { +                op_errno = ENOENT; +                op_ret = -1; +                gf_uuid_unparse (uuid, uuid_str); +                gf_uuid_unparse (stbuf.ia_gfid, gfid_str); +                gf_msg_debug (this->name, op_errno, "Mismatch in gfid for path " +                              "%s. Aborting the unlink. loc->gfid = %s, " +                              "stbuf->ia_gfid = %s", real_path, +                              uuid_str, gfid_str); +                goto out; +        } + +        op_ret = dict_get_int32 (xdata, DHT_SKIP_OPEN_FD_UNLINK, +                                 &check_open_fd); + +        if (!op_ret && check_open_fd) { + +                LOCK (&loc->inode->lock); + +                if (loc->inode->fd_count) { +                        skip_unlink = 1; +                } + +                UNLOCK (&loc->inode->lock); + +                gf_msg (this->name, GF_LOG_INFO, 0, P_MSG_KEY_STATUS_INFO, +                        "open-fd-key-status: %"PRIu32" for %s", skip_unlink, +                        real_path); + +                if (skip_unlink) { +                        op_ret = -1; +                        op_errno = EBUSY; +                        goto out; +                } +        } +        /* +         * If either of the function return true, skip_unlink. +         * If first first function itself return true, +         * we don't need to call second function, skip unlink. +         */ +        skip_unlink = posix_skip_non_linkto_unlink (xdata, loc, +                                                    DHT_SKIP_NON_LINKTO_UNLINK, +                                                    DHT_LINKTO, &stbuf, +                                                    real_path); +        skip_unlink = skip_unlink || posix_skip_non_linkto_unlink (xdata, loc, +                                                    TIER_SKIP_NON_LINKTO_UNLINK, +                                                    TIER_LINKTO, &stbuf, +                                                    real_path); +        if (skip_unlink) { +                op_ret = -1; +                op_errno = EBUSY; +                goto out; +        } + +        if (IA_ISREG (loc->inode->ia_type) && +            xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { +                fdstat_requested = 1; +        } + +        if (fdstat_requested || +            (priv->background_unlink && IA_ISREG (loc->inode->ia_type))) { +                fd = sys_open (real_path, O_RDONLY, 0); +                if (fd == -1) { +                        op_ret = -1; +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_OPEN_FAILED, +                                "open of %s failed", real_path); +                        goto out; +                } +        } + +        if (priv->update_pgfid_nlinks && (stbuf.ia_nlink > 1)) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                op_ret = posix_inode_ctx_get_all (loc->inode, this, &ctx); +                if (op_ret < 0) { +                        op_errno = ENOMEM; +                        goto out; +                } +                pthread_mutex_lock (&ctx->pgfid_lock); +                { +                        UNLINK_MODIFY_PGFID_XATTR (real_path, pgfid_xattr_key, +                                                   nlink_samepgfid, 0, op_ret, +                                                   this, unlock); +                } +        unlock: +                pthread_mutex_unlock (&ctx->pgfid_lock); + +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_XATTR_FAILED, "modification of " +                                "parent gfid xattr failed (path:%s gfid:%s)", +                                real_path, uuid_utoa (loc->inode->gfid)); +                        if (op_errno != ENOATTR) +                            /* Allow unlink if pgfid xattr is not set. */ +                            goto out; +                } +        } + +        if (priv->gfid2path && (stbuf.ia_nlink > 1)) { +                op_ret = posix_remove_gfid2path_xattr (this, real_path, +                                                       loc->pargfid, +                                                       loc->name); +                if (op_ret < 0) { +                        /* Allow unlink if pgfid xattr is not set. */ +                        if (errno != ENOATTR) +                                goto out; +                } +        } + +        unwind_dict = dict_new (); +        if (!unwind_dict) { +                op_errno = -ENOMEM; +                op_ret = -1; +                goto out; +        } + +        if (xdata && dict_get (xdata, GET_LINK_COUNT)) +                get_link_count = _gf_true; +        op_ret =  posix_unlink_gfid_handle_and_entry (this, real_path, &stbuf, +                                                      &op_errno, loc, +                                                      get_link_count, +                                                      unwind_dict); +        if (op_ret == -1) { +                goto out; +        } + +        if (fdstat_requested) { +                op_ret = posix_fdstat (this, fd, &postbuf); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FSTAT_FAILED, "post operation " +                                "fstat failed on fd=%d", fd); +                        goto out; +                } +                op_ret = posix_set_iatt_in_dict (unwind_dict, &postbuf); +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        unwind_dict = posix_dict_set_nlink (xdata, unwind_dict, stbuf.ia_nlink); +        op_ret = 0; +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, +                             &preparent, &postparent, unwind_dict); + +        if (fd != -1) { +                sys_close (fd); +        } + +        /* unref unwind_dict*/ +        if (unwind_dict) { +                dict_unref (unwind_dict); +        } + +        return 0; +} + + +int +posix_rmdir (call_frame_t *frame, xlator_t *this, +             loc_t *loc, int flags, dict_t *xdata) +{ +        int32_t               op_ret     = -1; +        int32_t               op_errno   = 0; +        char                 *real_path  = NULL; +        char                 *par_path   = NULL; +        char                 *gfid_str   = NULL; +        struct iatt           preparent  = {0,}; +        struct iatt           postparent = {0,}; +        struct iatt           stbuf      = {0,}; +        struct posix_private *priv       = NULL; +        char                  tmp_path[PATH_MAX] = {0,}; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        /* The Hidden directory should be for housekeeping purpose and it +           should not get deleted from inside process */ +        if (__is_root_gfid (loc->pargfid) && +            (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { +                gf_msg (this->name, GF_LOG_WARNING, EPERM, +                        P_MSG_RMDIR_NOT_PERMITTED, "rmdir issued on %s, which" +                        "is not permitted", GF_HIDDEN_PATH); +                op_errno = EPERM; +                op_ret = -1; +                goto out; +        } + +        priv = this->private; + +        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); +        if (!real_path || !par_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        if (flags) { +                gfid_str = uuid_utoa (stbuf.ia_gfid); + +                op_ret = sys_mkdir (priv->trash_path, 0755); +                if (errno != EEXIST && op_ret == -1) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_MKDIR_FAILED, +                                "mkdir of %s failed", priv->trash_path); +                } else { +                        (void) snprintf (tmp_path, sizeof(tmp_path), "%s/%s", +                                         priv->trash_path, gfid_str); +                        op_ret = sys_rename (real_path, tmp_path); +                        pthread_cond_signal (&priv->janitor_cond); +                } +        } else { +                op_ret = sys_rmdir (real_path); +        } +        op_errno = errno; + +        if (op_ret == 0) { +                if (posix_symlinks_match (this, loc, stbuf.ia_gfid)) +                        posix_handle_unset (this, stbuf.ia_gfid, NULL); +        } + +        if (op_errno == EEXIST) +                /* Solaris sets errno = EEXIST instead of ENOTEMPTY */ +                op_errno = ENOTEMPTY; + +        /* No need to log a common error as ENOTEMPTY */ +        if (op_ret == -1 && op_errno != ENOTEMPTY) { +                gf_msg (this->name, GF_LOG_ERROR, op_errno, P_MSG_RMDIR_FAILED, +                        "rmdir of %s failed", real_path); +        } + +        if (op_ret == -1) { +                if (op_errno == ENOTEMPTY) { +                        gf_msg_debug (this->name, 0, "%s on %s failed", (flags) +                                      ? "rename" : "rmdir", real_path); +                } else { +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_DIR_OPERATION_FAILED, "%s on %s failed", +                                (flags) ? "rename" : "rmdir", real_path); +                } +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent of %s failed", +                        par_path); +                goto out; +        } + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, +                             &preparent, &postparent, NULL); + +        return 0; +} + + +int +posix_symlink (call_frame_t *frame, xlator_t *this, +               const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata) +{ +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char *                real_path       = 0; +        char *                par_path        = 0; +        struct iatt           stbuf           = { 0, }; +        struct posix_private *priv            = NULL; +        gid_t                 gid             = 0; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        char                 *pgfid_xattr_key = NULL; +        int32_t               nlink_samepgfid = 0; +        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (linkname, out); +        VALIDATE_OR_GOTO (loc, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, +                                  out); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); + +        gid = frame->root->gid; +        if (!real_path || !par_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        SET_FS_ID (frame->root->uid, gid); + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        if (preparent.ia_prot.sgid) { +                gid = preparent.ia_gid; +        } + +        op_ret = sys_symlink (linkname, real_path); + +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_SYMLINK_FAILED, +                        "symlink of %s --> %s failed", +                        real_path, linkname); +                goto out; +        } + +        entry_created = _gf_true; + +#ifndef HAVE_SET_FSID +        op_ret = sys_lchown (real_path, frame->root->uid, gid); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LCHOWN_FAILED, +                        "lchown failed on %s", real_path); +                goto out; +        } +#endif +        op_ret = posix_acl_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACL_FAILED, +                        "setting ACLs on %s failed", real_path); +        } + +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                nlink_samepgfid = 1; +                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, +                                 XATTR_CREATE, op_ret, this, ignore); +        } + +        if (priv->gfid2path) { +                posix_set_gfid2path_xattr (this, real_path, loc->pargfid, +                                           loc->name); +        } + +ignore: +        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, +                        "setting xattrs on %s failed ", real_path); +        } + +        op_ret = posix_gfid_set (this, real_path, loc, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, +                        "setting gfid on %s failed", real_path); +        } else { +                gfid_set = _gf_true; +        } + +        op_ret = posix_pstat (this, NULL, real_path, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat failed on %s", real_path); +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, +                             (loc)?loc->inode:NULL, &stbuf, &preparent, +                             &postparent, NULL); + +        if (op_ret < 0) { +                if (entry_created) +                        sys_unlink (real_path); + +                if (gfid_set) +                        posix_gfid_unset (this, xdata); +        } + +        return 0; +} + + +int +posix_rename (call_frame_t *frame, xlator_t *this, +              loc_t *oldloc, loc_t *newloc, dict_t *xdata) +{ +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_oldpath    = NULL; +        char                 *real_newpath    = NULL; +        char                 *par_oldpath     = NULL; +        char                 *par_newpath     = NULL; +        struct iatt           stbuf           = {0, }; +        struct posix_private *priv            = NULL; +        char                  was_present     = 1; +        struct iatt           preoldparent    = {0, }; +        struct iatt           postoldparent   = {0, }; +        struct iatt           prenewparent    = {0, }; +        struct iatt           postnewparent   = {0, }; +        char                  olddirid[64]; +        char                  newdirid[64]; +        uuid_t                victim          = {0}; +        int                   was_dir         = 0; +        int                   nlink           = 0; +        char                 *pgfid_xattr_key = NULL; +        int32_t               nlink_samepgfid = 0; +        char                 *gfid_path            = NULL; +        dict_t               *unwind_dict     = NULL; +        gf_boolean_t          locked          = _gf_false; +        gf_boolean_t          get_link_count  = _gf_false; +        posix_inode_ctx_t    *ctx_old         = NULL; +        posix_inode_ctx_t    *ctx_new         = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (oldloc, out); +        VALIDATE_OR_GOTO (newloc, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); +        MAKE_ENTRY_HANDLE (real_oldpath, par_oldpath, this, oldloc, NULL); +        if (!real_oldpath || !par_oldpath) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        MAKE_ENTRY_HANDLE (real_newpath, par_newpath, this, newloc, &stbuf); +        if (!real_newpath || !par_newpath) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        unwind_dict = dict_new (); +        if (!unwind_dict) { +                op_ret = -1; +                op_errno = ENOMEM; +                goto out; +        } + +        op_ret = posix_pstat (this, oldloc->pargfid, par_oldpath, &preoldparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent %s failed", +                        par_oldpath); +                goto out; +        } + +        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &prenewparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent of %s failed", +                        par_newpath); +                goto out; +        } + +        op_ret = posix_pstat (this, NULL, real_newpath, &stbuf); +        if ((op_ret == -1) && (errno == ENOENT)){ +                was_present = 0; +        } else { +                gf_uuid_copy (victim, stbuf.ia_gfid); +                if (IA_ISDIR (stbuf.ia_type)) +                        was_dir = 1; +                nlink = stbuf.ia_nlink; +        } + +        if (was_present && IA_ISDIR(stbuf.ia_type) && !newloc->inode) { +                gf_msg (this->name, GF_LOG_WARNING, EEXIST, P_MSG_DIR_FOUND, +                        "found directory at %s while expecting ENOENT", +                        real_newpath); +                op_ret = -1; +                op_errno = EEXIST; +                goto out; +        } + +        if (was_present && IA_ISDIR(stbuf.ia_type) && +            gf_uuid_compare (newloc->inode->gfid, stbuf.ia_gfid)) { +                gf_msg (this->name, GF_LOG_WARNING, EEXIST, P_MSG_DIR_FOUND, +                        "found directory %s at %s while renaming %s", +                        uuid_utoa_r (newloc->inode->gfid, olddirid), +                        real_newpath, +                        uuid_utoa_r (stbuf.ia_gfid, newdirid)); +                op_ret = -1; +                op_errno = EEXIST; +                goto out; +        } + +        op_ret = posix_inode_ctx_get_all (oldloc->inode, this, &ctx_old); +        if (op_ret < 0) { +                op_ret = -1; +                op_errno = ENOMEM; +                goto out; +        } + +        if (newloc->inode) { +                op_ret = posix_inode_ctx_get_all (newloc->inode, this, &ctx_new); +                if (op_ret < 0) { +                        op_ret = -1; +                        op_errno = ENOMEM; +                        goto out; +                } +        } + +        if (IA_ISDIR (oldloc->inode->ia_type)) +                posix_handle_unset (this, oldloc->inode->gfid, NULL); + +        pthread_mutex_lock (&ctx_old->pgfid_lock); +        { +                if (!IA_ISDIR (oldloc->inode->ia_type) +                    && priv->update_pgfid_nlinks) { +                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, +                                              PGFID_XATTR_KEY_PREFIX, +                                              oldloc->pargfid); +                        UNLINK_MODIFY_PGFID_XATTR (real_oldpath, +                                                   pgfid_xattr_key, +                                                   nlink_samepgfid, 0, +                                                   op_ret, +                                                   this, unlock); +                } + +                if ((xdata) && (dict_get (xdata, GET_LINK_COUNT)) +                    && (real_newpath) && (was_present)) { +                        pthread_mutex_lock (&ctx_new->pgfid_lock); +                        locked = _gf_true; +                        get_link_count = _gf_true; +                        op_ret = posix_pstat (this, newloc->gfid, real_newpath, +                                              &stbuf); +                        if ((op_ret == -1) && (errno != ENOENT)) { +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_LSTAT_FAILED, +                                        "lstat on %s failed", real_newpath); +                                goto unlock; +                        } +                } + +                op_ret = sys_rename (real_oldpath, real_newpath); +                if (op_ret == -1) { +                        op_errno = errno; +                        if (op_errno == ENOTEMPTY) { +                                gf_msg_debug (this->name, 0, "rename of %s to" +                                              " %s failed: %s", real_oldpath, +                                              real_newpath, +                                              strerror (op_errno)); +                        } else { +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_RENAME_FAILED, +                                        "rename of %s to %s failed", +                                        real_oldpath, real_newpath); +                       } + +                        if (priv->update_pgfid_nlinks +                            && !IA_ISDIR (oldloc->inode->ia_type)) { +                                LINK_MODIFY_PGFID_XATTR (real_oldpath, +                                                         pgfid_xattr_key, +                                                         nlink_samepgfid, 0, +                                                         op_ret, +                                                         this, unlock); +                        } + +                        goto unlock; +                } + +                if (locked) { +                        pthread_mutex_unlock (&ctx_new->pgfid_lock); +                        locked = _gf_false; +                } + +                if ((get_link_count) && +                    (dict_set_uint32 (unwind_dict, GET_LINK_COUNT, +                                      stbuf.ia_nlink))) +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_SET_XDATA_FAIL, "failed to set " +                                GET_LINK_COUNT" for %s", real_newpath); + +                if (!IA_ISDIR (oldloc->inode->ia_type) +                    && priv->update_pgfid_nlinks) { +                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, +                                              PGFID_XATTR_KEY_PREFIX, +                                              newloc->pargfid); +                        LINK_MODIFY_PGFID_XATTR (real_newpath, +                                                 pgfid_xattr_key, +                                                 nlink_samepgfid, 0, +                                                 op_ret, +                                                 this, unlock); +                } + +                if (!IA_ISDIR (oldloc->inode->ia_type) && priv->gfid2path) { +                        MAKE_HANDLE_ABSPATH (gfid_path, this, +                                             oldloc->inode->gfid); + +                        posix_remove_gfid2path_xattr (this, gfid_path, +                                                      oldloc->pargfid, +                                                      oldloc->name); +                        posix_set_gfid2path_xattr (this, gfid_path, +                                                   newloc->pargfid, +                                                   newloc->name); +                } +        } + +unlock: +        if (locked) { +                pthread_mutex_unlock (&ctx_new->pgfid_lock); +                locked = _gf_false; +        } +        pthread_mutex_unlock (&ctx_old->pgfid_lock); + +        if (op_ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_XATTR_FAILED, +                        "modification of " +                        "parent gfid xattr failed (gfid:%s)", +                        uuid_utoa (oldloc->inode->gfid)); +                goto out; +        } + +        if (was_dir) +                posix_handle_unset (this, victim, NULL); + +        if (was_present && !was_dir && nlink == 1) +                posix_handle_unset (this, victim, NULL); + +        if (IA_ISDIR (oldloc->inode->ia_type)) { +                posix_handle_soft (this, real_newpath, newloc, +                                   oldloc->inode->gfid, NULL); +        } + +        op_ret = posix_pstat (this, NULL, real_newpath, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat on %s failed", real_newpath); +                goto out; +        } + +        op_ret = posix_pstat (this, oldloc->pargfid, par_oldpath, &postoldparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent %s failed", +                        par_oldpath); +                goto out; +        } + +        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &postnewparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent %s failed", +                        par_newpath); +                goto out; +        } + +        if (was_present) +                unwind_dict = posix_dict_set_nlink (xdata, unwind_dict, nlink); +        op_ret = 0; +out: + +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, &stbuf, +                             &preoldparent, &postoldparent, +                             &prenewparent, &postnewparent, unwind_dict); + +        if (unwind_dict) +                dict_unref (unwind_dict); + +        return 0; +} + + +int +posix_link (call_frame_t *frame, xlator_t *this, +            loc_t *oldloc, loc_t *newloc, dict_t *xdata) +{ +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_oldpath    = 0; +        char                 *real_newpath    = 0; +        char                 *par_newpath     = 0; +        struct iatt           stbuf           = {0, }; +        struct posix_private *priv            = NULL; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        int32_t               nlink_samepgfid = 0; +        char                 *pgfid_xattr_key = NULL; +        gf_boolean_t          entry_created   = _gf_false; +        posix_inode_ctx_t    *ctx             = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (oldloc, out); +        VALIDATE_OR_GOTO (newloc, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); +        MAKE_INODE_HANDLE (real_oldpath, this, oldloc, &stbuf); +        if (!real_oldpath) { +                op_errno = errno; +                goto out; +        } + +        MAKE_ENTRY_HANDLE (real_newpath, par_newpath, this, newloc, &stbuf); +        if (!real_newpath || !par_newpath) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat failed: %s", par_newpath); +                goto out; +        } + + +        op_ret = sys_link (real_oldpath, real_newpath); + +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LINK_FAILED, +                        "link %s to %s failed", +                        real_oldpath, real_newpath); +                goto out; +        } + +        entry_created = _gf_true; + +        op_ret = posix_pstat (this, NULL, real_newpath, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat on %s failed", real_newpath); +                goto out; +        } + +        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat failed: %s", par_newpath); +                goto out; +        } + +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      newloc->pargfid); + +                op_ret = posix_inode_ctx_get_all (newloc->inode, this, &ctx); +                if (op_ret < 0) { +                        op_errno = ENOMEM; +                        goto out; +                } + +                pthread_mutex_lock (&ctx->pgfid_lock); +                { +                        LINK_MODIFY_PGFID_XATTR (real_newpath, pgfid_xattr_key, +                                                 nlink_samepgfid, 0, op_ret, +                                                 this, unlock); +                } +        unlock: +                pthread_mutex_unlock (&ctx->pgfid_lock); + +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_XATTR_FAILED, "modification of " +                                "parent gfid xattr failed (path:%s gfid:%s)", +                                real_newpath, uuid_utoa (newloc->inode->gfid)); +                        goto out; +                } +        } + +        if (priv->gfid2path) { +                if (stbuf.ia_nlink <= MAX_GFID2PATH_LINK_SUP) { +                        op_ret = posix_set_gfid2path_xattr (this, real_newpath, +                                                            newloc->pargfid, +                                                            newloc->name); +                        if (op_ret) { +                                op_errno = errno; +                                goto out; +                        } +                 } else { +                        gf_msg (this->name, GF_LOG_INFO, 0, +                                P_MSG_XATTR_NOTSUP, "Link count exceeded. " +                                "gfid2path xattr not set (path:%s gfid:%s)", +                                real_newpath, uuid_utoa (newloc->inode->gfid)); +                 } +        } + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, +                             (oldloc)?oldloc->inode:NULL, &stbuf, &preparent, +                             &postparent, NULL); + +        if (op_ret < 0) { +                if (entry_created) +                        sys_unlink (real_newpath); +        } + +        return 0; +} + +int +posix_create (call_frame_t *frame, xlator_t *this, +              loc_t *loc, int32_t flags, mode_t mode, +              mode_t umask, fd_t *fd, dict_t *xdata) +{ +        int32_t                op_ret          = -1; +        int32_t                op_errno        = 0; +        int32_t                _fd             = -1; +        int                    _flags          = 0; +        char *                 real_path       = NULL; +        char *                 par_path        = NULL; +        struct iatt            stbuf           = {0, }; +        struct posix_fd *      pfd             = NULL; +        struct posix_private * priv            = NULL; +        char                   was_present     = 1; + +        gid_t                  gid             = 0; +        struct iatt            preparent       = {0,}; +        struct iatt            postparent      = {0,}; + +        int                    nlink_samepgfid = 0; +        char *                 pgfid_xattr_key = NULL; +        gf_boolean_t           entry_created   = _gf_false, gfid_set = _gf_false; +        mode_t                 mode_bit        = 0; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (this->private, out); +        VALIDATE_OR_GOTO (loc, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, +                                  out); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); + +        gid = frame->root->gid; + +        SET_FS_ID (frame->root->uid, gid); +        if (!real_path || !par_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        if (preparent.ia_prot.sgid) { +                gid = preparent.ia_gid; +        } + +        if (!flags) { +                _flags = O_CREAT | O_RDWR | O_EXCL; +        } +        else { +                _flags = flags | O_CREAT; +        } + +        op_ret = posix_pstat (this, NULL, real_path, &stbuf); +        if ((op_ret == -1) && (errno == ENOENT)) { +                was_present = 0; +        } + +        if (priv->o_direct) +                _flags |= O_DIRECT; + +        mode_bit = (priv->create_mask & mode) | priv->force_create_mode; +        mode = posix_override_umask (mode, mode_bit); +        _fd = sys_open (real_path, _flags, mode); + +        if (_fd == -1) { +                op_errno = errno; +                op_ret = -1; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_OPEN_FAILED, +                        "open on %s failed", real_path); +                goto out; +        } + +        if ((_flags & O_CREAT) && (_flags & O_EXCL)) { +                entry_created = _gf_true; +        } + + +        if (was_present) +                goto fill_stat; + +#ifndef HAVE_SET_FSID +        op_ret = sys_chown (real_path, frame->root->uid, gid); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_CHOWN_FAILED, +                        "chown on %s failed", real_path); +        } +#endif +        op_ret = posix_acl_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACL_FAILED, +                        "setting ACLs on %s failed", real_path); +        } + +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                nlink_samepgfid = 1; +                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, +                                 XATTR_CREATE, op_ret, this, ignore); +        } + +        if (priv->gfid2path) { +                posix_set_gfid2path_xattr (this, real_path, loc->pargfid, +                                            loc->name); +        } +ignore: +        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, +                        "setting xattrs on %s failed ", real_path); +        } + +fill_stat: +        op_ret = posix_gfid_set (this, real_path, loc, xdata); +        if (op_ret) { +                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, +                        "setting gfid on %s failed", real_path); +        } else { +                gfid_set = _gf_true; +        } + +        op_ret = posix_fdstat (this, _fd, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fstat on %d failed", _fd); +                goto out; +        } + +        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "post-operation lstat on parent %s failed", +                        par_path); +                goto out; +        } + +        op_ret = -1; +        pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); +        if (!pfd) { +                op_errno = errno; +                goto out; +        } + +        pfd->flags = flags; +        pfd->fd    = _fd; + +        op_ret = fd_ctx_set (fd, this, (uint64_t)(long)pfd); +        if (op_ret) +                gf_msg (this->name, GF_LOG_WARNING, 0, +                        P_MSG_FD_PATH_SETTING_FAILED, +                        "failed to set the fd context path=%s fd=%p", +                        real_path, fd); + +        LOCK (&priv->lock); +        { +                priv->nr_files++; +        } +        UNLOCK (&priv->lock); + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        if ((-1 == op_ret) && (_fd != -1)) { +                sys_close (_fd); +        } + +        STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, +                             fd, (loc)?loc->inode:NULL, &stbuf, &preparent, +                             &postparent, xdata); + +        if (op_ret < 0) { +                if (entry_created) +                        sys_unlink (real_path); + +                if (gfid_set) +                        posix_gfid_unset (this, xdata); +        } + +        return 0; +} diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index 38e3198d812..99501177138 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -26,6 +26,9 @@  #include "compat-errno.h" +int +posix_handle_mkdir_hashes (xlator_t *this, const char *newpath); +  inode_t *  posix_resolve (xlator_t *this, inode_table_t *itable, inode_t *parent,                 char *bname, struct iatt *iabuf) diff --git a/xlators/storage/posix/src/posix-handle.h b/xlators/storage/posix/src/posix-handle.h index c76e618546f..97186f91e64 100644 --- a/xlators/storage/posix/src/posix-handle.h +++ b/xlators/storage/posix/src/posix-handle.h @@ -1,5 +1,5 @@  /* -   Copyright (c) 2011-2012 Red Hat, Inc. <http://www.redhat.com> +   Copyright (c) 2011-2017 Red Hat, Inc. <http://www.redhat.com>     This file is part of GlusterFS.     This file is licensed to you under your choice of the GNU Lesser @@ -10,29 +10,12 @@  #ifndef _POSIX_HANDLE_H  #define _POSIX_HANDLE_H -#include <limits.h> -#include <sys/types.h> -#include "xlator.h" -#include "posix-messages.h" - -/* From Open Group Base Specifications Issue 6 */ -#ifndef _XOPEN_PATH_MAX -#define _XOPEN_PATH_MAX 1024 -#endif - -#define TRASH_DIR "landfill" - -#define UUID0_STR "00000000-0000-0000-0000-000000000000" -#define SLEN(str) (sizeof(str) - 1) +#include "posix-inode-handle.h"  #define HANDLE_ABSPATH_LEN(this) (POSIX_BASE_PATH_LEN(this) + \                                    SLEN("/" GF_HIDDEN_PATH "/00/00/" \                                    UUID0_STR) + 1) -#define LOC_HAS_ABSPATH(loc) (loc && (loc->path) && (loc->path[0] == '/')) -#define LOC_IS_DIR(loc) (loc && (loc->inode) && \ -                (loc->inode->ia_type == IA_IFDIR)) -  #define MAKE_PGFID_XATTR_KEY(var, prefix, pgfid) do {                   \          var = alloca (strlen (prefix) + UUID_CANONICAL_FORM_LEN + 1);   \          strcpy (var, prefix);                                           \ @@ -123,32 +106,6 @@         }                                                                \      } while (0) -#define MAKE_REAL_PATH(var, this, path) do {                            \ -        size_t path_len = strlen(path);                                 \ -        size_t var_len = path_len + POSIX_BASE_PATH_LEN(this) + 1;      \ -        if (POSIX_PATH_MAX(this) != -1 &&                               \ -            var_len >= POSIX_PATH_MAX(this)) {                          \ -                var = alloca (path_len + 1);                            \ -                strcpy (var, (path[0] == '/') ? path + 1 : path);       \ -        } else {                                                        \ -                var = alloca (var_len);                                 \ -                strcpy (var, POSIX_BASE_PATH(this));                    \ -                strcpy (&var[POSIX_BASE_PATH_LEN(this)], path);         \ -        }                                                               \ -    } while (0) - -#define MAKE_HANDLE_PATH(var, this, gfid, base) do {                    \ -        int __len;                                                      \ -        __len = posix_handle_path (this, gfid, base, NULL, 0);          \ -        if (__len <= 0)                                                 \ -                break;                                                  \ -        var = alloca (__len);                                           \ -        __len = posix_handle_path (this, gfid, base, var, __len);       \ -        if (__len <= 0)                                                 \ -                var = NULL;                                             \ -        } while (0) - -  #define MAKE_HANDLE_GFID_PATH(var, this, gfid, base) do {               \          int __len = 0;                                                  \          __len = posix_handle_gfid_path (this, gfid, base, NULL, 0);     \ @@ -168,7 +125,6 @@          __len = posix_handle_relpath (this, gfid, base, var, __len);    \          } while (0) -  #define MAKE_HANDLE_ABSPATH(var, this, gfid) do {                       \          struct posix_private * __priv = this->private;                  \          int __len = HANDLE_ABSPATH_LEN(this);                           \ @@ -177,36 +133,6 @@                   __priv->base_path, gfid[0], gfid[1], uuid_utoa(gfid)); \          } while (0) - -#define MAKE_INODE_HANDLE(rpath, this, loc, iatt_p) do {                \ -        if (gf_uuid_is_null (loc->gfid)) {                              \ -                gf_msg (this->name, GF_LOG_ERROR, 0,                    \ -                        P_MSG_INODE_HANDLE_CREATE,                      \ -                        "null gfid for path %s", (loc)->path);          \ -                break;                                                  \ -        }                                                               \ -        if (LOC_IS_DIR (loc) && LOC_HAS_ABSPATH (loc)) {                \ -                MAKE_REAL_PATH (rpath, this, (loc)->path);              \ -                op_ret = posix_pstat (this, (loc)->gfid, rpath, iatt_p); \ -                break;                                                  \ -        }                                                               \ -        errno = 0;                                                      \ -        op_ret = posix_istat (this, loc->gfid, NULL, iatt_p);           \ -        if (errno != ELOOP) {                                           \ -                MAKE_HANDLE_PATH (rpath, this, (loc)->gfid, NULL);      \ -                if (!rpath) {                                           \ -                        op_ret = -1;                                    \ -                        gf_msg (this->name, GF_LOG_ERROR, errno,        \ -                                P_MSG_INODE_HANDLE_CREATE,            \ -                                "Failed to create inode handle "        \ -                                "for path %s", (loc)->path);            \ -                }                                                       \ -                break;                                                  \ -        }                                                               \ -        /* __ret == -1 && errno == ELOOP */                             \ -        } while (0) - -  #define MAKE_ENTRY_HANDLE(entp, parp, this, loc, ent_p) do {            \          char *__parp;                                                   \                                                                          \ @@ -240,25 +166,6 @@          /* expand ELOOP */                                              \          } while (0) - -#define POSIX_ANCESTRY_PATH (1 << 0) -#define POSIX_ANCESTRY_DENTRY (1 << 1) - -int -posix_handle_path (xlator_t *this, uuid_t gfid, const char *basename, char *buf, -                   size_t len); - -int -posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, -                             gf_dirent_t *head, int type, uuid_t gfid, -                             const size_t handle_size, -                             const char *priv_base_path, -                             inode_table_t *table, inode_t **parent, -                             dict_t *xdata, int32_t *op_errno); -int -posix_handle_path_safe (xlator_t *this, uuid_t gfid, const char *basename, -                        char *buf, size_t len); -  int  posix_handle_gfid_path (xlator_t *this, uuid_t gfid, const char *basename,                          char *buf, size_t len); @@ -275,13 +182,8 @@ posix_handle_soft (xlator_t *this, const char *real_path, loc_t *loc,  int  posix_handle_unset (xlator_t *this, uuid_t gfid, const char *basename); -int posix_handle_mkdir_hashes (xlator_t *this, const char *newpath); - -int posix_handle_init (xlator_t *this); - -int posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid, -                                      char *real_path, inode_table_t *itable); -  int -posix_handle_trash_init (xlator_t *this); +posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid, +                                  char *real_path, inode_table_t *itable); +  #endif /* !_POSIX_HANDLE_H */ diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index 5a3f4b129fb..8f550f9fe0d 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -38,6 +38,8 @@  #include "dict.h"  #include "logging.h"  #include "posix.h" +#include "posix-messages.h" +#include "posix-handle.h"  #include "xlator.h"  #include "defaults.h"  #include "common-utils.h" @@ -2643,3 +2645,36 @@ posix_is_bulk_removexattr (char *name, dict_t *xdata)                  return _gf_true;          return _gf_false;  } + +int32_t +posix_set_iatt_in_dict (dict_t *dict, struct iatt *in_stbuf) +{ +        int ret             = -1; +        struct iatt *stbuf  = NULL; +        int32_t len         = sizeof(struct iatt); + +        if (!dict || !in_stbuf) +                return ret; + +        stbuf = GF_CALLOC (1, len, gf_common_mt_char); +        if (!stbuf) +                return ret; + +        memcpy (stbuf, in_stbuf, len); + +        ret = dict_set_bin (dict, DHT_IATT_IN_XDATA_KEY, stbuf, len); +        if (ret) +                GF_FREE (stbuf); + +        return ret; +} + +mode_t +posix_override_umask (mode_t mode, mode_t mode_bit) +{ +        gf_msg_debug ("posix", 0, "The value of mode is %u", mode); +        mode = mode >> 9; /* 3x3 (bits for each octal digit)*/ +        mode = (mode << 9) | mode_bit; +        gf_msg_debug ("posix", 0, "The value of mode is %u", mode); +        return mode; +} diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c new file mode 100644 index 00000000000..9d1b19ac9a0 --- /dev/null +++ b/xlators/storage/posix/src/posix-inode-fd-ops.c @@ -0,0 +1,4975 @@ +/* +   Copyright (c) 2006-2017 Red Hat, Inc. <http://www.redhat.com> +   This file is part of GlusterFS. + +   This file is licensed to you under your choice of the GNU Lesser +   General Public License, version 3 or any later version (LGPLv3 or +   later), or the GNU General Public License, version 2 (GPLv2), in all +   cases as published by the Free Software Foundation. +*/ +#define __XOPEN_SOURCE 500 + +/* for SEEK_HOLE and SEEK_DATA */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <openssl/md5.h> +#include <stdint.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <errno.h> +#include <libgen.h> +#include <pthread.h> +#include <ftw.h> +#include <sys/stat.h> +#include <signal.h> +#include <sys/uio.h> +#include <unistd.h> +#include <ftw.h> + +#ifndef GF_BSD_HOST_OS +#include <alloca.h> +#endif /* GF_BSD_HOST_OS */ + +#ifdef HAVE_LINKAT +#include <fcntl.h> +#endif /* HAVE_LINKAT */ + +#include "glusterfs.h" +#include "checksum.h" +#include "dict.h" +#include "logging.h" +#include "posix.h" +#include "xlator.h" +#include "defaults.h" +#include "common-utils.h" +#include "compat-errno.h" +#include "compat.h" +#include "byte-order.h" +#include "syscall.h" +#include "statedump.h" +#include "locking.h" +#include "timer.h" +#include "glusterfs3-xdr.h" +#include "hashfn.h" +#include "posix-aio.h" +#include "glusterfs-acl.h" +#include "posix-messages.h" +#include "events.h" +#include "posix-gfid-path.h" +#include "compat-uuid.h" + +extern char *marker_xattrs[]; +#define ALIGN_SIZE 4096 + +#undef HAVE_SET_FSID +#ifdef HAVE_SET_FSID + +#define DECLARE_OLD_FS_ID_VAR uid_t old_fsuid; gid_t old_fsgid; + +#define SET_FS_ID(uid, gid) do {                \ +                old_fsuid = setfsuid (uid);     \ +                old_fsgid = setfsgid (gid);     \ +        } while (0) + +#define SET_TO_OLD_FS_ID() do {                 \ +                setfsuid (old_fsuid);           \ +                setfsgid (old_fsgid);           \ +        } while (0) + +#else + +#define DECLARE_OLD_FS_ID_VAR +#define SET_FS_ID(uid, gid) +#define SET_TO_OLD_FS_ID() + +#endif + +/* Setting microseconds or nanoseconds depending on what's supported: +   The passed in `tv` can be +       struct timespec +   if supported (better, because it supports nanosecond resolution) or +       struct timeval +   otherwise. */ +#if HAVE_UTIMENSAT +#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ +        tv.tv_nsec = nanosecs +#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ +        (sys_utimensat (AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW)) +#else +#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ +        tv.tv_usec = nanosecs / 1000 +#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ +        (lutimes (path, tv)) +#endif + +static char *disallow_removexattrs[] = { +        GF_XATTR_VOL_ID_KEY, +        GFID_XATTR_KEY, +        NULL +}; + +int32_t +posix_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ +        struct iatt           buf       = {0,}; +        int32_t               op_ret    = -1; +        int32_t               op_errno  = 0; +        struct posix_private *priv      = NULL; +        char                 *real_path = NULL; +        dict_t               *xattr_rsp = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        MAKE_INODE_HANDLE (real_path, this, loc, &buf); + +        if (op_ret == -1) { +                op_errno = errno; +                if (op_errno == ENOENT) { +                        gf_msg_debug(this->name, 0, "lstat on %s failed: %s", +                                     real_path ? real_path : "<null>", +                                     strerror (op_errno)); +                } else { +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_LSTAT_FAILED, "lstat on %s failed", +                                real_path ? real_path : "<null>"); +                } +                goto out; +        } +        if (xdata) +                xattr_rsp = posix_xattr_fill (this, real_path, loc, NULL, -1, +                                              xdata, &buf); + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID(); +        STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, &buf, xattr_rsp); +        if (xattr_rsp) +                dict_unref (xattr_rsp); + +        return 0; +} + +static int +posix_do_chmod (xlator_t *this, const char *path, struct iatt *stbuf) +{ +        int32_t     ret = -1; +        mode_t      mode = 0; +        mode_t      mode_bit = 0; +        struct posix_private *priv = NULL; +        struct stat stat; +        int         is_symlink = 0; + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        ret = sys_lstat (path, &stat); +        if (ret != 0) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_LSTAT_FAILED, +                        "lstat failed: %s", path); +                goto out; +        } + +        if (S_ISLNK (stat.st_mode)) +                is_symlink = 1; + +        if (S_ISDIR (stat.st_mode)) { +                mode = st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type); +                mode_bit = (mode & priv->create_directory_mask) +                            | priv->force_directory_mode; +                mode = posix_override_umask(mode, mode_bit); +        } else { +                mode = st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type); +                mode_bit = (mode & priv->create_mask) +                            | priv->force_create_mode; +                mode = posix_override_umask(mode, mode_bit); +        } +        ret = lchmod (path, mode); +        if ((ret == -1) && (errno == ENOSYS)) { +                /* in Linux symlinks are always in mode 0777 and no +                   such call as lchmod exists. +                */ +                gf_msg_debug (this->name, 0, "%s (%s)", path, strerror (errno)); +                if (is_symlink) { +                        ret = 0; +                        goto out; +                } + +                ret = sys_chmod (path, mode); +        } +out: +        return ret; +} + +static int +posix_do_chown (xlator_t *this, +                const char *path, +                struct iatt *stbuf, +                int32_t valid) +{ +        int32_t ret = -1; +        uid_t uid = -1; +        gid_t gid = -1; + +        if (valid & GF_SET_ATTR_UID) +                uid = stbuf->ia_uid; + +        if (valid & GF_SET_ATTR_GID) +                gid = stbuf->ia_gid; + +        ret = sys_lchown (path, uid, gid); + +        return ret; +} + +static int +posix_do_utimes (xlator_t *this, +                 const char *path, +                 struct iatt *stbuf, +                 int valid) +{ +        int32_t ret = -1; +#if defined(HAVE_UTIMENSAT) +        struct timespec tv[2]    = { {0,}, {0,} }; +#else +        struct timeval tv[2]     = { {0,}, {0,} }; +#endif +        struct stat stat; +        int    is_symlink = 0; + +        ret = sys_lstat (path, &stat); +        if (ret != 0) { +                gf_msg (this->name, GF_LOG_WARNING, errno, +                        P_MSG_FILE_OP_FAILED, "%s", path); +                goto out; +        } + +        if (S_ISLNK (stat.st_mode)) +                is_symlink = 1; + +        if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) { +                tv[0].tv_sec  = stbuf->ia_atime; +                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[0], stbuf->ia_atime_nsec); +        } else { +                /* atime is not given, use current values */ +                tv[0].tv_sec  = ST_ATIM_SEC (&stat); +                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[0], ST_ATIM_NSEC (&stat)); +        } + +        if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) { +                tv[1].tv_sec  = stbuf->ia_mtime; +                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[1], stbuf->ia_mtime_nsec); +        } else { +                /* mtime is not given, use current values */ +                tv[1].tv_sec  = ST_MTIM_SEC (&stat); +                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[1], ST_MTIM_NSEC (&stat)); +        } + +        ret = PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv); +        if ((ret == -1) && (errno == ENOSYS)) { +                gf_msg_debug (this->name, 0, "%s (%s)", +                        path, strerror (errno)); +                if (is_symlink) { +                        ret = 0; +                        goto out; +                } + +                ret = PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv); +        } + +out: +        return ret; +} + +int +posix_setattr (call_frame_t *frame, xlator_t *this, +               loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) +{ +        int32_t        op_ret    = -1; +        int32_t        op_errno  = 0; +        char *         real_path = 0; +        struct iatt    statpre     = {0,}; +        struct iatt    statpost    = {0,}; +        dict_t        *xattr_rsp   = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); +        MAKE_INODE_HANDLE (real_path, this, loc, &statpre); + +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "setattr (lstat) on %s failed", +                        real_path ? real_path : "<null>"); +                goto out; +        } + +        if (valid & (GF_SET_ATTR_UID | GF_SET_ATTR_GID)){ +                op_ret = posix_do_chown (this, real_path, stbuf, valid); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_CHOWN_FAILED, "setattr (chown) on %s " +                                "failed", real_path); +                        goto out; +                } +        } + +        if (valid & GF_SET_ATTR_MODE) { +                op_ret = posix_do_chmod (this, real_path, stbuf); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_CHMOD_FAILED,  "setattr (chmod) on %s " +                                "failed", real_path); +                        goto out; +                } +        } + +        if (valid & (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME)) { +                op_ret = posix_do_utimes (this, real_path, stbuf, valid); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_UTIMES_FAILED, "setattr (utimes) on %s " +                                "failed", real_path); +                        goto out; +                } +        } + +        if (!valid) { +                op_ret = sys_lchown (real_path, -1, -1); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_LCHOWN_FAILED, "lchown (%s, -1, -1) " +                                "failed", real_path); + +                        goto out; +                } +        } + +        op_ret = posix_pstat (this, loc->gfid, real_path, &statpost); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "setattr (lstat) on %s failed", real_path); +                goto out; +        } + +        if (xdata) +                xattr_rsp = posix_xattr_fill (this, real_path, loc, NULL, -1, +                                              xdata, &statpost); +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, +                             &statpre, &statpost, xattr_rsp); +        if (xattr_rsp) +                dict_unref (xattr_rsp); + +        return 0; +} + +int32_t +posix_do_fchown (xlator_t *this, +                 int fd, +                 struct iatt *stbuf, +                 int32_t valid) +{ +        int   ret      = -1; +        uid_t uid = -1; +        gid_t gid = -1; + +        if (valid & GF_SET_ATTR_UID) +                uid = stbuf->ia_uid; + +        if (valid & GF_SET_ATTR_GID) +                gid = stbuf->ia_gid; + +        ret = sys_fchown (fd, uid, gid); + +        return ret; +} + + +int32_t +posix_do_fchmod (xlator_t *this, +                 int fd, struct iatt *stbuf) +{ +        int32_t     ret = -1; +        mode_t      mode = 0; +        mode_t      mode_bit = 0; +        struct posix_private *priv = NULL; + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); +        mode = st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type); +        mode_bit = (mode & priv->create_mask) +                    | priv->force_create_mode; +        mode = posix_override_umask (mode, mode_bit); +        ret = sys_fchmod (fd, mode); +out: +        return ret; +} + +static int +posix_do_futimes (xlator_t *this, int fd, struct iatt *stbuf, int valid) +{ +        int32_t ret              =     -1; +        struct timeval tv[2]     =     { {0,}, {0,} }; +        struct stat stat         =     {0,}; + +        ret = sys_fstat (fd, &stat); +        if (ret != 0) { +                gf_msg (this->name, GF_LOG_WARNING, errno, +                        P_MSG_FILE_OP_FAILED, "%d", fd); +                goto out; +        } + +        if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) { +                tv[0].tv_sec  = stbuf->ia_atime; +                tv[0].tv_usec = stbuf->ia_atime_nsec / 1000; +        } else { +                /* atime is not given, use current values */ +                tv[0].tv_sec  = ST_ATIM_SEC (&stat); +                tv[0].tv_usec = ST_ATIM_NSEC (&stat) / 1000; +        } + +        if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) { +                tv[1].tv_sec  = stbuf->ia_mtime; +                tv[1].tv_usec = stbuf->ia_mtime_nsec / 1000; +        } else { +                /* mtime is not given, use current values */ +                tv[1].tv_sec  = ST_MTIM_SEC (&stat); +                tv[1].tv_usec = ST_MTIM_NSEC (&stat) / 1000; +        } + +        ret = sys_futimes (fd, tv); +        if (ret == -1) +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FUTIMES_FAILED, +                        "%d", fd); + +out: +        return ret; +} + +int +posix_fsetattr (call_frame_t *frame, xlator_t *this, +                fd_t *fd, struct iatt *stbuf, int32_t valid, dict_t *xdata) +{ +        int32_t        op_ret    = -1; +        int32_t        op_errno  = 0; +        struct iatt    statpre     = {0,}; +        struct iatt    statpost    = {0,}; +        struct posix_fd *pfd = NULL; +        dict_t          *xattr_rsp = NULL; +        int32_t          ret = -1; + +        DECLARE_OLD_FS_ID_VAR; + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        op_ret = posix_fdstat (this, pfd->fd, &statpre); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fsetattr (fstat) failed on fd=%p", fd); +                goto out; +        } + +        if (valid & (GF_SET_ATTR_UID | GF_SET_ATTR_GID)) { +                op_ret = posix_do_fchown (this, pfd->fd, stbuf, valid); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FCHOWN_FAILED, "fsetattr (fchown) failed" +                                " on fd=%p", fd); +                        goto out; +                } + +        } + +        if (valid & GF_SET_ATTR_MODE) { +                op_ret = posix_do_fchmod (this, pfd->fd, stbuf); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FCHMOD_FAILED, "fsetattr (fchmod) failed" +                                " on fd=%p", fd); +                        goto out; +                } +        } + +        if (valid & (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME)) { +                op_ret = posix_do_futimes (this, pfd->fd, stbuf, valid); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FUTIMES_FAILED, "fsetattr (futimes) on " +                                "failed fd=%p", fd); +                        goto out; +                } +        } + +        if (!valid) { +                op_ret = sys_fchown (pfd->fd, -1, -1); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FCHOWN_FAILED, +                                "fchown (%d, -1, -1) failed", +                                pfd->fd); + +                        goto out; +                } +        } + +        op_ret = posix_fdstat (this, pfd->fd, &statpost); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fsetattr (fstat) failed on fd=%p", fd); +                goto out; +        } + +        if (xdata) +                xattr_rsp = posix_xattr_fill (this, NULL, NULL, fd, pfd->fd, +                                              xdata, &statpost); +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, +                             &statpre, &statpost, xattr_rsp); +        if (xattr_rsp) +                dict_unref (xattr_rsp); + +        return 0; +} + +static int32_t +posix_do_fallocate (call_frame_t *frame, xlator_t *this, fd_t *fd, +                    int32_t flags, off_t offset, size_t len, +                    struct iatt *statpre, struct iatt *statpost, dict_t *xdata) +{ +        int32_t             ret    = -1; +        int32_t             op_errno = 0; +        struct posix_fd    *pfd    = NULL; +        gf_boolean_t        locked = _gf_false; +        posix_inode_ctx_t  *ctx    = NULL; +        struct  posix_private *priv = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, ret, ret, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        ret = posix_inode_ctx_get_all (fd->inode, this, &ctx); +        if (ret < 0) { +                ret = -ENOMEM; +                goto out; +        } + +        if (xdata && dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) { +                locked = _gf_true; +                pthread_mutex_lock (&ctx->write_atomic_lock); +        } + +        ret = posix_fdstat (this, pfd->fd, statpre); +        if (ret == -1) { +                ret = -errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fallocate (fstat) failed on fd=%p", fd); +                goto out; +        } + +        ret = sys_fallocate (pfd->fd, flags, offset, len); +        if (ret == -1) { +                ret = -errno; +                gf_msg (this->name, GF_LOG_ERROR, -ret, P_MSG_FALLOCATE_FAILED, +                        "fallocate failed on %s offset: %jd, " +                        "len:%zu, flags: %d", uuid_utoa (fd->inode->gfid), +                        offset, len, flags); +                goto out; +        } + +        ret = posix_fdstat (this, pfd->fd, statpost); +        if (ret == -1) { +                ret = -errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fallocate (fstat) failed on fd=%p", fd); +                goto out; +        } + +out: +        if (locked) { +                pthread_mutex_unlock (&ctx->write_atomic_lock); +                locked = _gf_false; +        } +        SET_TO_OLD_FS_ID (); +        if (ret == ENOSPC) +                ret = -ENOSPC; + +        return ret; +} + +char* +_page_aligned_alloc (size_t size, char **aligned_buf) +{ +        char            *alloc_buf = NULL; +        char            *buf = NULL; + +        alloc_buf = GF_CALLOC (1, (size + ALIGN_SIZE), gf_posix_mt_char); +        if (!alloc_buf) +                goto out; +        /* page aligned buffer */ +        buf = GF_ALIGN_BUF (alloc_buf, ALIGN_SIZE); +        *aligned_buf = buf; +out: +        return alloc_buf; +} + +static int32_t +_posix_do_zerofill(int fd, off_t offset, off_t len, int o_direct) +{ +        off_t               num_vect            = 0; +        off_t               num_loop            = 1; +        off_t               idx                 = 0; +        int32_t             op_ret              = -1; +        int32_t             vect_size           = VECTOR_SIZE; +        off_t               remain              = 0; +        off_t               extra               = 0; +        struct iovec       *vector              = NULL; +        char               *iov_base            = NULL; +        char               *alloc_buf           = NULL; + +        if (len == 0) +                return 0; +        if (len < VECTOR_SIZE) +                vect_size = len; + +        num_vect = len / (vect_size); +        remain = len % vect_size ; +        if (num_vect > MAX_NO_VECT) { +                extra = num_vect % MAX_NO_VECT; +                num_loop = num_vect / MAX_NO_VECT; +                num_vect = MAX_NO_VECT; +        } + +        vector = GF_CALLOC (num_vect, sizeof(struct iovec), +                             gf_common_mt_iovec); +        if (!vector) +                  return -1; +        if (o_direct) { +                alloc_buf = _page_aligned_alloc(vect_size, &iov_base); +                if (!alloc_buf) { +                        GF_FREE(vector); +                        return -1; +                } +        } else { +                iov_base = GF_CALLOC (vect_size, sizeof(char), +                                        gf_common_mt_char); +                if (!iov_base) { +                        GF_FREE(vector); +                        return -1; +                 } +        } + +        for (idx = 0; idx < num_vect; idx++) { +                vector[idx].iov_base = iov_base; +                vector[idx].iov_len  = vect_size; +        } +        if (sys_lseek (fd, offset, SEEK_SET) < 0) { +                op_ret = -1; +                goto err; +        } + +        for (idx = 0; idx < num_loop; idx++) { +                op_ret = sys_writev (fd, vector, num_vect); +                if (op_ret < 0) +                        goto err; +        } +        if (extra) { +                op_ret = sys_writev (fd, vector, extra); +                if (op_ret < 0) +                        goto err; +        } +        if (remain) { +                vector[0].iov_len = remain; +                op_ret = sys_writev (fd, vector , 1); +                if (op_ret < 0) +                        goto err; +        } +err: +        if (o_direct) +                GF_FREE(alloc_buf); +        else +                GF_FREE(iov_base); +        GF_FREE(vector); +        return op_ret; +} + +static int32_t +posix_do_zerofill (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +                   off_t len, struct iatt *statpre, struct iatt *statpost, +                   dict_t *xdata) +{ +        int32_t            ret       = -1; +        int32_t            op_errno  = 0; +        int32_t            flags     = 0; +        struct posix_fd   *pfd       = NULL; +        gf_boolean_t       locked    = _gf_false; +        posix_inode_ctx_t *ctx       = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        ret = posix_inode_ctx_get_all (fd->inode, this, &ctx); +        if (ret < 0) { +                ret = -ENOMEM; +                goto out; +        } + +        if (dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) { +                locked = _gf_true; +                pthread_mutex_lock (&ctx->write_atomic_lock); +        } + +        ret = posix_fdstat (this, pfd->fd, statpre); +        if (ret == -1) { +                ret = -errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "pre-operation fstat failed on fd = %p", fd); +                goto out; +        } + +        /* See if we can use FALLOC_FL_ZERO_RANGE to perform the zero fill. +         * If it fails, fall back to _posix_do_zerofill() and an optional fsync. +         */ +        flags = FALLOC_FL_ZERO_RANGE; +        ret = sys_fallocate (pfd->fd, flags, offset, len); +        if (ret == 0) +                goto fsync; + +        ret = _posix_do_zerofill (pfd->fd, offset, len, pfd->flags & O_DIRECT); +        if (ret < 0) { +                ret = -errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ZEROFILL_FAILED, +                       "zerofill failed on fd %d length %" PRId64 , +                        pfd->fd, len); +                goto out; +        } + +fsync: +        if (pfd->flags & (O_SYNC|O_DSYNC)) { +                ret = sys_fsync (pfd->fd); +                if (ret) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_WRITEV_FAILED, "fsync() in writev on fd" +                                "%d failed", pfd->fd); +                        ret = -errno; +                        goto out; +                } +        } + +        ret = posix_fdstat (this, pfd->fd, statpost); +        if (ret == -1) { +                ret = -errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "post operation fstat failed on fd=%p", fd); +                goto out; +        } + +out: +        if (locked) { +                pthread_mutex_unlock (&ctx->write_atomic_lock); +                locked = _gf_false; +        } +        SET_TO_OLD_FS_ID (); + +        return ret; +} + +int32_t +posix_glfallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t keep_size, +                off_t offset, size_t len, dict_t *xdata) +{ +        int32_t ret; +        int32_t flags = 0; +        struct iatt statpre = {0,}; +        struct iatt statpost = {0,}; + +#ifdef FALLOC_FL_KEEP_SIZE +        if (keep_size) +                flags = FALLOC_FL_KEEP_SIZE; +#endif /* FALLOC_FL_KEEP_SIZE */ + +        ret = posix_do_fallocate (frame, this, fd, flags, offset, len, +                                  &statpre, &statpost, xdata); +        if (ret < 0) +                goto err; + +        STACK_UNWIND_STRICT(fallocate, frame, 0, 0, &statpre, &statpost, NULL); +        return 0; + +err: +        STACK_UNWIND_STRICT(fallocate, frame, -1, -ret, NULL, NULL, NULL); +        return 0; +} + +int32_t +posix_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +              size_t len, dict_t *xdata) +{ +        int32_t ret; +#ifndef FALLOC_FL_KEEP_SIZE +        ret = EOPNOTSUPP; + +#else /* FALLOC_FL_KEEP_SIZE */ +        int32_t flags = FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE; +        struct iatt statpre = {0,}; +        struct iatt statpost = {0,}; + +        ret = posix_do_fallocate (frame, this, fd, flags, offset, len, +                                  &statpre, &statpost, xdata); +        if (ret < 0) +                goto err; + +        STACK_UNWIND_STRICT(discard, frame, 0, 0, &statpre, &statpost, NULL); +        return 0; + +err: +#endif /* FALLOC_FL_KEEP_SIZE */ +        STACK_UNWIND_STRICT(discard, frame, -1, -ret, NULL, NULL, NULL); +        return 0; +} + +int32_t +posix_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +                off_t len, dict_t *xdata) +{ +        int32_t ret                      =  0; +        struct  iatt statpre             = {0,}; +        struct  iatt statpost            = {0,}; +        struct  posix_private *priv      = NULL; +        int     op_ret                   = -1; +        int     op_errno                 = -EINVAL; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); + +        priv = this->private; +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        ret = posix_do_zerofill (frame, this, fd, offset, len, +                                 &statpre, &statpost, xdata); +        if (ret < 0) { +                op_ret = -1; +                op_errno = -ret; +                goto out; +        } + +        STACK_UNWIND_STRICT(zerofill, frame, 0, 0, &statpre, &statpost, NULL); +        return 0; + +out: +        STACK_UNWIND_STRICT(zerofill, frame, op_ret, op_errno, NULL, NULL, NULL); +        return 0; +} + +int32_t +posix_ipc (call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata) +{ +        /* +         * IPC is for inter-translator communication.  If one gets here, it +         * means somebody sent one that nobody else recognized, which is an +         * error much like an uncaught exception. +         */ +        gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_IPC_NOT_HANDLE, +                "GF_LOG_IPC(%d) not handled", op); +        STACK_UNWIND_STRICT (ipc, frame, -1, -EOPNOTSUPP, NULL); +        return 0; + +} + +#ifdef HAVE_SEEK_HOLE +int32_t +posix_seek (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +            gf_seek_what_t what, dict_t *xdata) +{ +        struct posix_fd *pfd       = NULL; +        off_t            ret       = -1; +        int              err       = 0; +        int              whence    = 0; + +        DECLARE_OLD_FS_ID_VAR; + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        switch (what) { +        case GF_SEEK_DATA: +                whence = SEEK_DATA; +                break; +        case GF_SEEK_HOLE: +                whence = SEEK_HOLE; +                break; +        default: +                err = ENOTSUP; +                gf_msg (this->name, GF_LOG_ERROR, ENOTSUP, +                        P_MSG_SEEK_UNKOWN, "don't know what to seek"); +                goto out; +        } + +        ret = posix_fd_ctx_get (fd, this, &pfd, &err); +        if (ret < 0) { +                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        ret = sys_lseek (pfd->fd, offset, whence); +        if (ret == -1) { +                err = errno; +                gf_msg (this->name, GF_LOG_ERROR, err, P_MSG_SEEK_FAILED, +                        "seek failed on fd %d length %" PRId64 , pfd->fd, +                        offset); +                goto out; +        } + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (seek, frame, (ret == -1 ? -1 : 0), err, +                             (ret == -1 ? -1 : ret), xdata); +        return 0; +} +#endif + +int32_t +posix_opendir (call_frame_t *frame, xlator_t *this, +               loc_t *loc, fd_t *fd, dict_t *xdata) +{ +        char *            real_path = NULL; +        int32_t           op_ret    = -1; +        int32_t           op_errno  = EINVAL; +        DIR *             dir       = NULL; +        struct posix_fd * pfd       = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); +        VALIDATE_OR_GOTO (fd, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); +        MAKE_INODE_HANDLE (real_path, this, loc, NULL); +        if (!real_path) { +                op_errno = ESTALE; +                goto out; +        } + +        op_ret = -1; +        dir = sys_opendir (real_path); + +        if (dir == NULL) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_OPENDIR_FAILED, +                        "opendir failed on %s", real_path); +                goto out; +        } + +        op_ret = dirfd (dir); +        if (op_ret < 0) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_DIRFD_FAILED, +                        "dirfd() failed on %s", real_path); +                goto out; +        } + +        pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); +        if (!pfd) { +                op_errno = errno; +                goto out; +        } + +        pfd->dir = dir; +        pfd->dir_eof = -1; +        pfd->fd = op_ret; + +        op_ret = fd_ctx_set (fd, this, (uint64_t)(long)pfd); +        if (op_ret) +                gf_msg (this->name, GF_LOG_WARNING, 0, +                        P_MSG_FD_PATH_SETTING_FAILED, "failed to set the fd" +                        "context path=%s fd=%p", real_path, fd); + +        op_ret = 0; + +out: +        if (op_ret == -1) { +                if (dir) { +                        (void) sys_closedir (dir); +                        dir = NULL; +                } +                if (pfd) { +                        GF_FREE (pfd); +                        pfd = NULL; +                } +        } + +        SET_TO_OLD_FS_ID (); +        STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd, NULL); +        return 0; +} + +int32_t +posix_releasedir (xlator_t *this, +                  fd_t *fd) +{ +        struct posix_fd * pfd      = NULL; +        uint64_t          tmp_pfd  = 0; +        int               ret      = 0; + +        struct posix_private *priv = NULL; + +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        ret = fd_ctx_del (fd, this, &tmp_pfd); +        if (ret < 0) { +                gf_msg_debug (this->name, 0, "pfd from fd=%p is NULL", fd); +                goto out; +        } + +        pfd = (struct posix_fd *)(long)tmp_pfd; +        if (!pfd->dir) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_PFD_NULL, +                        "pfd->dir is NULL for fd=%p", fd); +                goto out; +        } + +        priv = this->private; + +        pthread_mutex_lock (&priv->janitor_lock); +        { +                INIT_LIST_HEAD (&pfd->list); +                list_add_tail (&pfd->list, &priv->janitor_fds); +                pthread_cond_signal (&priv->janitor_cond); +        } +        pthread_mutex_unlock (&priv->janitor_lock); + +out: +        return 0; +} + + +int32_t +posix_readlink (call_frame_t *frame, xlator_t *this, +                loc_t *loc, size_t size, dict_t *xdata) +{ +        char *  dest      = NULL; +        int32_t op_ret    = -1; +        int32_t op_errno  = 0; +        char *  real_path = NULL; +        struct iatt stbuf = {0,}; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        dest = alloca (size + 1); + +        MAKE_INODE_HANDLE (real_path, this, loc, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat on %s failed", +                        loc->path ? loc->path : "<null>"); +                goto out; +        } + +        op_ret = sys_readlink (real_path, dest, size); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_READYLINK_FAILED, +                        "readlink on %s failed", real_path); +                goto out; +        } + +        dest[op_ret] = 0; +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (readlink, frame, op_ret, op_errno, dest, &stbuf, NULL); + +        return 0; +} + +int32_t +posix_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, +                dict_t *xdata) +{ +        int32_t               op_ret    = -1; +        int32_t               op_errno  = 0; +        char                 *real_path = 0; +        struct posix_private *priv      = NULL; +        struct iatt           prebuf    = {0,}; +        struct iatt           postbuf   = {0,}; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        MAKE_INODE_HANDLE (real_path, this, loc, &prebuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "pre-operation lstat on %s failed", +                        real_path ? real_path : "<null>"); +                goto out; +        } + +        op_ret = sys_truncate (real_path, offset); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_TRUNCATE_FAILED, +                        "truncate on %s failed", real_path); +                goto out; +        } + +        op_ret = posix_pstat (this, loc->gfid, real_path, &postbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "lstat on %s failed", real_path); +                goto out; +        } + +        op_ret = 0; +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, +                             &prebuf, &postbuf, NULL); + +        return 0; +} + +int32_t +posix_open (call_frame_t *frame, xlator_t *this, +            loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata) +{ +        int32_t               op_ret       = -1; +        int32_t               op_errno     = 0; +        char                 *real_path    = NULL; +        int32_t               _fd          = -1; +        struct posix_fd      *pfd          = NULL; +        struct posix_private *priv         = NULL; +        struct iatt           stbuf        = {0, }; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (this->private, out); +        VALIDATE_OR_GOTO (loc, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); + +        if (flags & O_CREAT) +                DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        MAKE_INODE_HANDLE (real_path, this, loc, &stbuf); +        if (!real_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        if (IA_ISLNK (stbuf.ia_type)) { +                op_ret = -1; +                op_errno = ELOOP; +                goto out; +        } + +        op_ret = -1; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        if (priv->o_direct) +                flags |= O_DIRECT; + +        _fd = sys_open (real_path, flags, priv->force_create_mode); +        if (_fd == -1) { +                op_ret   = -1; +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FILE_OP_FAILED, +                        "open on %s, flags: %d", real_path, flags); +                goto out; +        } + +        pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); +        if (!pfd) { +                op_errno = errno; +                goto out; +        } + +        pfd->flags = flags; +        pfd->fd    = _fd; + +        op_ret = fd_ctx_set (fd, this, (uint64_t)(long)pfd); +        if (op_ret) +                gf_msg (this->name, GF_LOG_WARNING, 0, +                        P_MSG_FD_PATH_SETTING_FAILED, +                        "failed to set the fd context path=%s fd=%p", +                        real_path, fd); + +        LOCK (&priv->lock); +        { +                priv->nr_files++; +        } +        UNLOCK (&priv->lock); + +        op_ret = 0; + +out: +        if (op_ret == -1) { +                if (_fd != -1) { +                        sys_close (_fd); +                } +        } + +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, NULL); + +        return 0; +} + +int +posix_readv (call_frame_t *frame, xlator_t *this, +             fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) +{ +        int32_t                op_ret     = -1; +        int32_t                op_errno   = 0; +        int                    _fd        = -1; +        struct posix_private * priv       = NULL; +        struct iobuf         * iobuf      = NULL; +        struct iobref        * iobref     = NULL; +        struct iovec           vec        = {0,}; +        struct posix_fd *      pfd        = NULL; +        struct iatt            stbuf      = {0,}; +        int                    ret        = -1; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); +        VALIDATE_OR_GOTO (this->private, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        if (!size) { +                op_errno = EINVAL; +                gf_msg (this->name, GF_LOG_WARNING, EINVAL, +                        P_MSG_INVALID_ARGUMENT, "size=%"GF_PRI_SIZET, size); +                goto out; +        } + +        iobuf = iobuf_get_page_aligned (this->ctx->iobuf_pool, size, +                                        ALIGN_SIZE); +        if (!iobuf) { +                op_errno = ENOMEM; +                goto out; +        } + +        _fd = pfd->fd; +        op_ret = sys_pread (_fd, iobuf->ptr, size, offset); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_READ_FAILED, "read failed on gfid=%s, " +                        "fd=%p, offset=%"PRIu64" size=%"GF_PRI_SIZET", " +                        "buf=%p", uuid_utoa (fd->inode->gfid), fd, +                        offset, size, iobuf->ptr); +                goto out; +        } + +        LOCK (&priv->lock); +        { +                priv->read_value    += op_ret; +        } +        UNLOCK (&priv->lock); + +        vec.iov_base = iobuf->ptr; +        vec.iov_len  = op_ret; + +        iobref = iobref_new (); + +        iobref_add (iobref, iobuf); + +        /* +         *  readv successful, and we need to get the stat of the file +         *  we read from +         */ + +        op_ret = posix_fdstat (this, _fd, &stbuf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fstat failed on fd=%p", fd); +                goto out; +        } + +        /* Hack to notify higher layers of EOF. */ +        if (!stbuf.ia_size || (offset + vec.iov_len) >= stbuf.ia_size) +                op_errno = ENOENT; + +        op_ret = vec.iov_len; +out: + +        STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, +                             &vec, 1, &stbuf, iobref, NULL); + +        if (iobref) +                iobref_unref (iobref); +        if (iobuf) +                iobuf_unref (iobuf); + +        return 0; +} + + +int32_t +__posix_pwritev (int fd, struct iovec *vector, int count, off_t offset) +{ +        int32_t         op_ret = 0; +        int             idx = 0; +        int             retval = 0; +        off_t           internal_off = 0; + +        if (!vector) +                return -EFAULT; + +        internal_off = offset; +        for (idx = 0; idx < count; idx++) { +                retval = sys_pwrite (fd, vector[idx].iov_base, vector[idx].iov_len, +                                 internal_off); +                if (retval == -1) { +                        op_ret = -errno; +                        goto err; +                } +                op_ret += retval; +                internal_off += retval; +        } + +err: +        return op_ret; +} + +int32_t +__posix_writev (int fd, struct iovec *vector, int count, off_t startoff, +                int odirect) +{ +        int32_t         op_ret = 0; +        int             idx = 0; +        int             max_buf_size = 0; +        int             retval = 0; +        char            *buf = NULL; +        char            *alloc_buf = NULL; +        off_t           internal_off = 0; + +        /* Check for the O_DIRECT flag during open() */ +        if (!odirect) +                return __posix_pwritev (fd, vector, count, startoff); + +        for (idx = 0; idx < count; idx++) { +                if (max_buf_size < vector[idx].iov_len) +                        max_buf_size = vector[idx].iov_len; +        } + +        alloc_buf = _page_aligned_alloc (max_buf_size, &buf); +        if (!alloc_buf) { +                op_ret = -errno; +                goto err; +        } + +        internal_off = startoff; +        for (idx = 0; idx < count; idx++) { +                memcpy (buf, vector[idx].iov_base, vector[idx].iov_len); + +                /* not sure whether writev works on O_DIRECT'd fd */ +                retval = sys_pwrite (fd, buf, vector[idx].iov_len, internal_off); +                if (retval == -1) { +                        op_ret = -errno; +                        goto err; +                } + +                op_ret += retval; +                internal_off += retval; +        } + +err: +        GF_FREE (alloc_buf); + +        return op_ret; +} + +dict_t* +_fill_writev_xdata (fd_t *fd, dict_t *xdata, xlator_t *this, int is_append) +{ +        dict_t  *rsp_xdata = NULL; +        int32_t ret = 0; +        inode_t *inode = NULL; + +        if (fd) +                inode = fd->inode; + +        if (!fd || !fd->inode || gf_uuid_is_null (fd->inode->gfid)) { +                gf_msg_callingfn (this->name, GF_LOG_ERROR, EINVAL, +                                  P_MSG_XATTR_FAILED, "fd: %p inode: %p" +                                  "gfid:%s", fd, inode?inode:0, +                                  inode?uuid_utoa(inode->gfid):"N/A"); +                goto out; +        } + +        if (!xdata) +                goto out; + +        rsp_xdata = dict_new(); +        if (!rsp_xdata) +                goto out; + +        if (dict_get (xdata, GLUSTERFS_OPEN_FD_COUNT)) { +                ret = dict_set_uint32 (rsp_xdata, GLUSTERFS_OPEN_FD_COUNT, +                                       fd->inode->fd_count); +                if (ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_DICT_SET_FAILED, "%s: Failed to set " +                                "dictionary value for %s", +                                uuid_utoa (fd->inode->gfid), +                                GLUSTERFS_OPEN_FD_COUNT); +                } +        } + +        if (dict_get (xdata, GLUSTERFS_WRITE_IS_APPEND)) { +                ret = dict_set_uint32 (rsp_xdata, GLUSTERFS_WRITE_IS_APPEND, +                                       is_append); +                if (ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_DICT_SET_FAILED, "%s: Failed to set " +                                "dictionary value for %s", +                                uuid_utoa (fd->inode->gfid), +                                GLUSTERFS_WRITE_IS_APPEND); +                } +        } +out: +        return rsp_xdata; +} + +int32_t +posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, +              struct iovec *vector, int32_t count, off_t offset, +              uint32_t flags, struct iobref *iobref, dict_t *xdata) +{ +        int32_t                op_ret   = -1; +        int32_t                op_errno = 0; +        int                    _fd      = -1; +        struct posix_private * priv     = NULL; +        struct posix_fd *      pfd      = NULL; +        struct iatt            preop    = {0,}; +        struct iatt            postop    = {0,}; +        int                      ret      = -1; +        dict_t                *rsp_xdata = NULL; +        int                    is_append = 0; +        gf_boolean_t           locked = _gf_false; +        gf_boolean_t           write_append = _gf_false; +        gf_boolean_t           update_atomic = _gf_false; +        posix_inode_ctx_t     *ctx      = NULL; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); +        VALIDATE_OR_GOTO (vector, out); +        VALIDATE_OR_GOTO (this->private, out); + +        priv = this->private; + +        VALIDATE_OR_GOTO (priv, out); +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, ret, P_MSG_PFD_NULL, +                        "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        _fd = pfd->fd; + +        if (xdata) { +                if (dict_get (xdata, GLUSTERFS_WRITE_IS_APPEND)) +                        write_append = _gf_true; +                if (dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) +                        update_atomic = _gf_true; +        } + +        /* The write_is_append check and write must happen +           atomically. Else another write can overtake this +           write after the check and get written earlier. + +           So lock before preop-stat and unlock after write. +        */ + +        /* +         * The update_atomic option is to instruct posix to do prestat, +         * write and poststat atomically. This is to prevent any modification to +         * ia_size and ia_blocks until poststat and the diff in their values +         * between pre and poststat could be of use for some translators (shard +         * as of today). +         */ + +        op_ret = posix_inode_ctx_get_all (fd->inode, this, &ctx); +        if (op_ret < 0) { +                op_errno = ENOMEM; +                goto out; +        } + +        if (write_append || update_atomic) { +                locked = _gf_true; +                pthread_mutex_lock (&ctx->write_atomic_lock); +        } + +        op_ret = posix_fdstat (this, _fd, &preop); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "pre-operation fstat failed on fd=%p", fd); +                goto out; +        } + +        if (locked && write_append) { +                if (preop.ia_size == offset || (fd->flags & O_APPEND)) +                        is_append = 1; +        } + +        op_ret = __posix_writev (_fd, vector, count, offset, +                                 (pfd->flags & O_DIRECT)); + +        if (locked && (!update_atomic)) { +                pthread_mutex_unlock (&ctx->write_atomic_lock); +                locked = _gf_false; +        } + +        if (op_ret < 0) { +                op_errno = -op_ret; +                op_ret = -1; +                gf_msg (this->name, GF_LOG_ERROR, op_errno, P_MSG_WRITE_FAILED, +                        "write failed: offset %"PRIu64 +                        ",", offset); +                goto out; +        } + +        rsp_xdata = _fill_writev_xdata (fd, xdata, this, is_append); +        /* writev successful, we also need to get the stat of +         * the file we wrote to +         */ + +        ret = posix_fdstat (this, _fd, &postop); +        if (ret == -1) { +                op_ret = -1; +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, +                        P_MSG_FSTAT_FAILED, +                        "post-operation fstat failed on fd=%p", +                        fd); +                goto out; +        } + +        if (locked) { +                pthread_mutex_unlock (&ctx->write_atomic_lock); +                locked = _gf_false; +        } + +        if (flags & (O_SYNC|O_DSYNC)) { +                ret = sys_fsync (_fd); +                if (ret) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_WRITEV_FAILED, +                                "fsync() in writev on fd %d failed", +                                _fd); +                        op_ret = -1; +                        op_errno = errno; +                        goto out; +                } +        } + +        LOCK (&priv->lock); +        { +                priv->write_value    += op_ret; +        } +        UNLOCK (&priv->lock); + +out: + +        if (locked) { +                pthread_mutex_unlock (&ctx->write_atomic_lock); +                locked = _gf_false; +        } + +        STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, &preop, &postop, +                             rsp_xdata); + +        if (rsp_xdata) +                dict_unref (rsp_xdata); +        return 0; +} + + +int32_t +posix_statfs (call_frame_t *frame, xlator_t *this, +              loc_t *loc, dict_t *xdata) +{ +        char *                 real_path = NULL; +        int32_t                op_ret    = -1; +        int32_t                op_errno  = 0; +        struct statvfs         buf       = {0, }; +        struct posix_private * priv      = NULL; +        int                    shared_by = 1; +        int                    percent   = 0; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); +        VALIDATE_OR_GOTO (this->private, out); + +        MAKE_INODE_HANDLE (real_path, this, loc, NULL); +        if (!real_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        priv = this->private; + +        op_ret = sys_statvfs (real_path, &buf); + +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_STATVFS_FAILED, +                        "statvfs failed on %s", real_path); +                goto out; +        } + +        percent = priv->disk_reserve; +        buf.f_bfree = (buf.f_bfree - ((buf.f_blocks * percent) / 100)); + +        shared_by = priv->shared_brick_count; +        if (shared_by > 1) { +                buf.f_blocks /= shared_by; +                buf.f_bfree  /= shared_by; +                buf.f_bavail /= shared_by; +                buf.f_files  /= shared_by; +                buf.f_ffree  /= shared_by; +                buf.f_favail /= shared_by; +        } + +        if (!priv->export_statfs) { +                buf.f_blocks = 0; +                buf.f_bfree  = 0; +                buf.f_bavail = 0; +                buf.f_files  = 0; +                buf.f_ffree  = 0; +                buf.f_favail = 0; +        } + +        op_ret = 0; + +out: +        STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, &buf, NULL); +        return 0; +} + + +int32_t +posix_flush (call_frame_t *frame, xlator_t *this, +             fd_t *fd, dict_t *xdata) +{ +        int32_t           op_ret   = -1; +        int32_t           op_errno = 0; +        int               ret      = -1; +        struct posix_fd  *pfd      = NULL; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL on fd=%p", fd); +                goto out; +        } + +        op_ret = 0; + +out: +        STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, NULL); + +        return 0; +} + + +int32_t +posix_release (xlator_t *this, fd_t *fd) +{ +        struct posix_private * priv     = NULL; +        struct posix_fd *      pfd      = NULL; +        int                    ret      = -1; +        uint64_t               tmp_pfd  = 0; + +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; + +        ret = fd_ctx_del (fd, this, &tmp_pfd); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_PFD_NULL, +                        "pfd is NULL from fd=%p", fd); +                goto out; +        } +        pfd = (struct posix_fd *)(long)tmp_pfd; + +        if (pfd->dir) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_DIR_NOT_NULL, +                        "pfd->dir is %p (not NULL) for file fd=%p", +                        pfd->dir, fd); +        } + +        pthread_mutex_lock (&priv->janitor_lock); +        { +                INIT_LIST_HEAD (&pfd->list); +                list_add_tail (&pfd->list, &priv->janitor_fds); +                pthread_cond_signal (&priv->janitor_cond); +        } +        pthread_mutex_unlock (&priv->janitor_lock); + +        LOCK (&priv->lock); +        { +                priv->nr_files--; +        } +        UNLOCK (&priv->lock); + +out: +        return 0; +} + + +int +posix_batch_fsync (call_frame_t *frame, xlator_t *this, +                     fd_t *fd, int datasync, dict_t *xdata) +{ +        call_stub_t *stub = NULL; +        struct posix_private *priv = NULL; + +        priv = this->private; + +        stub = fop_fsync_stub (frame, default_fsync, fd, datasync, xdata); +        if (!stub) { +                STACK_UNWIND_STRICT (fsync, frame, -1, ENOMEM, 0, 0, 0); +                return 0; +        } + +        pthread_mutex_lock (&priv->fsync_mutex); +        { +                list_add_tail (&stub->list, &priv->fsyncs); +                priv->fsync_queue_count++; +                pthread_cond_signal (&priv->fsync_cond); +        } +        pthread_mutex_unlock (&priv->fsync_mutex); + +        return 0; +} + + +int32_t +posix_fsync (call_frame_t *frame, xlator_t *this, +             fd_t *fd, int32_t datasync, dict_t *xdata) +{ +        int32_t           op_ret   = -1; +        int32_t           op_errno = 0; +        int               _fd      = -1; +        struct posix_fd * pfd      = NULL; +        int               ret      = -1; +        struct iatt       preop = {0,}; +        struct iatt       postop = {0,}; +        struct posix_private *priv = NULL; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +#ifdef GF_DARWIN_HOST_OS +        /* Always return success in case of fsync in MAC OS X */ +        op_ret = 0; +        goto out; +#endif + +        priv = this->private; + +        if (priv->batch_fsync_mode && xdata && dict_get (xdata, "batch-fsync")) { +                posix_batch_fsync (frame, this, fd, datasync, xdata); +                return 0; +        } + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd not found in fd's ctx"); +                goto out; +        } + +        _fd = pfd->fd; + +        op_ret = posix_fdstat (this, _fd, &preop); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_FSTAT_FAILED, +                        "pre-operation fstat failed on fd=%p", fd); +                goto out; +        } + +        if (datasync) { +                op_ret = sys_fdatasync (_fd); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FSYNC_FAILED, "fdatasync on fd=%p" +                                "failed:", fd); +                        goto out; +                } +        } else { +                op_ret = sys_fsync (_fd); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_FSYNC_FAILED, "fsync on fd=%p " +                                "failed", fd); +                        goto out; +                } +        } + +        op_ret = posix_fdstat (this, _fd, &postop); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_FSTAT_FAILED, +                        "post-operation fstat failed on fd=%p", fd); +                goto out; +        } + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (fsync, frame, op_ret, op_errno, &preop, &postop, +                             NULL); + +        return 0; +} + +static int gf_posix_xattr_enotsup_log; +static int +_handle_setxattr_keyvalue_pair (dict_t *d, char *k, data_t *v, +                                void *tmp) +{ +        posix_xattr_filler_t *filler = NULL; + +        filler = tmp; + +        return posix_handle_pair (filler->this, filler->real_path, k, v, +                                  filler->flags, filler->stbuf); +} + +#ifdef GF_DARWIN_HOST_OS +static int +map_xattr_flags(int flags) +{ +        /* DARWIN has different defines on XATTR_ flags. +           There do not seem to be a POSIX standard +           Parse any other flags over. +        */ +        int darwinflags = flags & ~(GF_XATTR_CREATE | GF_XATTR_REPLACE | XATTR_REPLACE); +        if (GF_XATTR_CREATE & flags) +                darwinflags |= XATTR_CREATE; +        if (GF_XATTR_REPLACE & flags) +                darwinflags |= XATTR_REPLACE; +        return darwinflags; +} +#endif + +int32_t +posix_setxattr (call_frame_t *frame, xlator_t *this, +                loc_t *loc, dict_t *dict, int flags, dict_t *xdata) +{ +        int32_t       op_ret                  = -1; +        int32_t       op_errno                = 0; +        char *        real_path               = NULL; +        char         *acl_xattr               = NULL; +        struct iatt   stbuf                   = {0}; +        int32_t       ret                     = 0; +        ssize_t       acl_size                = 0; +        dict_t       *xattr                   = NULL; +        posix_xattr_filler_t filler = {0,}; +        struct  posix_private *priv           = NULL; + +        DECLARE_OLD_FS_ID_VAR; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); +        VALIDATE_OR_GOTO (dict, out); + +        priv = this->private; +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        MAKE_INODE_HANDLE (real_path, this, loc, NULL); +        if (!real_path) { +                op_ret = -1; +                op_errno = ESTALE; +                goto out; +        } + +        posix_pstat(this, loc->gfid, real_path, &stbuf); + +        op_ret = -1; + +        dict_del (dict, GFID_XATTR_KEY); +        dict_del (dict, GF_XATTR_VOL_ID_KEY); +        /* the io-stats-dump key should not reach disk */ +        dict_del (dict, GF_XATTR_IOSTATS_DUMP_KEY); + +        filler.real_path = real_path; +        filler.this = this; +        filler.stbuf = &stbuf; + +#ifdef GF_DARWIN_HOST_OS +        filler.flags = map_xattr_flags(flags); +#else +        filler.flags = flags; +#endif +        op_ret = dict_foreach (dict, _handle_setxattr_keyvalue_pair, +                               &filler); +        if (op_ret < 0) { +                op_errno = -op_ret; +                op_ret = -1; +                goto out; +        } + +        xattr = dict_new(); +        if (!xattr) +                goto out; + +/* + * FIXFIX: Send the stbuf info in the xdata for now + * This is used by DHT to redirect FOPs if the file is being migrated + * Ignore errors for now + */ +        if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { +                ret = posix_pstat(this, loc->gfid, real_path, &stbuf); +                if (ret) +                        goto out; + +               ret = posix_set_iatt_in_dict (xattr, &stbuf); +        } + +/* + * ACL can be set on a file/folder using GF_POSIX_ACL_*_KEY xattrs which + * won't aware of access-control xlator. To update its context correctly, + * POSIX_ACL_*_XATTR stored in xdata which is send in the call_back path. + */ +        if (dict_get (dict, GF_POSIX_ACL_ACCESS)) { + +                /* +                 * The size of buffer will be know after calling sys_lgetxattr, +                 * so first we allocate buffer with large size(~4k), then we +                 * reduced into required size using GF_REALLO(). +                 */ +                acl_xattr = GF_CALLOC (1, ACL_BUFFER_MAX, gf_posix_mt_char); +                if (!acl_xattr) +                        goto out; + +                acl_size = sys_lgetxattr (real_path, POSIX_ACL_ACCESS_XATTR, +                                          acl_xattr, ACL_BUFFER_MAX); + +                if (acl_size < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_XATTR_FAILED, "Posix acl is not set " +                                "properly at the backend"); +                        goto out; +                } + +                /* If acl_size is more than max buffer size, just ignore it */ +                if (acl_size >= ACL_BUFFER_MAX) { +                        gf_msg (this->name, GF_LOG_WARNING, ENOMEM, +                                P_MSG_BUFFER_OVERFLOW, "size of acl is more" +                                "than the buffer"); +                        goto out; +                } + +                acl_xattr = GF_REALLOC (acl_xattr, acl_size); +                if (!acl_xattr) +                        goto out; + +                ret = dict_set_bin (xattr, POSIX_ACL_ACCESS_XATTR, +                                    acl_xattr, acl_size); +                if (ret) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_SET_XDATA_FAIL, "failed to set" +                                "xdata for acl"); +                        GF_FREE (acl_xattr); +                        goto out; +                } +        } + +        if (dict_get (dict, GF_POSIX_ACL_DEFAULT)) { + +                acl_xattr = GF_CALLOC (1, ACL_BUFFER_MAX, gf_posix_mt_char); +                if (!acl_xattr) +                        goto out; + +                acl_size = sys_lgetxattr (real_path, POSIX_ACL_DEFAULT_XATTR, +                                          acl_xattr, ACL_BUFFER_MAX); + +                if (acl_size < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_XATTR_FAILED, "Posix acl is not set " +                                "properly at the backend"); +                        goto out; +                } + +                if (acl_size >= ACL_BUFFER_MAX) { +                        gf_msg (this->name, GF_LOG_WARNING, ENOMEM, +                                P_MSG_BUFFER_OVERFLOW, "size of acl is more" +                                "than the buffer"); +                        goto out; +                } + +                acl_xattr = GF_REALLOC (acl_xattr, acl_size); +                if (!acl_xattr) +                        goto out; + +                ret = dict_set_bin (xattr, POSIX_ACL_DEFAULT_XATTR, +                                    acl_xattr, acl_size); +                if (ret) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_SET_XDATA_FAIL, "failed to set" +                                "xdata for acl"); +                        GF_FREE (acl_xattr); +                        goto out; +                } +        } +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xattr); + +        if (xattr) +                dict_unref (xattr); + +        return 0; +} + + +int +posix_xattr_get_real_filename (call_frame_t *frame, xlator_t *this, loc_t *loc, +                               const char *key, dict_t *dict, dict_t *xdata) +{ +        int            ret        = -1; +        int            op_ret     = -1; +        const char    *fname      = NULL; +        char          *real_path  = NULL; +        char          *found      = NULL; +        DIR           *fd         = NULL; +        struct dirent *entry      = NULL; +        struct dirent  scratch[2] = {{0,},}; + +        MAKE_INODE_HANDLE (real_path, this, loc, NULL); +        if (!real_path) { +                return -ESTALE; +        } +        if (op_ret == -1) { +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, +                        "posix_xattr_get_real_filename (lstat) on %s failed", +                        real_path); +                return -errno; +        } + +        fd = sys_opendir (real_path); +        if (!fd) +                return -errno; + +        fname = key + strlen (GF_XATTR_GET_REAL_FILENAME_KEY); + +        for (;;) { +                errno = 0; +                entry = sys_readdir (fd, scratch); +                if (!entry || errno != 0) +                        break; + +                if (strcasecmp (entry->d_name, fname) == 0) { +                        found = gf_strdup (entry->d_name); +                        if (!found) { +                                (void) sys_closedir (fd); +                                return -ENOMEM; +                        } +                        break; +                } +        } + +        (void) sys_closedir (fd); + +        if (!found) +                return -ENOENT; + +        ret = dict_set_dynstr (dict, (char *)key, found); +        if (ret) { +                GF_FREE (found); +                return -ENOMEM; +        } +        ret = strlen (found) + 1; + +        return ret; +} + +int +posix_get_ancestry_directory (xlator_t *this, inode_t *leaf_inode, +                              gf_dirent_t *head, char **path, int type, +                              int32_t *op_errno, dict_t *xdata) +{ +        ssize_t               handle_size = 0; +        struct posix_private *priv        = NULL; +        inode_t              *inode       = NULL; +        int                   ret         = -1; +        char                  dirpath[PATH_MAX] = {0,}; + +        priv = this->private; + +        handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); + +        ret = posix_make_ancestryfromgfid (this, dirpath, PATH_MAX + 1, head, +                                           type | POSIX_ANCESTRY_PATH, +                                           leaf_inode->gfid, +                                           handle_size, priv->base_path, +                                           leaf_inode->table, &inode, xdata, +                                           op_errno); +        if (ret < 0) +                goto out; + + +        /* there is already a reference in loc->inode */ +        inode_unref (inode); + +        if ((type & POSIX_ANCESTRY_PATH) && (path != NULL)) { +                if (strcmp (dirpath, "/")) +                        dirpath[strlen (dirpath) - 1] = '\0'; + +                *path = gf_strdup (dirpath); +        } + +out: +        return ret; +} + +int32_t +posix_links_in_same_directory (char *dirpath, int count, inode_t *leaf_inode, +                               inode_t *parent, struct stat *stbuf, +                               gf_dirent_t *head, char **path, +                               int type, dict_t *xdata, int32_t *op_errno) +{ +        int                   op_ret       = -1; +        gf_dirent_t          *gf_entry     = NULL; +        xlator_t             *this         = NULL; +        struct posix_private *priv         = NULL; +        DIR                  *dirp         = NULL; +        struct dirent        *entry        = NULL; +        struct dirent         scratch[2]   = {{0,},}; +        char                  temppath[PATH_MAX] = {0,}; +        char                  scr[PATH_MAX * 4] = {0,}; + +        this = THIS; + +        priv = this->private; + +        dirp = sys_opendir (dirpath); +        if (!dirp) { +                *op_errno = errno; +                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_OPEN_FAILED, +                        "could not opendir %s", dirpath); +                goto out; +        } + +        while (count > 0) { +                errno = 0; +                entry = sys_readdir (dirp, scratch); +                if (!entry || errno != 0) +                        break; + +                if (entry->d_ino != stbuf->st_ino) +                        continue; + +                /* Linking an inode here, can cause a race in posix_acl. +                   Parent inode gets linked here, but before +                   it reaches posix_acl_readdirp_cbk, create/lookup can +                   come on a leaf-inode, as parent-inode-ctx not yet updated +                   in posix_acl_readdirp_cbk, create and lookup can fail +                   with EACCESS. So do the inode linking in the quota xlator + +                linked_inode = inode_link (leaf_inode, parent, +                                           entry->d_name, NULL); + +                GF_ASSERT (linked_inode == leaf_inode); +                inode_unref (linked_inode);*/ + +                if (type & POSIX_ANCESTRY_DENTRY) { +                        loc_t loc = {0, }; + +                        loc.inode = inode_ref (leaf_inode); +                        gf_uuid_copy (loc.gfid, leaf_inode->gfid); + +                        (void) snprintf (temppath, sizeof(temppath), "%s/%s", +                                         dirpath, entry->d_name); + +                        gf_entry = gf_dirent_for_name (entry->d_name); +                        gf_entry->inode = inode_ref (leaf_inode); +                        gf_entry->dict +                                = posix_xattr_fill (this, temppath, &loc, NULL, +                                                    -1, xdata, NULL); +                        iatt_from_stat (&(gf_entry->d_stat), stbuf); + +                        list_add_tail (&gf_entry->list, &head->list); +                        loc_wipe (&loc); +                } + +                if (type & POSIX_ANCESTRY_PATH) { +                        (void) snprintf (temppath, sizeof(temppath), "%s/%s", +                                         &dirpath[priv->base_path_length], +                                         entry->d_name); +                        if (!*path) { +                                *path = gf_strdup (temppath); +                        } else { +                                /* creating a colon separated */ +                                /* list of hard links */ +                                (void) snprintf (scr, sizeof(scr), "%s:%s", +                                                 *path, temppath); + +                                GF_FREE (*path); +                                *path = gf_strdup (scr); +                        } +                        if (!*path) { +                                op_ret = -1; +                                *op_errno = ENOMEM; +                                goto out; +                        } +                } + +                count--; +        } + +        op_ret = 0; +out: +        if (dirp) { +                op_ret = sys_closedir (dirp); +                if (op_ret == -1) { +                        *op_errno = errno; +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_CLOSE_FAILED, "closedir failed"); +                } +        } + +        return op_ret; +} + +int +posix_get_ancestry_non_directory (xlator_t *this, inode_t *leaf_inode, +                                  gf_dirent_t *head, char **path, int type, +                                  int32_t *op_errno, dict_t *xdata) +{ +        size_t                remaining_size    = 0; +        int                   op_ret            = -1, pathlen = -1; +        ssize_t               handle_size       = 0; +        uuid_t                pgfid             = {0,}; +        int                   nlink_samepgfid   = 0; +        struct stat           stbuf             = {0,}; +        char                 *list              = NULL; +        int32_t               list_offset       = 0; +        struct posix_private *priv              = NULL; +        ssize_t               size              = 0; +        inode_t              *parent            = NULL; +        loc_t                *loc               = NULL; +        char                 *leaf_path         = NULL; +        char                  key[4096]         = {0,}; +        char                  dirpath[PATH_MAX] = {0,}; +        char                  pgfidstr[UUID_CANONICAL_FORM_LEN+1] = {0,}; + +        priv = this->private; + +        loc = GF_CALLOC (1, sizeof (*loc), gf_posix_mt_char); +        if (loc == NULL) { +                op_ret = -1; +                *op_errno = ENOMEM; +                goto out; +        } + +        gf_uuid_copy (loc->gfid, leaf_inode->gfid); + +        MAKE_INODE_HANDLE (leaf_path, this, loc, NULL); +        if (!leaf_path) { +                GF_FREE (loc); +                *op_errno = ESTALE; +                goto out; +        } +        GF_FREE (loc); + +        size = sys_llistxattr (leaf_path, NULL, 0); +        if (size == -1) { +                *op_errno = errno; +                if ((errno == ENOTSUP) || (errno == ENOSYS)) { +                        GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, +                                             this->name, GF_LOG_WARNING, +                                             "Extended attributes not " +                                             "supported (try remounting brick" +                                             " with 'user_xattr' flag)"); + +                } else { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_XATTR_FAILED, "listxattr failed on" +                                "%s", leaf_path); + +                } + +                goto out; +        } + +        if (size == 0) { +                op_ret = 0; +                goto out; +        } + +        list = alloca (size); +        if (!list) { +                *op_errno = errno; +                goto out; +        } + +        size = sys_llistxattr (leaf_path, list, size); +        if (size < 0) { +                op_ret = -1; +                *op_errno = errno; +                goto out; +        } +        remaining_size = size; +        list_offset = 0; + +        op_ret = sys_lstat (leaf_path, &stbuf); +        if (op_ret == -1) { +                *op_errno = errno; +                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_LSTAT_FAILED, +                        "lstat failed on %s", leaf_path); +                goto out; +        } + +        while (remaining_size > 0) { +                strncpy (key, list + list_offset, sizeof(key)-1); +                key[sizeof(key)-1] = '\0'; +                if (strncmp (key, PGFID_XATTR_KEY_PREFIX, +                             strlen (PGFID_XATTR_KEY_PREFIX)) != 0) +                        goto next; + +                op_ret = sys_lgetxattr (leaf_path, key, +                                        &nlink_samepgfid, +                                        sizeof(nlink_samepgfid)); +                if (op_ret == -1) { +                        *op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_XATTR_FAILED, "getxattr failed on " +                                "%s: key = %s ", leaf_path, key); +                        goto out; +                } + +                nlink_samepgfid = ntoh32 (nlink_samepgfid); + +                strncpy (pgfidstr, key + strlen(PGFID_XATTR_KEY_PREFIX), +                         sizeof(pgfidstr)-1); +                pgfidstr[sizeof(pgfidstr)-1] = '\0'; +                gf_uuid_parse (pgfidstr, pgfid); + +                handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); + +                /* constructing the absolute real path of parent dir */ +                strncpy (dirpath, priv->base_path, sizeof(dirpath)-1); +                dirpath[sizeof(dirpath)-1] = '\0'; +                pathlen = PATH_MAX + 1 - priv->base_path_length; + +                op_ret = posix_make_ancestryfromgfid (this, +                                                      dirpath + priv->base_path_length, +                                                      pathlen, +                                                      head, +                                                      type | POSIX_ANCESTRY_PATH, +                                                      pgfid, +                                                      handle_size, +                                                      priv->base_path, +                                                      leaf_inode->table, +                                                      &parent, xdata, op_errno); +                if (op_ret < 0) { +                        goto next; +                } + +                dirpath[strlen (dirpath) - 1] = '\0'; + +                posix_links_in_same_directory (dirpath, nlink_samepgfid, +                                               leaf_inode, parent, &stbuf, head, +                                               path, type, xdata, op_errno); + +                if (parent != NULL) { +                        inode_unref (parent); +                        parent = NULL; +                } + +        next: +                remaining_size -= strlen (key) + 1; +                list_offset += strlen (key) + 1; +        } /* while (remaining_size > 0) */ + +        op_ret = 0; + +out: +        return op_ret; +} + +int +posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, +                    gf_dirent_t *head, char **path, int type, int32_t *op_errno, +                    dict_t *xdata) +{ +        int                   ret  = -1; +        struct posix_private *priv = NULL; + +        priv = this->private; + +        if (IA_ISDIR (leaf_inode->ia_type)) { +                ret = posix_get_ancestry_directory (this, leaf_inode, +                                                    head, path, type, op_errno, +                                                    xdata); +        } else  { + +                if (!priv->update_pgfid_nlinks) +                        goto out; +                ret = posix_get_ancestry_non_directory (this, leaf_inode, +                                                        head, path, type, +                                                        op_errno, xdata); +        } + +out: +        if (ret && path && *path) { +                GF_FREE (*path); +                *path = NULL; +        } + +        return ret; +} + +/** + * posix_getxattr - this function returns a dictionary with all the + *                  key:value pair present as xattr. used for + *                  both 'listxattr' and 'getxattr'. + */ +int32_t +posix_getxattr (call_frame_t *frame, xlator_t *this, +                loc_t *loc, const char *name, dict_t *xdata) +{ +        struct posix_private *priv                  = NULL; +        int32_t               op_ret                = -1; +        int32_t               op_errno              = 0; +        char                 *value                 = NULL; +        char                 *real_path             = NULL; +        dict_t               *dict                  = NULL; +        char                 *file_contents         = NULL; +        int                   ret                   = -1; +        char                 *path                  = NULL; +        char                 *rpath                 = NULL; +        ssize_t               size                  = 0; +        char                 *list                  = NULL; +        int32_t               list_offset           = 0; +        size_t                remaining_size        = 0; +        char                 *host_buf              = NULL; +        char                 *keybuffer             = NULL; +        char                 *value_buf             = NULL; +        gf_boolean_t          have_val              = _gf_false; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); +        MAKE_INODE_HANDLE (real_path, this, loc, NULL); + +        op_ret = -1; +        priv = this->private; + +        ret = posix_handle_georep_xattrs (frame, name, &op_errno, _gf_true); +        if (ret == -1) { +                op_ret = -1; +                /* errno should be set from the above function*/ +                goto out; +        } + +        if (name && posix_is_gfid2path_xattr (name)) { +                op_ret = -1; +                op_errno = ENOATTR; +                goto out; +        } + +        if (loc->inode && IA_ISDIR(loc->inode->ia_type) && name && +            ZR_FILE_CONTENT_REQUEST(name)) { +                ret = posix_get_file_contents (this, loc->gfid, &name[15], +                                               &file_contents); +                if (ret < 0) { +                        op_errno = -ret; +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_FILE_FAILED, "getting file contents" +                                "failed"); +                        goto out; +                } +        } + +        dict = dict_new (); +        if (!dict) { +                op_errno = ENOMEM; +                goto out; +        } + +        if (loc->inode && name && GF_POSIX_ACL_REQUEST (name)) { +                ret = posix_pacl_get (real_path, name, &value); +                if (ret || !value) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_ACL_FAILED, "could not get acl (%s) for" +                                "%s", name, real_path); +                        op_ret = -1; +                        goto out; +                } + +                ret = dict_set_dynstr (dict, (char *)name, value); +                if (ret < 0) { +                        GF_FREE (value); +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_ACL_FAILED, "could not set acl (%s) for" +                                "%s in dictionary", name, real_path); +                        op_ret = -1; +                        op_errno = ENOMEM; +                        goto out; +                } + +                size = ret; +                goto done; +        } + +        if (loc->inode && name && +            (strncmp (name, GF_XATTR_GET_REAL_FILENAME_KEY, +                      strlen (GF_XATTR_GET_REAL_FILENAME_KEY)) == 0)) { +                ret = posix_xattr_get_real_filename (frame, this, loc, +                                                     name, dict, xdata); +                if (ret < 0) { +                        op_ret = -1; +                        op_errno = -ret; +                        if (op_errno == ENOENT) { +                                gf_msg_debug (this->name, 0, "Failed to get " +                                              "real filename (%s, %s)", +                                              loc->path, name); +                        } else { +                                gf_msg (this->name, GF_LOG_WARNING, op_errno, +                                        P_MSG_GETTING_FILENAME_FAILED, +                                        "Failed to get real filename (%s, %s):" +                                        , loc->path, name); +                        } +                        goto out; +                } + +                size = ret; +                goto done; +        } + +        if (loc->inode && name && !strcmp (name, GLUSTERFS_OPEN_FD_COUNT)) { +                if (!fd_list_empty (loc->inode)) { +                        ret = dict_set_uint32 (dict, (char *)name, 1); +                        if (ret < 0) { +                                gf_msg (this->name, GF_LOG_WARNING, 0, +                                        P_MSG_DICT_SET_FAILED, "Failed to set " +                                        "dictionary value for %s", name); +                                op_errno = ENOMEM; +                                goto out; +                        } +                } else { +                        ret = dict_set_uint32 (dict, (char *)name, 0); +                        if (ret < 0) { +                                gf_msg (this->name, GF_LOG_WARNING, 0, +                                        P_MSG_DICT_SET_FAILED,  "Failed to set " +                                        "dictionary value for %s", name); +                                op_errno = ENOMEM; +                                goto out; +                        } +                } +                goto done; +        } +        if (loc->inode && name && (XATTR_IS_PATHINFO (name))) { +                if (LOC_HAS_ABSPATH (loc)) +                        MAKE_REAL_PATH (rpath, this, loc->path); +                else +                        rpath = real_path; + +                size = gf_asprintf (&host_buf, "<POSIX(%s):%s:%s>", +                                    priv->base_path, +                                    ((priv->node_uuid_pathinfo && +                                     !gf_uuid_is_null(priv->glusterd_uuid)) +                                     ? uuid_utoa (priv->glusterd_uuid) +                                     : priv->hostname), rpath); +                if (size < 0) { +                        op_errno = ENOMEM; +                        goto out; +                } +                ret = dict_set_dynstr (dict, (char *)name, host_buf); +                if (ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_DICT_SET_FAILED, "could not set value" +                                " (%s) in dictionary", host_buf); +                        GF_FREE (host_buf); +                        op_errno = ENOMEM; +                        goto out; +                } + +                goto done; +        } + +        if (loc->inode && name && +            (strcmp (name, GF_XATTR_NODE_UUID_KEY) == 0) +            && !gf_uuid_is_null (priv->glusterd_uuid)) { +                size = gf_asprintf (&host_buf, "%s", +                                    uuid_utoa (priv->glusterd_uuid)); +                if (size == -1) { +                        op_errno = ENOMEM; +                        goto out; +                } +                ret = dict_set_dynstr (dict, GF_XATTR_NODE_UUID_KEY, +                                       host_buf); +                if (ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, -ret, +                                P_MSG_DICT_SET_FAILED, "could not set value" +                                "(%s) in dictionary", host_buf); +                        GF_FREE (host_buf); +                        op_errno = -ret; +                        goto out; +                } +                goto done; +        } + +        if (loc->inode && name && +            (strcmp (name, GFID_TO_PATH_KEY) == 0)) { +                ret = inode_path (loc->inode, NULL, &path); +                if (ret < 0) { +                        op_errno = -ret; +                        gf_msg (this->name, GF_LOG_WARNING, op_errno, +                                P_MSG_INODE_PATH_GET_FAILED, +                                "%s: could not get " +                                "inode path", uuid_utoa (loc->inode->gfid)); +                        goto out; +                } + +                size = ret; +                ret = dict_set_dynstr (dict, GFID_TO_PATH_KEY, path); +                if (ret < 0) { +                        op_errno = ENOMEM; +                        GF_FREE (path); +                        goto out; +                } +                goto done; +        } + +        if (loc->inode && name && +            (strcmp (name, GFID2PATH_VIRT_XATTR_KEY) == 0)) { +                if (!priv->gfid2path) { +                        op_errno = ENOATTR; +                        op_ret = -1; +                        goto out; +                } +                ret = posix_get_gfid2path (this, loc->inode, real_path, +                                           &op_errno, dict); +                if (ret < 0) { +                        op_ret = -1; +                        goto out; +                } +                size = ret; +                goto done; +        } + +        if (loc->inode && name +            && (strcmp (name, GET_ANCESTRY_PATH_KEY) == 0)) { +                int type = POSIX_ANCESTRY_PATH; + +                op_ret = posix_get_ancestry (this, loc->inode, NULL, +                                             &path, type, &op_errno, +                                             xdata); +                if (op_ret < 0) { +                        op_ret = -1; +                        op_errno = ENODATA; +                        goto out; +                } +                size = op_ret; +                op_ret = dict_set_dynstr (dict, GET_ANCESTRY_PATH_KEY, path); +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, -op_ret, +                                P_MSG_GET_KEY_VALUE_FAILED, "could not get " +                                "value for key (%s)", GET_ANCESTRY_PATH_KEY); +                        GF_FREE (path); +                        op_errno = ENOMEM; +                        goto out; +                } + +                goto done; +        } + +        if (loc->inode && name +             && (strncmp (name, GLUSTERFS_GET_OBJECT_SIGNATURE, +                          strlen (GLUSTERFS_GET_OBJECT_SIGNATURE)) == 0)) { +                op_ret = posix_get_objectsignature (real_path, dict); +                if (op_ret < 0) { +                        op_errno = -op_ret; +                        goto out; +                } + +                goto done; +        } + +        /* here allocate value_buf of 8192 bytes to avoid one extra getxattr +           call,If buffer size is small to hold the xattr result then it will +           allocate a new buffer value of required size and call getxattr again +        */ + +        value_buf = alloca (XATTR_VAL_BUF_SIZE); +        if (name) { +                char *key = (char *)name; + +                keybuffer = key; +#if defined(GF_DARWIN_HOST_OS_DISABLED) +                if (priv->xattr_user_namespace == XATTR_STRIP) { +                        if (strncmp(key, "user.",5) == 0) { +                                key += 5; +                                gf_msg_debug (this->name, 0, "getxattr for file %s" +                                        " stripping user key: %s -> %s", +                                        real_path, keybuffer, key); +                        } +                } +#endif +                memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); +                size = sys_lgetxattr (real_path, key, value_buf, +                                      XATTR_VAL_BUF_SIZE-1); +                if (size >= 0) { +                        have_val = _gf_true; +                } else { +                        if (errno == ERANGE) { +                                gf_msg (this->name, GF_LOG_INFO, errno, +                                        P_MSG_XATTR_FAILED, +                                        "getxattr failed due to overflow of buffer" +                                        " on %s: %s ", real_path, key); +                                size = sys_lgetxattr (real_path, key, NULL, 0); +                        } +                        if (size == -1) { +                                op_errno = errno; +                                if ((op_errno == ENOTSUP) || +                                                         (op_errno == ENOSYS)) { +                                        GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, +                                                             this->name, +                                                             GF_LOG_WARNING, +                                                             "Extended attributes not " +                                                             "supported (try remounting" +                                                             " brick with 'user_xattr' " +                                                             "flag)"); +                                } +                                if ((op_errno == ENOATTR) || +                                                       (op_errno == ENODATA)) { +                                        gf_msg_debug (this->name, 0, +                                                      "No such attribute:%s for file %s", +                                                      key, real_path); +                                } else { +                                        gf_msg (this->name, GF_LOG_ERROR, +                                                op_errno, P_MSG_XATTR_FAILED, +                                                "getxattr failed on %s: %s ", +                                                real_path, key); +                                } +                                goto out; +                        } +                } +                value = GF_CALLOC (size + 1, sizeof(char), gf_posix_mt_char); +                if (!value) { +                        op_ret = -1; +                        op_errno = ENOMEM; +                        goto out; +                } +                if (have_val) { +                        memcpy (value, value_buf, size); +                } else { +                        size = sys_lgetxattr (real_path, key, value, size); +                        if (size == -1) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, +                                        "getxattr failed on %s: key = %s", +                                        real_path, key); +                                GF_FREE (value); +                                goto out; +                        } +                } +                value [size] = '\0'; +                op_ret = dict_set_dynptr (dict, key, value, size); +                if (op_ret < 0) { +                        op_errno = -op_ret; +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_DICT_SET_FAILED, "dict set operation " +                                "on %s for the key %s failed.", real_path, key); +                        GF_FREE (value); +                        goto out; +                } + +                goto done; +        } + +        have_val = _gf_false; +        memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); +        size = sys_llistxattr (real_path, value_buf, XATTR_VAL_BUF_SIZE-1); +        if (size > 0) { +                have_val = _gf_true; +        } else { +                if (errno == ERANGE) { +                        gf_msg (this->name, GF_LOG_INFO, errno, +                                P_MSG_XATTR_FAILED, +                                "listxattr failed due to overflow of buffer" +                                " on %s ", real_path); +                        size = sys_llistxattr (real_path, NULL, 0); +                } +                if (size == -1) { +                        op_errno = errno; +                        if ((errno == ENOTSUP) || (errno == ENOSYS)) { +                                GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, +                                                     this->name, GF_LOG_WARNING, +                                                     "Extended attributes not " +                                                     "supported (try remounting" +                                                     " brick with 'user_xattr' " +                                                     "flag)"); +                        } else { +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, +                                        "listxattr failed on %s", real_path); +                        } +                        goto out; +                } +                if (size == 0) +                        goto done; +        } +        list = alloca (size); +        if (!list) { +                op_errno = errno; +                goto out; +        } +        if (have_val) { +                memcpy (list, value_buf, size); +        } else { +                size = sys_llistxattr (real_path, list, size); +                if (size < 0) { +                        op_ret = -1; +                        op_errno = errno; +                        goto out; +                } +        } +        remaining_size = size; +        list_offset = 0; +        keybuffer = alloca (XATTR_KEY_BUF_SIZE); +        while (remaining_size > 0) { +                strncpy (keybuffer, list + list_offset, XATTR_KEY_BUF_SIZE-1); +                keybuffer[XATTR_KEY_BUF_SIZE-1] = '\0'; + +                ret = posix_handle_georep_xattrs (frame, keybuffer, NULL, +                                                  _gf_false); +                if (ret == -1) +                        goto ignore; + +                if (posix_is_gfid2path_xattr (keybuffer)) { +                        goto ignore; +                } + +                memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); +                have_val = _gf_false; +                size = sys_lgetxattr (real_path, keybuffer, value_buf, +                                      XATTR_VAL_BUF_SIZE-1); +                if (size >= 0) { +                        have_val = _gf_true; +                } else { +                        if (errno == ERANGE) { +                                gf_msg (this->name, GF_LOG_INFO, op_errno, +                                        P_MSG_XATTR_FAILED, +                                        "getxattr failed due to overflow of" +                                        "  buffer on %s: %s ", real_path, +                                        keybuffer); +                                size = sys_lgetxattr (real_path, keybuffer, +                                                      NULL, 0); +                        } +                        if (size == -1) { +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, "getxattr failed on" +                                        " %s: key = %s ", real_path, keybuffer); +                                goto out; +                        } +                } +                value = GF_CALLOC (size + 1, sizeof(char), +                                   gf_posix_mt_char); +                if (!value) { +                        op_errno = errno; +                        goto out; +                } +                if (have_val) { +                        memcpy (value, value_buf, size); +                } else { +                        size = sys_lgetxattr (real_path, keybuffer, value, size); +                        if (size == -1) { +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, "getxattr failed on" +                                        " %s: key = %s ", real_path, keybuffer); +                                GF_FREE (value); +                                goto out; +                        } +                } +                value [size] = '\0'; +#ifdef GF_DARWIN_HOST_OS +                /* The protocol expect namespace for now */ +                char *newkey = NULL; +                gf_add_prefix (XATTR_USER_PREFIX, keybuffer, &newkey); +                strncpy (keybuffer, newkey, sizeof(keybuffer)); +                GF_FREE (newkey); +#endif +                op_ret = dict_set_dynptr (dict, keybuffer, value, size); +                if (op_ret < 0) { +                        op_errno = -op_ret; +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_DICT_SET_FAILED, "dict set operation " +                                "on %s for the key %s failed.", real_path, +                                keybuffer); +                        GF_FREE (value); +                        goto out; +                } + +ignore: +                remaining_size -= strlen (keybuffer) + 1; +                list_offset += strlen (keybuffer) + 1; + +        } /* while (remaining_size > 0) */ + +done: +        op_ret = size; + +        if (dict) { +                dict_del (dict, GFID_XATTR_KEY); +                dict_del (dict, GF_XATTR_VOL_ID_KEY); +        } + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, NULL); + +        if (dict) { +                dict_unref (dict); +        } + +        return 0; +} + + +int32_t +posix_fgetxattr (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, const char *name, dict_t *xdata) +{ +        int32_t           op_ret         = -1; +        int32_t           op_errno       = EINVAL; +        struct posix_fd * pfd            = NULL; +        int               _fd            = -1; +        int32_t           list_offset    = 0; +        ssize_t           size           = 0; +        size_t            remaining_size = 0; +        char *            value          = NULL; +        char *            list           = NULL; +        dict_t *          dict           = NULL; +        int               ret            = -1; +        char              key[4096]      = {0,}; +        char             *value_buf      = NULL; +        gf_boolean_t      have_val        = _gf_false; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                op_ret = -1; +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL from fd=%p", fd); +                goto out; +        } + +        _fd = pfd->fd; + +        /* Get the total size */ +        dict = dict_new (); +        if (!dict) { +                op_ret = -1; +                op_errno = ENOMEM; +                goto out; +        } + +        if (name && !strcmp (name, GLUSTERFS_OPEN_FD_COUNT)) { +                ret = dict_set_uint32 (dict, (char *)name, 1); +                if (ret < 0) { +                        op_ret = -1; +                        size = -1; +                        op_errno = ENOMEM; +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_DICT_SET_FAILED, "Failed to set " +                                "dictionary value for %s", name); +                        goto out; +                } +                goto done; +        } + +        if (name && strncmp (name, GLUSTERFS_GET_OBJECT_SIGNATURE, +                      strlen (GLUSTERFS_GET_OBJECT_SIGNATURE)) == 0) { +                op_ret = posix_fdget_objectsignature (_fd, dict); +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_ERROR, 0, 0, +                                "posix_fdget_objectsignature failed"); +                        op_errno = -op_ret; +                        op_ret = -1; +                        size = -1; +                        goto out; +                } + +                goto done; +        } + +        /* here allocate value_buf of 8192 bytes to avoid one extra getxattr +           call,If buffer size is small to hold the xattr result then it will +           allocate a new buffer value of required size and call getxattr again +        */ +        value_buf = alloca (XATTR_VAL_BUF_SIZE); +        memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); + +        if (name) { +                strncpy (key, name, sizeof(key)); +#ifdef GF_DARWIN_HOST_OS +                struct posix_private *priv       = NULL; +                priv = this->private; +                if (priv->xattr_user_namespace == XATTR_STRIP) { +                        char *newkey = NULL; +                        gf_add_prefix (XATTR_USER_PREFIX, key, &newkey); +                        strncpy (key, newkey, sizeof(key)); +                        GF_FREE (newkey); +                } +#endif +                size = sys_fgetxattr (_fd, key, value_buf, +                                      XATTR_VAL_BUF_SIZE-1); +                if (size >= 0) { +                        have_val = _gf_true; +                } else { +                        if (errno == ERANGE) { +                                gf_msg (this->name, GF_LOG_INFO, errno, +                                        P_MSG_XATTR_FAILED, +                                        "fgetxattr failed due to overflow of" +                                        "buffer  on %s ", key); +                                size = sys_fgetxattr (_fd, key, NULL, 0); +                        } +                        if (size == -1) { +                                op_errno = errno; +                                if (errno == ENODATA || errno == ENOATTR) { +                                        gf_msg_debug (this->name, 0, "fgetxattr" +                                                      " failed on key %s (%s)", +                                                      key, strerror (op_errno)); +                                } else { +                                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                                P_MSG_XATTR_FAILED, "fgetxattr" +                                                " failed on key %s", key); +                                } +                                goto done; +                        } +                } +                value = GF_CALLOC (size + 1, sizeof(char), gf_posix_mt_char); +                if (!value) { +                        op_ret = -1; +                        op_errno = ENOMEM; +                        goto out; +                } +                if (have_val) { +                        memcpy (value, value_buf, size); +                } else { +                        size = sys_fgetxattr (_fd, key, value, size); +                        if (size == -1) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, "fgetxattr" +                                        " failed on fd %p for the key %s ", +                                        fd, key); +                                GF_FREE (value); +                                goto out; +                        } +                } + +                value [size] = '\0'; +                op_ret = dict_set_dynptr (dict, key, value, size); +                if (op_ret < 0) { +                        op_errno = -op_ret; +                        op_ret = -1; +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_DICT_SET_FAILED, "dict set operation " +                                "on key %s failed", key); +                        GF_FREE (value); +                        goto out; +                } + +                goto done; +        } +        memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); +        size = sys_flistxattr (_fd, value_buf, XATTR_VAL_BUF_SIZE-1); +        if (size > 0) { +                have_val = _gf_true; +        } else { +                if (errno == ERANGE) { +                        gf_msg (this->name, GF_LOG_INFO, errno, +                                P_MSG_XATTR_FAILED, +                                "listxattr failed due to overflow of buffer" +                                " on %p ", fd); +                        size = sys_flistxattr (_fd, NULL, 0); +                } +                if (size == -1) { +                        op_ret = -1; +                        op_errno = errno; +                        if ((errno == ENOTSUP) || (errno == ENOSYS)) { +                                GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, +                                                     this->name, GF_LOG_WARNING, +                                                     "Extended attributes not " +                                                     "supported (try remounting " +                                                     "brick with 'user_xattr' flag)"); +                        } else { +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, "listxattr failed " +                                        "on %p:", fd); +                        } +                        goto out; +                } +                if (size == 0) +                        goto done; +        } +        list = alloca (size + 1); +        if (!list) { +                op_ret = -1; +                op_errno = ENOMEM; +                goto out; +        } +        if (have_val) +                memcpy (list, value_buf, size); +        else +                size = sys_flistxattr (_fd, list, size); + +        remaining_size = size; +        list_offset = 0; +        while (remaining_size > 0) { +                if(*(list + list_offset) == '\0') +                        break; + +                strncpy (key, list + list_offset, sizeof(key)); +                memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); +                have_val = _gf_false; +                size = sys_fgetxattr (_fd, key, value_buf, +                                      XATTR_VAL_BUF_SIZE-1); +                if (size >= 0) { +                        have_val = _gf_true; +                } else { +                        if (errno == ERANGE) { +                                gf_msg (this->name, GF_LOG_INFO, errno, +                                        P_MSG_XATTR_FAILED, +                                        "fgetxattr failed due to overflow of buffer" +                                        " on fd %p: for the key %s ", fd, key); +                                size = sys_fgetxattr (_fd, key, NULL, 0); +                        } +                        if (size == -1) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, "fgetxattr failed " +                                        "on fd %p for the key %s ", fd, key); +                                break; +                        } +                } +                value = GF_CALLOC (size + 1, sizeof(char), +                                   gf_posix_mt_char); +                if (!value) { +                        op_ret = -1; +                        op_errno = errno; +                        goto out; +                } +                if (have_val) { +                        memcpy (value, value_buf, size); +                } else { +                        size = sys_fgetxattr (_fd, key, value, size); +                        if (size == -1) { +                                op_ret = -1; +                                op_errno = errno; +                                gf_msg (this->name, GF_LOG_ERROR, errno, +                                        P_MSG_XATTR_FAILED, "fgetxattr failed o" +                                        "n the fd %p for the key %s ", fd, key); +                                GF_FREE (value); +                                break; +                        } +                } +                value [size] = '\0'; + +                op_ret = dict_set_dynptr (dict, key, value, size); +                if (op_ret) { +                        op_errno = -op_ret; +                        op_ret = -1; +                        gf_msg (this->name, GF_LOG_ERROR, 0, +                                P_MSG_DICT_SET_FAILED, "dict set operation " +                                "failed on key %s", key); +                        GF_FREE (value); +                        goto out; +                } +                remaining_size -= strlen (key) + 1; +                list_offset += strlen (key) + 1; + +        } /* while (remaining_size > 0) */ + +done: +        op_ret = size; + +        if (dict) { +                dict_del (dict, GFID_XATTR_KEY); +                dict_del (dict, GF_XATTR_VOL_ID_KEY); +        } + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, NULL); + +        if (dict) +                dict_unref (dict); + +        return 0; +} + +static int +_handle_fsetxattr_keyvalue_pair (dict_t *d, char *k, data_t *v, +                                void *tmp) +{ +        posix_xattr_filler_t *filler = NULL; + +        filler = tmp; + +        return posix_fhandle_pair (filler->this, filler->fdnum, k, v, +                                   filler->flags, filler->stbuf); +} + +int32_t +posix_fsetxattr (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, dict_t *dict, int flags, dict_t *xdata) +{ +        int32_t            op_ret         = -1; +        int32_t            op_errno       = 0; +        struct posix_fd   *pfd            = NULL; +        int                _fd            = -1; +        int                ret            = -1; +        struct  iatt       stbuf          = {0,}; +        dict_t            *xattr          = NULL; +        posix_xattr_filler_t filler       = {0,}; +        struct  posix_private *priv       = NULL; + +        DECLARE_OLD_FS_ID_VAR; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); +        VALIDATE_OR_GOTO (dict, out); + +        priv = this->private; +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL from fd=%p", fd); +                goto out; +        } +        _fd = pfd->fd; + +        ret = posix_fdstat (this, pfd->fd, &stbuf); +        if (ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, op_errno, +                        P_MSG_FSTAT_FAILED, "fsetxattr (fstat)" +                        "failed on fd=%p", fd); +                goto out; +        } + +        dict_del (dict, GFID_XATTR_KEY); +        dict_del (dict, GF_XATTR_VOL_ID_KEY); + +        filler.fdnum = _fd; +        filler.this = this; +        filler.stbuf = &stbuf; +#ifdef GF_DARWIN_HOST_OS +        filler.flags = map_xattr_flags(flags); +#else +        filler.flags = flags; +#endif +        op_ret = dict_foreach (dict, _handle_fsetxattr_keyvalue_pair, +                               &filler); +        if (op_ret < 0) { +                op_errno = -op_ret; +                op_ret = -1; +        } + +        if (!ret && xdata && dict_get (xdata, GLUSTERFS_DURABLE_OP)) { +                op_ret = sys_fsync (_fd); +                if (op_ret < 0) { +                        op_ret = -1; +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_DURABILITY_REQ_NOT_SATISFIED, +                                "could not satisfy durability request: " +                                "reason "); +                } +        } + +        if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { +                ret = posix_fdstat (this, pfd->fd, &stbuf); +                if (ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_XATTR_FAILED, "fsetxattr (fstat)" +                                "failed on fd=%p", fd); +                        goto out; +                } + +                xattr = dict_new (); +                if (!xattr) +                        goto out; +                ret = posix_set_iatt_in_dict (xattr, &stbuf); +        } + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xattr); + +        if (xattr) +                dict_unref (xattr); + +        return 0; +} + +int +_posix_remove_xattr (dict_t *dict, char *key, data_t *value, void *data) +{ +        int32_t               op_ret   = 0; +        xlator_t             *this     = NULL; +        posix_xattr_filler_t *filler   = NULL; + +        filler = (posix_xattr_filler_t *) data; +        this = filler->this; +#ifdef GF_DARWIN_HOST_OS +        struct posix_private  *priv = NULL; +        priv = (struct posix_private *) this->private; +        char *newkey = NULL; +        if (priv->xattr_user_namespace == XATTR_STRIP) { +                gf_remove_prefix (XATTR_USER_PREFIX, key, &newkey); +                gf_msg_debug ("remove_xattr", 0, "key %s => %s" , key, +                       newkey); +                key = newkey; +        } +#endif +    /* Bulk remove xattr is internal fop in gluster. Some of the xattrs may +     * have special behavior. Ex: removexattr("posix.system_acl_access"), +     * removes more than one xattr on the file that could be present in the +     * bulk-removal request.  Removexattr of these deleted xattrs will fail +     * with either ENODATA/ENOATTR.  Since all this fop cares is removal of the +     * xattrs in bulk-remove request and if they are already deleted, it can be +     * treated as success. +     */ + +        if (filler->real_path) +                op_ret = sys_lremovexattr (filler->real_path, key); +        else +                op_ret = sys_fremovexattr (filler->fdnum, key); + +        if (op_ret == -1) { +                if (errno == ENODATA || errno == ENOATTR) +                        op_ret = 0; +        } + +        if (op_ret == -1) { +                filler->op_errno = errno; +                if (errno != ENOATTR && errno != ENODATA && errno != EPERM) { +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_XATTR_FAILED, "removexattr failed on " +                                "file/dir %s with gfid: %s (for %s)", +                                filler->real_path?filler->real_path:"", +                                uuid_utoa (filler->inode->gfid), key); +                } +        } +#ifdef GF_DARWIN_HOST_OS +        GF_FREE(newkey); +#endif +        return op_ret; +} + +int +posix_common_removexattr (call_frame_t *frame, loc_t *loc, fd_t *fd, +                          const char *name, dict_t *xdata, int *op_errno, +                          dict_t **xdata_rsp) +{ +        gf_boolean_t         bulk_removexattr = _gf_false; +        gf_boolean_t         disallow         = _gf_false; +        char                 *real_path       = NULL; +        struct posix_fd      *pfd             = NULL; +        int                  op_ret           = 0; +        struct iatt          stbuf            = {0}; +        int                  ret              = 0; +        int                  _fd              = -1; +        xlator_t             *this            = frame->this; +        inode_t              *inode           = NULL; +        posix_xattr_filler_t filler           = {0}; + +        DECLARE_OLD_FS_ID_VAR; + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        if (loc) { +                MAKE_INODE_HANDLE (real_path, this, loc, NULL); +                if (!real_path) { +                        op_ret = -1; +                        *op_errno = ESTALE; +                        goto out; +                } +                inode = loc->inode; +        } else { +                op_ret = posix_fd_ctx_get (fd, this, &pfd, op_errno); +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, *op_errno, +                                P_MSG_PFD_NULL, "pfd is NULL from fd=%p", fd); +                        goto out; +                } +                _fd = pfd->fd; +                inode = fd->inode; +        } + +        if (posix_is_gfid2path_xattr (name)) { +                op_ret = -1; +                *op_errno = ENOATTR; +                goto out; +        } + +        if (gf_get_index_by_elem (disallow_removexattrs, (char *)name) >= 0) { +                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_XATTR_NOT_REMOVED, +                        "Remove xattr called on %s for file/dir %s with gfid: " +                        "%s", name, real_path?real_path:"", +                        uuid_utoa(inode->gfid)); +                op_ret = -1; +                *op_errno = EPERM; +                goto out; +        } else if (posix_is_bulk_removexattr ((char *)name, xdata)) { +                bulk_removexattr = _gf_true; +                (void) dict_has_key_from_array (xdata, disallow_removexattrs, +                                                &disallow); +                if (disallow) { +                        gf_msg (this->name, GF_LOG_WARNING, 0, +                                P_MSG_XATTR_NOT_REMOVED, +                                "Bulk removexattr has keys that shouldn't be " +                                "removed for file/dir %s with gfid: %s", +                                real_path?real_path:"", uuid_utoa(inode->gfid)); +                        op_ret = -1; +                        *op_errno = EPERM; +                        goto out; +                } +        } + +        if (bulk_removexattr) { +                filler.real_path = real_path; +                filler.this = this; +                filler.fdnum = _fd; +                filler.inode = inode; +                op_ret = dict_foreach (xdata, _posix_remove_xattr, &filler); +                if (op_ret) { +                        *op_errno = filler.op_errno; +                        goto out; +                } +        } else { +                if (loc) +                        op_ret = sys_lremovexattr (real_path, name); +                else +                        op_ret = sys_fremovexattr (_fd, name); +                if (op_ret == -1) { +                        *op_errno = errno; +                        if (*op_errno != ENOATTR && *op_errno != ENODATA && +                            *op_errno != EPERM) { +                                gf_msg (this->name, GF_LOG_ERROR, *op_errno, +                                        P_MSG_XATTR_FAILED, +                                        "removexattr on %s with gfid %s " +                                        "(for %s)", real_path, +                                        uuid_utoa (inode->gfid), name); +                        } +                        goto out; +                } +        } + +        if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { +                if (loc) +                        ret = posix_pstat(this, loc->gfid, real_path, &stbuf); +                else +                        ret = posix_fdstat (this, _fd, &stbuf); +                if (ret) +                        goto out; +                *xdata_rsp = dict_new(); +                if (!*xdata_rsp) +                        goto out; + +                ret = posix_set_iatt_in_dict (*xdata_rsp, &stbuf); +        } +        op_ret = 0; +out: +        SET_TO_OLD_FS_ID (); +        return op_ret; +} + +int32_t +posix_removexattr (call_frame_t *frame, xlator_t *this, +                   loc_t *loc, const char *name, dict_t *xdata) +{ +        int    op_ret     = 0; +        int    op_errno   = 0; +        dict_t *xdata_rsp = NULL; + +        op_ret = posix_common_removexattr (frame, loc, NULL, name, xdata, +                                           &op_errno, &xdata_rsp); +        STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, xdata_rsp); + +        if (xdata_rsp) +                dict_unref (xdata_rsp); + +        return 0; +} + +int32_t +posix_fremovexattr (call_frame_t *frame, xlator_t *this, +                    fd_t *fd, const char *name, dict_t *xdata) +{ +        int32_t op_ret     = 0; +        int32_t op_errno   = 0; +        dict_t  *xdata_rsp = NULL; + +        op_ret = posix_common_removexattr (frame, NULL, fd, name, xdata, +                                           &op_errno, &xdata_rsp); +        STACK_UNWIND_STRICT (fremovexattr, frame, op_ret, op_errno, xdata_rsp); + +        if (xdata_rsp) +                dict_unref (xdata_rsp); + +        return 0; +} + + +int32_t +posix_fsyncdir (call_frame_t *frame, xlator_t *this, +                fd_t *fd, int datasync, dict_t *xdata) +{ +        int32_t           op_ret   = -1; +        int32_t           op_errno = 0; +        int               ret      = -1; +        struct posix_fd  *pfd      = NULL; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL, fd=%p", fd); +                goto out; +        } + +        op_ret = 0; + +out: +        STACK_UNWIND_STRICT (fsyncdir, frame, op_ret, op_errno, NULL); + +        return 0; +} + + +void +posix_print_xattr (dict_t *this, +                   char *key, +                   data_t *value, +                   void *data) +{ +        gf_msg_debug ("posix", 0, +                "(key/val) = (%s/%d)", key, data_to_int32 (value)); +} + + +/** + * add_array - add two arrays of 32-bit numbers (stored in network byte order) + * dest = dest + src + * @count: number of 32-bit numbers + * FIXME: handle overflow + */ + +static void +__add_array (int32_t *dest, int32_t *src, int count) +{ +        int     i = 0; +        int32_t destval = 0; +        for (i = 0; i < count; i++) { +                destval = ntoh32 (dest[i]); +                dest[i] = hton32 (destval + ntoh32 (src[i])); +        } +} + +static void +__add_long_array (int64_t *dest, int64_t *src, int count) +{ +        int i = 0; +        for (i = 0; i < count; i++) { +                dest[i] = hton64 (ntoh64 (dest[i]) + ntoh64 (src[i])); +        } +} + + +/* functions: +       __add_array_with_default +       __add_long_array_with_default + +   xattrop type: +       GF_XATTROP_ADD_ARRAY_WITH_DEFAULT +       GF_XATTROP_ADD_ARRAY64_WITH_DEFAULT + +   These operations are similar to 'GF_XATTROP_ADD_ARRAY', +   except that it adds a default value if xattr is missing +   or its value is zero on disk. + +   One use-case of this operation is in inode-quota. +   When a new directory is created, its default dir_count +   should be set to 1. So when a xattrop performed setting +   inode-xattrs, it should account initial dir_count +   1 if the xattrs are not present + +   Here is the usage of this operation + +   value required in xdata for each key +   struct array { +       int32_t   newvalue_1; +       int32_t   newvalue_2; +       ... +       int32_t   newvalue_n; +       int32_t   default_1; +       int32_t   default_2; +       ... +       int32_t   default_n; +   }; + +   or + +   struct array { +       int32_t   value_1; +       int32_t   value_2; +       ... +       int32_t   value_n; +   } data[2]; +   fill data[0] with new value to add +   fill data[1] with default value + +   xattrop GF_XATTROP_ADD_ARRAY_WITH_DEFAULT +   for i from 1 to n +   { +       if (xattr (dest_i) is zero or not set in the disk) +           dest_i = newvalue_i + default_i +       else +           dest_i = dest_i + newvalue_i +   } + +   value in xdata after xattrop is successful +   struct array { +       int32_t   dest_1; +       int32_t   dest_2; +       ... +       int32_t   dest_n; +   }; +*/ +static void +__add_array_with_default (int32_t *dest, int32_t *src, int count) +{ +        int     i       = 0; +        int32_t destval = 0; + +        for (i = 0; i < count; i++) { +                destval = ntoh32 (dest[i]); +                if (destval == 0) +                        dest[i] = hton32 (ntoh32 (src[i]) + +                                          ntoh32 (src[count + i])); +                else +                        dest[i] = hton32 (destval + ntoh32 (src[i])); +        } +} + +static void +__add_long_array_with_default (int64_t *dest, int64_t *src, int count) +{ +        int     i       = 0; +        int64_t destval = 0; + +        for (i = 0; i < count; i++) { +                destval = ntoh64 (dest[i]); +                if (destval == 0) +                        dest[i] = hton64 (ntoh64 (src[i]) + +                                          ntoh64 (src[i + count])); +                else +                        dest[i] = hton64 (destval + ntoh64 (src[i])); +        } +} + +static int +_posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v, +                                   void *tmp) +{ +        int                   size     = 0; +        int                   count    = 0; +        int                   op_ret   = 0; +        int                   op_errno = 0; +        gf_xattrop_flags_t    optype   = 0; +        char                 *array    = NULL; +        char                 *dst_data = NULL; +        inode_t              *inode    = NULL; +        xlator_t             *this     = NULL; +        posix_xattr_filler_t *filler   = NULL; +        posix_inode_ctx_t    *ctx      = NULL; + +        filler = tmp; + +        optype = (gf_xattrop_flags_t)(filler->flags); +        this = filler->this; +        inode = filler->inode; +        count = v->len; +        if (optype == GF_XATTROP_ADD_ARRAY_WITH_DEFAULT || +            optype == GF_XATTROP_ADD_ARRAY64_WITH_DEFAULT) +                count = count / 2; + +        array = GF_CALLOC (count, sizeof (char), gf_posix_mt_char); + +#ifdef GF_DARWIN_HOST_OS +        struct posix_private *priv     = NULL; +        priv = this->private; +        if (priv->xattr_user_namespace == XATTR_STRIP) { +                if (strncmp(k, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) == 0) { +                        k += XATTR_USER_PREFIX_LEN; +                } +        } +#endif +        op_ret = posix_inode_ctx_get_all (inode, this, &ctx); +        if (op_ret < 0) { +                op_errno = ENOMEM; +                goto out; +        } + +        pthread_mutex_lock (&ctx->xattrop_lock); +        { +                if (filler->real_path) { +                        size = sys_lgetxattr (filler->real_path, k, +                                              (char *)array, count); +                } else { +                        size = sys_fgetxattr (filler->fdnum, k, (char *)array, +                                              count); +                } + +                op_errno = errno; +                if ((size == -1) && (op_errno != ENODATA) && +                    (op_errno != ENOATTR)) { +                        if (op_errno == ENOTSUP) { +                                GF_LOG_OCCASIONALLY(gf_posix_xattr_enotsup_log, +                                                    this->name, GF_LOG_WARNING, +                                                    "Extended attributes not " +                                                    "supported by filesystem"); +                        } else if (op_errno != ENOENT || +                                   !posix_special_xattr (marker_xattrs, +                                                         k)) { +                                if (filler->real_path) +                                        gf_msg (this->name, fop_log_level (GF_FOP_XATTROP, +                                                op_errno),  op_errno, P_MSG_XATTR_FAILED, +                                                "getxattr failed on %s while " +                                                "doing xattrop: Key:%s ", +                                                filler->real_path, k); +                                else +                                        gf_msg (this->name, GF_LOG_ERROR, +                                                op_errno, P_MSG_XATTR_FAILED, +                                                "fgetxattr failed on gfid=%s " +                                                "while doing xattrop: " +                                                "Key:%s (%s)", +                                                uuid_utoa (filler->inode->gfid), +                                                k, strerror (op_errno)); +                        } + +                        op_ret = -1; +                        goto unlock; +                } + +                if (size == -1 && optype == GF_XATTROP_GET_AND_SET) { +                        GF_FREE (array); +                        array = NULL; +                } + +                /* We only write back the xattr if it has been really modified +                 * (i.e. v->data is not all 0's). Otherwise we return its value +                 * but we don't update anything. +                 * +                 * If the xattr does not exist, a value of all 0's is returned +                 * without creating it. */ +                size = count; +                if (optype != GF_XATTROP_GET_AND_SET && +                    mem_0filled(v->data, v->len) == 0) +                        goto unlock; + +                dst_data = array; +                switch (optype) { + +                case GF_XATTROP_ADD_ARRAY: +                        __add_array ((int32_t *) array, +                                     (int32_t *) v->data, count / 4); +                        break; + +                case GF_XATTROP_ADD_ARRAY64: +                        __add_long_array ((int64_t *) array, +                                          (int64_t *) v->data, +                                          count / 8); +                        break; + +                case GF_XATTROP_ADD_ARRAY_WITH_DEFAULT: +                        __add_array_with_default ((int32_t *) array, +                                                  (int32_t *) v->data, +                                                  count / 4); +                        break; + +                case GF_XATTROP_ADD_ARRAY64_WITH_DEFAULT: +                        __add_long_array_with_default ((int64_t *) array, +                                                       (int64_t *) v->data, +                                                       count / 8); +                        break; + +                case GF_XATTROP_GET_AND_SET: +                        dst_data = v->data; +                        break; + +                default: +                        gf_msg (this->name, GF_LOG_ERROR, EINVAL, +                                P_MSG_UNKNOWN_OP, "Unknown xattrop type (%d)" +                                " on %s. Please send a bug report to " +                                "gluster-devel@gluster.org", optype, +                                filler->real_path); +                        op_ret = -1; +                        op_errno = EINVAL; +                        goto unlock; +                } + +                if (filler->real_path) { +                        size = sys_lsetxattr (filler->real_path, k, +                                              dst_data, count, 0); +                } else { +                        size = sys_fsetxattr (filler->fdnum, k, +                                              (char *)dst_data, +                                              count, 0); +                } +                op_errno = errno; +        } +unlock: +        pthread_mutex_unlock (&ctx->xattrop_lock); + +        if (op_ret == -1) +                goto out; + +        if (size == -1) { +                if (filler->real_path) +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_XATTR_FAILED, "setxattr failed on %s " +                                "while doing xattrop: key=%s", +                                filler->real_path, k); +                else +                        gf_msg (this->name, GF_LOG_ERROR, op_errno, +                                P_MSG_XATTR_FAILED, +                                "fsetxattr failed on gfid=%s while doing " +                                "xattrop: key=%s (%s)", +                                uuid_utoa (filler->inode->gfid), +                                k, strerror (op_errno)); +                op_ret = -1; +                goto out; +        } else if (array) { +                op_ret = dict_set_bin (filler->xattr, k, array, count); +                if (op_ret) { +                        if (filler->real_path) +                                gf_msg_debug (this->name, 0, +                                        "dict_set_bin failed (path=%s): " +                                        "key=%s (%s)", filler->real_path, +                                        k, strerror (-size)); +                        else +                                gf_msg_debug (this->name, 0, +                                        "dict_set_bin failed (gfid=%s): " +                                        "key=%s (%s)", +                                        uuid_utoa (filler->inode->gfid), +                                        k, strerror (-size)); + +                        op_ret = -1; +                        op_errno = EINVAL; +                        GF_FREE (array); +                        goto out; +                } +                array = NULL; +        } + +out: +        if (op_ret < 0) +                filler->op_errno = op_errno; + +        if (array) +                GF_FREE (array); + +        return op_ret; +} + +/** + * xattrop - xattr operations - for internal use by GlusterFS + * @optype: ADD_ARRAY: + *            dict should contain: + *               "key" ==> array of 32-bit numbers + */ + +int +do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, +            gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) +{ +        int                   op_ret    = 0; +        int                   op_errno  = 0; +        int                   _fd       = -1; +        char                 *real_path = NULL; +        struct posix_fd      *pfd       = NULL; +        inode_t              *inode     = NULL; +        posix_xattr_filler_t  filler    = {0,}; +        dict_t               *xattr_rsp = NULL; +        dict_t               *xdata_rsp = NULL; +        struct iatt           stbuf = {0}; +        struct  posix_private *priv     = NULL; + + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (xattr, out); +        VALIDATE_OR_GOTO (this, out); + +        priv = this->private; +        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); + +        if (fd) { +                op_ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +                if (op_ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, +                                fop_log_level(GF_FOP_FXATTROP, op_errno), +                                P_MSG_PFD_GET_FAILED, "failed to get pfd from" +                                " fd=%p", fd); +                        goto out; +                } +                _fd = pfd->fd; +        } + +        if (loc && !gf_uuid_is_null (loc->gfid)) { +                MAKE_INODE_HANDLE (real_path, this, loc, NULL); +                if (!real_path) { +                        op_ret = -1; +                        op_errno = ESTALE; +                        goto out; +                } +        } + +        if (real_path) { +                inode = loc->inode; +        } else if (fd) { +                inode = fd->inode; +        } + +        xattr_rsp = dict_new (); +        if (xattr_rsp == NULL) { +                op_ret = -1; +                op_errno = ENOMEM; +                goto out; +        } + +        filler.this = this; +        filler.fdnum = _fd; +        filler.real_path = real_path; +        filler.flags = (int)optype; +        filler.inode = inode; +        filler.xattr = xattr_rsp; + +        op_ret = dict_foreach (xattr, _posix_handle_xattr_keyvalue_pair, +                               &filler); +        op_errno = filler.op_errno; +        if (op_ret < 0) +                goto out; + +        if (!xdata) +                goto out; + +        if (fd) { +                op_ret = posix_fdstat (this, _fd, &stbuf); +        } else { +                op_ret = posix_pstat (this, inode->gfid, real_path, +                                      &stbuf); +        } +        if (op_ret < 0) { +                op_errno = errno; +                goto out; +        } +        xdata_rsp = posix_xattr_fill (this, real_path, loc, fd, _fd, +                                              xdata, &stbuf); +        if (!xdata_rsp) { +                op_ret = -1; +                op_errno = ENOMEM; +        } +out: + +        STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, xattr_rsp, +                             xdata_rsp); + +        if (xattr_rsp) +                dict_unref (xattr_rsp); + +        if (xdata_rsp) +                dict_unref (xdata_rsp); +        return 0; +} + + +int +posix_xattrop (call_frame_t *frame, xlator_t *this, +               loc_t *loc, gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) +{ +        do_xattrop (frame, this, loc, NULL, optype, xattr, xdata); +        return 0; +} + + +int +posix_fxattrop (call_frame_t *frame, xlator_t *this, +                fd_t *fd, gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) +{ +        do_xattrop (frame, this, NULL, fd, optype, xattr, xdata); +        return 0; +} + +int +posix_access (call_frame_t *frame, xlator_t *this, +              loc_t *loc, int32_t mask, dict_t *xdata) +{ +        int32_t                 op_ret    = -1; +        int32_t                 op_errno  = 0; +        char                   *real_path = NULL; + +        DECLARE_OLD_FS_ID_VAR; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (loc, out); + +        MAKE_INODE_HANDLE (real_path, this, loc, NULL); +        if (!real_path) { +                op_ret = -1; +                op_errno = errno; +                goto out; +        } + +        op_ret = sys_access (real_path, mask & 07); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACCESS_FAILED, +                        "access failed on %s", real_path); +                goto out; +        } +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (access, frame, op_ret, op_errno, NULL); +        return 0; +} + + +int32_t +posix_ftruncate (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, off_t offset, dict_t *xdata) +{ +        int32_t               op_ret   = -1; +        int32_t               op_errno = 0; +        int                   _fd      = -1; +        struct iatt           preop    = {0,}; +        struct iatt           postop   = {0,}; +        struct posix_fd      *pfd      = NULL; +        int                   ret      = -1; +        struct posix_private *priv     = NULL; + +        DECLARE_OLD_FS_ID_VAR; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL, fd=%p", fd); +                goto out; +        } + +        _fd = pfd->fd; + +        op_ret = posix_fdstat (this, _fd, &preop); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "pre-operation fstat failed on fd=%p", fd); +                goto out; +        } + +        op_ret = sys_ftruncate (_fd, offset); + +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_TRUNCATE_FAILED, +                        "ftruncate failed on fd=%p (%"PRId64"", fd, offset); +                goto out; +        } + +        op_ret = posix_fdstat (this, _fd, &postop); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "post-operation fstat failed on fd=%p", fd); +                goto out; +        } + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, &preop, +                             &postop, NULL); + +        return 0; +} + + +int32_t +posix_fstat (call_frame_t *frame, xlator_t *this, +             fd_t *fd, dict_t *xdata) +{ +        int                   _fd      = -1; +        int32_t               op_ret   = -1; +        int32_t               op_errno = 0; +        struct iatt           buf      = {0,}; +        struct posix_fd      *pfd      = NULL; +        dict_t               *xattr_rsp = NULL; +        int                   ret      = -1; +        struct posix_private *priv     = NULL; + +        DECLARE_OLD_FS_ID_VAR; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; +        VALIDATE_OR_GOTO (priv, out); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL, fd=%p", fd); +                goto out; +        } + +        _fd = pfd->fd; + +        op_ret = posix_fdstat (this, _fd, &buf); +        if (op_ret == -1) { +                op_errno = errno; +                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, +                        "fstat failed on fd=%p", fd); +                goto out; +        } + +        if (xdata) +                xattr_rsp = posix_xattr_fill (this, NULL, NULL, fd, _fd, xdata, +                                              &buf); + +        op_ret = 0; + +out: +        SET_TO_OLD_FS_ID (); + +        STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, &buf, xattr_rsp); +        if (xattr_rsp) +                dict_unref (xattr_rsp); +        return 0; +} + +int32_t +posix_lease (call_frame_t *frame, xlator_t *this, +             loc_t *loc, struct gf_lease *lease, dict_t *xdata) +{ +        struct gf_lease nullease = {0, }; + +        gf_msg (this->name, GF_LOG_CRITICAL, EINVAL, P_MSG_LEASE_DISABLED, +                "\"features/leases\" translator is not loaded. You need" +                "to use it for proper functioning of your application"); + +        STACK_UNWIND_STRICT (lease, frame, -1, ENOSYS, &nullease, NULL); +        return 0; +} + +static int gf_posix_lk_log; + +int32_t +posix_lk (call_frame_t *frame, xlator_t *this, +          fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata) +{ +        struct gf_flock nullock = {0, }; + +        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, +                             "\"features/locks\" translator is " +                             "not loaded. You need to use it for proper " +                             "functioning of your application."); + +        STACK_UNWIND_STRICT (lk, frame, -1, ENOSYS, &nullock, NULL); +        return 0; +} + +int32_t +posix_inodelk (call_frame_t *frame, xlator_t *this, +               const char *volume, loc_t *loc, int32_t cmd, +               struct gf_flock *lock, dict_t *xdata) +{ +        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, +                             "\"features/locks\" translator is " +                             "not loaded. You need to use it for proper " +                             "functioning of your application."); + +        STACK_UNWIND_STRICT (inodelk, frame, -1, ENOSYS, NULL); +        return 0; +} + +int32_t +posix_finodelk (call_frame_t *frame, xlator_t *this, +                const char *volume, fd_t *fd, int32_t cmd, +                struct gf_flock *lock, dict_t *xdata) +{ +        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, +                             "\"features/locks\" translator is " +                             "not loaded. You need to use it for proper " +                             "functioning of your application."); + +        STACK_UNWIND_STRICT (finodelk, frame, -1, ENOSYS, NULL); +        return 0; +} + + +int32_t +posix_entrylk (call_frame_t *frame, xlator_t *this, +               const char *volume, loc_t *loc, const char *basename, +               entrylk_cmd cmd, entrylk_type type, dict_t *xdata) +{ +        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, +                             "\"features/locks\" translator is " +                             "not loaded. You need to use it for proper " +                             "functioning of your application."); + +        STACK_UNWIND_STRICT (entrylk, frame, -1, ENOSYS, NULL); +        return 0; +} + +int32_t +posix_fentrylk (call_frame_t *frame, xlator_t *this, +                const char *volume, fd_t *fd, const char *basename, +                entrylk_cmd cmd, entrylk_type type, dict_t *xdata) +{ +        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, +                             "\"features/locks\" translator is " +                             "not loaded. You need to use it for proper " +                             "functioning of your application."); + +        STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOSYS, NULL); +        return 0; +} + + +int +posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, +                    gf_dirent_t *entries, xlator_t *this, int32_t skip_dirs) +{ +        off_t            in_case        = -1; +        off_t            last_off       = 0; +        size_t           filled         = 0; +        int              count          = 0; +        int32_t          this_size      = -1; +        gf_dirent_t     *this_entry     = NULL; +        struct posix_fd *pfd            = NULL; +        struct stat      stbuf          = {0,}; +        char            *hpath          = NULL; +        int              len            = 0; +        int              ret            = 0; +        int              op_errno       = 0; +        struct dirent   *entry          = NULL; +        struct dirent    scratch[2]     = {{0,},}; + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL, fd=%p", fd); +                count = -1; +                errno = op_errno; +                goto out; +        } + +        if (skip_dirs) { +                len = posix_handle_path (this, fd->inode->gfid, NULL, NULL, 0); +                if (len <= 0) { +                        errno = ESTALE; +                        count = -1; +                        goto out; +                } +                hpath = alloca (len + 256); /* NAME_MAX */ + +                if (posix_handle_path (this, fd->inode->gfid, NULL, hpath, +                                       len) <= 0) { +                        errno = ESTALE; +                        count = -1; +                        goto out; +                } + +                len = strlen (hpath); +                hpath[len] = '/'; +        } + +        if (!off) { +                rewinddir (dir); +        } else { +                seekdir (dir, off); +#ifndef GF_LINUX_HOST_OS +                if ((u_long)telldir(dir) != off && off != pfd->dir_eof) { +                        gf_msg (THIS->name, GF_LOG_ERROR, EINVAL, +                                P_MSG_DIR_OPERATION_FAILED, +                                "seekdir(0x%llx) failed on dir=%p: " +                                "Invalid argument (offset reused from " +                                "another DIR * structure?)", off, dir); +                        errno = EINVAL; +                        count = -1; +                        goto out; +                } +#endif /* GF_LINUX_HOST_OS */ +        } + +        while (filled <= size) { +                in_case = (u_long)telldir (dir); + +                if (in_case == -1) { +                        gf_msg (THIS->name, GF_LOG_ERROR, errno, +                                P_MSG_DIR_OPERATION_FAILED, +                                "telldir failed on dir=%p", dir); +                        goto out; +                } + +                errno = 0; + +                entry = sys_readdir (dir, scratch); + +                if (!entry || errno != 0) { +                        if (errno == EBADF) { +                                gf_msg (THIS->name, GF_LOG_WARNING, errno, +                                        P_MSG_DIR_OPERATION_FAILED, +                                        "readdir failed on dir=%p", +                                        dir); +                                goto out; +                        } +                        break; +                } + +#ifdef __NetBSD__ +               /* +                * NetBSD with UFS1 backend uses backing files for +                * extended attributes. They can be found in a +                * .attribute file located at the root of the filesystem +                * We hide it to glusterfs clients, since chaos will occur +                * when the cluster/dht xlator decides to distribute +                * exended attribute backing file across storage servers. +                */ +                if (__is_root_gfid (fd->inode->gfid) == 0 +                    && (!strcmp(entry->d_name, ".attribute"))) +                        continue; +#endif /* __NetBSD__ */ + +                if (__is_root_gfid (fd->inode->gfid) +                    && (!strcmp (GF_HIDDEN_PATH, entry->d_name))) { +                        continue; +                } + +                if (skip_dirs) { +                        if (DT_ISDIR (entry->d_type)) { +                                continue; +                        } else if (hpath) { +                                strcpy (&hpath[len+1], entry->d_name); +                                ret = sys_lstat (hpath, &stbuf); +                                if (!ret && S_ISDIR (stbuf.st_mode)) +                                        continue; +                        } +                } + +                this_size = max (sizeof (gf_dirent_t), +                                 sizeof (gfs3_dirplist)) +                        + strlen (entry->d_name) + 1; + +                if (this_size + filled > size) { +                        seekdir (dir, in_case); +#ifndef GF_LINUX_HOST_OS +                        if ((u_long)telldir(dir) != in_case && +                            in_case != pfd->dir_eof) { +                                gf_msg (THIS->name, GF_LOG_ERROR, EINVAL, +                                        P_MSG_DIR_OPERATION_FAILED, +                                        "seekdir(0x%llx) failed on dir=%p: " +                                        "Invalid argument (offset reused from " +                                        "another DIR * structure?)", +                                        in_case, dir); +                                errno = EINVAL; +                                count = -1; +                                goto out; +                        } +#endif /* GF_LINUX_HOST_OS */ +                        break; +                } + +                this_entry = gf_dirent_for_name (entry->d_name); + +                if (!this_entry) { +                        gf_msg (THIS->name, GF_LOG_ERROR, errno, +                                P_MSG_GF_DIRENT_CREATE_FAILED, +                                "could not create " +                                "gf_dirent for entry %s", entry->d_name); +                        goto out; +                } +                /* +                 * we store the offset of next entry here, which is +                 * probably not intended, but code using syncop_readdir() +                 * (glfs-heal.c, afr-self-heald.c, pump.c) rely on it +                 * for directory read resumption. +                 */ +                last_off = (u_long)telldir(dir); +                this_entry->d_off = last_off; +                this_entry->d_ino = entry->d_ino; +                this_entry->d_type = entry->d_type; + +                list_add_tail (&this_entry->list, &entries->list); + +                filled += this_size; +                count ++; +        } + +        if ((!sys_readdir (dir, scratch) && (errno == 0))) { +                /* Indicate EOF */ +                errno = ENOENT; +                /* Remember EOF offset for later detection */ +                pfd->dir_eof = (u_long)last_off; +        } +out: +        return count; +} + +dict_t * +posix_entry_xattr_fill (xlator_t *this, inode_t *inode, +                        fd_t *fd, char *entry_path, dict_t *dict, +                        struct iatt *stbuf) +{ +        loc_t  tmp_loc    = {0,}; + +        /* if we don't send the 'loc', open-fd-count be a problem. */ +        tmp_loc.inode = inode; + +        return posix_xattr_fill (this, entry_path, &tmp_loc, NULL, -1, dict, +                                 stbuf); + +} + + +#ifdef _DIRENT_HAVE_D_TYPE +static int +posix_d_type_from_ia_type (ia_type_t type) +{ +        switch (type) { +        case IA_IFDIR:      return DT_DIR; +        case IA_IFCHR:      return DT_CHR; +        case IA_IFBLK:      return DT_BLK; +        case IA_IFIFO:      return DT_FIFO; +        case IA_IFLNK:      return DT_LNK; +        case IA_IFREG:      return DT_REG; +        case IA_IFSOCK:     return DT_SOCK; +        default:            return DT_UNKNOWN; +        } +} +#endif + + +int +posix_readdirp_fill (xlator_t *this, fd_t *fd, gf_dirent_t *entries, dict_t *dict) +{ +        gf_dirent_t     *entry    = NULL; +        inode_table_t   *itable   = NULL; +        inode_t         *inode    = NULL; +        char            *hpath    = NULL; +        int              len      = 0; +        struct iatt      stbuf    = {0, }; +        uuid_t           gfid; +        int              ret      = -1; + +        if (list_empty(&entries->list)) +                return 0; + +        itable = fd->inode->table; + +        len = posix_handle_path (this, fd->inode->gfid, NULL, NULL, 0); +        if (len <= 0) +                return -1; +        hpath = alloca (len + 256); /* NAME_MAX */ +        if (posix_handle_path (this, fd->inode->gfid, NULL, hpath, len) <= 0) +                return -1; +        len = strlen (hpath); +        hpath[len] = '/'; + +        list_for_each_entry (entry, &entries->list, list) { +                memset (gfid, 0, 16); +                inode = inode_grep (fd->inode->table, fd->inode, +                                    entry->d_name); +                if (inode) +                        gf_uuid_copy (gfid, inode->gfid); + +                strcpy (&hpath[len+1], entry->d_name); + +                ret = posix_pstat (this, gfid, hpath, &stbuf); + +                if (ret == -1) { +                        if (inode) +                                inode_unref (inode); +                      continue; +                } + +                if (!inode) +                        inode = inode_find (itable, stbuf.ia_gfid); + +                if (!inode) +                        inode = inode_new (itable); + +                entry->inode = inode; + +                if (dict) { +                        entry->dict = +                                posix_entry_xattr_fill (this, entry->inode, +                                                        fd, hpath, +                                                        dict, &stbuf); +                } + +                entry->d_stat = stbuf; +                if (stbuf.ia_ino) +                        entry->d_ino = stbuf.ia_ino; + +#ifdef _DIRENT_HAVE_D_TYPE +                if (entry->d_type == DT_UNKNOWN && !IA_ISINVAL(stbuf.ia_type)) { +                        /* The platform supports d_type but the underlying +                           filesystem doesn't. We set d_type to the correct +                           value from ia_type */ +                        entry->d_type = +                                posix_d_type_from_ia_type (stbuf.ia_type); +                } +#endif + +                inode = NULL; +        } + +        return 0; +} + + +int32_t +posix_do_readdir (call_frame_t *frame, xlator_t *this, +                  fd_t *fd, size_t size, off_t off, int whichop, dict_t *dict) +{ +        struct posix_fd *pfd       = NULL; +        DIR             *dir       = NULL; +        int              ret       = -1; +        int              count     = 0; +        int32_t          op_ret    = -1; +        int32_t          op_errno  = 0; +        gf_dirent_t      entries; +        int32_t          skip_dirs = 0; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        INIT_LIST_HEAD (&entries.list); + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, +                        "pfd is NULL, fd=%p", fd); +                goto out; +        } + +        dir = pfd->dir; + +        if (!dir) { +                gf_msg (this->name, GF_LOG_WARNING, EINVAL, P_MSG_PFD_NULL, +                        "dir is NULL for fd=%p", fd); +                op_errno = EINVAL; +                goto out; +        } + +        /* When READDIR_FILTER option is set to on, we can filter out +         * directory's entry from the entry->list. +         */ +        ret = dict_get_int32 (dict, GF_READDIR_SKIP_DIRS, &skip_dirs); + +        LOCK (&fd->lock); +        { +                /* posix_fill_readdir performs multiple separate individual +                   readdir() calls to fill up the buffer. + +                   In case of NFS where the same anonymous FD is shared between +                   different applications, reading a common directory can +                   result in the anonymous fd getting re-used unsafely between +                   the two readdir requests (in two different io-threads). + +                   It would also help, in the future, to replace the loop +                   around readdir() with a single large getdents() call. +                */ +                count = posix_fill_readdir (fd, dir, off, size, &entries, this, +                                            skip_dirs); +        } +        UNLOCK (&fd->lock); + +        /* pick ENOENT to indicate EOF */ +        op_errno = errno; +        op_ret = count; + +        if (whichop != GF_FOP_READDIRP) +                goto out; + +        posix_readdirp_fill (this, fd, &entries, dict); + +out: +        STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, &entries, NULL); + +        gf_dirent_free (&entries); + +        return 0; +} + + +int32_t +posix_readdir (call_frame_t *frame, xlator_t *this, +               fd_t *fd, size_t size, off_t off, dict_t *xdata) +{ +        posix_do_readdir (frame, this, fd, size, off, GF_FOP_READDIR, xdata); +        return 0; +} + + +int32_t +posix_readdirp (call_frame_t *frame, xlator_t *this, +                fd_t *fd, size_t size, off_t off, dict_t *dict) +{ +        gf_dirent_t entries; +        int32_t     op_ret = -1, op_errno = 0; +        gf_dirent_t     *entry     = NULL; + + +        if ((dict != NULL) && (dict_get (dict, GET_ANCESTRY_DENTRY_KEY))) { +                INIT_LIST_HEAD (&entries.list); + +                op_ret = posix_get_ancestry (this, fd->inode, &entries, NULL, +                                             POSIX_ANCESTRY_DENTRY, +                                             &op_errno, dict); +                if (op_ret >= 0) { +                        op_ret = 0; + +                        list_for_each_entry (entry, &entries.list, list) { +                                op_ret++; +                        } +                } + +                STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, &entries, +                                     NULL); + +                gf_dirent_free (&entries); +                return 0; +        } + +        posix_do_readdir (frame, this, fd, size, off, GF_FOP_READDIRP, dict); +        return 0; +} + +int32_t +posix_rchecksum (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, off_t offset, int32_t len, dict_t *xdata) +{ +        char                    *alloc_buf      = NULL; +        char                    *buf            = NULL; +        int                     _fd             = -1; +        struct posix_fd         *pfd            = NULL; +        int                     op_ret          = -1; +        int                     op_errno        = 0; +        int                     ret             = 0; +        ssize_t                 bytes_read      = 0; +        int32_t                 weak_checksum   = 0; +        int32_t                 zerofillcheck   = 0; +        unsigned char           strong_checksum[MD5_DIGEST_LENGTH] = {0}; +        struct posix_private    *priv           = NULL; +        dict_t                  *rsp_xdata      = NULL; +        gf_boolean_t            buf_has_zeroes  = _gf_false; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        priv = this->private; +        memset (strong_checksum, 0, MD5_DIGEST_LENGTH); + +        alloc_buf = _page_aligned_alloc (len, &buf); +        if (!alloc_buf) { +                op_errno = ENOMEM; +                goto out; +        } + +        rsp_xdata = dict_new(); +        if (!rsp_xdata) { +                op_errno = ENOMEM; +                goto out; +        } + +        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, -ret, P_MSG_PFD_NULL, +                        "pfd is NULL, fd=%p", fd); +                goto out; +        } + +        _fd = pfd->fd; + +        LOCK (&fd->lock); +        { +                if (priv->aio_capable && priv->aio_init_done) +                        __posix_fd_set_odirect (fd, pfd, 0, offset, len); + +                bytes_read = sys_pread (_fd, buf, len, offset); +                if (bytes_read < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, errno, +                                P_MSG_PREAD_FAILED, +                                "pread of %d bytes returned %zd", len, +                                bytes_read); + +                        op_errno = errno; +                } + +        } +        UNLOCK (&fd->lock); + +        if (bytes_read < 0) +                goto out; + +        if (xdata && dict_get_int32 (xdata, "check-zero-filled", +                                     &zerofillcheck) == 0) { +                buf_has_zeroes = (mem_0filled (buf, bytes_read)) ? _gf_false : +                                 _gf_true; +                ret = dict_set_uint32 (rsp_xdata, "buf-has-zeroes", +                                       buf_has_zeroes); +                if (ret) { +                        gf_msg (this->name, GF_LOG_WARNING, -ret, +                                P_MSG_DICT_SET_FAILED, "%s: Failed to set " +                                "dictionary value for key: %s", +                                uuid_utoa (fd->inode->gfid), "buf-has-zeroes"); +                        op_errno = -ret; +                        goto out; +                } +        } +        weak_checksum = gf_rsync_weak_checksum ((unsigned char *) buf, (size_t) ret); +        gf_rsync_strong_checksum ((unsigned char *) buf, (size_t) bytes_read, +                                  (unsigned char *) strong_checksum); + +        op_ret = 0; +out: +        STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno, +                             weak_checksum, strong_checksum, rsp_xdata); +        if (rsp_xdata) +                dict_unref (rsp_xdata); +        GF_FREE (alloc_buf); + +        return 0; +} + +int +posix_forget (xlator_t *this, inode_t *inode) +{ +        int                     ret         = 0; +        char                   *unlink_path = NULL; +        uint64_t                ctx_uint    = 0; +        posix_inode_ctx_t      *ctx         = NULL; +        struct posix_private   *priv_posix  = NULL; + +        priv_posix = (struct posix_private *) this->private; + +        ret = inode_ctx_del (inode, this, &ctx_uint); +        if (!ctx_uint) +                return 0; + +        ctx = (posix_inode_ctx_t *)ctx_uint; + +        if (ctx->unlink_flag == GF_UNLINK_TRUE) { +                POSIX_GET_FILE_UNLINK_PATH(priv_posix->base_path, +                                           inode->gfid, unlink_path); +                if (!unlink_path) { +                        gf_msg (this->name, GF_LOG_ERROR, ENOMEM, +                                P_MSG_UNLINK_FAILED, +                                "Failed to remove gfid :%s", +                                uuid_utoa (inode->gfid)); +                        ret = -1; +                        goto out; +                } +                ret = sys_unlink(unlink_path); +        } +out: +        pthread_mutex_destroy (&ctx->xattrop_lock); +        pthread_mutex_destroy (&ctx->write_atomic_lock); +        pthread_mutex_destroy (&ctx->pgfid_lock); +        GF_FREE (ctx); +        return ret; +} diff --git a/xlators/storage/posix/src/posix-inode-handle.h b/xlators/storage/posix/src/posix-inode-handle.h new file mode 100644 index 00000000000..6849276d3db --- /dev/null +++ b/xlators/storage/posix/src/posix-inode-handle.h @@ -0,0 +1,106 @@ +/* +   Copyright (c) 2011-2017 Red Hat, Inc. <http://www.redhat.com> +   This file is part of GlusterFS. + +   This file is licensed to you under your choice of the GNU Lesser +   General Public License, version 3 or any later version (LGPLv3 or +   later), or the GNU General Public License, version 2 (GPLv2), in all +   cases as published by the Free Software Foundation. +*/ +#ifndef _POSIX_INODE_HANDLE_H +#define _POSIX_INODE_HANDLE_H + +#include <limits.h> +#include <sys/types.h> +#include "xlator.h" +#include "gf-dirent.h" +#include "posix.h" + +/* From Open Group Base Specifications Issue 6 */ +#ifndef _XOPEN_PATH_MAX +#define _XOPEN_PATH_MAX 1024 +#endif + +#define TRASH_DIR "landfill" + +#define UUID0_STR "00000000-0000-0000-0000-000000000000" +#define SLEN(str) (sizeof(str) - 1) + +#define LOC_HAS_ABSPATH(loc) (loc && (loc->path) && (loc->path[0] == '/')) +#define LOC_IS_DIR(loc) (loc && (loc->inode) && \ +                (loc->inode->ia_type == IA_IFDIR)) +#define MAKE_REAL_PATH(var, this, path) do {                            \ +        size_t path_len = strlen(path);                                 \ +        size_t var_len = path_len + POSIX_BASE_PATH_LEN(this) + 1;      \ +        if (POSIX_PATH_MAX(this) != -1 &&                               \ +            var_len >= POSIX_PATH_MAX(this)) {                          \ +                var = alloca (path_len + 1);                            \ +                strcpy (var, (path[0] == '/') ? path + 1 : path);       \ +        } else {                                                        \ +                var = alloca (var_len);                                 \ +                strcpy (var, POSIX_BASE_PATH(this));                    \ +                strcpy (&var[POSIX_BASE_PATH_LEN(this)], path);         \ +        }                                                               \ +    } while (0) + +#define MAKE_HANDLE_PATH(var, this, gfid, base) do {                    \ +        int __len;                                                      \ +        __len = posix_handle_path (this, gfid, base, NULL, 0);          \ +        if (__len <= 0)                                                 \ +                break;                                                  \ +        var = alloca (__len);                                           \ +        __len = posix_handle_path (this, gfid, base, var, __len);       \ +        if (__len <= 0)                                                 \ +                var = NULL;                                             \ +        } while (0) + +#define MAKE_INODE_HANDLE(rpath, this, loc, iatt_p) do {                \ +        if (gf_uuid_is_null (loc->gfid)) {                              \ +                gf_msg (this->name, GF_LOG_ERROR, 0,                    \ +                        P_MSG_INODE_HANDLE_CREATE,                      \ +                        "null gfid for path %s", (loc)->path);          \ +                break;                                                  \ +        }                                                               \ +        if (LOC_IS_DIR (loc) && LOC_HAS_ABSPATH (loc)) {                \ +                MAKE_REAL_PATH (rpath, this, (loc)->path);              \ +                op_ret = posix_pstat (this, (loc)->gfid, rpath, iatt_p); \ +                break;                                                  \ +        }                                                               \ +        errno = 0;                                                      \ +        op_ret = posix_istat (this, loc->gfid, NULL, iatt_p);           \ +        if (errno != ELOOP) {                                           \ +                MAKE_HANDLE_PATH (rpath, this, (loc)->gfid, NULL);      \ +                if (!rpath) {                                           \ +                        op_ret = -1;                                    \ +                        gf_msg (this->name, GF_LOG_ERROR, errno,        \ +                                P_MSG_INODE_HANDLE_CREATE,            \ +                                "Failed to create inode handle "        \ +                                "for path %s", (loc)->path);            \ +                }                                                       \ +                break;                                                  \ +        }                                                               \ +        /* __ret == -1 && errno == ELOOP */                             \ +        } while (0) + +#define POSIX_ANCESTRY_PATH (1 << 0) +#define POSIX_ANCESTRY_DENTRY (1 << 1) + +int +posix_handle_path (xlator_t *this, uuid_t gfid, const char *basename, char *buf, +                   size_t len); + +int +posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, +                             gf_dirent_t *head, int type, uuid_t gfid, +                             const size_t handle_size, +                             const char *priv_base_path, +                             inode_table_t *table, inode_t **parent, +                             dict_t *xdata, int32_t *op_errno); + +int +posix_handle_init (xlator_t *this); + +int +posix_handle_trash_init (xlator_t *this); + +#endif /* !_POSIX_INODE_HANDLE_H */ diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 3b03779f305..d8d908f83cd 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -1,5 +1,5 @@  /* -   Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> +   Copyright (c) 2006-2017 Red Hat, Inc. <http://www.redhat.com>     This file is part of GlusterFS.     This file is licensed to you under your choice of the GNU Lesser @@ -14,8026 +14,16 @@  #define _GNU_SOURCE  #endif -#include <openssl/md5.h> -#include <stdint.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <errno.h> -#include <libgen.h> -#include <pthread.h> -#include <ftw.h> -#include <sys/stat.h> -#include <signal.h> -#include <sys/uio.h> -#include <unistd.h> -#include <ftw.h> - -#ifndef GF_BSD_HOST_OS -#include <alloca.h> -#endif /* GF_BSD_HOST_OS */ - -#ifdef HAVE_LINKAT -#include <fcntl.h> -#endif /* HAVE_LINKAT */ - -#include "glusterfs.h" -#include "checksum.h" -#include "dict.h" -#include "logging.h" -#include "posix.h"  #include "xlator.h" -#include "defaults.h" -#include "common-utils.h" -#include "compat-errno.h" -#include "compat.h" -#include "byte-order.h" -#include "syscall.h" -#include "statedump.h" -#include "locking.h" -#include "timer.h" -#include "glusterfs3-xdr.h" -#include "hashfn.h" -#include "posix-aio.h" -#include "glusterfs-acl.h" -#include "posix-messages.h" -#include "events.h" -#include "posix-gfid-path.h" - -extern char *marker_xattrs[]; -#define ALIGN_SIZE 4096 - -#undef HAVE_SET_FSID -#ifdef HAVE_SET_FSID - -#define DECLARE_OLD_FS_ID_VAR uid_t old_fsuid; gid_t old_fsgid; - -#define SET_FS_ID(uid, gid) do {                \ -                old_fsuid = setfsuid (uid);     \ -                old_fsgid = setfsgid (gid);     \ -        } while (0) - -#define SET_TO_OLD_FS_ID() do {                 \ -                setfsuid (old_fsuid);           \ -                setfsgid (old_fsgid);           \ -        } while (0) - -#else - -#define DECLARE_OLD_FS_ID_VAR -#define SET_FS_ID(uid, gid) -#define SET_TO_OLD_FS_ID() - -#endif - -/* Setting microseconds or nanoseconds depending on what's supported: -   The passed in `tv` can be -       struct timespec -   if supported (better, because it supports nanosecond resolution) or -       struct timeval -   otherwise. */ -#if HAVE_UTIMENSAT -#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ -        tv.tv_nsec = nanosecs -#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ -        (sys_utimensat (AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW)) -#else -#define SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, nanosecs) \ -        tv.tv_usec = nanosecs / 1000 -#define PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv) \ -        (lutimes (path, tv)) -#endif +#include "posix.h" -static char *disallow_removexattrs[] = { -        GF_XATTR_VOL_ID_KEY, -        GFID_XATTR_KEY, -        NULL +class_methods_t class_methods = { +        .init           = posix_init, +        .fini           = posix_fini, +        .reconfigure    = posix_reconfigure, +        .notify         = posix_notify  }; -gf_boolean_t -posix_symlinks_match (xlator_t *this, loc_t *loc, uuid_t gfid) -{ -        struct posix_private *priv = NULL; -        char linkname_actual[PATH_MAX] = {0,}; -        char linkname_expected[PATH_MAX] = {0}; -        char *dir_handle = NULL; -        ssize_t len = 0; -        size_t handle_size = 0; -        gf_boolean_t ret = _gf_false; - -        priv = this->private; -        handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); -        dir_handle = alloca0 (handle_size); - -        snprintf (linkname_expected, handle_size, "../../%02x/%02x/%s/%s", -                  loc->pargfid[0], loc->pargfid[1], uuid_utoa (loc->pargfid), -                  loc->name); - -        MAKE_HANDLE_GFID_PATH (dir_handle, this, gfid, NULL); -        len = sys_readlink (dir_handle, linkname_actual, PATH_MAX); -        if (len < 0) -                goto out; -        linkname_actual[len] = '\0'; - -        if (!strncmp (linkname_actual, linkname_expected, handle_size)) -                ret = _gf_true; - -out: -        return ret; -} - -dict_t* -posix_dict_set_nlink (dict_t *req, dict_t *res, int32_t nlink) -{ -        int   ret  =  -1; - -        if (req == NULL || !dict_get (req, GF_REQUEST_LINK_COUNT_XDATA)) -                goto out; - -        if (res == NULL) -                res = dict_new (); -        if (res == NULL) -                goto out; - -        ret = dict_set_uint32 (res, GF_RESPONSE_LINK_COUNT_XDATA, nlink); -        if (ret == -1) -                gf_msg ("posix", GF_LOG_WARNING, 0, P_MSG_SET_XDATA_FAIL, -                        "Failed to set GF_RESPONSE_LINK_COUNT_XDATA"); -out: -        return res; -} - -int -posix_forget (xlator_t *this, inode_t *inode) -{ -        int                     ret         = 0; -        char                   *unlink_path = NULL; -        uint64_t                ctx_uint    = 0; -        posix_inode_ctx_t      *ctx         = NULL; -        struct posix_private   *priv_posix  = NULL; - -        priv_posix = (struct posix_private *) this->private; - -        ret = inode_ctx_del (inode, this, &ctx_uint); -        if (!ctx_uint) -                return 0; - -        ctx = (posix_inode_ctx_t *)ctx_uint; - -        if (ctx->unlink_flag == GF_UNLINK_TRUE) { -                POSIX_GET_FILE_UNLINK_PATH(priv_posix->base_path, -                                           inode->gfid, unlink_path); -                if (!unlink_path) { -                        gf_msg (this->name, GF_LOG_ERROR, ENOMEM, -                                P_MSG_UNLINK_FAILED, -                                "Failed to remove gfid :%s", -                                uuid_utoa (inode->gfid)); -                        ret = -1; -                        goto out; -                } -                ret = sys_unlink(unlink_path); -        } -out: -        pthread_mutex_destroy (&ctx->xattrop_lock); -        pthread_mutex_destroy (&ctx->write_atomic_lock); -        pthread_mutex_destroy (&ctx->pgfid_lock); -        GF_FREE (ctx); -        return ret; -} - -/* Regular fops */ - -int32_t -posix_lookup (call_frame_t *frame, xlator_t *this, -              loc_t *loc, dict_t *xdata) -{ -        struct iatt buf                = {0, }; -        int32_t     op_ret             = -1; -        int32_t     entry_ret          = 0; -        int32_t     op_errno           = 0; -        dict_t *    xattr              = NULL; -        char *      real_path          = NULL; -        char *      par_path           = NULL; -        struct iatt postparent         = {0,}; -        int32_t     gfidless           = 0; -        char        *pgfid_xattr_key   = NULL; -        int32_t     nlink_samepgfid    = 0; -        struct  posix_private *priv    = NULL; -        posix_inode_ctx_t *ctx         = NULL; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        priv = this->private; - -        /* The Hidden directory should be for housekeeping purpose and it -           should not get any gfid on it */ -        if (__is_root_gfid (loc->pargfid) && loc->name -            && (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { -                gf_msg (this->name, GF_LOG_WARNING, EPERM, -                        P_MSG_LOOKUP_NOT_PERMITTED, "Lookup issued on %s," -                        " which is not permitted", GF_HIDDEN_PATH); -                op_errno = EPERM; -                op_ret = -1; -                goto out; -        } - -        op_ret = dict_get_int32 (xdata, GF_GFIDLESS_LOOKUP, &gfidless); -        op_ret = -1; -        if (gf_uuid_is_null (loc->pargfid) || (loc->name == NULL)) { -                /* nameless lookup */ -                MAKE_INODE_HANDLE (real_path, this, loc, &buf); -        } else { -                MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &buf); - -                if (gf_uuid_is_null (loc->inode->gfid)) { -                        op_ret = posix_gfid_heal (this, real_path, loc, xdata); -                        if (op_ret < 0) { -                                op_errno = -op_ret; -                                op_ret = -1; -                                goto out; -                        } -                        MAKE_ENTRY_HANDLE (real_path, par_path, this, -                                           loc, &buf); -                } -        } - -        op_errno = errno; - -        if (op_ret == -1) { -                if (op_errno != ENOENT) { -                        gf_msg (this->name, GF_LOG_WARNING, op_errno, -                                P_MSG_LSTAT_FAILED, -                                "lstat on %s failed", -                                real_path ? real_path : "null"); -                } - -                entry_ret = -1; -                goto parent; -        } - -        if (xdata && (op_ret == 0)) { -                xattr = posix_xattr_fill (this, real_path, loc, NULL, -1, xdata, -                                          &buf); -        } - -        if (priv->update_pgfid_nlinks) { -                if (!gf_uuid_is_null (loc->pargfid) && !IA_ISDIR (buf.ia_type)) { -                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, -                                              PGFID_XATTR_KEY_PREFIX, -                                              loc->pargfid); - -                        op_ret = posix_inode_ctx_get_all (loc->inode, this, -                                                          &ctx); -                        if (op_ret < 0) { -                                op_errno = ENOMEM; -                                goto out; -                        } - -                        pthread_mutex_lock (&ctx->pgfid_lock); -                        { -                                SET_PGFID_XATTR_IF_ABSENT (real_path, -                                                           pgfid_xattr_key, -                                                           nlink_samepgfid, -                                                           XATTR_CREATE, op_ret, -                                                           this, unlock); -                        } -unlock: -                        pthread_mutex_unlock (&ctx->pgfid_lock); -                } -        } - -parent: -        if (par_path) { -                op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_LSTAT_FAILED, "post-operation lstat on" -                                " parent %s failed", par_path); -			if (op_errno == ENOENT) -				/* If parent directory is missing in a lookup, -				   errno should be ESTALE (bad handle) and not -				   ENOENT (missing entry) -				*/ -				op_errno = ESTALE; -                        goto out; -                } -        } - -        op_ret = entry_ret; -out: -        if (!op_ret && !gfidless && gf_uuid_is_null (buf.ia_gfid)) { -                gf_msg (this->name, GF_LOG_ERROR, ENODATA, P_MSG_NULL_GFID, -                        "buf->ia_gfid is null for " -                        "%s", (real_path) ? real_path: ""); -                op_ret = -1; -                op_errno = ENODATA; -        } - -        if (op_ret == 0) -                op_errno = 0; -        STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, -                             (loc)?loc->inode:NULL, &buf, xattr, &postparent); - -        if (xattr) -                dict_unref (xattr); - -        return 0; -} - - -int32_t -posix_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) -{ -        struct iatt           buf       = {0,}; -        int32_t               op_ret    = -1; -        int32_t               op_errno  = 0; -        struct posix_private *priv      = NULL; -        char                 *real_path = NULL; -        dict_t               *xattr_rsp = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        MAKE_INODE_HANDLE (real_path, this, loc, &buf); - -        if (op_ret == -1) { -                op_errno = errno; -                if (op_errno == ENOENT) { -                        gf_msg_debug(this->name, 0, "lstat on %s failed: %s", -                                     real_path ? real_path : "<null>", -                                     strerror (op_errno)); -                } else { -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_LSTAT_FAILED, "lstat on %s failed", -                                real_path ? real_path : "<null>"); -                } -                goto out; -        } -        if (xdata) -                xattr_rsp = posix_xattr_fill (this, real_path, loc, NULL, -1, -                                              xdata, &buf); - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID(); -        STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, &buf, xattr_rsp); -        if (xattr_rsp) -                dict_unref (xattr_rsp); - -        return 0; -} - -static inline mode_t override_umask (mode_t mode, mode_t mode_bit) -{ -        gf_msg_debug ("posix", 0, "The value of mode is %u", mode); -        mode = mode >> 9; /* 3x3 (bits for each octal digit)*/ -        mode = (mode << 9) | mode_bit; -        gf_msg_debug ("posix", 0, "The value of mode is %u", mode); -        return mode; -} - -static int -posix_do_chmod (xlator_t *this, const char *path, struct iatt *stbuf) -{ -        int32_t     ret = -1; -        mode_t      mode = 0; -        mode_t      mode_bit = 0; -        struct posix_private *priv = NULL; -        struct stat stat; -        int         is_symlink = 0; - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        ret = sys_lstat (path, &stat); -        if (ret != 0) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_LSTAT_FAILED, -                        "lstat failed: %s", path); -                goto out; -        } - -        if (S_ISLNK (stat.st_mode)) -                is_symlink = 1; - -        if (S_ISDIR (stat.st_mode)) { -                mode = st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type); -                mode_bit = (mode & priv->create_directory_mask) -                            | priv->force_directory_mode; -                mode = override_umask(mode, mode_bit); -        } else { -                mode = st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type); -                mode_bit = (mode & priv->create_mask) -                            | priv->force_create_mode; -                mode = override_umask(mode, mode_bit); -        } -        ret = lchmod (path, mode); -        if ((ret == -1) && (errno == ENOSYS)) { -                /* in Linux symlinks are always in mode 0777 and no -                   such call as lchmod exists. -                */ -                gf_msg_debug (this->name, 0, "%s (%s)", path, strerror (errno)); -                if (is_symlink) { -                        ret = 0; -                        goto out; -                } - -                ret = sys_chmod (path, mode); -        } -out: -        return ret; -} - -static int -posix_do_chown (xlator_t *this, -                const char *path, -                struct iatt *stbuf, -                int32_t valid) -{ -        int32_t ret = -1; -        uid_t uid = -1; -        gid_t gid = -1; - -        if (valid & GF_SET_ATTR_UID) -                uid = stbuf->ia_uid; - -        if (valid & GF_SET_ATTR_GID) -                gid = stbuf->ia_gid; - -        ret = sys_lchown (path, uid, gid); - -        return ret; -} - -static int -posix_do_utimes (xlator_t *this, -                 const char *path, -                 struct iatt *stbuf, -                 int valid) -{ -        int32_t ret = -1; -#if defined(HAVE_UTIMENSAT) -        struct timespec tv[2]    = { {0,}, {0,} }; -#else -        struct timeval tv[2]     = { {0,}, {0,} }; -#endif -        struct stat stat; -        int    is_symlink = 0; - -        ret = sys_lstat (path, &stat); -        if (ret != 0) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_FILE_OP_FAILED, "%s", path); -                goto out; -        } - -        if (S_ISLNK (stat.st_mode)) -                is_symlink = 1; - -        if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) { -                tv[0].tv_sec  = stbuf->ia_atime; -                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[0], stbuf->ia_atime_nsec); -        } else { -                /* atime is not given, use current values */ -                tv[0].tv_sec  = ST_ATIM_SEC (&stat); -                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[0], ST_ATIM_NSEC (&stat)); -        } - -        if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) { -                tv[1].tv_sec  = stbuf->ia_mtime; -                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[1], stbuf->ia_mtime_nsec); -        } else { -                /* mtime is not given, use current values */ -                tv[1].tv_sec  = ST_MTIM_SEC (&stat); -                SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv[1], ST_MTIM_NSEC (&stat)); -        } - -        ret = PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv); -        if ((ret == -1) && (errno == ENOSYS)) { -                gf_msg_debug (this->name, 0, "%s (%s)", -                        path, strerror (errno)); -                if (is_symlink) { -                        ret = 0; -                        goto out; -                } - -                ret = PATH_SET_TIMESPEC_OR_TIMEVAL(path, tv); -        } - -out: -        return ret; -} - -int -posix_setattr (call_frame_t *frame, xlator_t *this, -               loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) -{ -        int32_t        op_ret    = -1; -        int32_t        op_errno  = 0; -        char *         real_path = 0; -        struct iatt    statpre     = {0,}; -        struct iatt    statpost    = {0,}; -        dict_t        *xattr_rsp   = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); -        MAKE_INODE_HANDLE (real_path, this, loc, &statpre); - -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "setattr (lstat) on %s failed", -                        real_path ? real_path : "<null>"); -                goto out; -        } - -        if (valid & (GF_SET_ATTR_UID | GF_SET_ATTR_GID)){ -                op_ret = posix_do_chown (this, real_path, stbuf, valid); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_CHOWN_FAILED, "setattr (chown) on %s " -                                "failed", real_path); -                        goto out; -                } -        } - -        if (valid & GF_SET_ATTR_MODE) { -                op_ret = posix_do_chmod (this, real_path, stbuf); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_CHMOD_FAILED,  "setattr (chmod) on %s " -                                "failed", real_path); -                        goto out; -                } -        } - -        if (valid & (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME)) { -                op_ret = posix_do_utimes (this, real_path, stbuf, valid); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_UTIMES_FAILED, "setattr (utimes) on %s " -                                "failed", real_path); -                        goto out; -                } -        } - -        if (!valid) { -                op_ret = sys_lchown (real_path, -1, -1); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_LCHOWN_FAILED, "lchown (%s, -1, -1) " -                                "failed", real_path); - -                        goto out; -                } -        } - -        op_ret = posix_pstat (this, loc->gfid, real_path, &statpost); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "setattr (lstat) on %s failed", real_path); -                goto out; -        } - -        if (xdata) -                xattr_rsp = posix_xattr_fill (this, real_path, loc, NULL, -1, -                                              xdata, &statpost); -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, -                             &statpre, &statpost, xattr_rsp); -        if (xattr_rsp) -                dict_unref (xattr_rsp); - -        return 0; -} - -int32_t -posix_do_fchown (xlator_t *this, -                 int fd, -                 struct iatt *stbuf, -                 int32_t valid) -{ -        int   ret      = -1; -        uid_t uid = -1; -        gid_t gid = -1; - -        if (valid & GF_SET_ATTR_UID) -                uid = stbuf->ia_uid; - -        if (valid & GF_SET_ATTR_GID) -                gid = stbuf->ia_gid; - -        ret = sys_fchown (fd, uid, gid); - -        return ret; -} - - -int32_t -posix_do_fchmod (xlator_t *this, -                 int fd, struct iatt *stbuf) -{ -        int32_t     ret = -1; -        mode_t      mode = 0; -        mode_t      mode_bit = 0; -        struct posix_private *priv = NULL; - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        mode = st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type); -        mode_bit = (mode & priv->create_mask) -                    | priv->force_create_mode; -        mode = override_umask (mode, mode_bit); -        ret = sys_fchmod (fd, mode); -out: -        return ret; -} - -static int -posix_do_futimes (xlator_t *this, int fd, struct iatt *stbuf, int valid) -{ -        int32_t ret              =     -1; -        struct timeval tv[2]     =     { {0,}, {0,} }; -        struct stat stat         =     {0,}; - -        ret = sys_fstat (fd, &stat); -        if (ret != 0) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_FILE_OP_FAILED, "%d", fd); -                goto out; -        } - -        if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) { -                tv[0].tv_sec  = stbuf->ia_atime; -                tv[0].tv_usec = stbuf->ia_atime_nsec / 1000; -        } else { -                /* atime is not given, use current values */ -                tv[0].tv_sec  = ST_ATIM_SEC (&stat); -                tv[0].tv_usec = ST_ATIM_NSEC (&stat) / 1000; -        } - -        if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) { -                tv[1].tv_sec  = stbuf->ia_mtime; -                tv[1].tv_usec = stbuf->ia_mtime_nsec / 1000; -        } else { -                /* mtime is not given, use current values */ -                tv[1].tv_sec  = ST_MTIM_SEC (&stat); -                tv[1].tv_usec = ST_MTIM_NSEC (&stat) / 1000; -        } - -        ret = sys_futimes (fd, tv); -        if (ret == -1) -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FUTIMES_FAILED, -                        "%d", fd); - -out: -        return ret; -} - -int -posix_fsetattr (call_frame_t *frame, xlator_t *this, -                fd_t *fd, struct iatt *stbuf, int32_t valid, dict_t *xdata) -{ -        int32_t        op_ret    = -1; -        int32_t        op_errno  = 0; -        struct iatt    statpre     = {0,}; -        struct iatt    statpost    = {0,}; -        struct posix_fd *pfd = NULL; -        dict_t          *xattr_rsp = NULL; -        int32_t          ret = -1; - -        DECLARE_OLD_FS_ID_VAR; - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        op_ret = posix_fdstat (this, pfd->fd, &statpre); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fsetattr (fstat) failed on fd=%p", fd); -                goto out; -        } - -        if (valid & (GF_SET_ATTR_UID | GF_SET_ATTR_GID)) { -                op_ret = posix_do_fchown (this, pfd->fd, stbuf, valid); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FCHOWN_FAILED, "fsetattr (fchown) failed" -                                " on fd=%p", fd); -                        goto out; -                } - -        } - -        if (valid & GF_SET_ATTR_MODE) { -                op_ret = posix_do_fchmod (this, pfd->fd, stbuf); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FCHMOD_FAILED, "fsetattr (fchmod) failed" -                                " on fd=%p", fd); -                        goto out; -                } -        } - -        if (valid & (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME)) { -                op_ret = posix_do_futimes (this, pfd->fd, stbuf, valid); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FUTIMES_FAILED, "fsetattr (futimes) on " -                                "failed fd=%p", fd); -                        goto out; -                } -        } - -        if (!valid) { -                op_ret = sys_fchown (pfd->fd, -1, -1); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FCHOWN_FAILED, -                                "fchown (%d, -1, -1) failed", -                                pfd->fd); - -                        goto out; -                } -        } - -        op_ret = posix_fdstat (this, pfd->fd, &statpost); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fsetattr (fstat) failed on fd=%p", fd); -                goto out; -        } - -        if (xdata) -                xattr_rsp = posix_xattr_fill (this, NULL, NULL, fd, pfd->fd, -                                              xdata, &statpost); -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, -                             &statpre, &statpost, xattr_rsp); -        if (xattr_rsp) -                dict_unref (xattr_rsp); - -        return 0; -} - -static int32_t -posix_do_fallocate (call_frame_t *frame, xlator_t *this, fd_t *fd, -                    int32_t flags, off_t offset, size_t len, -                    struct iatt *statpre, struct iatt *statpost, dict_t *xdata) -{ -        int32_t             ret    = -1; -        int32_t             op_errno = 0; -        struct posix_fd    *pfd    = NULL; -        gf_boolean_t        locked = _gf_false; -        posix_inode_ctx_t  *ctx    = NULL; -        struct  posix_private *priv = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, ret, ret, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        ret = posix_inode_ctx_get_all (fd->inode, this, &ctx); -        if (ret < 0) { -                ret = -ENOMEM; -                goto out; -        } - -        if (xdata && dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) { -                locked = _gf_true; -                pthread_mutex_lock (&ctx->write_atomic_lock); -        } - -        ret = posix_fdstat (this, pfd->fd, statpre); -        if (ret == -1) { -                ret = -errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fallocate (fstat) failed on fd=%p", fd); -                goto out; -        } - -        ret = sys_fallocate (pfd->fd, flags, offset, len); -        if (ret == -1) { -                ret = -errno; -                gf_msg (this->name, GF_LOG_ERROR, -ret, P_MSG_FALLOCATE_FAILED, -                        "fallocate failed on %s offset: %jd, " -                        "len:%zu, flags: %d", uuid_utoa (fd->inode->gfid), -                        offset, len, flags); -                goto out; -        } - -        ret = posix_fdstat (this, pfd->fd, statpost); -        if (ret == -1) { -                ret = -errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fallocate (fstat) failed on fd=%p", fd); -                goto out; -        } - -out: -        if (locked) { -                pthread_mutex_unlock (&ctx->write_atomic_lock); -                locked = _gf_false; -        } -        SET_TO_OLD_FS_ID (); -        if (ret == ENOSPC) -                ret = -ENOSPC; - -        return ret; -} - -char* -_page_aligned_alloc (size_t size, char **aligned_buf) -{ -        char            *alloc_buf = NULL; -        char            *buf = NULL; - -        alloc_buf = GF_CALLOC (1, (size + ALIGN_SIZE), gf_posix_mt_char); -        if (!alloc_buf) -                goto out; -        /* page aligned buffer */ -        buf = GF_ALIGN_BUF (alloc_buf, ALIGN_SIZE); -        *aligned_buf = buf; -out: -        return alloc_buf; -} - -static int32_t -_posix_do_zerofill(int fd, off_t offset, off_t len, int o_direct) -{ -        off_t               num_vect            = 0; -        off_t               num_loop            = 1; -        off_t               idx                 = 0; -        int32_t             op_ret              = -1; -        int32_t             vect_size           = VECTOR_SIZE; -        off_t               remain              = 0; -        off_t               extra               = 0; -        struct iovec       *vector              = NULL; -        char               *iov_base            = NULL; -        char               *alloc_buf           = NULL; - -        if (len == 0) -                return 0; -        if (len < VECTOR_SIZE) -                vect_size = len; - -        num_vect = len / (vect_size); -        remain = len % vect_size ; -        if (num_vect > MAX_NO_VECT) { -                extra = num_vect % MAX_NO_VECT; -                num_loop = num_vect / MAX_NO_VECT; -                num_vect = MAX_NO_VECT; -        } - -        vector = GF_CALLOC (num_vect, sizeof(struct iovec), -                             gf_common_mt_iovec); -        if (!vector) -                  return -1; -        if (o_direct) { -                alloc_buf = _page_aligned_alloc(vect_size, &iov_base); -                if (!alloc_buf) { -                        GF_FREE(vector); -                        return -1; -                } -        } else { -                iov_base = GF_CALLOC (vect_size, sizeof(char), -                                        gf_common_mt_char); -                if (!iov_base) { -                        GF_FREE(vector); -                        return -1; -                 } -        } - -        for (idx = 0; idx < num_vect; idx++) { -                vector[idx].iov_base = iov_base; -                vector[idx].iov_len  = vect_size; -        } -        if (sys_lseek (fd, offset, SEEK_SET) < 0) { -                op_ret = -1; -                goto err; -        } - -        for (idx = 0; idx < num_loop; idx++) { -                op_ret = sys_writev (fd, vector, num_vect); -                if (op_ret < 0) -                        goto err; -        } -        if (extra) { -                op_ret = sys_writev (fd, vector, extra); -                if (op_ret < 0) -                        goto err; -        } -        if (remain) { -                vector[0].iov_len = remain; -                op_ret = sys_writev (fd, vector , 1); -                if (op_ret < 0) -                        goto err; -        } -err: -        if (o_direct) -                GF_FREE(alloc_buf); -        else -                GF_FREE(iov_base); -        GF_FREE(vector); -        return op_ret; -} - -static int32_t -posix_do_zerofill (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, -                   off_t len, struct iatt *statpre, struct iatt *statpost, -                   dict_t *xdata) -{ -        int32_t            ret       = -1; -        int32_t            op_errno  = 0; -        int32_t            flags     = 0; -        struct posix_fd   *pfd       = NULL; -        gf_boolean_t       locked    = _gf_false; -        posix_inode_ctx_t *ctx       = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        ret = posix_inode_ctx_get_all (fd->inode, this, &ctx); -        if (ret < 0) { -                ret = -ENOMEM; -                goto out; -        } - -        if (dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) { -                locked = _gf_true; -                pthread_mutex_lock (&ctx->write_atomic_lock); -        } - -        ret = posix_fdstat (this, pfd->fd, statpre); -        if (ret == -1) { -                ret = -errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "pre-operation fstat failed on fd = %p", fd); -                goto out; -        } - -        /* See if we can use FALLOC_FL_ZERO_RANGE to perform the zero fill. -         * If it fails, fall back to _posix_do_zerofill() and an optional fsync. -         */ -        flags = FALLOC_FL_ZERO_RANGE; -        ret = sys_fallocate (pfd->fd, flags, offset, len); -        if (ret == 0) -                goto fsync; - -        ret = _posix_do_zerofill (pfd->fd, offset, len, pfd->flags & O_DIRECT); -        if (ret < 0) { -                ret = -errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ZEROFILL_FAILED, -                       "zerofill failed on fd %d length %" PRId64 , -                        pfd->fd, len); -                goto out; -        } - -fsync: -        if (pfd->flags & (O_SYNC|O_DSYNC)) { -                ret = sys_fsync (pfd->fd); -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_WRITEV_FAILED, "fsync() in writev on fd" -                                "%d failed", pfd->fd); -                        ret = -errno; -                        goto out; -                } -        } - -        ret = posix_fdstat (this, pfd->fd, statpost); -        if (ret == -1) { -                ret = -errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "post operation fstat failed on fd=%p", fd); -                goto out; -        } - -out: -	if (locked) { -		pthread_mutex_unlock (&ctx->write_atomic_lock); -		locked = _gf_false; -	} -        SET_TO_OLD_FS_ID (); - -        return ret; -} - -static int32_t -_posix_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t keep_size, -		off_t offset, size_t len, dict_t *xdata) -{ -	int32_t ret; -	int32_t flags = 0; -        struct iatt statpre = {0,}; -        struct iatt statpost = {0,}; - -#ifdef FALLOC_FL_KEEP_SIZE -	if (keep_size) -		flags = FALLOC_FL_KEEP_SIZE; -#endif /* FALLOC_FL_KEEP_SIZE */ - -	ret = posix_do_fallocate (frame, this, fd, flags, offset, len, -				  &statpre, &statpost, xdata); -	if (ret < 0) -		goto err; - -	STACK_UNWIND_STRICT(fallocate, frame, 0, 0, &statpre, &statpost, NULL); -	return 0; - -err: -	STACK_UNWIND_STRICT(fallocate, frame, -1, -ret, NULL, NULL, NULL); -	return 0; -} - -static int32_t -posix_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, -	      size_t len, dict_t *xdata) -{ -	int32_t ret; -#ifndef FALLOC_FL_KEEP_SIZE -	ret = EOPNOTSUPP; - -#else /* FALLOC_FL_KEEP_SIZE */ -	int32_t flags = FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE; -        struct iatt statpre = {0,}; -        struct iatt statpost = {0,}; - -	ret = posix_do_fallocate (frame, this, fd, flags, offset, len, -				  &statpre, &statpost, xdata); -	if (ret < 0) -		goto err; - -	STACK_UNWIND_STRICT(discard, frame, 0, 0, &statpre, &statpost, NULL); -	return 0; - -err: -#endif /* FALLOC_FL_KEEP_SIZE */ -	STACK_UNWIND_STRICT(discard, frame, -1, -ret, NULL, NULL, NULL); -	return 0; -} - -static int32_t -posix_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, -                off_t len, dict_t *xdata) -{ -        int32_t ret                      =  0; -        struct  iatt statpre             = {0,}; -        struct  iatt statpost            = {0,}; -        struct  posix_private *priv      = NULL; -        int     op_ret                   = -1; -        int     op_errno                 = -EINVAL; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); - -        priv = this->private; -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        ret = posix_do_zerofill (frame, this, fd, offset, len, -                                 &statpre, &statpost, xdata); -        if (ret < 0) { -                op_ret = -1; -                op_errno = -ret; -                goto out; -        } - -        STACK_UNWIND_STRICT(zerofill, frame, 0, 0, &statpre, &statpost, NULL); -        return 0; - -out: -        STACK_UNWIND_STRICT(zerofill, frame, op_ret, op_errno, NULL, NULL, NULL); -        return 0; -} - -static int32_t -posix_ipc (call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata) -{ -        /* -         * IPC is for inter-translator communication.  If one gets here, it -         * means somebody sent one that nobody else recognized, which is an -         * error much like an uncaught exception. -         */ -        gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_IPC_NOT_HANDLE, -                "GF_LOG_IPC(%d) not handled", op); -        STACK_UNWIND_STRICT (ipc, frame, -1, -EOPNOTSUPP, NULL); -        return 0; - -} - -#ifdef HAVE_SEEK_HOLE -static int32_t -posix_seek (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, -            gf_seek_what_t what, dict_t *xdata) -{ -        struct posix_fd *pfd       = NULL; -        off_t            ret       = -1; -        int              err       = 0; -        int              whence    = 0; - -        DECLARE_OLD_FS_ID_VAR; - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        switch (what) { -        case GF_SEEK_DATA: -                whence = SEEK_DATA; -                break; -        case GF_SEEK_HOLE: -                whence = SEEK_HOLE; -                break; -        default: -                err = ENOTSUP; -                gf_msg (this->name, GF_LOG_ERROR, ENOTSUP, -                        P_MSG_SEEK_UNKOWN, "don't know what to seek"); -                goto out; -        } - -        ret = posix_fd_ctx_get (fd, this, &pfd, &err); -        if (ret < 0) { -                gf_msg_debug (this->name, 0, "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        ret = sys_lseek (pfd->fd, offset, whence); -        if (ret == -1) { -                err = errno; -                gf_msg (this->name, GF_LOG_ERROR, err, P_MSG_SEEK_FAILED, -                        "seek failed on fd %d length %" PRId64 , pfd->fd, -                        offset); -                goto out; -        } - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (seek, frame, (ret == -1 ? -1 : 0), err, -                             (ret == -1 ? -1 : ret), xdata); -        return 0; -} -#endif - -int32_t -posix_opendir (call_frame_t *frame, xlator_t *this, -               loc_t *loc, fd_t *fd, dict_t *xdata) -{ -        char *            real_path = NULL; -        int32_t           op_ret    = -1; -        int32_t           op_errno  = EINVAL; -        DIR *             dir       = NULL; -        struct posix_fd * pfd       = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); -        VALIDATE_OR_GOTO (fd, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); -        MAKE_INODE_HANDLE (real_path, this, loc, NULL); -        if (!real_path) { -                op_errno = ESTALE; -                goto out; -        } - -        op_ret = -1; -        dir = sys_opendir (real_path); - -        if (dir == NULL) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_OPENDIR_FAILED, -                        "opendir failed on %s", real_path); -                goto out; -        } - -        op_ret = dirfd (dir); -        if (op_ret < 0) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_DIRFD_FAILED, -                        "dirfd() failed on %s", real_path); -                goto out; -        } - -        pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); -        if (!pfd) { -                op_errno = errno; -                goto out; -        } - -        pfd->dir = dir; -        pfd->dir_eof = -1; -        pfd->fd = op_ret; - -        op_ret = fd_ctx_set (fd, this, (uint64_t)(long)pfd); -        if (op_ret) -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_FD_PATH_SETTING_FAILED, "failed to set the fd" -                        "context path=%s fd=%p", real_path, fd); - -        op_ret = 0; - -out: -        if (op_ret == -1) { -                if (dir) { -                        (void) sys_closedir (dir); -                        dir = NULL; -                } -                if (pfd) { -                        GF_FREE (pfd); -                        pfd = NULL; -                } -        } - -        SET_TO_OLD_FS_ID (); -        STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd, NULL); -        return 0; -} - -int32_t -posix_releasedir (xlator_t *this, -                  fd_t *fd) -{ -        struct posix_fd * pfd      = NULL; -        uint64_t          tmp_pfd  = 0; -        int               ret      = 0; - -        struct posix_private *priv = NULL; - -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        ret = fd_ctx_del (fd, this, &tmp_pfd); -        if (ret < 0) { -                gf_msg_debug (this->name, 0, "pfd from fd=%p is NULL", fd); -                goto out; -        } - -        pfd = (struct posix_fd *)(long)tmp_pfd; -        if (!pfd->dir) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_PFD_NULL, -                        "pfd->dir is NULL for fd=%p", fd); -                goto out; -        } - -        priv = this->private; - -        pthread_mutex_lock (&priv->janitor_lock); -        { -                INIT_LIST_HEAD (&pfd->list); -                list_add_tail (&pfd->list, &priv->janitor_fds); -                pthread_cond_signal (&priv->janitor_cond); -        } -        pthread_mutex_unlock (&priv->janitor_lock); - -out: -        return 0; -} - - -int32_t -posix_readlink (call_frame_t *frame, xlator_t *this, -                loc_t *loc, size_t size, dict_t *xdata) -{ -        char *  dest      = NULL; -        int32_t op_ret    = -1; -        int32_t op_errno  = 0; -        char *  real_path = NULL; -        struct iatt stbuf = {0,}; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        dest = alloca (size + 1); - -        MAKE_INODE_HANDLE (real_path, this, loc, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat on %s failed", -                        loc->path ? loc->path : "<null>"); -                goto out; -        } - -        op_ret = sys_readlink (real_path, dest, size); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_READYLINK_FAILED, -                        "readlink on %s failed", real_path); -                goto out; -        } - -        dest[op_ret] = 0; -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (readlink, frame, op_ret, op_errno, dest, &stbuf, NULL); - -        return 0; -} - - -int -posix_mknod (call_frame_t *frame, xlator_t *this, -             loc_t *loc, mode_t mode, dev_t dev, mode_t umask, dict_t *xdata) -{ -        int                   tmp_fd          = 0; -        int32_t               op_ret          = -1; -        int32_t               op_errno        = 0; -        char                 *real_path       = 0; -        char                 *par_path        = 0; -        struct iatt           stbuf           = { 0, }; -        struct posix_private *priv            = NULL; -        gid_t                 gid             = 0; -        struct iatt           preparent       = {0,}; -        struct iatt           postparent      = {0,}; -        void *                uuid_req        = NULL; -        int32_t               nlink_samepgfid = 0; -        char                 *pgfid_xattr_key = NULL; -        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; -        gf_boolean_t          linked          = _gf_false; -        gf_loglevel_t         level           = GF_LOG_NONE; -        mode_t                mode_bit        = 0; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, -                                  out); -        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, NULL); - -        mode_bit = (priv->create_mask & mode) | priv->force_create_mode; -        mode = override_umask (mode, mode_bit); - -        gid = frame->root->gid; - -        SET_FS_ID (frame->root->uid, gid); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); -        if (!real_path || !par_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent of %s failed", -                        real_path); -                goto out; -        } - -        if (preparent.ia_prot.sgid) { -                gid = preparent.ia_gid; -        } - -        /* Check if the 'gfid' already exists, because this mknod may be an -           internal call from distribute for creating 'linkfile', and that -           linkfile may be for a hardlinked file */ -        if (dict_get (xdata, GLUSTERFS_INTERNAL_FOP_KEY)) { -                dict_del (xdata, GLUSTERFS_INTERNAL_FOP_KEY); -                op_ret = dict_get_ptr (xdata, "gfid-req", &uuid_req); -                if (op_ret) { -                        gf_msg_debug (this->name, 0, "failed to get the gfid from " -                                "dict for %s", loc->path); -                        goto real_op; -                } -                op_ret = posix_create_link_if_gfid_exists (this, uuid_req, -                                                           real_path, -                                                           loc->inode->table); -                if (!op_ret) { -                        linked = _gf_true; -                        goto post_op; -                } -        } - -real_op: -#ifdef __NetBSD__ -        if (S_ISFIFO(mode)) -                op_ret = mkfifo (real_path, mode); -        else -#endif /* __NetBSD__ */ -        op_ret = sys_mknod (real_path, mode, dev); - -        if (op_ret == -1) { -                op_errno = errno; -                if ((op_errno == EINVAL) && S_ISREG (mode)) { -                        /* Over Darwin, mknod with (S_IFREG|mode) -                           doesn't work */ -                        tmp_fd = sys_creat (real_path, mode); -                        if (tmp_fd == -1) { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_CREATE_FAILED, "create failed on" -                                        "%s", real_path); -                                goto out; -                        } -                        sys_close (tmp_fd); -                } else { -                        if (op_errno == EEXIST) -                                level = GF_LOG_DEBUG; -                        else -                                level = GF_LOG_ERROR; -                        gf_msg (this->name, level, errno, P_MSG_MKNOD_FAILED, -                                "mknod on %s failed", real_path); -                        goto out; -                } -        } - -        entry_created = _gf_true; - -#ifndef HAVE_SET_FSID -        op_ret = sys_lchown (real_path, frame->root->uid, gid); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LCHOWN_FAILED, -                        "lchown on %s failed", real_path); -                goto out; -        } -#endif - -post_op: -        op_ret = posix_acl_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_ACL_FAILED, -                        "setting ACLs on %s failed", real_path); -        } - -        if (priv->update_pgfid_nlinks) { -                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, -                                      loc->pargfid); -                nlink_samepgfid = 1; - -                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, -                                 XATTR_CREATE, op_ret, this, ignore); -        } - -        if (priv->gfid2path) { -                posix_set_gfid2path_xattr (this, real_path, loc->pargfid, -                                           loc->name); -        } - -ignore: -        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); -        if (op_ret) { -                if (errno != EEXIST) -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_XATTR_FAILED, -                                "setting xattrs on %s failed", real_path); -                else -                        gf_msg_debug (this->name, 0, -                                      "setting xattrs on %s failed", real_path); -        } - -        if (!linked) { -                op_ret = posix_gfid_set (this, real_path, loc, xdata); -                if (op_ret) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, -                                "setting gfid on %s failed", real_path); -                } else { -                        gfid_set = _gf_true; -                } -        } - -        op_ret = posix_pstat (this, NULL, real_path, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_MKNOD_FAILED, -                        "mknod on %s failed", real_path); -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, -                             (loc)?loc->inode:NULL, &stbuf, &preparent, -                             &postparent, NULL); - -        if (op_ret < 0) { -                if (entry_created) { -                        if (S_ISREG (mode)) -                                sys_unlink (real_path); -                        else -                                sys_rmdir (real_path); -                } - -                if (gfid_set) -                        posix_gfid_unset (this, xdata); -        } - -        return 0; -} - -int -posix_mkdir (call_frame_t *frame, xlator_t *this, -             loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata) -{ -        int32_t               op_ret          = -1; -        int32_t               op_errno        = 0; -        char                 *real_path       = NULL, *gfid_path = NULL; -        char                 *par_path        = NULL, *xattr_name = NULL; -        struct iatt           stbuf           = {0, }; -        struct posix_private *priv            = NULL; -        gid_t                 gid             = 0; -        struct iatt           preparent       = {0,}; -        struct iatt           postparent      = {0,}; -        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; -        void                 *uuid_req        = NULL; -        ssize_t               size            = 0; -        dict_t               *xdata_rsp       = NULL; -        void                 *disk_xattr      = NULL; -        data_t               *arg_data        = NULL; -        char          pgfid[GF_UUID_BUF_SIZE] = {0}; -        char                 value_buf[4096]  = {0,}; -        gf_boolean_t         have_val         = _gf_false; -        mode_t               mode_bit         = 0; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        /* The Hidden directory should be for housekeeping purpose and it -           should not get created from a user request */ -        if (__is_root_gfid (loc->pargfid) && -            (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { -                gf_msg (this->name, GF_LOG_WARNING, EPERM, -                        P_MSG_MKDIR_NOT_PERMITTED, "mkdir issued on %s, which" -                        "is not permitted", GF_HIDDEN_PATH); -                op_errno = EPERM; -                op_ret = -1; -                goto out; -        } - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, -                                  out); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, NULL); -        if (!real_path || !par_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        if (loc->parent) -                gf_uuid_unparse (loc->parent->gfid, pgfid); -        else -                gf_uuid_unparse (loc->pargfid, pgfid); - -        gid = frame->root->gid; - -        op_ret = posix_pstat (this, NULL, real_path, &stbuf); - -        SET_FS_ID (frame->root->uid, gid); - -        mode_bit = (priv->create_directory_mask & mode) -                   | priv->force_directory_mode; -        mode = override_umask (mode, mode_bit); - -        if (xdata) { -                op_ret = dict_get_ptr (xdata, "gfid-req", &uuid_req); -                if (!op_ret && !gf_uuid_compare (stbuf.ia_gfid, uuid_req)) { -                        op_ret = -1; -                        op_errno = EEXIST; -                        goto out; -                } -        } - -        if (uuid_req && !gf_uuid_is_null (uuid_req)) { -                op_ret = posix_istat (this, uuid_req, NULL, &stbuf); -                if ((op_ret == 0) && IA_ISDIR (stbuf.ia_type)) { -                        size = posix_handle_path (this, uuid_req, NULL, NULL, -                                                  0); -                        if (size > 0) -                                gfid_path = alloca (size); - -                        if (gfid_path) -                                posix_handle_path (this, uuid_req, NULL, -                                                   gfid_path, size); - -                        if (frame->root->pid != GF_CLIENT_PID_SELF_HEALD) { -                                gf_msg (this->name, GF_LOG_WARNING, 0, -                                        P_MSG_DIR_OF_SAME_ID, "mkdir (%s): " -                                        "gfid (%s) is already associated with " -                                        "directory (%s). Hence, both " -                                        "directories will share same gfid and " -                                        "this can lead to inconsistencies.", -                                        loc->path, uuid_utoa (uuid_req), -                                        gfid_path ? gfid_path : "<NULL>"); - -                                gf_event (EVENT_POSIX_SAME_GFID, "gfid=%s;" -                                          "path=%s;newpath=%s;brick=%s:%s", -                                          uuid_utoa (uuid_req), -                                          gfid_path ? gfid_path : "<NULL>", -                                          loc->path, priv->hostname, -                                          priv->base_path); -                        } -                        if (!posix_symlinks_match (this, loc, uuid_req)) -                                /* For afr selfheal of dir renames, we need to -                                 * remove the old symlink in order for -                                 * posix_gfid_set to set the symlink to the -                                 * new dir.*/ -                                posix_handle_unset (this, stbuf.ia_gfid, NULL); -                } -        } else if (!uuid_req && frame->root->pid != GF_SERVER_PID_TRASH) { -                op_ret = -1; -                op_errno = EPERM; -                gf_msg_callingfn (this->name, GF_LOG_WARNING, op_errno, -                        P_MSG_NULL_GFID, "mkdir (%s): is issued without " -                        "gfid-req %p", loc->path, xdata); -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        if (preparent.ia_prot.sgid) { -                gid = preparent.ia_gid; -                mode |= S_ISGID; -        } - -        op_ret = dict_get_str (xdata, GF_PREOP_PARENT_KEY, &xattr_name); -        if (xattr_name != NULL) { -                arg_data = dict_get (xdata, xattr_name); -                if (arg_data) { -                        size = sys_lgetxattr (par_path, xattr_name, value_buf, -                                              sizeof(value_buf) - 1); -                        if (size >= 0) { -                                have_val = _gf_true; -                        } else { -                                if (errno == ERANGE) { -                                        gf_msg (this->name, GF_LOG_INFO, errno, -                                                P_MSG_PREOP_CHECK_FAILED, -                                                "mkdir (%s/%s): getxattr on key " -                                                "(%s) path (%s) failed due to " -                                                " buffer overflow", pgfid, -                                                loc->name, xattr_name, -                                                par_path); -                                        size = sys_lgetxattr (par_path, -                                                              xattr_name, NULL, -                                                              0); -                                } -                                if (size < 0) { -                                        op_ret = -1; -                                        op_errno = errno; -                                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                                P_MSG_PREOP_CHECK_FAILED, -                                                "mkdir (%s/%s): getxattr on key (%s)" -                                                " path (%s) failed ", pgfid, -                                                loc->name, xattr_name, -                                                par_path); -                                        goto out; -                                } -                        } -                        disk_xattr = alloca (size); -                        if (disk_xattr == NULL) { -                                op_ret = -1; -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_PREOP_CHECK_FAILED, -                                        "mkdir (%s/%s): alloca failed during" -                                        " preop of mkdir (%s)", pgfid, -                                        loc->name, real_path); -                                goto out; -                        } -                        if (have_val) { -                                memcpy (disk_xattr, value_buf, size); -                        } else { -                                size = sys_lgetxattr (par_path, xattr_name, -                                                      disk_xattr, size); -                                if (size < 0) { -                                        op_errno = errno; -                                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                                P_MSG_PREOP_CHECK_FAILED, -                                                "mkdir (%s/%s): getxattr on " -                                                " key (%s) path (%s) failed " -                                                "(%s)", pgfid, loc->name, -                                                xattr_name, par_path, -                                                strerror (errno)); -                                        goto out; -                               } -                        } -                        if ((arg_data->len != size) -                            || (memcmp (arg_data->data, disk_xattr, size))) { -                                gf_msg (this->name, GF_LOG_INFO, EIO, -                                        P_MSG_PREOP_CHECK_FAILED, -                                        "mkdir (%s/%s): failing preop of " -                                        "mkdir (%s) as on-disk" -                                        " xattr value differs from argument " -                                        "value for key %s", pgfid, loc->name, -                                        real_path, xattr_name); -                                op_ret = -1; -                                op_errno = EIO; - -                                xdata_rsp = dict_new (); -                                if (xdata_rsp == NULL) { -                                        gf_msg (this->name, GF_LOG_ERROR, -                                                ENOMEM, -                                                P_MSG_PREOP_CHECK_FAILED, -                                                "mkdir (%s/%s):  " -                                                "dict allocation failed", pgfid, -                                                loc->name); -                                        op_errno = ENOMEM; -                                        goto out; -                                } - -                                op_errno = dict_set_int8 (xdata_rsp, -                                                          GF_PREOP_CHECK_FAILED, 1); -                                goto out; -                        } - -                        dict_del (xdata, xattr_name); -                } - -                dict_del (xdata, GF_PREOP_PARENT_KEY); -        } - -        op_ret = sys_mkdir (real_path, mode); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_MKDIR_FAILED, -                        "mkdir of %s failed", real_path); -                goto out; -        } - -        entry_created = _gf_true; - -#ifndef HAVE_SET_FSID -        op_ret = sys_chown (real_path, frame->root->uid, gid); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_CHOWN_FAILED, -                        "chown on %s failed", real_path); -                goto out; -        } -#endif -        op_ret = posix_acl_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACL_FAILED, -                        "setting ACLs on %s failed ", real_path); -        } - -        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, -                        "setting xattrs on %s failed", real_path); -        } - -        op_ret = posix_gfid_set (this, real_path, loc, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, -                        "setting gfid on %s failed", real_path); -        } else { -                gfid_set = _gf_true; -        } - -        op_ret = posix_pstat (this, NULL, real_path, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat on %s failed", real_path); -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent of %s failed", -                        real_path); -                goto out; -        } - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, -                             (loc)?loc->inode:NULL, &stbuf, &preparent, -                             &postparent, xdata_rsp); - -        if (op_ret < 0) { -                if (entry_created) -                        sys_rmdir (real_path); - -                if (gfid_set) -                        posix_gfid_unset (this, xdata); -        } - -        if (xdata_rsp) -                dict_unref (xdata_rsp); - -        return 0; -} - -int -posix_add_unlink_to_ctx (inode_t *inode, xlator_t *this, char *unlink_path) -{ -        uint64_t ctx = GF_UNLINK_FALSE; -        int ret = 0; - -        if (!unlink_path) { -                gf_msg (this->name, GF_LOG_ERROR, ENOMEM, -                        P_MSG_UNLINK_FAILED, -                        "Creation of unlink entry failed for gfid: %s", -                        unlink_path); -                ret = -1; -                goto out; -        } - -        ctx = GF_UNLINK_TRUE; -        ret = posix_inode_ctx_set_unlink_flag (inode, this, ctx); -        if (ret < 0) { -                goto out; -        } - -out: -        return ret; -} - -int32_t -posix_move_gfid_to_unlink (xlator_t *this, uuid_t gfid, loc_t *loc) -{ -        char *unlink_path = NULL; -        char *gfid_path = NULL; -        int ret = 0; -        struct posix_private    *priv_posix = NULL; - -        priv_posix = (struct posix_private *) this->private; - -        MAKE_HANDLE_GFID_PATH (gfid_path, this, gfid, NULL); - -        POSIX_GET_FILE_UNLINK_PATH (priv_posix->base_path, -                                    loc->inode->gfid, unlink_path); -        if (!unlink_path) { -                ret = -1; -                goto out; -        } -        gf_msg_debug (this->name, 0, -                      "Moving gfid: %s to unlink_path : %s", -                      gfid_path, unlink_path); -        ret = sys_rename (gfid_path, unlink_path); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_UNLINK_FAILED, -                        "Creation of unlink entry failed for gfid: %s", -                        unlink_path); -                goto out; -        } -        ret = posix_add_unlink_to_ctx (loc->inode, this, unlink_path); -        if (ret < 0) -                goto out; - -out: -        return ret; -} - -int32_t -posix_unlink_gfid_handle_and_entry (xlator_t *this, const char *real_path, -                                    struct iatt *stbuf, int32_t *op_errno, -                                    loc_t *loc, gf_boolean_t get_link_count, -                                    dict_t *rsp_dict) -{ -        int32_t                ret      = 0; -        struct iatt            prebuf   = {0,}; -        gf_boolean_t           locked   = _gf_false; - -        /*  Unlink the gfid_handle_first */ -        if (stbuf && stbuf->ia_nlink == 1) { - -                LOCK (&loc->inode->lock); - -                if (loc->inode->fd_count == 0) { -                        UNLOCK (&loc->inode->lock); -                        ret = posix_handle_unset (this, stbuf->ia_gfid, NULL); -                } else { -                        UNLOCK (&loc->inode->lock); -                        ret = posix_move_gfid_to_unlink (this, stbuf->ia_gfid, -                                                         loc); -                } -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_UNLINK_FAILED, "unlink of gfid handle " -                                "failed for path:%s with gfid %s", -                                real_path, uuid_utoa (stbuf->ia_gfid)); -                } -        } - -        if (get_link_count) { -                LOCK (&loc->inode->lock); -                locked = _gf_true; -                ret = posix_pstat (this, loc->gfid, real_path, &prebuf); -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_LSTAT_FAILED, "lstat on %s failed", -                                real_path); -                        goto err; -                } -        } - -        /* Unlink the actual file */ -        ret = sys_unlink (real_path); -        if (ret == -1) { -                if (op_errno) -                        *op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_UNLINK_FAILED, -                        "unlink of %s failed", real_path); -                goto err; -        } - -        if (locked) { -                UNLOCK (&loc->inode->lock); -                locked = _gf_false; -        } - -        ret = dict_set_uint32 (rsp_dict, GET_LINK_COUNT, prebuf.ia_nlink); -        if (ret) -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_SET_XDATA_FAIL, -                        "failed to set "GET_LINK_COUNT" for %s", real_path); - -        return 0; - -err: -        if (locked) { -                UNLOCK (&loc->inode->lock); -                locked = _gf_false; -        } -        return -1; -} - -static -int32_t posix_set_iatt_in_dict (dict_t *dict, struct iatt *in_stbuf) -{ -        int ret             = -1; -        struct iatt *stbuf  = NULL; -        int32_t len         = sizeof(struct iatt); - -        if (!dict || !in_stbuf) -                return ret; - -        stbuf = GF_CALLOC (1, len, gf_common_mt_char); -        if (!stbuf) -                return ret; - -        memcpy (stbuf, in_stbuf, len); - -        ret = dict_set_bin (dict, DHT_IATT_IN_XDATA_KEY, stbuf, len); -        if (ret) -                GF_FREE (stbuf); - -        return ret; -} - -gf_boolean_t -posix_skip_non_linkto_unlink (dict_t *xdata, loc_t *loc, char *key, -                              const char *linkto_xattr, struct iatt *stbuf, -                              const char *real_path) -{ -        gf_boolean_t     skip_unlink            = _gf_false; -        gf_boolean_t     is_dht_linkto_file     = _gf_false; -        int              unlink_if_linkto       = 0; -        ssize_t          xattr_size             = -1; -        int              op_ret                 = -1; - -        op_ret = dict_get_int32 (xdata, key, -                                 &unlink_if_linkto); - -        if (!op_ret && unlink_if_linkto) { - -                is_dht_linkto_file =  IS_DHT_LINKFILE_MODE (stbuf); -                if (!is_dht_linkto_file) -                        return _gf_true; - -                LOCK (&loc->inode->lock); - -                xattr_size = sys_lgetxattr (real_path, linkto_xattr, NULL, 0); - -                if (xattr_size <= 0) -                        skip_unlink = _gf_true; - -                UNLOCK (&loc->inode->lock); - -                gf_msg ("posix", GF_LOG_INFO, 0, P_MSG_XATTR_STATUS, -                        "linkto_xattr status: %"PRIu32" for %s", skip_unlink, -                        real_path); -        } -        return skip_unlink; - -} - -int32_t -posix_unlink (call_frame_t *frame, xlator_t *this, -              loc_t *loc, int xflag, dict_t *xdata) -{ -        int32_t                op_ret             = -1; -        int32_t                op_errno           = 0; -        char                   *real_path         = NULL; -        char                   *par_path          = NULL; -        int32_t                fd                 = -1; -        struct iatt            stbuf              = {0,}; -        struct iatt            postbuf            = {0,}; -        struct posix_private  *priv               = NULL; -        struct iatt            preparent          = {0,}; -        struct iatt            postparent         = {0,}; -        char                  *pgfid_xattr_key    = NULL; -        int32_t                nlink_samepgfid    = 0; -        int32_t                check_open_fd      = 0; -        int32_t                skip_unlink        = 0; -        int32_t                fdstat_requested   = 0; -        dict_t                *unwind_dict        = NULL; -        void                  *uuid               = NULL; -        char                   uuid_str[GF_UUID_BUF_SIZE] = {0}; -        char                   gfid_str[GF_UUID_BUF_SIZE] = {0}; -        gf_boolean_t           get_link_count     = _gf_false; -        posix_inode_ctx_t     *ctx                = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); -        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); -        if (!real_path || !par_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        priv = this->private; - -        op_ret = dict_get_ptr (xdata, TIER_LINKFILE_GFID, &uuid); - -        if (!op_ret && gf_uuid_compare (uuid, stbuf.ia_gfid)) { -                op_errno = ENOENT; -                op_ret = -1; -                gf_uuid_unparse (uuid, uuid_str); -                gf_uuid_unparse (stbuf.ia_gfid, gfid_str); -                gf_msg_debug (this->name, op_errno, "Mismatch in gfid for path " -                              "%s. Aborting the unlink. loc->gfid = %s, " -                              "stbuf->ia_gfid = %s", real_path, -                              uuid_str, gfid_str); -                goto out; -        } - -        op_ret = dict_get_int32 (xdata, DHT_SKIP_OPEN_FD_UNLINK, -                                 &check_open_fd); - -        if (!op_ret && check_open_fd) { - -                LOCK (&loc->inode->lock); - -                if (loc->inode->fd_count) { -                        skip_unlink = 1; -                } - -                UNLOCK (&loc->inode->lock); - -                gf_msg (this->name, GF_LOG_INFO, 0, P_MSG_KEY_STATUS_INFO, -                        "open-fd-key-status: %"PRIu32" for %s", skip_unlink, -                        real_path); - -                if (skip_unlink) { -                        op_ret = -1; -                        op_errno = EBUSY; -                        goto out; -                } -        } -        /* -         * If either of the function return true, skip_unlink. -         * If first first function itself return true, -         * we don't need to call second function, skip unlink. -         */ -        skip_unlink = posix_skip_non_linkto_unlink (xdata, loc, -                                                    DHT_SKIP_NON_LINKTO_UNLINK, -                                                    DHT_LINKTO, &stbuf, -                                                    real_path); -        skip_unlink = skip_unlink || posix_skip_non_linkto_unlink (xdata, loc, -                                                    TIER_SKIP_NON_LINKTO_UNLINK, -                                                    TIER_LINKTO, &stbuf, -                                                    real_path); -        if (skip_unlink) { -                op_ret = -1; -                op_errno = EBUSY; -                goto out; -        } - -        if (IA_ISREG (loc->inode->ia_type) && -            xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { -                fdstat_requested = 1; -        } - -        if (fdstat_requested || -            (priv->background_unlink && IA_ISREG (loc->inode->ia_type))) { -                fd = sys_open (real_path, O_RDONLY, 0); -                if (fd == -1) { -                        op_ret = -1; -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_OPEN_FAILED, -                                "open of %s failed", real_path); -                        goto out; -                } -        } - -        if (priv->update_pgfid_nlinks && (stbuf.ia_nlink > 1)) { -                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, -                                      loc->pargfid); -                op_ret = posix_inode_ctx_get_all (loc->inode, this, &ctx); -                if (op_ret < 0) { -                        op_errno = ENOMEM; -                        goto out; -                } -                pthread_mutex_lock (&ctx->pgfid_lock); -                { -                        UNLINK_MODIFY_PGFID_XATTR (real_path, pgfid_xattr_key, -                                                   nlink_samepgfid, 0, op_ret, -                                                   this, unlock); -                } -        unlock: -                pthread_mutex_unlock (&ctx->pgfid_lock); - -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_XATTR_FAILED, "modification of " -                                "parent gfid xattr failed (path:%s gfid:%s)", -                                real_path, uuid_utoa (loc->inode->gfid)); -                        if (op_errno != ENOATTR) -                            /* Allow unlink if pgfid xattr is not set. */ -                            goto out; -                } -        } - -        if (priv->gfid2path && (stbuf.ia_nlink > 1)) { -                op_ret = posix_remove_gfid2path_xattr (this, real_path, -                                                       loc->pargfid, -                                                       loc->name); -                if (op_ret < 0) { -                        /* Allow unlink if pgfid xattr is not set. */ -                        if (errno != ENOATTR) -                                goto out; -                } -        } - -        unwind_dict = dict_new (); -        if (!unwind_dict) { -                op_errno = -ENOMEM; -                op_ret = -1; -                goto out; -        } - -        if (xdata && dict_get (xdata, GET_LINK_COUNT)) -                get_link_count = _gf_true; -        op_ret =  posix_unlink_gfid_handle_and_entry (this, real_path, &stbuf, -                                                      &op_errno, loc, -                                                      get_link_count, -                                                      unwind_dict); -        if (op_ret == -1) { -                goto out; -        } - -        if (fdstat_requested) { -                op_ret = posix_fdstat (this, fd, &postbuf); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FSTAT_FAILED, "post operation " -                                "fstat failed on fd=%d", fd); -                        goto out; -                } -                op_ret = posix_set_iatt_in_dict (unwind_dict, &postbuf); -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        unwind_dict = posix_dict_set_nlink (xdata, unwind_dict, stbuf.ia_nlink); -        op_ret = 0; -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, -                             &preparent, &postparent, unwind_dict); - -        if (fd != -1) { -                sys_close (fd); -        } - -        /* unref unwind_dict*/ -        if (unwind_dict) { -                dict_unref (unwind_dict); -        } - -        return 0; -} - - -int -posix_rmdir (call_frame_t *frame, xlator_t *this, -             loc_t *loc, int flags, dict_t *xdata) -{ -        int32_t               op_ret     = -1; -        int32_t               op_errno   = 0; -        char                 *real_path  = NULL; -        char                 *par_path   = NULL; -        char                 *gfid_str   = NULL; -        struct iatt           preparent  = {0,}; -        struct iatt           postparent = {0,}; -        struct iatt           stbuf      = {0,}; -        struct posix_private *priv       = NULL; -        char                  tmp_path[PATH_MAX] = {0,}; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        /* The Hidden directory should be for housekeeping purpose and it -           should not get deleted from inside process */ -        if (__is_root_gfid (loc->pargfid) && -            (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { -                gf_msg (this->name, GF_LOG_WARNING, EPERM, -                        P_MSG_RMDIR_NOT_PERMITTED, "rmdir issued on %s, which" -                        "is not permitted", GF_HIDDEN_PATH); -                op_errno = EPERM; -                op_ret = -1; -                goto out; -        } - -        priv = this->private; - -        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); -        if (!real_path || !par_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        if (flags) { -                gfid_str = uuid_utoa (stbuf.ia_gfid); - -                op_ret = sys_mkdir (priv->trash_path, 0755); -                if (errno != EEXIST && op_ret == -1) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_MKDIR_FAILED, -                                "mkdir of %s failed", priv->trash_path); -                } else { -                        (void) snprintf (tmp_path, sizeof(tmp_path), "%s/%s", -                                         priv->trash_path, gfid_str); -                        op_ret = sys_rename (real_path, tmp_path); -                        pthread_cond_signal (&priv->janitor_cond); -                } -        } else { -                op_ret = sys_rmdir (real_path); -        } -        op_errno = errno; - -        if (op_ret == 0) { -                if (posix_symlinks_match (this, loc, stbuf.ia_gfid)) -                        posix_handle_unset (this, stbuf.ia_gfid, NULL); -        } - -        if (op_errno == EEXIST) -                /* Solaris sets errno = EEXIST instead of ENOTEMPTY */ -                op_errno = ENOTEMPTY; - -        /* No need to log a common error as ENOTEMPTY */ -        if (op_ret == -1 && op_errno != ENOTEMPTY) { -                gf_msg (this->name, GF_LOG_ERROR, op_errno, P_MSG_RMDIR_FAILED, -                        "rmdir of %s failed", real_path); -        } - -        if (op_ret == -1) { -                if (op_errno == ENOTEMPTY) { -                        gf_msg_debug (this->name, 0, "%s on %s failed", (flags) -                                      ? "rename" : "rmdir", real_path); -                } else { -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_DIR_OPERATION_FAILED, "%s on %s failed", -                                (flags) ? "rename" : "rmdir", real_path); -                } -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent of %s failed", -                        par_path); -                goto out; -        } - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, -                             &preparent, &postparent, NULL); - -        return 0; -} - - -int -posix_symlink (call_frame_t *frame, xlator_t *this, -               const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata) -{ -        int32_t               op_ret          = -1; -        int32_t               op_errno        = 0; -        char *                real_path       = 0; -        char *                par_path        = 0; -        struct iatt           stbuf           = { 0, }; -        struct posix_private *priv            = NULL; -        gid_t                 gid             = 0; -        struct iatt           preparent       = {0,}; -        struct iatt           postparent      = {0,}; -        char                 *pgfid_xattr_key = NULL; -        int32_t               nlink_samepgfid = 0; -        gf_boolean_t          entry_created   = _gf_false, gfid_set = _gf_false; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (linkname, out); -        VALIDATE_OR_GOTO (loc, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, -                                  out); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); - -        gid = frame->root->gid; -        if (!real_path || !par_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        SET_FS_ID (frame->root->uid, gid); - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        if (preparent.ia_prot.sgid) { -                gid = preparent.ia_gid; -        } - -        op_ret = sys_symlink (linkname, real_path); - -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_SYMLINK_FAILED, -                        "symlink of %s --> %s failed", -                        real_path, linkname); -                goto out; -        } - -        entry_created = _gf_true; - -#ifndef HAVE_SET_FSID -        op_ret = sys_lchown (real_path, frame->root->uid, gid); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LCHOWN_FAILED, -                        "lchown failed on %s", real_path); -                goto out; -        } -#endif -        op_ret = posix_acl_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACL_FAILED, -                        "setting ACLs on %s failed", real_path); -        } - -        if (priv->update_pgfid_nlinks) { -                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, -                                      loc->pargfid); -                nlink_samepgfid = 1; -                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, -                                 XATTR_CREATE, op_ret, this, ignore); -        } - -        if (priv->gfid2path) { -                posix_set_gfid2path_xattr (this, real_path, loc->pargfid, -                                           loc->name); -        } - -ignore: -        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, -                        "setting xattrs on %s failed ", real_path); -        } - -        op_ret = posix_gfid_set (this, real_path, loc, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, -                        "setting gfid on %s failed", real_path); -        } else { -                gfid_set = _gf_true; -        } - -        op_ret = posix_pstat (this, NULL, real_path, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat failed on %s", real_path); -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, -                             (loc)?loc->inode:NULL, &stbuf, &preparent, -                             &postparent, NULL); - -        if (op_ret < 0) { -                if (entry_created) -                        sys_unlink (real_path); - -                if (gfid_set) -                        posix_gfid_unset (this, xdata); -        } - -        return 0; -} - - -int -posix_rename (call_frame_t *frame, xlator_t *this, -              loc_t *oldloc, loc_t *newloc, dict_t *xdata) -{ -        int32_t               op_ret          = -1; -        int32_t               op_errno        = 0; -        char                 *real_oldpath    = NULL; -        char                 *real_newpath    = NULL; -        char                 *par_oldpath     = NULL; -        char                 *par_newpath     = NULL; -        struct iatt           stbuf           = {0, }; -        struct posix_private *priv            = NULL; -        char                  was_present     = 1; -        struct iatt           preoldparent    = {0, }; -        struct iatt           postoldparent   = {0, }; -        struct iatt           prenewparent    = {0, }; -        struct iatt           postnewparent   = {0, }; -        char                  olddirid[64]; -        char                  newdirid[64]; -        uuid_t                victim          = {0}; -        int                   was_dir         = 0; -        int                   nlink           = 0; -        char                 *pgfid_xattr_key = NULL; -        int32_t               nlink_samepgfid = 0; -        char                 *gfid_path            = NULL; -        dict_t               *unwind_dict     = NULL; -        gf_boolean_t          locked          = _gf_false; -        gf_boolean_t          get_link_count  = _gf_false; -        posix_inode_ctx_t    *ctx_old         = NULL; -        posix_inode_ctx_t    *ctx_new         = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (oldloc, out); -        VALIDATE_OR_GOTO (newloc, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); -        MAKE_ENTRY_HANDLE (real_oldpath, par_oldpath, this, oldloc, NULL); -        if (!real_oldpath || !par_oldpath) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        MAKE_ENTRY_HANDLE (real_newpath, par_newpath, this, newloc, &stbuf); -        if (!real_newpath || !par_newpath) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        unwind_dict = dict_new (); -        if (!unwind_dict) { -                op_ret = -1; -                op_errno = ENOMEM; -                goto out; -        } - -        op_ret = posix_pstat (this, oldloc->pargfid, par_oldpath, &preoldparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent %s failed", -                        par_oldpath); -                goto out; -        } - -        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &prenewparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent of %s failed", -                        par_newpath); -                goto out; -        } - -        op_ret = posix_pstat (this, NULL, real_newpath, &stbuf); -        if ((op_ret == -1) && (errno == ENOENT)){ -                was_present = 0; -        } else { -                gf_uuid_copy (victim, stbuf.ia_gfid); -                if (IA_ISDIR (stbuf.ia_type)) -                        was_dir = 1; -                nlink = stbuf.ia_nlink; -        } - -        if (was_present && IA_ISDIR(stbuf.ia_type) && !newloc->inode) { -                gf_msg (this->name, GF_LOG_WARNING, EEXIST, P_MSG_DIR_FOUND, -                        "found directory at %s while expecting ENOENT", -                        real_newpath); -                op_ret = -1; -                op_errno = EEXIST; -                goto out; -        } - -        if (was_present && IA_ISDIR(stbuf.ia_type) && -            gf_uuid_compare (newloc->inode->gfid, stbuf.ia_gfid)) { -                gf_msg (this->name, GF_LOG_WARNING, EEXIST, P_MSG_DIR_FOUND, -                        "found directory %s at %s while renaming %s", -                        uuid_utoa_r (newloc->inode->gfid, olddirid), -                        real_newpath, -                        uuid_utoa_r (stbuf.ia_gfid, newdirid)); -                op_ret = -1; -                op_errno = EEXIST; -                goto out; -        } - -        op_ret = posix_inode_ctx_get_all (oldloc->inode, this, &ctx_old); -        if (op_ret < 0) { -                op_ret = -1; -                op_errno = ENOMEM; -                goto out; -        } - -        if (newloc->inode) { -                op_ret = posix_inode_ctx_get_all (newloc->inode, this, &ctx_new); -                if (op_ret < 0) { -                        op_ret = -1; -                        op_errno = ENOMEM; -                        goto out; -                } -        } - -        if (IA_ISDIR (oldloc->inode->ia_type)) -                posix_handle_unset (this, oldloc->inode->gfid, NULL); - -        pthread_mutex_lock (&ctx_old->pgfid_lock); -        { -                if (!IA_ISDIR (oldloc->inode->ia_type) -                    && priv->update_pgfid_nlinks) { -                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, -                                              PGFID_XATTR_KEY_PREFIX, -                                              oldloc->pargfid); -                        UNLINK_MODIFY_PGFID_XATTR (real_oldpath, -                                                   pgfid_xattr_key, -                                                   nlink_samepgfid, 0, -                                                   op_ret, -                                                   this, unlock); -                } - -                if ((xdata) && (dict_get (xdata, GET_LINK_COUNT)) -                    && (real_newpath) && (was_present)) { -                        pthread_mutex_lock (&ctx_new->pgfid_lock); -                        locked = _gf_true; -                        get_link_count = _gf_true; -                        op_ret = posix_pstat (this, newloc->gfid, real_newpath, -                                              &stbuf); -                        if ((op_ret == -1) && (errno != ENOENT)) { -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_LSTAT_FAILED, -                                        "lstat on %s failed", real_newpath); -                                goto unlock; -                        } -                } - -                op_ret = sys_rename (real_oldpath, real_newpath); -                if (op_ret == -1) { -                        op_errno = errno; -                        if (op_errno == ENOTEMPTY) { -                                gf_msg_debug (this->name, 0, "rename of %s to" -                                              " %s failed: %s", real_oldpath, -                                              real_newpath, -                                              strerror (op_errno)); -                        } else { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_RENAME_FAILED, -                                        "rename of %s to %s failed", -                                        real_oldpath, real_newpath); -                       } - -                        if (priv->update_pgfid_nlinks -                            && !IA_ISDIR (oldloc->inode->ia_type)) { -                                LINK_MODIFY_PGFID_XATTR (real_oldpath, -                                                         pgfid_xattr_key, -                                                         nlink_samepgfid, 0, -                                                         op_ret, -                                                         this, unlock); -                        } - -                        goto unlock; -                } - -                if (locked) { -                        pthread_mutex_unlock (&ctx_new->pgfid_lock); -                        locked = _gf_false; -                } - -                if ((get_link_count) && -                    (dict_set_uint32 (unwind_dict, GET_LINK_COUNT, -                                      stbuf.ia_nlink))) -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_SET_XDATA_FAIL, "failed to set " -                                GET_LINK_COUNT" for %s", real_newpath); - -                if (!IA_ISDIR (oldloc->inode->ia_type) -                    && priv->update_pgfid_nlinks) { -                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, -                                              PGFID_XATTR_KEY_PREFIX, -                                              newloc->pargfid); -                        LINK_MODIFY_PGFID_XATTR (real_newpath, -                                                 pgfid_xattr_key, -                                                 nlink_samepgfid, 0, -                                                 op_ret, -                                                 this, unlock); -                } - -                if (!IA_ISDIR (oldloc->inode->ia_type) && priv->gfid2path) { -                        MAKE_HANDLE_ABSPATH (gfid_path, this, -                                             oldloc->inode->gfid); - -                        posix_remove_gfid2path_xattr (this, gfid_path, -                                                      oldloc->pargfid, -                                                      oldloc->name); -                        posix_set_gfid2path_xattr (this, gfid_path, -                                                   newloc->pargfid, -                                                   newloc->name); -                } -        } - -unlock: -        if (locked) { -                pthread_mutex_unlock (&ctx_new->pgfid_lock); -                locked = _gf_false; -        } -        pthread_mutex_unlock (&ctx_old->pgfid_lock); - -        if (op_ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_XATTR_FAILED, -                        "modification of " -                        "parent gfid xattr failed (gfid:%s)", -                        uuid_utoa (oldloc->inode->gfid)); -                goto out; -        } - -        if (was_dir) -                posix_handle_unset (this, victim, NULL); - -        if (was_present && !was_dir && nlink == 1) -                posix_handle_unset (this, victim, NULL); - -        if (IA_ISDIR (oldloc->inode->ia_type)) { -                posix_handle_soft (this, real_newpath, newloc, -                                   oldloc->inode->gfid, NULL); -        } - -        op_ret = posix_pstat (this, NULL, real_newpath, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat on %s failed", real_newpath); -                goto out; -        } - -        op_ret = posix_pstat (this, oldloc->pargfid, par_oldpath, &postoldparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent %s failed", -                        par_oldpath); -                goto out; -        } - -        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &postnewparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent %s failed", -                        par_newpath); -                goto out; -        } - -        if (was_present) -                unwind_dict = posix_dict_set_nlink (xdata, unwind_dict, nlink); -        op_ret = 0; -out: - -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, &stbuf, -                             &preoldparent, &postoldparent, -                             &prenewparent, &postnewparent, unwind_dict); - -        if (unwind_dict) -                dict_unref (unwind_dict); - -        return 0; -} - - -int -posix_link (call_frame_t *frame, xlator_t *this, -            loc_t *oldloc, loc_t *newloc, dict_t *xdata) -{ -        int32_t               op_ret          = -1; -        int32_t               op_errno        = 0; -        char                 *real_oldpath    = 0; -        char                 *real_newpath    = 0; -        char                 *par_newpath     = 0; -        struct iatt           stbuf           = {0, }; -        struct posix_private *priv            = NULL; -        struct iatt           preparent       = {0,}; -        struct iatt           postparent      = {0,}; -        int32_t               nlink_samepgfid = 0; -        char                 *pgfid_xattr_key = NULL; -        gf_boolean_t          entry_created   = _gf_false; -        posix_inode_ctx_t    *ctx             = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (oldloc, out); -        VALIDATE_OR_GOTO (newloc, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); -        MAKE_INODE_HANDLE (real_oldpath, this, oldloc, &stbuf); -        if (!real_oldpath) { -                op_errno = errno; -                goto out; -        } - -        MAKE_ENTRY_HANDLE (real_newpath, par_newpath, this, newloc, &stbuf); -        if (!real_newpath || !par_newpath) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat failed: %s", par_newpath); -                goto out; -        } - - -        op_ret = sys_link (real_oldpath, real_newpath); - -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LINK_FAILED, -                        "link %s to %s failed", -                        real_oldpath, real_newpath); -                goto out; -        } - -        entry_created = _gf_true; - -        op_ret = posix_pstat (this, NULL, real_newpath, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat on %s failed", real_newpath); -                goto out; -        } - -        op_ret = posix_pstat (this, newloc->pargfid, par_newpath, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat failed: %s", par_newpath); -                goto out; -        } - -        if (priv->update_pgfid_nlinks) { -                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, -                                      newloc->pargfid); - -                op_ret = posix_inode_ctx_get_all (newloc->inode, this, &ctx); -                if (op_ret < 0) { -                        op_errno = ENOMEM; -                        goto out; -                } - -                pthread_mutex_lock (&ctx->pgfid_lock); -                { -                        LINK_MODIFY_PGFID_XATTR (real_newpath, pgfid_xattr_key, -                                                 nlink_samepgfid, 0, op_ret, -                                                 this, unlock); -                } -        unlock: -                pthread_mutex_unlock (&ctx->pgfid_lock); - -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_XATTR_FAILED, "modification of " -                                "parent gfid xattr failed (path:%s gfid:%s)", -                                real_newpath, uuid_utoa (newloc->inode->gfid)); -                        goto out; -                } -        } - -        if (priv->gfid2path) { -                if (stbuf.ia_nlink <= MAX_GFID2PATH_LINK_SUP) { -                        op_ret = posix_set_gfid2path_xattr (this, real_newpath, -                                                            newloc->pargfid, -                                                            newloc->name); -                        if (op_ret) { -                                op_errno = errno; -                                goto out; -                        } -                 } else { -                        gf_msg (this->name, GF_LOG_INFO, 0, -                                P_MSG_XATTR_NOTSUP, "Link count exceeded. " -                                "gfid2path xattr not set (path:%s gfid:%s)", -                                real_newpath, uuid_utoa (newloc->inode->gfid)); -                 } -        } - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, -                             (oldloc)?oldloc->inode:NULL, &stbuf, &preparent, -                             &postparent, NULL); - -        if (op_ret < 0) { -                if (entry_created) -                        sys_unlink (real_newpath); -        } - -        return 0; -} - - -int32_t -posix_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, -                dict_t *xdata) -{ -        int32_t               op_ret    = -1; -        int32_t               op_errno  = 0; -        char                 *real_path = 0; -        struct posix_private *priv      = NULL; -        struct iatt           prebuf    = {0,}; -        struct iatt           postbuf   = {0,}; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        MAKE_INODE_HANDLE (real_path, this, loc, &prebuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on %s failed", -                        real_path ? real_path : "<null>"); -                goto out; -        } - -        op_ret = sys_truncate (real_path, offset); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_TRUNCATE_FAILED, -                        "truncate on %s failed", real_path); -                goto out; -        } - -        op_ret = posix_pstat (this, loc->gfid, real_path, &postbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "lstat on %s failed", real_path); -                goto out; -        } - -        op_ret = 0; -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, -                             &prebuf, &postbuf, NULL); - -        return 0; -} - - -int -posix_create (call_frame_t *frame, xlator_t *this, -              loc_t *loc, int32_t flags, mode_t mode, -              mode_t umask, fd_t *fd, dict_t *xdata) -{ -        int32_t                op_ret          = -1; -        int32_t                op_errno        = 0; -        int32_t                _fd             = -1; -        int                    _flags          = 0; -        char *                 real_path       = NULL; -        char *                 par_path        = NULL; -        struct iatt            stbuf           = {0, }; -        struct posix_fd *      pfd             = NULL; -        struct posix_private * priv            = NULL; -        char                   was_present     = 1; - -        gid_t                  gid             = 0; -        struct iatt            preparent       = {0,}; -        struct iatt            postparent      = {0,}; - -        int                    nlink_samepgfid = 0; -        char *                 pgfid_xattr_key = NULL; -        gf_boolean_t           entry_created   = _gf_false, gfid_set = _gf_false; -        mode_t                 mode_bit        = 0; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (this->private, out); -        VALIDATE_OR_GOTO (loc, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); -        GFID_NULL_CHECK_AND_GOTO (frame, this, loc, xdata, op_ret, op_errno, -                                  out); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &stbuf); - -        gid = frame->root->gid; - -        SET_FS_ID (frame->root->uid, gid); -        if (!real_path || !par_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "pre-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        if (preparent.ia_prot.sgid) { -                gid = preparent.ia_gid; -        } - -        if (!flags) { -                _flags = O_CREAT | O_RDWR | O_EXCL; -        } -        else { -                _flags = flags | O_CREAT; -        } - -        op_ret = posix_pstat (this, NULL, real_path, &stbuf); -        if ((op_ret == -1) && (errno == ENOENT)) { -                was_present = 0; -        } - -        if (priv->o_direct) -                _flags |= O_DIRECT; - - -        mode_bit = (priv->create_mask & mode) | priv->force_create_mode; -        mode = override_umask (mode, mode_bit); -        _fd = sys_open (real_path, _flags, mode); - -        if (_fd == -1) { -                op_errno = errno; -                op_ret = -1; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_OPEN_FAILED, -                        "open on %s failed", real_path); -                goto out; -        } - -        if ((_flags & O_CREAT) && (_flags & O_EXCL)) { -                entry_created = _gf_true; -        } - - -        if (was_present) -                goto fill_stat; - -#ifndef HAVE_SET_FSID -        op_ret = sys_chown (real_path, frame->root->uid, gid); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_CHOWN_FAILED, -                        "chown on %s failed", real_path); -        } -#endif -        op_ret = posix_acl_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACL_FAILED, -                        "setting ACLs on %s failed", real_path); -        } - -        if (priv->update_pgfid_nlinks) { -                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, -                                      loc->pargfid); -                nlink_samepgfid = 1; -                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, -                                 XATTR_CREATE, op_ret, this, ignore); -        } - -        if (priv->gfid2path) { -                posix_set_gfid2path_xattr (this, real_path, loc->pargfid, -                                            loc->name); -        } -ignore: -        op_ret = posix_entry_create_xattr_set (this, real_path, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, -                        "setting xattrs on %s failed ", real_path); -        } - -fill_stat: -        op_ret = posix_gfid_set (this, real_path, loc, xdata); -        if (op_ret) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_GFID_FAILED, -                        "setting gfid on %s failed", real_path); -        } else { -                gfid_set = _gf_true; -        } - -        op_ret = posix_fdstat (this, _fd, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fstat on %d failed", _fd); -                goto out; -        } - -        op_ret = posix_pstat (this, loc->pargfid, par_path, &postparent); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "post-operation lstat on parent %s failed", -                        par_path); -                goto out; -        } - -        op_ret = -1; -        pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); -        if (!pfd) { -                op_errno = errno; -                goto out; -        } - -        pfd->flags = flags; -        pfd->fd    = _fd; - -        op_ret = fd_ctx_set (fd, this, (uint64_t)(long)pfd); -        if (op_ret) -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_FD_PATH_SETTING_FAILED, -                        "failed to set the fd context path=%s fd=%p", -                        real_path, fd); - -        LOCK (&priv->lock); -        { -                priv->nr_files++; -        } -        UNLOCK (&priv->lock); - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        if ((-1 == op_ret) && (_fd != -1)) { -                sys_close (_fd); -        } - -        STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, -                             fd, (loc)?loc->inode:NULL, &stbuf, &preparent, -                             &postparent, xdata); - -        if (op_ret < 0) { -                if (entry_created) -                        sys_unlink (real_path); - -                if (gfid_set) -                        posix_gfid_unset (this, xdata); -        } - -        return 0; -} - -int32_t -posix_open (call_frame_t *frame, xlator_t *this, -            loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata) -{ -        int32_t               op_ret       = -1; -        int32_t               op_errno     = 0; -        char                 *real_path    = NULL; -        int32_t               _fd          = -1; -        struct posix_fd      *pfd          = NULL; -        struct posix_private *priv         = NULL; -        struct iatt           stbuf        = {0, }; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (this->private, out); -        VALIDATE_OR_GOTO (loc, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); - -        if (flags & O_CREAT) -                DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        MAKE_INODE_HANDLE (real_path, this, loc, &stbuf); -        if (!real_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        if (IA_ISLNK (stbuf.ia_type)) { -                op_ret = -1; -                op_errno = ELOOP; -                goto out; -        } - -        op_ret = -1; -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        if (priv->o_direct) -                flags |= O_DIRECT; - -        _fd = sys_open (real_path, flags, priv->force_create_mode); -        if (_fd == -1) { -                op_ret   = -1; -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FILE_OP_FAILED, -                        "open on %s, flags: %d", real_path, flags); -                goto out; -        } - -        pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); -        if (!pfd) { -                op_errno = errno; -                goto out; -        } - -        pfd->flags = flags; -        pfd->fd    = _fd; - -        op_ret = fd_ctx_set (fd, this, (uint64_t)(long)pfd); -        if (op_ret) -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_FD_PATH_SETTING_FAILED, -                        "failed to set the fd context path=%s fd=%p", -                        real_path, fd); - -        LOCK (&priv->lock); -        { -                priv->nr_files++; -        } -        UNLOCK (&priv->lock); - -        op_ret = 0; - -out: -        if (op_ret == -1) { -                if (_fd != -1) { -                        sys_close (_fd); -                } -        } - -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, NULL); - -        return 0; -} - -int -posix_readv (call_frame_t *frame, xlator_t *this, -             fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) -{ -        int32_t                op_ret     = -1; -        int32_t                op_errno   = 0; -        int                    _fd        = -1; -        struct posix_private * priv       = NULL; -        struct iobuf         * iobuf      = NULL; -        struct iobref        * iobref     = NULL; -        struct iovec           vec        = {0,}; -        struct posix_fd *      pfd        = NULL; -        struct iatt            stbuf      = {0,}; -        int                    ret        = -1; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); -        VALIDATE_OR_GOTO (this->private, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        if (!size) { -                op_errno = EINVAL; -                gf_msg (this->name, GF_LOG_WARNING, EINVAL, -                        P_MSG_INVALID_ARGUMENT, "size=%"GF_PRI_SIZET, size); -                goto out; -        } - -        iobuf = iobuf_get_page_aligned (this->ctx->iobuf_pool, size, -                                        ALIGN_SIZE); -        if (!iobuf) { -                op_errno = ENOMEM; -                goto out; -        } - -        _fd = pfd->fd; -        op_ret = sys_pread (_fd, iobuf->ptr, size, offset); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_READ_FAILED, "read failed on gfid=%s, " -                        "fd=%p, offset=%"PRIu64" size=%"GF_PRI_SIZET", " -                        "buf=%p", uuid_utoa (fd->inode->gfid), fd, -                        offset, size, iobuf->ptr); -                goto out; -        } - -        LOCK (&priv->lock); -        { -                priv->read_value    += op_ret; -        } -        UNLOCK (&priv->lock); - -        vec.iov_base = iobuf->ptr; -        vec.iov_len  = op_ret; - -        iobref = iobref_new (); - -        iobref_add (iobref, iobuf); - -        /* -         *  readv successful, and we need to get the stat of the file -         *  we read from -         */ - -        op_ret = posix_fdstat (this, _fd, &stbuf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fstat failed on fd=%p", fd); -                goto out; -        } - -        /* Hack to notify higher layers of EOF. */ -        if (!stbuf.ia_size || (offset + vec.iov_len) >= stbuf.ia_size) -                op_errno = ENOENT; - -        op_ret = vec.iov_len; -out: - -        STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, -                             &vec, 1, &stbuf, iobref, NULL); - -        if (iobref) -                iobref_unref (iobref); -        if (iobuf) -                iobuf_unref (iobuf); - -        return 0; -} - - -int32_t -__posix_pwritev (int fd, struct iovec *vector, int count, off_t offset) -{ -        int32_t         op_ret = 0; -        int             idx = 0; -        int             retval = 0; -        off_t           internal_off = 0; - -        if (!vector) -                return -EFAULT; - -        internal_off = offset; -        for (idx = 0; idx < count; idx++) { -                retval = sys_pwrite (fd, vector[idx].iov_base, vector[idx].iov_len, -                                 internal_off); -                if (retval == -1) { -                        op_ret = -errno; -                        goto err; -                } -                op_ret += retval; -                internal_off += retval; -        } - -err: -        return op_ret; -} - -int32_t -__posix_writev (int fd, struct iovec *vector, int count, off_t startoff, -                int odirect) -{ -        int32_t         op_ret = 0; -        int             idx = 0; -        int             max_buf_size = 0; -        int             retval = 0; -        char            *buf = NULL; -        char            *alloc_buf = NULL; -        off_t           internal_off = 0; - -        /* Check for the O_DIRECT flag during open() */ -        if (!odirect) -                return __posix_pwritev (fd, vector, count, startoff); - -        for (idx = 0; idx < count; idx++) { -                if (max_buf_size < vector[idx].iov_len) -                        max_buf_size = vector[idx].iov_len; -        } - -        alloc_buf = _page_aligned_alloc (max_buf_size, &buf); -        if (!alloc_buf) { -                op_ret = -errno; -                goto err; -        } - -        internal_off = startoff; -        for (idx = 0; idx < count; idx++) { -                memcpy (buf, vector[idx].iov_base, vector[idx].iov_len); - -                /* not sure whether writev works on O_DIRECT'd fd */ -                retval = sys_pwrite (fd, buf, vector[idx].iov_len, internal_off); -                if (retval == -1) { -                        op_ret = -errno; -                        goto err; -                } - -                op_ret += retval; -                internal_off += retval; -        } - -err: -        GF_FREE (alloc_buf); - -        return op_ret; -} - -dict_t* -_fill_writev_xdata (fd_t *fd, dict_t *xdata, xlator_t *this, int is_append) -{ -        dict_t  *rsp_xdata = NULL; -        int32_t ret = 0; -        inode_t *inode = NULL; - -        if (fd) -                inode = fd->inode; - -        if (!fd || !fd->inode || gf_uuid_is_null (fd->inode->gfid)) { -                gf_msg_callingfn (this->name, GF_LOG_ERROR, EINVAL, -                                  P_MSG_XATTR_FAILED, "fd: %p inode: %p" -                                  "gfid:%s", fd, inode?inode:0, -                                  inode?uuid_utoa(inode->gfid):"N/A"); -                goto out; -        } - -        if (!xdata) -                goto out; - -        rsp_xdata = dict_new(); -        if (!rsp_xdata) -                goto out; - -        if (dict_get (xdata, GLUSTERFS_OPEN_FD_COUNT)) { -                ret = dict_set_uint32 (rsp_xdata, GLUSTERFS_OPEN_FD_COUNT, -                                       fd->inode->fd_count); -                if (ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_DICT_SET_FAILED, "%s: Failed to set " -                                "dictionary value for %s", -                                uuid_utoa (fd->inode->gfid), -                                GLUSTERFS_OPEN_FD_COUNT); -                } -        } - -        if (dict_get (xdata, GLUSTERFS_WRITE_IS_APPEND)) { -                ret = dict_set_uint32 (rsp_xdata, GLUSTERFS_WRITE_IS_APPEND, -                                       is_append); -                if (ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_DICT_SET_FAILED, "%s: Failed to set " -                                "dictionary value for %s", -                                uuid_utoa (fd->inode->gfid), -                                GLUSTERFS_WRITE_IS_APPEND); -                } -        } -out: -        return rsp_xdata; -} - -int32_t -posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, -              struct iovec *vector, int32_t count, off_t offset, -              uint32_t flags, struct iobref *iobref, dict_t *xdata) -{ -        int32_t                op_ret   = -1; -        int32_t                op_errno = 0; -        int                    _fd      = -1; -        struct posix_private * priv     = NULL; -        struct posix_fd *      pfd      = NULL; -        struct iatt            preop    = {0,}; -        struct iatt            postop    = {0,}; -        int                      ret      = -1; -        dict_t                *rsp_xdata = NULL; -	int                    is_append = 0; -	gf_boolean_t           locked = _gf_false; -	gf_boolean_t           write_append = _gf_false; -	gf_boolean_t           update_atomic = _gf_false; -        posix_inode_ctx_t     *ctx      = NULL; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); -        VALIDATE_OR_GOTO (vector, out); -        VALIDATE_OR_GOTO (this->private, out); - -        priv = this->private; - -        VALIDATE_OR_GOTO (priv, out); -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, ret, P_MSG_PFD_NULL, -                        "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        _fd = pfd->fd; - -        if (xdata) { -                if (dict_get (xdata, GLUSTERFS_WRITE_IS_APPEND)) -                        write_append = _gf_true; -                if (dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) -                        update_atomic = _gf_true; -	} - -        /* The write_is_append check and write must happen -           atomically. Else another write can overtake this -           write after the check and get written earlier. - -           So lock before preop-stat and unlock after write. -        */ - -        /* -         * The update_atomic option is to instruct posix to do prestat, -         * write and poststat atomically. This is to prevent any modification to -         * ia_size and ia_blocks until poststat and the diff in their values -         * between pre and poststat could be of use for some translators (shard -         * as of today). -         */ - -        op_ret = posix_inode_ctx_get_all (fd->inode, this, &ctx); -        if (op_ret < 0) { -                op_errno = ENOMEM; -                goto out; -        } - -        if (write_append || update_atomic) { -		locked = _gf_true; -		pthread_mutex_lock (&ctx->write_atomic_lock); -        } - -        op_ret = posix_fdstat (this, _fd, &preop); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "pre-operation fstat failed on fd=%p", fd); -                goto out; -        } - -	if (locked && write_append) { -		if (preop.ia_size == offset || (fd->flags & O_APPEND)) -			is_append = 1; -	} - -        op_ret = __posix_writev (_fd, vector, count, offset, -                                 (pfd->flags & O_DIRECT)); - -	if (locked && (!update_atomic)) { -		pthread_mutex_unlock (&ctx->write_atomic_lock); -		locked = _gf_false; -	} - -        if (op_ret < 0) { -                op_errno = -op_ret; -                op_ret = -1; -                gf_msg (this->name, GF_LOG_ERROR, op_errno, P_MSG_WRITE_FAILED, -                        "write failed: offset %"PRIu64 -                        ",", offset); -                goto out; -        } - -        rsp_xdata = _fill_writev_xdata (fd, xdata, this, is_append); -        /* writev successful, we also need to get the stat of -         * the file we wrote to -         */ - -        ret = posix_fdstat (this, _fd, &postop); -        if (ret == -1) { -                op_ret = -1; -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_FSTAT_FAILED, -                        "post-operation fstat failed on fd=%p", -                        fd); -                goto out; -        } - -	if (locked) { -		pthread_mutex_unlock (&ctx->write_atomic_lock); -		locked = _gf_false; -	} - -        if (flags & (O_SYNC|O_DSYNC)) { -                ret = sys_fsync (_fd); -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_WRITEV_FAILED, -                                "fsync() in writev on fd %d failed", -                                _fd); -                        op_ret = -1; -                        op_errno = errno; -                        goto out; -                } -        } - -        LOCK (&priv->lock); -        { -                priv->write_value    += op_ret; -        } -        UNLOCK (&priv->lock); - -out: - -	if (locked) { -		pthread_mutex_unlock (&ctx->write_atomic_lock); -		locked = _gf_false; -	} - -        STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, &preop, &postop, -                             rsp_xdata); - -        if (rsp_xdata) -                dict_unref (rsp_xdata); -        return 0; -} - - -int32_t -posix_statfs (call_frame_t *frame, xlator_t *this, -              loc_t *loc, dict_t *xdata) -{ -        char *                 real_path = NULL; -        int32_t                op_ret    = -1; -        int32_t                op_errno  = 0; -        struct statvfs         buf       = {0, }; -        struct posix_private * priv      = NULL; -        int                    shared_by = 1; -        int                    percent   = 0; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); -        VALIDATE_OR_GOTO (this->private, out); - -        MAKE_INODE_HANDLE (real_path, this, loc, NULL); -        if (!real_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        priv = this->private; - -        op_ret = sys_statvfs (real_path, &buf); - -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_STATVFS_FAILED, -                        "statvfs failed on %s", real_path); -                goto out; -        } - -        percent = priv->disk_reserve; -        buf.f_bfree = (buf.f_bfree - ((buf.f_blocks * percent) / 100)); - -        shared_by = priv->shared_brick_count; -        if (shared_by > 1) { -                buf.f_blocks /= shared_by; -                buf.f_bfree  /= shared_by; -                buf.f_bavail /= shared_by; -                buf.f_files  /= shared_by; -                buf.f_ffree  /= shared_by; -                buf.f_favail /= shared_by; -        } - -        if (!priv->export_statfs) { -                buf.f_blocks = 0; -                buf.f_bfree  = 0; -                buf.f_bavail = 0; -                buf.f_files  = 0; -                buf.f_ffree  = 0; -                buf.f_favail = 0; -        } - -        op_ret = 0; - -out: -        STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, &buf, NULL); -        return 0; -} - - -int32_t -posix_flush (call_frame_t *frame, xlator_t *this, -             fd_t *fd, dict_t *xdata) -{ -        int32_t           op_ret   = -1; -        int32_t           op_errno = 0; -        int               ret      = -1; -        struct posix_fd  *pfd      = NULL; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL on fd=%p", fd); -                goto out; -        } - -        op_ret = 0; - -out: -        STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, NULL); - -        return 0; -} - - -int32_t -posix_release (xlator_t *this, fd_t *fd) -{ -        struct posix_private * priv     = NULL; -        struct posix_fd *      pfd      = NULL; -        int                    ret      = -1; -        uint64_t               tmp_pfd  = 0; - -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; - -        ret = fd_ctx_del (fd, this, &tmp_pfd); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_PFD_NULL, -                        "pfd is NULL from fd=%p", fd); -                goto out; -        } -        pfd = (struct posix_fd *)(long)tmp_pfd; - -        if (pfd->dir) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_DIR_NOT_NULL, -                        "pfd->dir is %p (not NULL) for file fd=%p", -                        pfd->dir, fd); -        } - -        pthread_mutex_lock (&priv->janitor_lock); -        { -                INIT_LIST_HEAD (&pfd->list); -                list_add_tail (&pfd->list, &priv->janitor_fds); -                pthread_cond_signal (&priv->janitor_cond); -        } -        pthread_mutex_unlock (&priv->janitor_lock); - -        LOCK (&priv->lock); -        { -                priv->nr_files--; -        } -        UNLOCK (&priv->lock); - -out: -        return 0; -} - - -int -posix_batch_fsync (call_frame_t *frame, xlator_t *this, -		     fd_t *fd, int datasync, dict_t *xdata) -{ -	call_stub_t *stub = NULL; -	struct posix_private *priv = NULL; - -	priv = this->private; - -	stub = fop_fsync_stub (frame, default_fsync, fd, datasync, xdata); -	if (!stub) { -		STACK_UNWIND_STRICT (fsync, frame, -1, ENOMEM, 0, 0, 0); -		return 0; -	} - -	pthread_mutex_lock (&priv->fsync_mutex); -	{ -		list_add_tail (&stub->list, &priv->fsyncs); -		priv->fsync_queue_count++; -		pthread_cond_signal (&priv->fsync_cond); -	} -	pthread_mutex_unlock (&priv->fsync_mutex); - -	return 0; -} - - -int32_t -posix_fsync (call_frame_t *frame, xlator_t *this, -             fd_t *fd, int32_t datasync, dict_t *xdata) -{ -        int32_t           op_ret   = -1; -        int32_t           op_errno = 0; -        int               _fd      = -1; -        struct posix_fd * pfd      = NULL; -        int               ret      = -1; -        struct iatt       preop = {0,}; -        struct iatt       postop = {0,}; -        struct posix_private *priv = NULL; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -#ifdef GF_DARWIN_HOST_OS -        /* Always return success in case of fsync in MAC OS X */ -        op_ret = 0; -        goto out; -#endif - -	priv = this->private; - -	if (priv->batch_fsync_mode && xdata && dict_get (xdata, "batch-fsync")) { -		posix_batch_fsync (frame, this, fd, datasync, xdata); -		return 0; -	} - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd not found in fd's ctx"); -                goto out; -        } - -        _fd = pfd->fd; - -        op_ret = posix_fdstat (this, _fd, &preop); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_FSTAT_FAILED, -                        "pre-operation fstat failed on fd=%p", fd); -                goto out; -        } - -        if (datasync) { -                op_ret = sys_fdatasync (_fd); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FSYNC_FAILED, "fdatasync on fd=%p" -                                "failed:", fd); -                        goto out; -                } -        } else { -                op_ret = sys_fsync (_fd); -                if (op_ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_FSYNC_FAILED, "fsync on fd=%p " -                                "failed", fd); -                        goto out; -                } -        } - -        op_ret = posix_fdstat (this, _fd, &postop); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_FSTAT_FAILED, -                        "post-operation fstat failed on fd=%p", fd); -                goto out; -        } - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (fsync, frame, op_ret, op_errno, &preop, &postop, -                             NULL); - -        return 0; -} - -static int gf_posix_xattr_enotsup_log; -static int -_handle_setxattr_keyvalue_pair (dict_t *d, char *k, data_t *v, -                                void *tmp) -{ -        posix_xattr_filler_t *filler = NULL; - -        filler = tmp; - -        return posix_handle_pair (filler->this, filler->real_path, k, v, -                                  filler->flags, filler->stbuf); -} - -#ifdef GF_DARWIN_HOST_OS -static int -map_xattr_flags(int flags) -{ -        /* DARWIN has different defines on XATTR_ flags. -           There do not seem to be a POSIX standard -           Parse any other flags over. -        */ -        int darwinflags = flags & ~(GF_XATTR_CREATE | GF_XATTR_REPLACE | XATTR_REPLACE); -        if (GF_XATTR_CREATE & flags) -                darwinflags |= XATTR_CREATE; -        if (GF_XATTR_REPLACE & flags) -                darwinflags |= XATTR_REPLACE; -        return darwinflags; -} -#endif - -int32_t -posix_setxattr (call_frame_t *frame, xlator_t *this, -                loc_t *loc, dict_t *dict, int flags, dict_t *xdata) -{ -        int32_t       op_ret                  = -1; -        int32_t       op_errno                = 0; -        char *        real_path               = NULL; -        char         *acl_xattr               = NULL; -        struct iatt   stbuf                   = {0}; -        int32_t       ret                     = 0; -        ssize_t       acl_size                = 0; -        dict_t       *xattr                   = NULL; -        posix_xattr_filler_t filler = {0,}; -        struct  posix_private *priv           = NULL; - -        DECLARE_OLD_FS_ID_VAR; -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); -        VALIDATE_OR_GOTO (dict, out); - -        priv = this->private; -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        MAKE_INODE_HANDLE (real_path, this, loc, NULL); -        if (!real_path) { -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        posix_pstat(this, loc->gfid, real_path, &stbuf); - -        op_ret = -1; - -        dict_del (dict, GFID_XATTR_KEY); -        dict_del (dict, GF_XATTR_VOL_ID_KEY); -        /* the io-stats-dump key should not reach disk */ -        dict_del (dict, GF_XATTR_IOSTATS_DUMP_KEY); - -        filler.real_path = real_path; -        filler.this = this; -        filler.stbuf = &stbuf; - -#ifdef GF_DARWIN_HOST_OS -        filler.flags = map_xattr_flags(flags); -#else -        filler.flags = flags; -#endif -        op_ret = dict_foreach (dict, _handle_setxattr_keyvalue_pair, -                               &filler); -        if (op_ret < 0) { -                op_errno = -op_ret; -                op_ret = -1; -                goto out; -        } - -        xattr = dict_new(); -        if (!xattr) -                goto out; - -/* - * FIXFIX: Send the stbuf info in the xdata for now - * This is used by DHT to redirect FOPs if the file is being migrated - * Ignore errors for now - */ -        if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { -                ret = posix_pstat(this, loc->gfid, real_path, &stbuf); -                if (ret) -                        goto out; - -               ret = posix_set_iatt_in_dict (xattr, &stbuf); -        } - -/* - * ACL can be set on a file/folder using GF_POSIX_ACL_*_KEY xattrs which - * won't aware of access-control xlator. To update its context correctly, - * POSIX_ACL_*_XATTR stored in xdata which is send in the call_back path. - */ -        if (dict_get (dict, GF_POSIX_ACL_ACCESS)) { - -                /* -                 * The size of buffer will be know after calling sys_lgetxattr, -                 * so first we allocate buffer with large size(~4k), then we -                 * reduced into required size using GF_REALLO(). -                 */ -                acl_xattr = GF_CALLOC (1, ACL_BUFFER_MAX, gf_posix_mt_char); -                if (!acl_xattr) -                        goto out; - -                acl_size = sys_lgetxattr (real_path, POSIX_ACL_ACCESS_XATTR, -                                          acl_xattr, ACL_BUFFER_MAX); - -                if (acl_size < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_XATTR_FAILED, "Posix acl is not set " -                                "properly at the backend"); -                        goto out; -                } - -                /* If acl_size is more than max buffer size, just ignore it */ -                if (acl_size >= ACL_BUFFER_MAX) { -                        gf_msg (this->name, GF_LOG_WARNING, ENOMEM, -                                P_MSG_BUFFER_OVERFLOW, "size of acl is more" -                                "than the buffer"); -                        goto out; -                } - -                acl_xattr = GF_REALLOC (acl_xattr, acl_size); -                if (!acl_xattr) -                        goto out; - -                ret = dict_set_bin (xattr, POSIX_ACL_ACCESS_XATTR, -                                    acl_xattr, acl_size); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_SET_XDATA_FAIL, "failed to set" -                                "xdata for acl"); -                        GF_FREE (acl_xattr); -                        goto out; -                } -        } - -        if (dict_get (dict, GF_POSIX_ACL_DEFAULT)) { - -                acl_xattr = GF_CALLOC (1, ACL_BUFFER_MAX, gf_posix_mt_char); -                if (!acl_xattr) -                        goto out; - -                acl_size = sys_lgetxattr (real_path, POSIX_ACL_DEFAULT_XATTR, -                                          acl_xattr, ACL_BUFFER_MAX); - -                if (acl_size < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_XATTR_FAILED, "Posix acl is not set " -                                "properly at the backend"); -                        goto out; -                } - -                if (acl_size >= ACL_BUFFER_MAX) { -                        gf_msg (this->name, GF_LOG_WARNING, ENOMEM, -                                P_MSG_BUFFER_OVERFLOW, "size of acl is more" -                                "than the buffer"); -                        goto out; -                } - -                acl_xattr = GF_REALLOC (acl_xattr, acl_size); -                if (!acl_xattr) -                        goto out; - -                ret = dict_set_bin (xattr, POSIX_ACL_DEFAULT_XATTR, -                                    acl_xattr, acl_size); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_SET_XDATA_FAIL, "failed to set" -                                "xdata for acl"); -                        GF_FREE (acl_xattr); -                        goto out; -                } -        } -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xattr); - -        if (xattr) -                dict_unref (xattr); - -        return 0; -} - - -int -posix_xattr_get_real_filename (call_frame_t *frame, xlator_t *this, loc_t *loc, -			       const char *key, dict_t *dict, dict_t *xdata) -{ -        int            ret        = -1; -        int            op_ret     = -1; -        const char    *fname      = NULL; -        char          *real_path  = NULL; -        char          *found      = NULL; -        DIR           *fd         = NULL; -        struct dirent *entry      = NULL; -        struct dirent  scratch[2] = {{0,},}; - -        MAKE_INODE_HANDLE (real_path, this, loc, NULL); -        if (!real_path) { -                return -ESTALE; -        } -        if (op_ret == -1) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED, -                        "posix_xattr_get_real_filename (lstat) on %s failed", -                        real_path); -                return -errno; -        } - -        fd = sys_opendir (real_path); -        if (!fd) -                return -errno; - -	fname = key + strlen (GF_XATTR_GET_REAL_FILENAME_KEY); - -        for (;;) { -                errno = 0; -                entry = sys_readdir (fd, scratch); -                if (!entry || errno != 0) -                        break; - -		if (strcasecmp (entry->d_name, fname) == 0) { -			found = gf_strdup (entry->d_name); -			if (!found) { -				(void) sys_closedir (fd); -				return -ENOMEM; -			} -			break; -		} -	} - -	(void) sys_closedir (fd); - -	if (!found) -		return -ENOENT; - -	ret = dict_set_dynstr (dict, (char *)key, found); -	if (ret) { -		GF_FREE (found); -		return -ENOMEM; -	} -	ret = strlen (found) + 1; - -	return ret; -} - -int -posix_get_ancestry_directory (xlator_t *this, inode_t *leaf_inode, -                              gf_dirent_t *head, char **path, int type, -                              int32_t *op_errno, dict_t *xdata) -{ -        ssize_t               handle_size = 0; -        struct posix_private *priv        = NULL; -        inode_t              *inode       = NULL; -        int                   ret         = -1; -        char                  dirpath[PATH_MAX] = {0,}; - -        priv = this->private; - -        handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); - -        ret = posix_make_ancestryfromgfid (this, dirpath, PATH_MAX + 1, head, -                                           type | POSIX_ANCESTRY_PATH, -                                           leaf_inode->gfid, -                                           handle_size, priv->base_path, -                                           leaf_inode->table, &inode, xdata, -                                           op_errno); -        if (ret < 0) -                goto out; - - -        /* there is already a reference in loc->inode */ -        inode_unref (inode); - -        if ((type & POSIX_ANCESTRY_PATH) && (path != NULL)) { -                if (strcmp (dirpath, "/")) -                        dirpath[strlen (dirpath) - 1] = '\0'; - -                *path = gf_strdup (dirpath); -        } - -out: -        return ret; -} - -int32_t -posix_links_in_same_directory (char *dirpath, int count, inode_t *leaf_inode, -                               inode_t *parent, struct stat *stbuf, -                               gf_dirent_t *head, char **path, -                               int type, dict_t *xdata, int32_t *op_errno) -{ -        int                   op_ret       = -1; -        gf_dirent_t          *gf_entry     = NULL; -        xlator_t             *this         = NULL; -        struct posix_private *priv         = NULL; -        DIR                  *dirp         = NULL; -        struct dirent        *entry        = NULL; -        struct dirent         scratch[2]   = {{0,},}; -        char                  temppath[PATH_MAX] = {0,}; -        char                  scr[PATH_MAX * 4] = {0,}; - -        this = THIS; - -        priv = this->private; - -        dirp = sys_opendir (dirpath); -        if (!dirp) { -                *op_errno = errno; -                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_OPEN_FAILED, -                        "could not opendir %s", dirpath); -                goto out; -        } - -        while (count > 0) { -                errno = 0; -                entry = sys_readdir (dirp, scratch); -                if (!entry || errno != 0) -                        break; - -                if (entry->d_ino != stbuf->st_ino) -                        continue; - -                /* Linking an inode here, can cause a race in posix_acl. -                   Parent inode gets linked here, but before -                   it reaches posix_acl_readdirp_cbk, create/lookup can -                   come on a leaf-inode, as parent-inode-ctx not yet updated -                   in posix_acl_readdirp_cbk, create and lookup can fail -                   with EACCESS. So do the inode linking in the quota xlator - -                linked_inode = inode_link (leaf_inode, parent, -                                           entry->d_name, NULL); - -                GF_ASSERT (linked_inode == leaf_inode); -                inode_unref (linked_inode);*/ - -                if (type & POSIX_ANCESTRY_DENTRY) { -                        loc_t loc = {0, }; - -                        loc.inode = inode_ref (leaf_inode); -                        gf_uuid_copy (loc.gfid, leaf_inode->gfid); - -                        (void) snprintf (temppath, sizeof(temppath), "%s/%s", -                                         dirpath, entry->d_name); - -                        gf_entry = gf_dirent_for_name (entry->d_name); -                        gf_entry->inode = inode_ref (leaf_inode); -                        gf_entry->dict -                                = posix_xattr_fill (this, temppath, &loc, NULL, -                                                    -1, xdata, NULL); -                        iatt_from_stat (&(gf_entry->d_stat), stbuf); - -                        list_add_tail (&gf_entry->list, &head->list); -                        loc_wipe (&loc); -                } - -                if (type & POSIX_ANCESTRY_PATH) { -                        (void) snprintf (temppath, sizeof(temppath), "%s/%s", -                                         &dirpath[priv->base_path_length], -                                         entry->d_name); -                        if (!*path) { -                                *path = gf_strdup (temppath); -                        } else { -                                /* creating a colon separated */ -                                /* list of hard links */ -                                (void) snprintf (scr, sizeof(scr), "%s:%s", -                                                 *path, temppath); - -                                GF_FREE (*path); -                                *path = gf_strdup (scr); -                        } -                        if (!*path) { -                                op_ret = -1; -                                *op_errno = ENOMEM; -                                goto out; -                        } -                } - -                count--; -        } - -        op_ret = 0; -out: -        if (dirp) { -                op_ret = sys_closedir (dirp); -                if (op_ret == -1) { -                        *op_errno = errno; -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_CLOSE_FAILED, "closedir failed"); -                } -        } - -        return op_ret; -} - -int -posix_get_ancestry_non_directory (xlator_t *this, inode_t *leaf_inode, -                                  gf_dirent_t *head, char **path, int type, -                                  int32_t *op_errno, dict_t *xdata) -{ -        size_t                remaining_size    = 0; -        int                   op_ret            = -1, pathlen = -1; -        ssize_t               handle_size       = 0; -        uuid_t                pgfid             = {0,}; -        int                   nlink_samepgfid   = 0; -        struct stat           stbuf             = {0,}; -        char                 *list              = NULL; -        int32_t               list_offset       = 0; -        struct posix_private *priv              = NULL; -        ssize_t               size              = 0; -        inode_t              *parent            = NULL; -        loc_t                *loc               = NULL; -        char                 *leaf_path         = NULL; -        char                  key[4096]         = {0,}; -        char                  dirpath[PATH_MAX] = {0,}; -        char                  pgfidstr[UUID_CANONICAL_FORM_LEN+1] = {0,}; - -        priv = this->private; - -        loc = GF_CALLOC (1, sizeof (*loc), gf_posix_mt_char); -        if (loc == NULL) { -                op_ret = -1; -                *op_errno = ENOMEM; -                goto out; -        } - -        gf_uuid_copy (loc->gfid, leaf_inode->gfid); - -        MAKE_INODE_HANDLE (leaf_path, this, loc, NULL); -        if (!leaf_path) { -                GF_FREE (loc); -                *op_errno = ESTALE; -                goto out; -        } -        GF_FREE (loc); - -        size = sys_llistxattr (leaf_path, NULL, 0); -        if (size == -1) { -                *op_errno = errno; -                if ((errno == ENOTSUP) || (errno == ENOSYS)) { -                        GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, -                                             this->name, GF_LOG_WARNING, -                                             "Extended attributes not " -                                             "supported (try remounting brick" -                                             " with 'user_xattr' flag)"); - -                } else { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_XATTR_FAILED, "listxattr failed on" -                                "%s", leaf_path); - -                } - -                goto out; -        } - -        if (size == 0) { -                op_ret = 0; -                goto out; -        } - -        list = alloca (size); -        if (!list) { -                *op_errno = errno; -                goto out; -        } - -        size = sys_llistxattr (leaf_path, list, size); -        if (size < 0) { -                op_ret = -1; -                *op_errno = errno; -                goto out; -        } -        remaining_size = size; -        list_offset = 0; - -        op_ret = sys_lstat (leaf_path, &stbuf); -        if (op_ret == -1) { -                *op_errno = errno; -                gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_LSTAT_FAILED, -                        "lstat failed on %s", leaf_path); -                goto out; -        } - -        while (remaining_size > 0) { -                strncpy (key, list + list_offset, sizeof(key)-1); -                key[sizeof(key)-1] = '\0'; -                if (strncmp (key, PGFID_XATTR_KEY_PREFIX, -                             strlen (PGFID_XATTR_KEY_PREFIX)) != 0) -                        goto next; - -                op_ret = sys_lgetxattr (leaf_path, key, -                                        &nlink_samepgfid, -                                        sizeof(nlink_samepgfid)); -                if (op_ret == -1) { -                        *op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_XATTR_FAILED, "getxattr failed on " -                                "%s: key = %s ", leaf_path, key); -                        goto out; -                } - -                nlink_samepgfid = ntoh32 (nlink_samepgfid); - -                strncpy (pgfidstr, key + strlen(PGFID_XATTR_KEY_PREFIX), -                         sizeof(pgfidstr)-1); -                pgfidstr[sizeof(pgfidstr)-1] = '\0'; -                gf_uuid_parse (pgfidstr, pgfid); - -                handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); - -                /* constructing the absolute real path of parent dir */ -                strncpy (dirpath, priv->base_path, sizeof(dirpath)-1); -                dirpath[sizeof(dirpath)-1] = '\0'; -                pathlen = PATH_MAX + 1 - priv->base_path_length; - -                op_ret = posix_make_ancestryfromgfid (this, -                                                      dirpath + priv->base_path_length, -                                                      pathlen, -                                                      head, -                                                      type | POSIX_ANCESTRY_PATH, -                                                      pgfid, -                                                      handle_size, -                                                      priv->base_path, -                                                      leaf_inode->table, -                                                      &parent, xdata, op_errno); -                if (op_ret < 0) { -                        goto next; -                } - -                dirpath[strlen (dirpath) - 1] = '\0'; - -                posix_links_in_same_directory (dirpath, nlink_samepgfid, -                                               leaf_inode, parent, &stbuf, head, -                                               path, type, xdata, op_errno); - -                if (parent != NULL) { -                        inode_unref (parent); -                        parent = NULL; -                } - -        next: -                remaining_size -= strlen (key) + 1; -                list_offset += strlen (key) + 1; -        } /* while (remaining_size > 0) */ - -        op_ret = 0; - -out: -        return op_ret; -} - -int -posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, -                    gf_dirent_t *head, char **path, int type, int32_t *op_errno, -                    dict_t *xdata) -{ -        int                   ret  = -1; -        struct posix_private *priv = NULL; - -        priv = this->private; - -        if (IA_ISDIR (leaf_inode->ia_type)) { -                ret = posix_get_ancestry_directory (this, leaf_inode, -                                                    head, path, type, op_errno, -                                                    xdata); -        } else  { - -                if (!priv->update_pgfid_nlinks) -                        goto out; -                ret = posix_get_ancestry_non_directory (this, leaf_inode, -                                                        head, path, type, -                                                        op_errno, xdata); -        } - -out: -        if (ret && path && *path) { -                GF_FREE (*path); -                *path = NULL; -        } - -        return ret; -} - -/** - * posix_getxattr - this function returns a dictionary with all the - *                  key:value pair present as xattr. used for - *                  both 'listxattr' and 'getxattr'. - */ -int32_t -posix_getxattr (call_frame_t *frame, xlator_t *this, -                loc_t *loc, const char *name, dict_t *xdata) -{ -        struct posix_private *priv                  = NULL; -        int32_t               op_ret                = -1; -        int32_t               op_errno              = 0; -        char                 *value                 = NULL; -        char                 *real_path             = NULL; -        dict_t               *dict                  = NULL; -        char                 *file_contents         = NULL; -        int                   ret                   = -1; -        char                 *path                  = NULL; -        char                 *rpath                 = NULL; -        ssize_t               size                  = 0; -        char                 *list                  = NULL; -        int32_t               list_offset           = 0; -        size_t                remaining_size        = 0; -        char                 *host_buf              = NULL; -        char                 *keybuffer             = NULL; -        char                 *value_buf             = NULL; -        gf_boolean_t          have_val              = _gf_false; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); -        MAKE_INODE_HANDLE (real_path, this, loc, NULL); - -        op_ret = -1; -        priv = this->private; - -        ret = posix_handle_georep_xattrs (frame, name, &op_errno, _gf_true); -        if (ret == -1) { -                op_ret = -1; -                goto out; -        } - -        if (name && posix_is_gfid2path_xattr (name)) { -                op_ret = -1; -                op_errno = ENOATTR; -                goto out; -        } - -        if (loc->inode && IA_ISDIR(loc->inode->ia_type) && name && -            ZR_FILE_CONTENT_REQUEST(name)) { -                ret = posix_get_file_contents (this, loc->gfid, &name[15], -                                               &file_contents); -                if (ret < 0) { -                        op_errno = -ret; -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_FILE_FAILED, "getting file contents" -                                "failed"); -                        goto out; -                } -        } - -        dict = dict_new (); -        if (!dict) { -                op_errno = ENOMEM; -                goto out; -        } - -        if (loc->inode && name && GF_POSIX_ACL_REQUEST (name)) { -                ret = posix_pacl_get (real_path, name, &value); -                if (ret || !value) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_ACL_FAILED, "could not get acl (%s) for" -                                "%s", name, real_path); -                        op_ret = -1; -                        goto out; -                } - -                ret = dict_set_dynstr (dict, (char *)name, value); -                if (ret < 0) { -                        GF_FREE (value); -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_ACL_FAILED, "could not set acl (%s) for" -                                "%s in dictionary", name, real_path); -                        op_ret = -1; -                        op_errno = ENOMEM; -                        goto out; -                } - -                size = ret; -                goto done; -        } - -	if (loc->inode && name && -	    (strncmp (name, GF_XATTR_GET_REAL_FILENAME_KEY, -		      strlen (GF_XATTR_GET_REAL_FILENAME_KEY)) == 0)) { -		ret = posix_xattr_get_real_filename (frame, this, loc, -						     name, dict, xdata); -		if (ret < 0) { -			op_ret = -1; -			op_errno = -ret; -                        if (op_errno == ENOENT) { -                                gf_msg_debug (this->name, 0, "Failed to get " -                                              "real filename (%s, %s)", -                                              loc->path, name); -                        } else { -                                gf_msg (this->name, GF_LOG_WARNING, op_errno, -                                        P_MSG_GETTING_FILENAME_FAILED, -				        "Failed to get real filename (%s, %s):" -                                        , loc->path, name); -                        } -			goto out; -		} - -		size = ret; -		goto done; -	} - -        if (loc->inode && name && !strcmp (name, GLUSTERFS_OPEN_FD_COUNT)) { -                if (!fd_list_empty (loc->inode)) { -                        ret = dict_set_uint32 (dict, (char *)name, 1); -                        if (ret < 0) { -                                gf_msg (this->name, GF_LOG_WARNING, 0, -                                        P_MSG_DICT_SET_FAILED, "Failed to set " -                                        "dictionary value for %s", name); -                                op_errno = ENOMEM; -                                goto out; -                        } -                } else { -                        ret = dict_set_uint32 (dict, (char *)name, 0); -                        if (ret < 0) { -                                gf_msg (this->name, GF_LOG_WARNING, 0, -                                        P_MSG_DICT_SET_FAILED,  "Failed to set " -                                        "dictionary value for %s", name); -                                op_errno = ENOMEM; -                                goto out; -                        } -                } -                goto done; -        } -        if (loc->inode && name && (XATTR_IS_PATHINFO (name))) { -                if (LOC_HAS_ABSPATH (loc)) -                        MAKE_REAL_PATH (rpath, this, loc->path); -                else -                        rpath = real_path; - -                size = gf_asprintf (&host_buf, "<POSIX(%s):%s:%s>", -                                    priv->base_path, -                                    ((priv->node_uuid_pathinfo && -                                     !gf_uuid_is_null(priv->glusterd_uuid)) -                                     ? uuid_utoa (priv->glusterd_uuid) -                                     : priv->hostname), rpath); -                if (size < 0) { -                        op_errno = ENOMEM; -                        goto out; -                } -                ret = dict_set_dynstr (dict, (char *)name, host_buf); -                if (ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_DICT_SET_FAILED, "could not set value" -                                " (%s) in dictionary", host_buf); -                        GF_FREE (host_buf); -                        op_errno = ENOMEM; -                        goto out; -                } - -                goto done; -        } - -        if (loc->inode && name && -            (strcmp (name, GF_XATTR_NODE_UUID_KEY) == 0) -            && !gf_uuid_is_null (priv->glusterd_uuid)) { -                size = gf_asprintf (&host_buf, "%s", -                                    uuid_utoa (priv->glusterd_uuid)); -                if (size == -1) { -                        op_errno = ENOMEM; -                        goto out; -                } -                ret = dict_set_dynstr (dict, GF_XATTR_NODE_UUID_KEY, -                                       host_buf); -                if (ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, -ret, -                                P_MSG_DICT_SET_FAILED, "could not set value" -                                "(%s) in dictionary", host_buf); -                        GF_FREE (host_buf); -                        op_errno = -ret; -                        goto out; -                } -                goto done; -        } - -        if (loc->inode && name && -            (strcmp (name, GFID_TO_PATH_KEY) == 0)) { -                ret = inode_path (loc->inode, NULL, &path); -                if (ret < 0) { -                        op_errno = -ret; -                        gf_msg (this->name, GF_LOG_WARNING, op_errno, -                                P_MSG_INODE_PATH_GET_FAILED, -                                "%s: could not get " -                                "inode path", uuid_utoa (loc->inode->gfid)); -                        goto out; -                } - -                size = ret; -                ret = dict_set_dynstr (dict, GFID_TO_PATH_KEY, path); -                if (ret < 0) { -                        op_errno = ENOMEM; -                        GF_FREE (path); -                        goto out; -                } -                goto done; -        } - -        if (loc->inode && name && -            (strcmp (name, GFID2PATH_VIRT_XATTR_KEY) == 0)) { -                if (!priv->gfid2path) { -                        op_errno = ENOATTR; -                        op_ret = -1; -                        goto out; -                } -                ret = posix_get_gfid2path (this, loc->inode, real_path, -                                           &op_errno, dict); -                if (ret < 0) { -                        op_ret = -1; -                        goto out; -                } -                size = ret; -                goto done; -        } - -        if (loc->inode && name -            && (strcmp (name, GET_ANCESTRY_PATH_KEY) == 0)) { -                int type = POSIX_ANCESTRY_PATH; - -                op_ret = posix_get_ancestry (this, loc->inode, NULL, -                                             &path, type, &op_errno, -                                             xdata); -                if (op_ret < 0) { -                        op_ret = -1; -                        op_errno = ENODATA; -                        goto out; -                } -                size = op_ret; -                op_ret = dict_set_dynstr (dict, GET_ANCESTRY_PATH_KEY, path); -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, -op_ret, -                                P_MSG_GET_KEY_VALUE_FAILED, "could not get " -                                "value for key (%s)", GET_ANCESTRY_PATH_KEY); -                        GF_FREE (path); -                        op_errno = ENOMEM; -                        goto out; -                } - -                goto done; -        } - -        if (loc->inode && name -             && (strncmp (name, GLUSTERFS_GET_OBJECT_SIGNATURE, -                          strlen (GLUSTERFS_GET_OBJECT_SIGNATURE)) == 0)) { -                op_ret = posix_get_objectsignature (real_path, dict); -                if (op_ret < 0) { -                        op_errno = -op_ret; -                        goto out; -                } - -                goto done; -        } - -        /* here allocate value_buf of 8192 bytes to avoid one extra getxattr -           call,If buffer size is small to hold the xattr result then it will -           allocate a new buffer value of required size and call getxattr again -        */ - -        value_buf = alloca (XATTR_VAL_BUF_SIZE); -        if (name) { -                char *key = (char *)name; - -                keybuffer = key; -#if defined(GF_DARWIN_HOST_OS_DISABLED) -                if (priv->xattr_user_namespace == XATTR_STRIP) { -                        if (strncmp(key, "user.",5) == 0) { -                                key += 5; -                                gf_msg_debug (this->name, 0, "getxattr for file %s" -                                        " stripping user key: %s -> %s", -                                        real_path, keybuffer, key); -                        } -                } -#endif -                memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); -                size = sys_lgetxattr (real_path, key, value_buf, -                                      XATTR_VAL_BUF_SIZE-1); -                if (size >= 0) { -                        have_val = _gf_true; -                } else { -                        if (errno == ERANGE) { -                                gf_msg (this->name, GF_LOG_INFO, errno, -                                        P_MSG_XATTR_FAILED, -                                        "getxattr failed due to overflow of buffer" -                                        " on %s: %s ", real_path, key); -                                size = sys_lgetxattr (real_path, key, NULL, 0); -                        } -                        if (size == -1) { -                                op_errno = errno; -                                if ((op_errno == ENOTSUP) || -                                                         (op_errno == ENOSYS)) { -                                        GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, -                                                             this->name, -                                                             GF_LOG_WARNING, -                                                             "Extended attributes not " -                                                             "supported (try remounting" -                                                             " brick with 'user_xattr' " -                                                             "flag)"); -                                } -                                if ((op_errno == ENOATTR) || -                                                       (op_errno == ENODATA)) { -                                        gf_msg_debug (this->name, 0, -                                                      "No such attribute:%s for file %s", -                                                      key, real_path); -                                } else { -                                        gf_msg (this->name, GF_LOG_ERROR, -                                                op_errno, P_MSG_XATTR_FAILED, -                                                "getxattr failed on %s: %s ", -                                                real_path, key); -                                } -                                goto out; -                        } -                } -                value = GF_CALLOC (size + 1, sizeof(char), gf_posix_mt_char); -                if (!value) { -                        op_ret = -1; -                        op_errno = ENOMEM; -                        goto out; -                } -                if (have_val) { -                        memcpy (value, value_buf, size); -                } else { -                        size = sys_lgetxattr (real_path, key, value, size); -                        if (size == -1) { -                                op_ret = -1; -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, -                                        "getxattr failed on %s: key = %s", -                                        real_path, key); -                                GF_FREE (value); -                                goto out; -                        } -                } -                value [size] = '\0'; -                op_ret = dict_set_dynptr (dict, key, value, size); -                if (op_ret < 0) { -                        op_errno = -op_ret; -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_DICT_SET_FAILED, "dict set operation " -                                "on %s for the key %s failed.", real_path, key); -                        GF_FREE (value); -                        goto out; -                } - -                goto done; -        } - -        have_val = _gf_false; -        memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); -        size = sys_llistxattr (real_path, value_buf, XATTR_VAL_BUF_SIZE-1); -        if (size > 0) { -                have_val = _gf_true; -        } else { -                if (errno == ERANGE) { -                        gf_msg (this->name, GF_LOG_INFO, errno, -                                P_MSG_XATTR_FAILED, -                                "listxattr failed due to overflow of buffer" -                                " on %s ", real_path); -                        size = sys_llistxattr (real_path, NULL, 0); -                } -                if (size == -1) { -                        op_errno = errno; -                        if ((errno == ENOTSUP) || (errno == ENOSYS)) { -                                GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, -                                                     this->name, GF_LOG_WARNING, -                                                     "Extended attributes not " -                                                     "supported (try remounting" -                                                     " brick with 'user_xattr' " -                                                     "flag)"); -                        } else { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, -                                        "listxattr failed on %s", real_path); -                        } -                        goto out; -                } -                if (size == 0) -                        goto done; -        } -        list = alloca (size); -        if (!list) { -                op_errno = errno; -                goto out; -        } -        if (have_val) { -                memcpy (list, value_buf, size); -        } else { -                size = sys_llistxattr (real_path, list, size); -                if (size < 0) { -                        op_ret = -1; -                        op_errno = errno; -                        goto out; -                } -        } -        remaining_size = size; -        list_offset = 0; -        keybuffer = alloca (XATTR_KEY_BUF_SIZE); -        while (remaining_size > 0) { -                strncpy (keybuffer, list + list_offset, XATTR_KEY_BUF_SIZE-1); -                keybuffer[XATTR_KEY_BUF_SIZE-1] = '\0'; - -                ret = posix_handle_georep_xattrs (frame, keybuffer, NULL, -                                                  _gf_false); -                if (ret == -1) -                        goto ignore; - -                if (posix_is_gfid2path_xattr (keybuffer)) { -                        goto ignore; -                } - -                memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); -                have_val = _gf_false; -                size = sys_lgetxattr (real_path, keybuffer, value_buf, -                                      XATTR_VAL_BUF_SIZE-1); -                if (size >= 0) { -                        have_val = _gf_true; -                } else { -                        if (errno == ERANGE) { -                                gf_msg (this->name, GF_LOG_INFO, op_errno, -                                        P_MSG_XATTR_FAILED, -                                        "getxattr failed due to overflow of" -                                        "  buffer on %s: %s ", real_path, -                                        keybuffer); -                                size = sys_lgetxattr (real_path, keybuffer, -                                                      NULL, 0); -                        } -                        if (size == -1) { -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, "getxattr failed on" -                                        " %s: key = %s ", real_path, keybuffer); -                                goto out; -                        } -                } -                value = GF_CALLOC (size + 1, sizeof(char), -                                   gf_posix_mt_char); -                if (!value) { -                        op_errno = errno; -                        goto out; -                } -                if (have_val) { -                        memcpy (value, value_buf, size); -                } else { -                        size = sys_lgetxattr (real_path, keybuffer, value, size); -                        if (size == -1) { -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, "getxattr failed on" -                                        " %s: key = %s ", real_path, keybuffer); -                                GF_FREE (value); -                                goto out; -                        } -                } -                value [size] = '\0'; -#ifdef GF_DARWIN_HOST_OS -                /* The protocol expect namespace for now */ -                char *newkey = NULL; -                gf_add_prefix (XATTR_USER_PREFIX, keybuffer, &newkey); -                strncpy (keybuffer, newkey, sizeof(keybuffer)); -                GF_FREE (newkey); -#endif -                op_ret = dict_set_dynptr (dict, keybuffer, value, size); -                if (op_ret < 0) { -                        op_errno = -op_ret; -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_DICT_SET_FAILED, "dict set operation " -                                "on %s for the key %s failed.", real_path, -                                keybuffer); -                        GF_FREE (value); -                        goto out; -                } - -ignore: -                remaining_size -= strlen (keybuffer) + 1; -                list_offset += strlen (keybuffer) + 1; - -        } /* while (remaining_size > 0) */ - -done: -        op_ret = size; - -        if (dict) { -                dict_del (dict, GFID_XATTR_KEY); -                dict_del (dict, GF_XATTR_VOL_ID_KEY); -        } - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, NULL); - -        if (dict) { -                dict_unref (dict); -        } - -        return 0; -} - - -int32_t -posix_fgetxattr (call_frame_t *frame, xlator_t *this, -                 fd_t *fd, const char *name, dict_t *xdata) -{ -        int32_t           op_ret         = -1; -        int32_t           op_errno       = EINVAL; -        struct posix_fd * pfd            = NULL; -        int               _fd            = -1; -        int32_t           list_offset    = 0; -        ssize_t           size           = 0; -        size_t            remaining_size = 0; -        char *            value          = NULL; -        char *            list           = NULL; -        dict_t *          dict           = NULL; -        int               ret            = -1; -        char              key[4096]      = {0,}; -        char             *value_buf      = NULL; -        gf_boolean_t      have_val        = _gf_false; - -        DECLARE_OLD_FS_ID_VAR; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                op_ret = -1; -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL from fd=%p", fd); -                goto out; -        } - -        _fd = pfd->fd; - -        /* Get the total size */ -        dict = dict_new (); -        if (!dict) { -                op_ret = -1; -                op_errno = ENOMEM; -                goto out; -        } - -        if (name && !strcmp (name, GLUSTERFS_OPEN_FD_COUNT)) { -                ret = dict_set_uint32 (dict, (char *)name, 1); -                if (ret < 0) { -                        op_ret = -1; -                        size = -1; -                        op_errno = ENOMEM; -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_DICT_SET_FAILED, "Failed to set " -                                "dictionary value for %s", name); -                        goto out; -                } -                goto done; -        } - -        if (name && strncmp (name, GLUSTERFS_GET_OBJECT_SIGNATURE, -                      strlen (GLUSTERFS_GET_OBJECT_SIGNATURE)) == 0) { -                op_ret = posix_fdget_objectsignature (_fd, dict); -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, 0, -                                "posix_fdget_objectsignature failed"); -                        op_errno = -op_ret; -                        op_ret = -1; -                        size = -1; -                        goto out; -                } - -                goto done; -        } - -        /* here allocate value_buf of 8192 bytes to avoid one extra getxattr -           call,If buffer size is small to hold the xattr result then it will -           allocate a new buffer value of required size and call getxattr again -        */ -        value_buf = alloca (XATTR_VAL_BUF_SIZE); -        memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); - -        if (name) { -                strncpy (key, name, sizeof(key)); -#ifdef GF_DARWIN_HOST_OS -                struct posix_private *priv       = NULL; -                priv = this->private; -                if (priv->xattr_user_namespace == XATTR_STRIP) { -                        char *newkey = NULL; -                        gf_add_prefix (XATTR_USER_PREFIX, key, &newkey); -                        strncpy (key, newkey, sizeof(key)); -                        GF_FREE (newkey); -                } -#endif -                size = sys_fgetxattr (_fd, key, value_buf, -                                      XATTR_VAL_BUF_SIZE-1); -                if (size >= 0) { -                        have_val = _gf_true; -                } else { -                        if (errno == ERANGE) { -                                gf_msg (this->name, GF_LOG_INFO, errno, -                                        P_MSG_XATTR_FAILED, -                                        "fgetxattr failed due to overflow of" -                                        "buffer  on %s ", key); -                                size = sys_fgetxattr (_fd, key, NULL, 0); -                        } -                        if (size == -1) { -                                op_errno = errno; -                                if (errno == ENODATA || errno == ENOATTR) { -                                        gf_msg_debug (this->name, 0, "fgetxattr" -                                                      " failed on key %s (%s)", -                                                      key, strerror (op_errno)); -                                } else { -                                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                                P_MSG_XATTR_FAILED, "fgetxattr" -                                                " failed on key %s", key); -                                } -                                goto done; -                        } -                } -                value = GF_CALLOC (size + 1, sizeof(char), gf_posix_mt_char); -                if (!value) { -                        op_ret = -1; -                        op_errno = ENOMEM; -                        goto out; -                } -                if (have_val) { -                        memcpy (value, value_buf, size); -                } else { -                        size = sys_fgetxattr (_fd, key, value, size); -                        if (size == -1) { -                                op_ret = -1; -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, "fgetxattr" -                                        " failed on fd %p for the key %s ", -                                        fd, key); -                                GF_FREE (value); -                                goto out; -                        } -                } - -                value [size] = '\0'; -                op_ret = dict_set_dynptr (dict, key, value, size); -                if (op_ret < 0) { -                        op_errno = -op_ret; -                        op_ret = -1; -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_DICT_SET_FAILED, "dict set operation " -                                "on key %s failed", key); -                        GF_FREE (value); -                        goto out; -                } - -                goto done; -        } -        memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); -        size = sys_flistxattr (_fd, value_buf, XATTR_VAL_BUF_SIZE-1); -        if (size > 0) { -                have_val = _gf_true; -        } else { -                if (errno == ERANGE) { -                        gf_msg (this->name, GF_LOG_INFO, errno, -                                P_MSG_XATTR_FAILED, -                                "listxattr failed due to overflow of buffer" -                                " on %p ", fd); -                        size = sys_flistxattr (_fd, NULL, 0); -                } -                if (size == -1) { -                        op_ret = -1; -                        op_errno = errno; -                        if ((errno == ENOTSUP) || (errno == ENOSYS)) { -                                GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, -                                                     this->name, GF_LOG_WARNING, -                                                     "Extended attributes not " -                                                     "supported (try remounting " -                                                     "brick with 'user_xattr' flag)"); -                        } else { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, "listxattr failed " -                                        "on %p:", fd); -                        } -                        goto out; -                } -                if (size == 0) -                        goto done; -        } -        list = alloca (size + 1); -        if (!list) { -                op_ret = -1; -                op_errno = ENOMEM; -                goto out; -        } -        if (have_val) -                memcpy (list, value_buf, size); -        else -                size = sys_flistxattr (_fd, list, size); - -        remaining_size = size; -        list_offset = 0; -        while (remaining_size > 0) { -                if(*(list + list_offset) == '\0') -                        break; - -                strncpy (key, list + list_offset, sizeof(key)); -                memset (value_buf, '\0', XATTR_VAL_BUF_SIZE); -                have_val = _gf_false; -                size = sys_fgetxattr (_fd, key, value_buf, -                                      XATTR_VAL_BUF_SIZE-1); -                if (size >= 0) { -                        have_val = _gf_true; -                } else { -                        if (errno == ERANGE) { -                                gf_msg (this->name, GF_LOG_INFO, errno, -                                        P_MSG_XATTR_FAILED, -                                        "fgetxattr failed due to overflow of buffer" -                                        " on fd %p: for the key %s ", fd, key); -                                size = sys_fgetxattr (_fd, key, NULL, 0); -                        } -                        if (size == -1) { -                                op_ret = -1; -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, "fgetxattr failed " -                                        "on fd %p for the key %s ", fd, key); -                                break; -                        } -                } -                value = GF_CALLOC (size + 1, sizeof(char), -                                   gf_posix_mt_char); -                if (!value) { -                        op_ret = -1; -                        op_errno = errno; -                        goto out; -                } -                if (have_val) { -                        memcpy (value, value_buf, size); -                } else { -                        size = sys_fgetxattr (_fd, key, value, size); -                        if (size == -1) { -                                op_ret = -1; -                                op_errno = errno; -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_XATTR_FAILED, "fgetxattr failed o" -                                        "n the fd %p for the key %s ", fd, key); -                                GF_FREE (value); -                                break; -                        } -                } -                value [size] = '\0'; - -                op_ret = dict_set_dynptr (dict, key, value, size); -                if (op_ret) { -                        op_errno = -op_ret; -                        op_ret = -1; -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_DICT_SET_FAILED, "dict set operation " -                                "failed on key %s", key); -                        GF_FREE (value); -                        goto out; -                } -                remaining_size -= strlen (key) + 1; -                list_offset += strlen (key) + 1; - -        } /* while (remaining_size > 0) */ - -done: -        op_ret = size; - -        if (dict) { -                dict_del (dict, GFID_XATTR_KEY); -                dict_del (dict, GF_XATTR_VOL_ID_KEY); -        } - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, NULL); - -        if (dict) -                dict_unref (dict); - -        return 0; -} - -static int -_handle_fsetxattr_keyvalue_pair (dict_t *d, char *k, data_t *v, -                                void *tmp) -{ -        posix_xattr_filler_t *filler = NULL; - -        filler = tmp; - -        return posix_fhandle_pair (filler->this, filler->fdnum, k, v, -                                   filler->flags, filler->stbuf); -} - -int32_t -posix_fsetxattr (call_frame_t *frame, xlator_t *this, -                 fd_t *fd, dict_t *dict, int flags, dict_t *xdata) -{ -        int32_t            op_ret         = -1; -        int32_t            op_errno       = 0; -        struct posix_fd   *pfd            = NULL; -        int                _fd            = -1; -        int                ret            = -1; -        struct  iatt       stbuf          = {0,}; -        dict_t            *xattr          = NULL; -        posix_xattr_filler_t filler       = {0,}; -        struct  posix_private *priv       = NULL; - -        DECLARE_OLD_FS_ID_VAR; -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); -        VALIDATE_OR_GOTO (dict, out); - -        priv = this->private; -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL from fd=%p", fd); -                goto out; -        } -        _fd = pfd->fd; - -        ret = posix_fdstat (this, pfd->fd, &stbuf); -        if (ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, op_errno, -                        P_MSG_FSTAT_FAILED, "fsetxattr (fstat)" -                        "failed on fd=%p", fd); -                goto out; -        } - -        dict_del (dict, GFID_XATTR_KEY); -        dict_del (dict, GF_XATTR_VOL_ID_KEY); - -        filler.fdnum = _fd; -        filler.this = this; -        filler.stbuf = &stbuf; -#ifdef GF_DARWIN_HOST_OS -        filler.flags = map_xattr_flags(flags); -#else -        filler.flags = flags; -#endif -        op_ret = dict_foreach (dict, _handle_fsetxattr_keyvalue_pair, -                               &filler); -        if (op_ret < 0) { -                op_errno = -op_ret; -                op_ret = -1; -        } - -        if (!ret && xdata && dict_get (xdata, GLUSTERFS_DURABLE_OP)) { -                op_ret = sys_fsync (_fd); -                if (op_ret < 0) { -                        op_ret = -1; -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_DURABILITY_REQ_NOT_SATISFIED, -                                "could not satisfy durability request: " -                                "reason "); -                } -        } - -        if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { -                ret = posix_fdstat (this, pfd->fd, &stbuf); -                if (ret == -1) { -                        op_errno = errno; -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_XATTR_FAILED, "fsetxattr (fstat)" -                                "failed on fd=%p", fd); -                        goto out; -                } - -                xattr = dict_new (); -                if (!xattr) -                        goto out; -                ret = posix_set_iatt_in_dict (xattr, &stbuf); -        } - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xattr); - -        if (xattr) -                dict_unref (xattr); - -        return 0; -} - -int -_posix_remove_xattr (dict_t *dict, char *key, data_t *value, void *data) -{ -        int32_t               op_ret   = 0; -        xlator_t             *this     = NULL; -        posix_xattr_filler_t *filler   = NULL; - -        filler = (posix_xattr_filler_t *) data; -        this = filler->this; -#ifdef GF_DARWIN_HOST_OS -        struct posix_private  *priv = NULL; -        priv = (struct posix_private *) this->private; -        char *newkey = NULL; -        if (priv->xattr_user_namespace == XATTR_STRIP) { -                gf_remove_prefix (XATTR_USER_PREFIX, key, &newkey); -                gf_msg_debug ("remove_xattr", 0, "key %s => %s" , key, -                       newkey); -                key = newkey; -        } -#endif -    /* Bulk remove xattr is internal fop in gluster. Some of the xattrs may -     * have special behavior. Ex: removexattr("posix.system_acl_access"), -     * removes more than one xattr on the file that could be present in the -     * bulk-removal request.  Removexattr of these deleted xattrs will fail -     * with either ENODATA/ENOATTR.  Since all this fop cares is removal of the -     * xattrs in bulk-remove request and if they are already deleted, it can be -     * treated as success. -     */ - -        if (filler->real_path) -                op_ret = sys_lremovexattr (filler->real_path, key); -        else -                op_ret = sys_fremovexattr (filler->fdnum, key); - -        if (op_ret == -1) { -                if (errno == ENODATA || errno == ENOATTR) -                        op_ret = 0; -        } - -        if (op_ret == -1) { -                filler->op_errno = errno; -                if (errno != ENOATTR && errno != ENODATA && errno != EPERM) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_XATTR_FAILED, "removexattr failed on " -                                "file/dir %s with gfid: %s (for %s)", -                                filler->real_path?filler->real_path:"", -                                uuid_utoa (filler->inode->gfid), key); -                } -        } -#ifdef GF_DARWIN_HOST_OS -        GF_FREE(newkey); -#endif -        return op_ret; -} - -int -posix_common_removexattr (call_frame_t *frame, loc_t *loc, fd_t *fd, -                          const char *name, dict_t *xdata, int *op_errno, -                          dict_t **xdata_rsp) -{ -        gf_boolean_t         bulk_removexattr = _gf_false; -        gf_boolean_t         disallow         = _gf_false; -        char                 *real_path       = NULL; -        struct posix_fd      *pfd             = NULL; -        int                  op_ret           = 0; -        struct iatt          stbuf            = {0}; -        int                  ret              = 0; -        int                  _fd              = -1; -        xlator_t             *this            = frame->this; -        inode_t              *inode           = NULL; -        posix_xattr_filler_t filler           = {0}; - -        DECLARE_OLD_FS_ID_VAR; - -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        if (loc) { -                MAKE_INODE_HANDLE (real_path, this, loc, NULL); -                if (!real_path) { -                        op_ret = -1; -                        *op_errno = ESTALE; -                        goto out; -                } -                inode = loc->inode; -        } else { -                op_ret = posix_fd_ctx_get (fd, this, &pfd, op_errno); -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, *op_errno, -                                P_MSG_PFD_NULL, "pfd is NULL from fd=%p", fd); -                        goto out; -                } -                _fd = pfd->fd; -                inode = fd->inode; -        } - -        if (posix_is_gfid2path_xattr (name)) { -                op_ret = -1; -                *op_errno = ENOATTR; -                goto out; -        } - -        if (gf_get_index_by_elem (disallow_removexattrs, (char *)name) >= 0) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_XATTR_NOT_REMOVED, -                        "Remove xattr called on %s for file/dir %s with gfid: " -                        "%s", name, real_path?real_path:"", -                        uuid_utoa(inode->gfid)); -                op_ret = -1; -                *op_errno = EPERM; -                goto out; -        } else if (posix_is_bulk_removexattr ((char *)name, xdata)) { -                bulk_removexattr = _gf_true; -                (void) dict_has_key_from_array (xdata, disallow_removexattrs, -                                                &disallow); -                if (disallow) { -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_XATTR_NOT_REMOVED, -                                "Bulk removexattr has keys that shouldn't be " -                                "removed for file/dir %s with gfid: %s", -                                real_path?real_path:"", uuid_utoa(inode->gfid)); -                        op_ret = -1; -                        *op_errno = EPERM; -                        goto out; -                } -        } - -        if (bulk_removexattr) { -                filler.real_path = real_path; -                filler.this = this; -                filler.fdnum = _fd; -                filler.inode = inode; -                op_ret = dict_foreach (xdata, _posix_remove_xattr, &filler); -                if (op_ret) { -                        *op_errno = filler.op_errno; -                        goto out; -                } -        } else { -                if (loc) -                        op_ret = sys_lremovexattr (real_path, name); -                else -                        op_ret = sys_fremovexattr (_fd, name); -                if (op_ret == -1) { -                        *op_errno = errno; -                        if (*op_errno != ENOATTR && *op_errno != ENODATA && -                            *op_errno != EPERM) { -                                gf_msg (this->name, GF_LOG_ERROR, *op_errno, -                                        P_MSG_XATTR_FAILED, -                                        "removexattr on %s with gfid %s " -                                        "(for %s)", real_path, -                                        uuid_utoa (inode->gfid), name); -                        } -                        goto out; -                } -        } - -        if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) { -                if (loc) -                        ret = posix_pstat(this, loc->gfid, real_path, &stbuf); -                else -                        ret = posix_fdstat (this, _fd, &stbuf); -                if (ret) -                        goto out; -                *xdata_rsp = dict_new(); -                if (!*xdata_rsp) -                        goto out; - -                ret = posix_set_iatt_in_dict (*xdata_rsp, &stbuf); -        } -        op_ret = 0; -out: -        SET_TO_OLD_FS_ID (); -        return op_ret; -} - -int32_t -posix_removexattr (call_frame_t *frame, xlator_t *this, -                   loc_t *loc, const char *name, dict_t *xdata) -{ -        int    op_ret     = 0; -        int    op_errno   = 0; -        dict_t *xdata_rsp = NULL; - -        op_ret = posix_common_removexattr (frame, loc, NULL, name, xdata, -                                           &op_errno, &xdata_rsp); -        STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, xdata_rsp); - -        if (xdata_rsp) -                dict_unref (xdata_rsp); - -        return 0; -} - -int32_t -posix_fremovexattr (call_frame_t *frame, xlator_t *this, -                    fd_t *fd, const char *name, dict_t *xdata) -{ -        int32_t op_ret     = 0; -        int32_t op_errno   = 0; -        dict_t  *xdata_rsp = NULL; - -        op_ret = posix_common_removexattr (frame, NULL, fd, name, xdata, -                                           &op_errno, &xdata_rsp); -        STACK_UNWIND_STRICT (fremovexattr, frame, op_ret, op_errno, xdata_rsp); - -        if (xdata_rsp) -                dict_unref (xdata_rsp); - -        return 0; -} - - -int32_t -posix_fsyncdir (call_frame_t *frame, xlator_t *this, -                fd_t *fd, int datasync, dict_t *xdata) -{ -        int32_t           op_ret   = -1; -        int32_t           op_errno = 0; -        int               ret      = -1; -        struct posix_fd  *pfd      = NULL; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL, fd=%p", fd); -                goto out; -        } - -        op_ret = 0; - -out: -        STACK_UNWIND_STRICT (fsyncdir, frame, op_ret, op_errno, NULL); - -        return 0; -} - - -void -posix_print_xattr (dict_t *this, -                   char *key, -                   data_t *value, -                   void *data) -{ -        gf_msg_debug ("posix", 0, -                "(key/val) = (%s/%d)", key, data_to_int32 (value)); -} - - -/** - * add_array - add two arrays of 32-bit numbers (stored in network byte order) - * dest = dest + src - * @count: number of 32-bit numbers - * FIXME: handle overflow - */ - -static void -__add_array (int32_t *dest, int32_t *src, int count) -{ -        int     i = 0; -        int32_t destval = 0; -        for (i = 0; i < count; i++) { -                destval = ntoh32 (dest[i]); -                dest[i] = hton32 (destval + ntoh32 (src[i])); -        } -} - -static void -__add_long_array (int64_t *dest, int64_t *src, int count) -{ -        int i = 0; -        for (i = 0; i < count; i++) { -                dest[i] = hton64 (ntoh64 (dest[i]) + ntoh64 (src[i])); -        } -} - - -/* functions: -       __add_array_with_default -       __add_long_array_with_default - -   xattrop type: -       GF_XATTROP_ADD_ARRAY_WITH_DEFAULT -       GF_XATTROP_ADD_ARRAY64_WITH_DEFAULT - -   These operations are similar to 'GF_XATTROP_ADD_ARRAY', -   except that it adds a default value if xattr is missing -   or its value is zero on disk. - -   One use-case of this operation is in inode-quota. -   When a new directory is created, its default dir_count -   should be set to 1. So when a xattrop performed setting -   inode-xattrs, it should account initial dir_count -   1 if the xattrs are not present - -   Here is the usage of this operation - -   value required in xdata for each key -   struct array { -       int32_t   newvalue_1; -       int32_t   newvalue_2; -       ... -       int32_t   newvalue_n; -       int32_t   default_1; -       int32_t   default_2; -       ... -       int32_t   default_n; -   }; - -   or - -   struct array { -       int32_t   value_1; -       int32_t   value_2; -       ... -       int32_t   value_n; -   } data[2]; -   fill data[0] with new value to add -   fill data[1] with default value - -   xattrop GF_XATTROP_ADD_ARRAY_WITH_DEFAULT -   for i from 1 to n -   { -       if (xattr (dest_i) is zero or not set in the disk) -           dest_i = newvalue_i + default_i -       else -           dest_i = dest_i + newvalue_i -   } - -   value in xdata after xattrop is successful -   struct array { -       int32_t   dest_1; -       int32_t   dest_2; -       ... -       int32_t   dest_n; -   }; -*/ -static void -__add_array_with_default (int32_t *dest, int32_t *src, int count) -{ -        int     i       = 0; -        int32_t destval = 0; - -        for (i = 0; i < count; i++) { -                destval = ntoh32 (dest[i]); -                if (destval == 0) -                        dest[i] = hton32 (ntoh32 (src[i]) + -                                          ntoh32 (src[count + i])); -                else -                        dest[i] = hton32 (destval + ntoh32 (src[i])); -        } -} - -static void -__add_long_array_with_default (int64_t *dest, int64_t *src, int count) -{ -        int     i       = 0; -        int64_t destval = 0; - -        for (i = 0; i < count; i++) { -                destval = ntoh64 (dest[i]); -                if (destval == 0) -                        dest[i] = hton64 (ntoh64 (src[i]) + -                                          ntoh64 (src[i + count])); -                else -                        dest[i] = hton64 (destval + ntoh64 (src[i])); -        } -} - -static int -_posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v, -                                   void *tmp) -{ -        int                   size     = 0; -        int                   count    = 0; -        int                   op_ret   = 0; -        int                   op_errno = 0; -        gf_xattrop_flags_t    optype   = 0; -        char                 *array    = NULL; -        char                 *dst_data = NULL; -        inode_t              *inode    = NULL; -        xlator_t             *this     = NULL; -        posix_xattr_filler_t *filler   = NULL; -        posix_inode_ctx_t    *ctx      = NULL; - -        filler = tmp; - -        optype = (gf_xattrop_flags_t)(filler->flags); -        this = filler->this; -        inode = filler->inode; -        count = v->len; -        if (optype == GF_XATTROP_ADD_ARRAY_WITH_DEFAULT || -            optype == GF_XATTROP_ADD_ARRAY64_WITH_DEFAULT) -                count = count / 2; - -        array = GF_CALLOC (count, sizeof (char), gf_posix_mt_char); - -#ifdef GF_DARWIN_HOST_OS -        struct posix_private *priv     = NULL; -        priv = this->private; -        if (priv->xattr_user_namespace == XATTR_STRIP) { -                if (strncmp(k, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) == 0) { -                        k += XATTR_USER_PREFIX_LEN; -                } -        } -#endif -        op_ret = posix_inode_ctx_get_all (inode, this, &ctx); -        if (op_ret < 0) { -                op_errno = ENOMEM; -                goto out; -        } - -        pthread_mutex_lock (&ctx->xattrop_lock); -        { -                if (filler->real_path) { -                        size = sys_lgetxattr (filler->real_path, k, -                                              (char *)array, count); -                } else { -                        size = sys_fgetxattr (filler->fdnum, k, (char *)array, -                                              count); -                } - -                op_errno = errno; -                if ((size == -1) && (op_errno != ENODATA) && -                    (op_errno != ENOATTR)) { -                        if (op_errno == ENOTSUP) { -                                GF_LOG_OCCASIONALLY(gf_posix_xattr_enotsup_log, -                                                    this->name, GF_LOG_WARNING, -                                                    "Extended attributes not " -                                                    "supported by filesystem"); -                        } else if (op_errno != ENOENT || -                                   !posix_special_xattr (marker_xattrs, -                                                         k)) { -                                if (filler->real_path) -                                        gf_msg (this->name, fop_log_level (GF_FOP_XATTROP, -                                                op_errno),  op_errno, P_MSG_XATTR_FAILED, -                                                "getxattr failed on %s while " -                                                "doing xattrop: Key:%s ", -                                                filler->real_path, k); -                                else -                                        gf_msg (this->name, GF_LOG_ERROR, -                                                op_errno, P_MSG_XATTR_FAILED, -                                                "fgetxattr failed on gfid=%s " -                                                "while doing xattrop: " -                                                "Key:%s (%s)", -                                                uuid_utoa (filler->inode->gfid), -                                                k, strerror (op_errno)); -                        } - -                        op_ret = -1; -                        goto unlock; -                } - -                if (size == -1 && optype == GF_XATTROP_GET_AND_SET) { -                        GF_FREE (array); -                        array = NULL; -                } - -                /* We only write back the xattr if it has been really modified -                 * (i.e. v->data is not all 0's). Otherwise we return its value -                 * but we don't update anything. -                 * -                 * If the xattr does not exist, a value of all 0's is returned -                 * without creating it. */ -                size = count; -                if (optype != GF_XATTROP_GET_AND_SET && -                    mem_0filled(v->data, v->len) == 0) -                        goto unlock; - -                dst_data = array; -                switch (optype) { - -                case GF_XATTROP_ADD_ARRAY: -                        __add_array ((int32_t *) array, -                                     (int32_t *) v->data, count / 4); -                        break; - -                case GF_XATTROP_ADD_ARRAY64: -                        __add_long_array ((int64_t *) array, -                                          (int64_t *) v->data, -                                          count / 8); -                        break; - -                case GF_XATTROP_ADD_ARRAY_WITH_DEFAULT: -                        __add_array_with_default ((int32_t *) array, -                                                  (int32_t *) v->data, -                                                  count / 4); -                        break; - -                case GF_XATTROP_ADD_ARRAY64_WITH_DEFAULT: -                        __add_long_array_with_default ((int64_t *) array, -                                                       (int64_t *) v->data, -                                                       count / 8); -                        break; - -                case GF_XATTROP_GET_AND_SET: -                        dst_data = v->data; -                        break; - -                default: -                        gf_msg (this->name, GF_LOG_ERROR, EINVAL, -                                P_MSG_UNKNOWN_OP, "Unknown xattrop type (%d)" -                                " on %s. Please send a bug report to " -                                "gluster-devel@gluster.org", optype, -                                filler->real_path); -                        op_ret = -1; -                        op_errno = EINVAL; -                        goto unlock; -                } - -                if (filler->real_path) { -                        size = sys_lsetxattr (filler->real_path, k, -                                              dst_data, count, 0); -                } else { -                        size = sys_fsetxattr (filler->fdnum, k, -                                              (char *)dst_data, -                                              count, 0); -                } -                op_errno = errno; -        } -unlock: -        pthread_mutex_unlock (&ctx->xattrop_lock); - -        if (op_ret == -1) -                goto out; - -        if (size == -1) { -                if (filler->real_path) -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_XATTR_FAILED, "setxattr failed on %s " -                                "while doing xattrop: key=%s", -                                filler->real_path, k); -                else -                        gf_msg (this->name, GF_LOG_ERROR, op_errno, -                                P_MSG_XATTR_FAILED, -                                "fsetxattr failed on gfid=%s while doing " -                                "xattrop: key=%s (%s)", -                                uuid_utoa (filler->inode->gfid), -                                k, strerror (op_errno)); -                op_ret = -1; -                goto out; -        } else if (array) { -                op_ret = dict_set_bin (filler->xattr, k, array, count); -                if (op_ret) { -                        if (filler->real_path) -                                gf_msg_debug (this->name, 0, -                                        "dict_set_bin failed (path=%s): " -                                        "key=%s (%s)", filler->real_path, -                                        k, strerror (-size)); -                        else -                                gf_msg_debug (this->name, 0, -                                        "dict_set_bin failed (gfid=%s): " -                                        "key=%s (%s)", -                                        uuid_utoa (filler->inode->gfid), -                                        k, strerror (-size)); - -                        op_ret = -1; -                        op_errno = EINVAL; -                        GF_FREE (array); -                        goto out; -                } -                array = NULL; -        } - -out: -        if (op_ret < 0) -                filler->op_errno = op_errno; - -        if (array) -                GF_FREE (array); - -        return op_ret; -} - -/** - * xattrop - xattr operations - for internal use by GlusterFS - * @optype: ADD_ARRAY: - *            dict should contain: - *               "key" ==> array of 32-bit numbers - */ - -int -do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, -            gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) -{ -        int                   op_ret    = 0; -        int                   op_errno  = 0; -        int                   _fd       = -1; -        char                 *real_path = NULL; -        struct posix_fd      *pfd       = NULL; -        inode_t              *inode     = NULL; -        posix_xattr_filler_t  filler    = {0,}; -        dict_t               *xattr_rsp = NULL; -        dict_t               *xdata_rsp = NULL; -        struct iatt           stbuf = {0}; -        struct  posix_private *priv     = NULL; - - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (xattr, out); -        VALIDATE_OR_GOTO (this, out); - -        priv = this->private; -        DISK_SPACE_CHECK_AND_GOTO (frame, priv, xdata, op_ret, op_errno, out); - -        if (fd) { -                op_ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, -                                fop_log_level(GF_FOP_FXATTROP, op_errno), -                                P_MSG_PFD_GET_FAILED, "failed to get pfd from" -                                " fd=%p", fd); -                        goto out; -                } -                _fd = pfd->fd; -        } - -        if (loc && !gf_uuid_is_null (loc->gfid)) { -                MAKE_INODE_HANDLE (real_path, this, loc, NULL); -                if (!real_path) { -                        op_ret = -1; -                        op_errno = ESTALE; -                        goto out; -                } -        } - -        if (real_path) { -                inode = loc->inode; -        } else if (fd) { -                inode = fd->inode; -        } - -        xattr_rsp = dict_new (); -        if (xattr_rsp == NULL) { -                op_ret = -1; -                op_errno = ENOMEM; -                goto out; -        } - -        filler.this = this; -        filler.fdnum = _fd; -        filler.real_path = real_path; -        filler.flags = (int)optype; -        filler.inode = inode; -        filler.xattr = xattr_rsp; - -        op_ret = dict_foreach (xattr, _posix_handle_xattr_keyvalue_pair, -                               &filler); -        op_errno = filler.op_errno; -        if (op_ret < 0) -                goto out; - -        if (!xdata) -                goto out; - -        if (fd) { -                op_ret = posix_fdstat (this, _fd, &stbuf); -        } else { -                op_ret = posix_pstat (this, inode->gfid, real_path, -                                      &stbuf); -        } -        if (op_ret < 0) { -                op_errno = errno; -                goto out; -        } -        xdata_rsp = posix_xattr_fill (this, real_path, loc, fd, _fd, -                                              xdata, &stbuf); -        if (!xdata_rsp) { -                op_ret = -1; -                op_errno = ENOMEM; -        } -out: - -        STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, xattr_rsp, -                             xdata_rsp); - -        if (xattr_rsp) -                dict_unref (xattr_rsp); - -        if (xdata_rsp) -                dict_unref (xdata_rsp); -        return 0; -} - - -int -posix_xattrop (call_frame_t *frame, xlator_t *this, -               loc_t *loc, gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) -{ -        do_xattrop (frame, this, loc, NULL, optype, xattr, xdata); -        return 0; -} - - -int -posix_fxattrop (call_frame_t *frame, xlator_t *this, -                fd_t *fd, gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) -{ -        do_xattrop (frame, this, NULL, fd, optype, xattr, xdata); -        return 0; -} - -int -posix_access (call_frame_t *frame, xlator_t *this, -              loc_t *loc, int32_t mask, dict_t *xdata) -{ -        int32_t                 op_ret    = -1; -        int32_t                 op_errno  = 0; -        char                   *real_path = NULL; - -        DECLARE_OLD_FS_ID_VAR; -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (loc, out); - -        MAKE_INODE_HANDLE (real_path, this, loc, NULL); -        if (!real_path) { -                op_ret = -1; -                op_errno = errno; -                goto out; -        } - -        op_ret = sys_access (real_path, mask & 07); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_ACCESS_FAILED, -                        "access failed on %s", real_path); -                goto out; -        } -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (access, frame, op_ret, op_errno, NULL); -        return 0; -} - - -int32_t -posix_ftruncate (call_frame_t *frame, xlator_t *this, -                 fd_t *fd, off_t offset, dict_t *xdata) -{ -        int32_t               op_ret   = -1; -        int32_t               op_errno = 0; -        int                   _fd      = -1; -        struct iatt           preop    = {0,}; -        struct iatt           postop   = {0,}; -        struct posix_fd      *pfd      = NULL; -        int                   ret      = -1; -        struct posix_private *priv     = NULL; - -        DECLARE_OLD_FS_ID_VAR; -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL, fd=%p", fd); -                goto out; -        } - -        _fd = pfd->fd; - -        op_ret = posix_fdstat (this, _fd, &preop); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "pre-operation fstat failed on fd=%p", fd); -                goto out; -        } - -        op_ret = sys_ftruncate (_fd, offset); - -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_TRUNCATE_FAILED, -                        "ftruncate failed on fd=%p (%"PRId64"", fd, offset); -                goto out; -        } - -        op_ret = posix_fdstat (this, _fd, &postop); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "post-operation fstat failed on fd=%p", fd); -                goto out; -        } - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, &preop, -                             &postop, NULL); - -        return 0; -} - - -int32_t -posix_fstat (call_frame_t *frame, xlator_t *this, -             fd_t *fd, dict_t *xdata) -{ -        int                   _fd      = -1; -        int32_t               op_ret   = -1; -        int32_t               op_errno = 0; -        struct iatt           buf      = {0,}; -        struct posix_fd      *pfd      = NULL; -        dict_t               *xattr_rsp = NULL; -        int                   ret      = -1; -        struct posix_private *priv     = NULL; - -        DECLARE_OLD_FS_ID_VAR; -        SET_FS_ID (frame->root->uid, frame->root->gid); - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; -        VALIDATE_OR_GOTO (priv, out); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL, fd=%p", fd); -                goto out; -        } - -        _fd = pfd->fd; - -        op_ret = posix_fdstat (this, _fd, &buf); -        if (op_ret == -1) { -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_FSTAT_FAILED, -                        "fstat failed on fd=%p", fd); -                goto out; -        } - -        if (xdata) -                xattr_rsp = posix_xattr_fill (this, NULL, NULL, fd, _fd, xdata, -                                              &buf); - -        op_ret = 0; - -out: -        SET_TO_OLD_FS_ID (); - -        STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, &buf, xattr_rsp); -        if (xattr_rsp) -                dict_unref (xattr_rsp); -        return 0; -} - -int32_t -posix_lease (call_frame_t *frame, xlator_t *this, -             loc_t *loc, struct gf_lease *lease, dict_t *xdata) -{ -        struct gf_lease nullease = {0, }; - -        gf_msg (this->name, GF_LOG_CRITICAL, EINVAL, P_MSG_LEASE_DISABLED, -                "\"features/leases\" translator is not loaded. You need" -                "to use it for proper functioning of your application"); - -        STACK_UNWIND_STRICT (lease, frame, -1, ENOSYS, &nullease, NULL); -        return 0; -} - -static int gf_posix_lk_log; - -int32_t -posix_lk (call_frame_t *frame, xlator_t *this, -          fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata) -{ -        struct gf_flock nullock = {0, }; - -        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, -                             "\"features/locks\" translator is " -                             "not loaded. You need to use it for proper " -                             "functioning of your application."); - -        STACK_UNWIND_STRICT (lk, frame, -1, ENOSYS, &nullock, NULL); -        return 0; -} - -int32_t -posix_inodelk (call_frame_t *frame, xlator_t *this, -               const char *volume, loc_t *loc, int32_t cmd, -               struct gf_flock *lock, dict_t *xdata) -{ -        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, -                             "\"features/locks\" translator is " -                             "not loaded. You need to use it for proper " -                             "functioning of your application."); - -        STACK_UNWIND_STRICT (inodelk, frame, -1, ENOSYS, NULL); -        return 0; -} - -int32_t -posix_finodelk (call_frame_t *frame, xlator_t *this, -                const char *volume, fd_t *fd, int32_t cmd, -                struct gf_flock *lock, dict_t *xdata) -{ -        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, -                             "\"features/locks\" translator is " -                             "not loaded. You need to use it for proper " -                             "functioning of your application."); - -        STACK_UNWIND_STRICT (finodelk, frame, -1, ENOSYS, NULL); -        return 0; -} - - -int32_t -posix_entrylk (call_frame_t *frame, xlator_t *this, -               const char *volume, loc_t *loc, const char *basename, -               entrylk_cmd cmd, entrylk_type type, dict_t *xdata) -{ -        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, -                             "\"features/locks\" translator is " -                             "not loaded. You need to use it for proper " -                             "functioning of your application."); - -        STACK_UNWIND_STRICT (entrylk, frame, -1, ENOSYS, NULL); -        return 0; -} - -int32_t -posix_fentrylk (call_frame_t *frame, xlator_t *this, -                const char *volume, fd_t *fd, const char *basename, -                entrylk_cmd cmd, entrylk_type type, dict_t *xdata) -{ -        GF_LOG_OCCASIONALLY (gf_posix_lk_log, this->name, GF_LOG_CRITICAL, -                             "\"features/locks\" translator is " -                             "not loaded. You need to use it for proper " -                             "functioning of your application."); - -        STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOSYS, NULL); -        return 0; -} - - -int -posix_fill_readdir (fd_t *fd, DIR *dir, off_t off, size_t size, -                    gf_dirent_t *entries, xlator_t *this, int32_t skip_dirs) -{ -        off_t            in_case        = -1; -        off_t            last_off       = 0; -        size_t           filled         = 0; -        int              count          = 0; -        int32_t          this_size      = -1; -        gf_dirent_t     *this_entry     = NULL; -        struct posix_fd *pfd            = NULL; -        struct stat      stbuf          = {0,}; -        char            *hpath          = NULL; -        int              len            = 0; -        int              ret            = 0; -        int              op_errno       = 0; -        struct dirent   *entry          = NULL; -        struct dirent    scratch[2]     = {{0,},}; - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL, fd=%p", fd); -                count = -1; -                errno = op_errno; -                goto out; -        } - -        if (skip_dirs) { -                len = posix_handle_path (this, fd->inode->gfid, NULL, NULL, 0); -                if (len <= 0) { -                        errno = ESTALE; -                        count = -1; -                        goto out; -                } -                hpath = alloca (len + 256); /* NAME_MAX */ - -                if (posix_handle_path (this, fd->inode->gfid, NULL, hpath, -                                       len) <= 0) { -                        errno = ESTALE; -                        count = -1; -                        goto out; -                } - -                len = strlen (hpath); -                hpath[len] = '/'; -        } - -        if (!off) { -                rewinddir (dir); -        } else { -                seekdir (dir, off); -#ifndef GF_LINUX_HOST_OS -                if ((u_long)telldir(dir) != off && off != pfd->dir_eof) { -                        gf_msg (THIS->name, GF_LOG_ERROR, EINVAL, -                                P_MSG_DIR_OPERATION_FAILED, -                                "seekdir(0x%llx) failed on dir=%p: " -                                "Invalid argument (offset reused from " -                                "another DIR * structure?)", off, dir); -                        errno = EINVAL; -                        count = -1; -                        goto out; -                } -#endif /* GF_LINUX_HOST_OS */ -        } - -        while (filled <= size) { -                in_case = (u_long)telldir (dir); - -                if (in_case == -1) { -                        gf_msg (THIS->name, GF_LOG_ERROR, errno, -                                P_MSG_DIR_OPERATION_FAILED, -                                "telldir failed on dir=%p", dir); -                        goto out; -                } - -                errno = 0; - -                entry = sys_readdir (dir, scratch); - -                if (!entry || errno != 0) { -                        if (errno == EBADF) { -                                gf_msg (THIS->name, GF_LOG_WARNING, errno, -                                        P_MSG_DIR_OPERATION_FAILED, -                                        "readdir failed on dir=%p", -                                        dir); -                                goto out; -                        } -                        break; -                } - -#ifdef __NetBSD__ -	       /* -		* NetBSD with UFS1 backend uses backing files for -		* extended attributes. They can be found in a -		* .attribute file located at the root of the filesystem -		* We hide it to glusterfs clients, since chaos will occur -		* when the cluster/dht xlator decides to distribute -		* exended attribute backing file across storage servers. -		*/ -		if (__is_root_gfid (fd->inode->gfid) == 0 -		    && (!strcmp(entry->d_name, ".attribute"))) -			continue; -#endif /* __NetBSD__ */ - -                if (__is_root_gfid (fd->inode->gfid) -                    && (!strcmp (GF_HIDDEN_PATH, entry->d_name))) { -                        continue; -                } - -                if (skip_dirs) { -                        if (DT_ISDIR (entry->d_type)) { -                                continue; -                        } else if (hpath) { -                                strcpy (&hpath[len+1], entry->d_name); -                                ret = sys_lstat (hpath, &stbuf); -                                if (!ret && S_ISDIR (stbuf.st_mode)) -                                        continue; -                        } -                } - -                this_size = max (sizeof (gf_dirent_t), -                                 sizeof (gfs3_dirplist)) -                        + strlen (entry->d_name) + 1; - -                if (this_size + filled > size) { -                        seekdir (dir, in_case); -#ifndef GF_LINUX_HOST_OS -                        if ((u_long)telldir(dir) != in_case && -                            in_case != pfd->dir_eof) { -                                gf_msg (THIS->name, GF_LOG_ERROR, EINVAL, -                                        P_MSG_DIR_OPERATION_FAILED, -                                        "seekdir(0x%llx) failed on dir=%p: " -                                        "Invalid argument (offset reused from " -                                        "another DIR * structure?)", -                                        in_case, dir); -                                errno = EINVAL; -                                count = -1; -                                goto out; -                        } -#endif /* GF_LINUX_HOST_OS */ -                        break; -                } - -                this_entry = gf_dirent_for_name (entry->d_name); - -                if (!this_entry) { -                        gf_msg (THIS->name, GF_LOG_ERROR, errno, -                                P_MSG_GF_DIRENT_CREATE_FAILED, -                                "could not create " -                                "gf_dirent for entry %s", entry->d_name); -                        goto out; -                } -                /* -                 * we store the offset of next entry here, which is -                 * probably not intended, but code using syncop_readdir() -                 * (glfs-heal.c, afr-self-heald.c, pump.c) rely on it -                 * for directory read resumption. -                 */ -                last_off = (u_long)telldir(dir); -                this_entry->d_off = last_off; -                this_entry->d_ino = entry->d_ino; -                this_entry->d_type = entry->d_type; - -                list_add_tail (&this_entry->list, &entries->list); - -                filled += this_size; -                count ++; -        } - -        if ((!sys_readdir (dir, scratch) && (errno == 0))) { -                /* Indicate EOF */ -                errno = ENOENT; -                /* Remember EOF offset for later detection */ -                pfd->dir_eof = (u_long)last_off; -        } -out: -        return count; -} - -dict_t * -posix_entry_xattr_fill (xlator_t *this, inode_t *inode, -                        fd_t *fd, char *entry_path, dict_t *dict, -                        struct iatt *stbuf) -{ -        loc_t  tmp_loc    = {0,}; - -        /* if we don't send the 'loc', open-fd-count be a problem. */ -        tmp_loc.inode = inode; - -        return posix_xattr_fill (this, entry_path, &tmp_loc, NULL, -1, dict, -                                 stbuf); - -} - - -#ifdef _DIRENT_HAVE_D_TYPE -static int -posix_d_type_from_ia_type (ia_type_t type) -{ -        switch (type) { -        case IA_IFDIR:      return DT_DIR; -        case IA_IFCHR:      return DT_CHR; -        case IA_IFBLK:      return DT_BLK; -        case IA_IFIFO:      return DT_FIFO; -        case IA_IFLNK:      return DT_LNK; -        case IA_IFREG:      return DT_REG; -        case IA_IFSOCK:     return DT_SOCK; -        default:            return DT_UNKNOWN; -        } -} -#endif - - -int -posix_readdirp_fill (xlator_t *this, fd_t *fd, gf_dirent_t *entries, dict_t *dict) -{ -        gf_dirent_t     *entry    = NULL; -        inode_table_t   *itable   = NULL; -	inode_t         *inode    = NULL; -	char            *hpath    = NULL; -	int              len      = 0; -        struct iatt      stbuf    = {0, }; -	uuid_t           gfid; -        int              ret      = -1; - -	if (list_empty(&entries->list)) -		return 0; - -        itable = fd->inode->table; - -	len = posix_handle_path (this, fd->inode->gfid, NULL, NULL, 0); -        if (len <= 0) -                return -1; -	hpath = alloca (len + 256); /* NAME_MAX */ -	if (posix_handle_path (this, fd->inode->gfid, NULL, hpath, len) <= 0) -                return -1; -	len = strlen (hpath); -	hpath[len] = '/'; - -        list_for_each_entry (entry, &entries->list, list) { -		memset (gfid, 0, 16); -		inode = inode_grep (fd->inode->table, fd->inode, -				    entry->d_name); -		if (inode) -			gf_uuid_copy (gfid, inode->gfid); - -		strcpy (&hpath[len+1], entry->d_name); - -                ret = posix_pstat (this, gfid, hpath, &stbuf); - -                if (ret == -1) { -                        if (inode) -                                inode_unref (inode); -                      continue; -                } - -		if (!inode) -			inode = inode_find (itable, stbuf.ia_gfid); - -		if (!inode) -			inode = inode_new (itable); - -		entry->inode = inode; - -                if (dict) { -                        entry->dict = -                                posix_entry_xattr_fill (this, entry->inode, -                                                        fd, hpath, -                                                        dict, &stbuf); -                } - -                entry->d_stat = stbuf; -                if (stbuf.ia_ino) -                        entry->d_ino = stbuf.ia_ino; - -#ifdef _DIRENT_HAVE_D_TYPE -                if (entry->d_type == DT_UNKNOWN && !IA_ISINVAL(stbuf.ia_type)) { -                        /* The platform supports d_type but the underlying -                           filesystem doesn't. We set d_type to the correct -                           value from ia_type */ -                        entry->d_type = -                                posix_d_type_from_ia_type (stbuf.ia_type); -                } -#endif - -		inode = NULL; -        } - -	return 0; -} - - -int32_t -posix_do_readdir (call_frame_t *frame, xlator_t *this, -                  fd_t *fd, size_t size, off_t off, int whichop, dict_t *dict) -{ -        struct posix_fd *pfd       = NULL; -        DIR             *dir       = NULL; -        int              ret       = -1; -        int              count     = 0; -        int32_t          op_ret    = -1; -        int32_t          op_errno  = 0; -        gf_dirent_t      entries; -        int32_t          skip_dirs = 0; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        INIT_LIST_HEAD (&entries.list); - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, op_errno, P_MSG_PFD_NULL, -                        "pfd is NULL, fd=%p", fd); -                goto out; -        } - -        dir = pfd->dir; - -        if (!dir) { -                gf_msg (this->name, GF_LOG_WARNING, EINVAL, P_MSG_PFD_NULL, -                        "dir is NULL for fd=%p", fd); -                op_errno = EINVAL; -                goto out; -	} - -        /* When READDIR_FILTER option is set to on, we can filter out -         * directory's entry from the entry->list. -         */ -        ret = dict_get_int32 (dict, GF_READDIR_SKIP_DIRS, &skip_dirs); - -	LOCK (&fd->lock); -	{ -		/* posix_fill_readdir performs multiple separate individual -		   readdir() calls to fill up the buffer. - -		   In case of NFS where the same anonymous FD is shared between -		   different applications, reading a common directory can -		   result in the anonymous fd getting re-used unsafely between -		   the two readdir requests (in two different io-threads). - -		   It would also help, in the future, to replace the loop -		   around readdir() with a single large getdents() call. -		*/ -		count = posix_fill_readdir (fd, dir, off, size, &entries, this, -					    skip_dirs); -	} -	UNLOCK (&fd->lock); - -        /* pick ENOENT to indicate EOF */ -        op_errno = errno; -        op_ret = count; - -        if (whichop != GF_FOP_READDIRP) -                goto out; - -	posix_readdirp_fill (this, fd, &entries, dict); - -out: -        STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, &entries, NULL); - -        gf_dirent_free (&entries); - -        return 0; -} - - -int32_t -posix_readdir (call_frame_t *frame, xlator_t *this, -               fd_t *fd, size_t size, off_t off, dict_t *xdata) -{ -        posix_do_readdir (frame, this, fd, size, off, GF_FOP_READDIR, xdata); -        return 0; -} - - -int32_t -posix_readdirp (call_frame_t *frame, xlator_t *this, -                fd_t *fd, size_t size, off_t off, dict_t *dict) -{ -        gf_dirent_t entries; -        int32_t     op_ret = -1, op_errno = 0; -        gf_dirent_t     *entry     = NULL; - - -        if ((dict != NULL) && (dict_get (dict, GET_ANCESTRY_DENTRY_KEY))) { -                INIT_LIST_HEAD (&entries.list); - -                op_ret = posix_get_ancestry (this, fd->inode, &entries, NULL, -                                             POSIX_ANCESTRY_DENTRY, -                                             &op_errno, dict); -                if (op_ret >= 0) { -                        op_ret = 0; - -                        list_for_each_entry (entry, &entries.list, list) { -                                op_ret++; -                        } -                } - -                STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, &entries, -                                     NULL); - -                gf_dirent_free (&entries); -                return 0; -        } - -        posix_do_readdir (frame, this, fd, size, off, GF_FOP_READDIRP, dict); -        return 0; -} - -int32_t -posix_priv (xlator_t *this) -{ -        struct posix_private *priv = NULL; -        char  key_prefix[GF_DUMP_MAX_BUF_LEN]; - -        (void) snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s", -                        this->type, this->name); -        gf_proc_dump_add_section(key_prefix); - -        if (!this) -                return 0; - -        priv = this->private; - -        if (!priv) -                return 0; - -        gf_proc_dump_write("base_path","%s", priv->base_path); -        gf_proc_dump_write("base_path_length","%d", priv->base_path_length); -        gf_proc_dump_write("max_read","%d", priv->read_value); -        gf_proc_dump_write("max_write","%d", priv->write_value); -        gf_proc_dump_write("nr_files","%ld", priv->nr_files); - -        return 0; -} - -int32_t -posix_inode (xlator_t *this) -{ -        return 0; -} - - -int32_t -posix_rchecksum (call_frame_t *frame, xlator_t *this, -                 fd_t *fd, off_t offset, int32_t len, dict_t *xdata) -{ -        char                    *alloc_buf      = NULL; -        char                    *buf            = NULL; -        int                     _fd             = -1; -        struct posix_fd         *pfd            = NULL; -        int                     op_ret          = -1; -        int                     op_errno        = 0; -        int                     ret             = 0; -        ssize_t                 bytes_read      = 0; -        int32_t                 weak_checksum   = 0; -        int32_t                 zerofillcheck   = 0; -        unsigned char           strong_checksum[MD5_DIGEST_LENGTH] = {0}; -        struct posix_private    *priv           = NULL; -        dict_t                  *rsp_xdata      = NULL; -        gf_boolean_t            buf_has_zeroes  = _gf_false; - -        VALIDATE_OR_GOTO (frame, out); -        VALIDATE_OR_GOTO (this, out); -        VALIDATE_OR_GOTO (fd, out); - -        priv = this->private; -        memset (strong_checksum, 0, MD5_DIGEST_LENGTH); - -        alloc_buf = _page_aligned_alloc (len, &buf); -        if (!alloc_buf) { -                op_errno = ENOMEM; -                goto out; -        } - -        rsp_xdata = dict_new(); -        if (!rsp_xdata) { -                op_errno = ENOMEM; -                goto out; -        } - -        ret = posix_fd_ctx_get (fd, this, &pfd, &op_errno); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_WARNING, -ret, P_MSG_PFD_NULL, -                        "pfd is NULL, fd=%p", fd); -                goto out; -        } - -        _fd = pfd->fd; - -        LOCK (&fd->lock); -        { -                if (priv->aio_capable && priv->aio_init_done) -                        __posix_fd_set_odirect (fd, pfd, 0, offset, len); - -                bytes_read = sys_pread (_fd, buf, len, offset); -                if (bytes_read < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_PREAD_FAILED, -                                "pread of %d bytes returned %zd", len, -                                bytes_read); - -                        op_errno = errno; -                } - -        } -        UNLOCK (&fd->lock); - -        if (bytes_read < 0) -                goto out; - -        if (xdata && dict_get_int32 (xdata, "check-zero-filled", -                                     &zerofillcheck) == 0) { -                buf_has_zeroes = (mem_0filled (buf, bytes_read)) ? _gf_false : -                                 _gf_true; -                ret = dict_set_uint32 (rsp_xdata, "buf-has-zeroes", -                                       buf_has_zeroes); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, -ret, -                                P_MSG_DICT_SET_FAILED, "%s: Failed to set " -                                "dictionary value for key: %s", -                                uuid_utoa (fd->inode->gfid), "buf-has-zeroes"); -                        op_errno = -ret; -                        goto out; -                } -        } -        weak_checksum = gf_rsync_weak_checksum ((unsigned char *) buf, (size_t) ret); -        gf_rsync_strong_checksum ((unsigned char *) buf, (size_t) bytes_read, -                                  (unsigned char *) strong_checksum); - -        op_ret = 0; -out: -        STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno, -                             weak_checksum, strong_checksum, rsp_xdata); -        if (rsp_xdata) -                dict_unref (rsp_xdata); -        GF_FREE (alloc_buf); - -        return 0; -} - - -/** - * notify - when parent sends PARENT_UP, send CHILD_UP event from here - */ -int32_t -notify (xlator_t *this, -        int32_t event, -        void *data, -        ...) -{ -        struct posix_private *priv = NULL; - -        priv = this->private; -        switch (event) -        { -        case GF_EVENT_PARENT_UP: -        { -                /* Tell the parent that posix xlator is up */ -                default_notify (this, GF_EVENT_CHILD_UP, data); -        } -        break; -        case GF_EVENT_CLEANUP: -                if (priv->health_check) { -                        priv->health_check_active = _gf_false; -                        pthread_cancel (priv->health_check); -                        priv->health_check = 0; -                } -                if (priv->disk_space_check) { -                        priv->disk_space_check_active = _gf_false; -                        pthread_cancel (priv->disk_space_check); -                        priv->disk_space_check = 0; -                } -                if (priv->janitor) { -                        (void) gf_thread_cleanup_xint (priv->janitor); -                        priv->janitor = 0; -                } -                if (priv->fsyncer) { -                        (void) gf_thread_cleanup_xint (priv->fsyncer); -                        priv->fsyncer = 0; -                } -                if (priv->mount_lock) { -                        (void) sys_closedir (priv->mount_lock); -                        priv->mount_lock = NULL; -                } - -        break; -        default: -                /* */ -                break; -        } -        return 0; -} - -int32_t -mem_acct_init (xlator_t *this) -{ -        int     ret = -1; - -        if (!this) -                return ret; - -        ret = xlator_mem_acct_init (this, gf_posix_mt_end + 1); - -        if (ret != 0) { -                return ret; -        } - -        return ret; -} - -static int -posix_set_owner (xlator_t *this, uid_t uid, gid_t gid) -{ -        struct posix_private *priv = NULL; -        int                   ret  = -1; -	struct stat st = {0,}; - -        priv = this->private; - -	ret = sys_lstat (priv->base_path, &st); -	if (ret) { -		gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_DIR_OPERATION_FAILED, "Failed to stat " -			"brick path %s", -			priv->base_path); -		return ret; -	} - -	if ((uid == -1 || st.st_uid == uid) && -	    (gid == -1 || st.st_gid == gid)) -		return 0; - -        ret = sys_chown (priv->base_path, uid, gid); -        if (ret) -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_DIR_OPERATION_FAILED, "Failed to set uid/gid for" -                        " brick path %s", priv->base_path); - -        return ret; -} -static int -set_gfid2path_separator (struct posix_private *priv, const char *str) -{ -        int str_len = 0; - -        str_len = strlen(str); -        if (str_len > 0 && str_len < 8) { -                strcpy (priv->gfid2path_sep, str); -                return 0; -        } - -        return -1; -} - -static int -set_batch_fsync_mode (struct posix_private *priv, const char *str) -{ -	if (strcmp (str, "none") == 0) -		priv->batch_fsync_mode = BATCH_NONE; -	else if (strcmp (str, "syncfs") == 0) -		priv->batch_fsync_mode = BATCH_SYNCFS; -	else if (strcmp (str, "syncfs-single-fsync") == 0) -		priv->batch_fsync_mode = BATCH_SYNCFS_SINGLE_FSYNC; -	else if (strcmp (str, "syncfs-reverse-fsync") == 0) -		priv->batch_fsync_mode = BATCH_SYNCFS_REVERSE_FSYNC; -	else if (strcmp (str, "reverse-fsync") == 0) -		priv->batch_fsync_mode = BATCH_REVERSE_FSYNC; -	else -		return -1; - -	return 0; -} - -#ifdef GF_DARWIN_HOST_OS -static int -set_xattr_user_namespace_mode (struct posix_private *priv, const char *str) -{ -        if (strcmp (str, "none") == 0) -                priv->xattr_user_namespace = XATTR_NONE; -        else if (strcmp (str, "strip") == 0) -                priv->xattr_user_namespace = XATTR_STRIP; -        else if (strcmp (str, "append") == 0) -                priv->xattr_user_namespace = XATTR_APPEND; -        else if (strcmp (str, "both") == 0) -                priv->xattr_user_namespace = XATTR_BOTH; -        else -                return -1; -        return 0; -} -#endif - -int -reconfigure (xlator_t *this, dict_t *options) -{ -	int                   ret = -1; -        struct posix_private *priv = NULL; -        int32_t               uid = -1; -        int32_t               gid = -1; -	char                 *batch_fsync_mode_str = NULL; -        char                 *gfid2path_sep = NULL; -        int32_t              force_create_mode = -1; -        int32_t              force_directory_mode = -1; -        int32_t              create_mask = -1; -        int32_t              create_directory_mask = -1; - -        priv = this->private; -        GF_OPTION_RECONF ("brick-uid", uid, options, int32, out); -        GF_OPTION_RECONF ("brick-gid", gid, options, int32, out); -	if (uid != -1 || gid != -1) -		posix_set_owner (this, uid, gid); - -	GF_OPTION_RECONF ("batch-fsync-delay-usec", priv->batch_fsync_delay_usec, -			  options, uint32, out); - -	GF_OPTION_RECONF ("batch-fsync-mode", batch_fsync_mode_str, -			  options, str, out); - -	if (set_batch_fsync_mode (priv, batch_fsync_mode_str) != 0) { -		gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, -                        "Unknown mode string: %s", batch_fsync_mode_str); -		goto out; -	} - -	GF_OPTION_RECONF ("gfid2path-separator", gfid2path_sep, options, -                          str, out); -        if (set_gfid2path_separator (priv, gfid2path_sep) != 0) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, -                        "Length of separator exceeds 7: %s", gfid2path_sep); -                goto out; -        } - -#ifdef GF_DARWIN_HOST_OS - -        char   *xattr_user_namespace_mode_str = NULL; - -        GF_OPTION_RECONF ("xattr-user-namespace-mode", xattr_user_namespace_mode_str, -                          options, str, out); - -        if (set_xattr_user_namespace_mode (priv, xattr_user_namespace_mode_str) != 0) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_UNKNOWN_ARGUMENT, -                        "Unknown xattr user namespace mode string: %s", -                        xattr_user_namespace_mode_str); -                goto out; -        } - -#endif - -	GF_OPTION_RECONF ("linux-aio", priv->aio_configured, -			  options, bool, out); - -	if (priv->aio_configured) -		posix_aio_on (this); -	else -		posix_aio_off (this); - -        GF_OPTION_RECONF ("update-link-count-parent", priv->update_pgfid_nlinks, -                          options, bool, out); - -        GF_OPTION_RECONF ("gfid2path", priv->gfid2path, -                          options, bool, out); - -        GF_OPTION_RECONF ("node-uuid-pathinfo", priv->node_uuid_pathinfo, -                          options, bool, out); - -        if (priv->node_uuid_pathinfo && -                        (gf_uuid_is_null (priv->glusterd_uuid))) { -                gf_msg (this->name, GF_LOG_INFO, 0, P_MSG_UUID_NULL, -                        "glusterd uuid is NULL, pathinfo xattr would" -                        " fallback to <hostname>:<export>"); -        } - -        GF_OPTION_RECONF ("reserve", priv->disk_reserve, -                          options, uint32, out); -        if (priv->disk_reserve) -                posix_spawn_disk_space_check_thread (this); - -        GF_OPTION_RECONF ("health-check-interval", priv->health_check_interval, -                          options, uint32, out); -        GF_OPTION_RECONF ("health-check-timeout", priv->health_check_timeout, -                          options, uint32, out); -        posix_spawn_health_check_thread (this); - -        GF_OPTION_RECONF ("shared-brick-count", priv->shared_brick_count, -                          options, int32, out); -        GF_OPTION_RECONF ("force-create-mode", force_create_mode, -                          options, int32, out); -        priv->force_create_mode = force_create_mode; - -        GF_OPTION_RECONF ("force-directory-mode", force_directory_mode, -                          options, int32, out); -        priv->force_directory_mode = force_directory_mode; - -        GF_OPTION_RECONF ("create-mask", create_mask, -                          options, int32, out); -        priv->create_mask = create_mask; - -        GF_OPTION_RECONF ("create-directory-mask", create_directory_mask, -                          options, int32, out); -        priv->create_directory_mask = create_directory_mask; - -        ret = 0; -out: -	return ret; -} - -int32_t -posix_delete_unlink_entry (const char *fpath, const struct stat *sb, -                   int typeflag, struct FTW *ftwbuf) { - -        int    ret = 0; - -        if (!fpath) -                goto out; - -        switch (typeflag) { -        case FTW_SL: -        case FTW_NS: -        case FTW_F: -        case FTW_SLN: -                ret = sys_unlink(fpath); -                break; -        case FTW_D: -        case FTW_DP: -        case FTW_DNR: -                if (ftwbuf->level != 0) { -                        ret = sys_rmdir(fpath); -                } -                break; -        default: -                break; -        } -        if (ret) { -                gf_msg ("posix_delete_unlink_entry", GF_LOG_WARNING, errno, -                        P_MSG_HANDLE_CREATE, -                        "Deletion of entries %s failed" -                        "Please delete it manually", -                        fpath); -        } -out: -        return 0; -} - -int32_t -posix_delete_unlink (const char *unlink_path) { - -        int    ret = -1; -        int    flags = 0; - -        flags |= (FTW_DEPTH | FTW_PHYS); - -        ret = nftw(unlink_path, posix_delete_unlink_entry, 2, flags); -        if (ret) { -                gf_msg ("posix_delete_unlink", GF_LOG_ERROR, 0, -                        P_MSG_HANDLE_CREATE, -                        "Deleting files from  %s failed", -                        unlink_path); -        } -        return ret; -} - -int32_t -posix_create_unlink_dir (xlator_t *this) { - -        struct posix_private *priv = NULL; -        struct stat           stbuf; -        int                   ret = -1; -        uuid_t                gfid = {0}; -        char                  gfid_str[64] = {0}; -        char                  unlink_path[PATH_MAX] = {0,}; -        char                  landfill_path[PATH_MAX] = {0,}; - -        priv = this->private; - -        (void) snprintf (unlink_path, sizeof(unlink_path), "%s/%s", -                         priv->base_path, GF_UNLINK_PATH); - -        gf_uuid_generate (gfid); -        uuid_utoa_r (gfid, gfid_str); - -        (void) snprintf (landfill_path, sizeof(landfill_path), "%s/%s/%s", -                         priv->base_path, GF_LANDFILL_PATH, gfid_str); - -        ret = sys_stat (unlink_path, &stbuf); -        switch (ret) { -        case -1: -                if (errno != ENOENT) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_HANDLE_CREATE, -                                "Checking for %s failed", -                                unlink_path); -                        return -1; -                } -                break; -        case 0: -                if (!S_ISDIR (stbuf.st_mode)) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_HANDLE_CREATE, -                                "Not a directory: %s", -                                unlink_path); -                        return -1; -                } -                ret = posix_delete_unlink (unlink_path); -                return 0; -        default: -                break; -        } -        ret = sys_mkdir (unlink_path, 0600); -        if (ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_HANDLE_CREATE, -                        "Creating directory %s failed", -                        unlink_path); -                return -1; -        } - -        return 0; -} - -/** - * init - - */ -int -init (xlator_t *this) -{ -        struct posix_private *_private      = NULL; -        data_t               *dir_data      = NULL; -        data_t               *tmp_data      = NULL; -        struct stat           buf           = {0,}; -        gf_boolean_t          tmp_bool      = 0; -        int                   ret           = 0; -        int                   op_ret        = -1; -        int                   op_errno      = 0; -        ssize_t               size          = -1; -        uuid_t                old_uuid      = {0,}; -        uuid_t                dict_uuid     = {0,}; -        uuid_t                gfid          = {0,}; -        uuid_t                rootgfid      = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; -        char                 *guuid         = NULL; -        int32_t               uid           = -1; -        int32_t               gid           = -1; -	char                 *batch_fsync_mode_str; -        char                 *gfid2path_sep = NULL; -        int                  force_create  = -1; -        int                  force_directory = -1; -        int                  create_mask  = -1; -        int                  create_directory_mask = -1; - -        dir_data = dict_get (this->options, "directory"); - -        if (this->children) { -                gf_msg (this->name, GF_LOG_CRITICAL, 0, P_MSG_SUBVOLUME_ERROR, -                        "FATAL: storage/posix cannot have subvolumes"); -                ret = -1; -                goto out; -        } - -        if (!this->parents) { -                gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_VOLUME_DANGLING, -                        "Volume is dangling. Please check the volume file."); -        } - -        if (!dir_data) { -                gf_msg (this->name, GF_LOG_CRITICAL, 0, -                        P_MSG_EXPORT_DIR_MISSING, -                        "Export directory not specified in volume file."); -                ret = -1; -                goto out; -        } - -        umask (000); // umask `masking' is done at the client side - -        /* Check whether the specified directory exists, if not log it. */ -        op_ret = sys_stat (dir_data->data, &buf); -        if ((op_ret != 0) || !S_ISDIR (buf.st_mode)) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_DIR_OPERATION_FAILED, -                        "Directory '%s' doesn't exist, exiting.", -                        dir_data->data); -                ret = -1; -                goto out; -        } - -        _private = GF_CALLOC (1, sizeof (*_private), -                              gf_posix_mt_posix_private); -        if (!_private) { -                ret = -1; -                goto out; -        } - -        _private->base_path = gf_strdup (dir_data->data); -        _private->base_path_length = strlen (_private->base_path); - -        ret = dict_get_str (this->options, "hostname", &_private->hostname); -        if (ret) { -                _private->hostname = GF_CALLOC (256, sizeof (char), -                                                gf_common_mt_char); -                if (!_private->hostname) { -                        goto out; -                } -                ret = gethostname (_private->hostname, 256); -                if (ret < 0) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HOSTNAME_MISSING, -                                "could not find hostname "); -                } -        } - -        /* Check for Extended attribute support, if not present, log it */ -        op_ret = sys_lsetxattr (dir_data->data, -                                "trusted.glusterfs.test", "working", 8, 0); -        if (op_ret != -1) { -                sys_lremovexattr (dir_data->data, "trusted.glusterfs.test"); -        } else { -                tmp_data = dict_get (this->options, -                                     "mandate-attribute"); -                if (tmp_data) { -                        if (gf_string2boolean (tmp_data->data, -                                               &tmp_bool) == -1) { -                                gf_msg (this->name, GF_LOG_ERROR, 0, -                                        P_MSG_INVALID_OPTION, -                                        "wrong option provided for key " -                                        "\"mandate-attribute\""); -                                ret = -1; -                                goto out; -                        } -                        if (!tmp_bool) { -                                gf_msg (this->name, GF_LOG_WARNING, 0, -                                        P_MSG_XATTR_NOTSUP, -                                        "Extended attribute not supported, " -                                        "starting as per option"); -                        } else { -                                gf_msg (this->name, GF_LOG_CRITICAL, 0, -                                        P_MSG_XATTR_NOTSUP, -                                        "Extended attribute not supported, " -                                        "exiting."); -                                ret = -1; -                                goto out; -                        } -                } else { -                        gf_msg (this->name, GF_LOG_CRITICAL, 0, -                                P_MSG_XATTR_NOTSUP, -                                "Extended attribute not supported, exiting."); -                        ret = -1; -                        goto out; -                } -        } - -        tmp_data = dict_get (this->options, "volume-id"); -        if (tmp_data) { -                op_ret = gf_uuid_parse (tmp_data->data, dict_uuid); -                if (op_ret < 0) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_INVALID_VOLUME_ID, -                                "wrong volume-id (%s) set" -                                " in volume file", tmp_data->data); -                        ret = -1; -                        goto out; -                } -                size = sys_lgetxattr (dir_data->data, -                                      "trusted.glusterfs.volume-id", old_uuid, 16); -                if (size == 16) { -                        if (gf_uuid_compare (old_uuid, dict_uuid)) { -                                gf_msg (this->name, GF_LOG_ERROR, 0, -                                        P_MSG_INVALID_VOLUME_ID, -                                        "mismatching volume-id (%s) received. " -                                        "already is a part of volume %s ", -                                        tmp_data->data, uuid_utoa (old_uuid)); -                                gf_event (EVENT_POSIX_ALREADY_PART_OF_VOLUME, -                                        "volume-id=%s;brick=%s:%s", -                                        uuid_utoa (old_uuid), -                                       _private->hostname, _private->base_path); -                                ret = -1; -                                goto out; -                        } -                } else if ((size == -1) && -                           (errno == ENODATA || errno == ENOATTR)) { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_VOLUME_ID_ABSENT, -                                        "Extended attribute trusted.glusterfs." -                                        "volume-id is absent"); -                                gf_event (EVENT_POSIX_BRICK_NOT_IN_VOLUME, -                                        "brick=%s:%s", -                                       _private->hostname, _private->base_path); -                                ret = -1; -                                goto out; - -                }  else if ((size == -1) && (errno != ENODATA) && -                            (errno != ENOATTR)) { -                        /* Wrong 'volume-id' is set, it should be error */ -                        gf_event (EVENT_POSIX_BRICK_VERIFICATION_FAILED, -                                "brick=%s:%s", -                                _private->hostname, _private->base_path); -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_VOLUME_ID_FETCH_FAILED, -                                "%s: failed to fetch volume-id", -                                dir_data->data); -                        ret = -1; -                        goto out; -                } else { -                        ret = -1; -                        gf_event (EVENT_POSIX_BRICK_VERIFICATION_FAILED, -                                "brick=%s:%s", -                                _private->hostname, _private->base_path); -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_VOLUME_ID_FETCH_FAILED, -                                "failed to fetch proper volume id from export"); -                        goto out; -                } -        } - -        /* Now check if the export directory has some other 'gfid', -           other than that of root '/' */ -        size = sys_lgetxattr (dir_data->data, "trusted.gfid", gfid, 16); -        if (size == 16) { -                if (!__is_root_gfid (gfid)) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_GFID_SET_FAILED, -                                "%s: gfid (%s) is not that of glusterfs '/' ", -                                dir_data->data, uuid_utoa (gfid)); -                        ret = -1; -                        goto out; -                } -        } else if (size != -1) { -                /* Wrong 'gfid' is set, it should be error */ -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_GFID_SET_FAILED, -                        "%s: wrong value set as gfid", -                        dir_data->data); -                ret = -1; -                goto out; -        } else if ((size == -1) && (errno != ENODATA) && -                   (errno != ENOATTR)) { -                /* Wrong 'gfid' is set, it should be error */ -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_GFID_SET_FAILED, -                        "%s: failed to fetch gfid", -                        dir_data->data); -                ret = -1; -                goto out; -        } else { -                /* First time volume, set the GFID */ -                size = sys_lsetxattr (dir_data->data, "trusted.gfid", rootgfid, -                                     16, XATTR_CREATE); -                if (size == -1) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_GFID_SET_FAILED, -                                "%s: failed to set gfid", -                                dir_data->data); -                        ret = -1; -                        goto out; -                } -        } - -        ret = 0; - -        size = sys_lgetxattr (dir_data->data, POSIX_ACL_ACCESS_XATTR, -                              NULL, 0); -        if ((size < 0) && (errno == ENOTSUP)) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_ACL_NOTSUP, -                        "Posix access control list is not supported."); -                gf_event (EVENT_POSIX_ACL_NOT_SUPPORTED, -                        "brick=%s:%s", _private->hostname, _private->base_path); -        } - -        /* -         * _XOPEN_PATH_MAX is the longest file path len we MUST -         * support according to POSIX standard. When prepended -         * by the brick base path it may exceed backed filesystem -         * capacity (which MAY be bigger than _XOPEN_PATH_MAX). If -         * this is the case, chdir() to the brick base path and -         * use relative paths when they are too long. See also -         * MAKE_REAL_PATH in posix-handle.h -          */ -        _private->path_max = pathconf(_private->base_path, _PC_PATH_MAX); -        if (_private->path_max != -1 && -            _XOPEN_PATH_MAX + _private->base_path_length > _private->path_max) { -                ret = chdir(_private->base_path); -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_BASEPATH_CHDIR_FAILED, -                                "chdir() to \"%s\" failed", -                                _private->base_path); -                        goto out; -                } -#ifdef __NetBSD__ -                /* -                 * At least on NetBSD, the chdir() above uncovers a -                 * race condition which cause file lookup to fail -                 * with ENODATA for a few seconds. The volume quickly -                 * reaches a sane state, but regression tests are fast -                 * enough to choke on it. The reason is obscure (as -                 * often with race conditions), but sleeping here for -                 * a second seems to workaround the problem. -                 */ -                sleep(1); -#endif -        } - - -        LOCK_INIT (&_private->lock); - -        _private->export_statfs = 1; -        tmp_data = dict_get (this->options, "export-statfs-size"); -        if (tmp_data) { -                if (gf_string2boolean (tmp_data->data, -                                       &_private->export_statfs) == -1) { -                        ret = -1; -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_INVALID_OPTION_VAL, -                                "'export-statfs-size' takes only boolean " -                                "options"); -                        goto out; -                } -                if (!_private->export_statfs) -                        gf_msg_debug (this->name, 0, -                                "'statfs()' returns dummy size"); -        } - -        _private->background_unlink = 0; -        tmp_data = dict_get (this->options, "background-unlink"); -        if (tmp_data) { -                if (gf_string2boolean (tmp_data->data, -                                       &_private->background_unlink) == -1) { -                        ret = -1; -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_INVALID_OPTION_VAL, "'background-unlink'" -                                " takes only boolean options"); -                        goto out; -                } - -                if (_private->background_unlink) -                        gf_msg_debug (this->name, 0, -                                "unlinks will be performed in background"); -        } - -        tmp_data = dict_get (this->options, "o-direct"); -        if (tmp_data) { -                if (gf_string2boolean (tmp_data->data, -                                       &_private->o_direct) == -1) { -                        ret = -1; -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_INVALID_OPTION_VAL, -                                "wrong option provided for 'o-direct'"); -                        goto out; -                } -                if (_private->o_direct) -                        gf_msg_debug (this->name, 0, "o-direct mode is enabled" -                                      " (O_DIRECT for every open)"); -        } - -        tmp_data = dict_get (this->options, "update-link-count-parent"); -        if (tmp_data) { -                if (gf_string2boolean (tmp_data->data, -                                       &_private->update_pgfid_nlinks) == -1) { -                        ret = -1; -                        gf_msg (this->name, GF_LOG_ERROR, 0, -                                P_MSG_INVALID_OPTION, "wrong value provided " -                                "for 'update-link-count-parent'"); -                        goto out; -                } -                if (_private->update_pgfid_nlinks) -                        gf_msg_debug (this->name, 0, "update-link-count-parent" -                                      " is enabled. Thus for each file an " -                                      "extended attribute representing the " -                                      "number of hardlinks for that file " -                                      "within the same parent directory is" -                                      " set."); -        } - -        ret = dict_get_str (this->options, "glusterd-uuid", &guuid); -        if (!ret) { -                if (gf_uuid_parse (guuid, _private->glusterd_uuid)) -                        gf_msg (this->name, GF_LOG_WARNING, 0, -                                P_MSG_INVALID_NODE_UUID, "Cannot parse " -                                "glusterd (node) UUID, node-uuid xattr " -                                "request would return - \"No such attribute\""); -        } else { -                gf_msg_debug (this->name, 0, "No glusterd (node) UUID passed -" -                              " node-uuid xattr request will return \"No such" -                              " attribute\""); -        } -        ret = 0; - -        GF_OPTION_INIT ("janitor-sleep-duration", -                        _private->janitor_sleep_duration, int32, out); - -        /* performing open dir on brick dir locks the brick dir -         * and prevents it from being unmounted -         */ -        _private->mount_lock = sys_opendir (dir_data->data); -        if (!_private->mount_lock) { -                ret = -1; -                op_errno = errno; -                gf_msg (this->name, GF_LOG_ERROR, 0, -                        P_MSG_DIR_OPERATION_FAILED, -                        "Could not lock brick directory (%s)", -                        strerror (op_errno)); -                goto out; -        } -#ifndef GF_DARWIN_HOST_OS -        { -                struct rlimit lim; -                lim.rlim_cur = 1048576; -                lim.rlim_max = 1048576; - -                if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_SET_ULIMIT_FAILED, -                                "Failed to set 'ulimit -n " -                                " 1048576'"); -                        lim.rlim_cur = 65536; -                        lim.rlim_max = 65536; - -                        if (setrlimit (RLIMIT_NOFILE, &lim) == -1) { -                                gf_msg (this->name, GF_LOG_WARNING, errno, -                                        P_MSG_SET_FILE_MAX_FAILED, -                                        "Failed to set maximum allowed open " -                                        "file descriptors to 64k"); -                        } -                        else { -                                gf_msg (this->name, GF_LOG_INFO, 0, -                                        P_MSG_MAX_FILE_OPEN, "Maximum allowed " -                                        "open file descriptors set to 65536"); -                        } -                } -        } -#endif -        _private->shared_brick_count = 1; -        ret = dict_get_int32 (this->options, "shared-brick-count", -                              &_private->shared_brick_count); -        if (ret == -1) { -                gf_msg (this->name, GF_LOG_ERROR, 0, -                        P_MSG_INVALID_OPTION_VAL, -                        "'shared-brick-count' takes only integer " -                        "values"); -                goto out; -        } - -        this->private = (void *)_private; - -        op_ret = posix_handle_init (this); -        if (op_ret == -1) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE, -                        "Posix handle setup failed"); -                ret = -1; -                goto out; -        } - -        op_ret = posix_handle_trash_init (this); -        if (op_ret < 0) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE_TRASH, -                        "Posix landfill setup failed"); -                ret = -1; -                goto out; -	} - -        op_ret = posix_create_unlink_dir (this); -        if (op_ret == -1) { -                gf_msg (this->name, GF_LOG_ERROR, 0, -                        P_MSG_HANDLE_CREATE, -                        "Creation of unlink directory failed"); -                ret = -1; -                goto out; -        } - -	_private->aio_init_done = _gf_false; -	_private->aio_capable = _gf_false; - -        GF_OPTION_INIT ("brick-uid", uid, int32, out); -        GF_OPTION_INIT ("brick-gid", gid, int32, out); -	if (uid != -1 || gid != -1) -		posix_set_owner (this, uid, gid); - -	GF_OPTION_INIT ("linux-aio", _private->aio_configured, bool, out); - -	if (_private->aio_configured) { -		op_ret = posix_aio_on (this); - -		if (op_ret == -1) { -			gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_POSIX_AIO, -				"Posix AIO init failed"); -			ret = -1; -			goto out; -		} -	} - -        GF_OPTION_INIT ("node-uuid-pathinfo", -                        _private->node_uuid_pathinfo, bool, out); -        if (_private->node_uuid_pathinfo && -            (gf_uuid_is_null (_private->glusterd_uuid))) { -                        gf_msg (this->name, GF_LOG_INFO, 0, P_MSG_UUID_NULL, -                                "glusterd uuid is NULL, pathinfo xattr would" -                                " fallback to <hostname>:<export>"); -        } - -        _private->disk_space_check_active = _gf_false; -        _private->disk_space_full          = 0; -        GF_OPTION_INIT ("reserve", -                        _private->disk_reserve, uint32, out); -        if (_private->disk_reserve) -                posix_spawn_disk_space_check_thread (this); - -        _private->health_check_active = _gf_false; -        GF_OPTION_INIT ("health-check-interval", -                        _private->health_check_interval, uint32, out); -        GF_OPTION_INIT ("health-check-timeout", -                        _private->health_check_timeout, uint32, out); -        if (_private->health_check_interval) -                posix_spawn_health_check_thread (this); - -        pthread_mutex_init (&_private->janitor_lock, NULL); -        pthread_cond_init (&_private->janitor_cond, NULL); -        INIT_LIST_HEAD (&_private->janitor_fds); - -        posix_spawn_janitor_thread (this); - -	pthread_mutex_init (&_private->fsync_mutex, NULL); -	pthread_cond_init (&_private->fsync_cond, NULL); -	INIT_LIST_HEAD (&_private->fsyncs); - -        ret = gf_thread_create (&_private->fsyncer, NULL, posix_fsyncer, this, -                                "posixfsy"); -	if (ret) { -		gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_FSYNCER_THREAD_CREATE_FAILED, -                        "fsyncer thread creation failed"); -		goto out; -	} - -	GF_OPTION_INIT ("batch-fsync-mode", batch_fsync_mode_str, str, out); - -	if (set_batch_fsync_mode (_private, batch_fsync_mode_str) != 0) { -		gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, -                        "Unknown mode string: %s", batch_fsync_mode_str); -		goto out; -	} - -        GF_OPTION_INIT ("gfid2path", _private->gfid2path, bool, out); - -	GF_OPTION_INIT ("gfid2path-separator", gfid2path_sep, str, out); -        if (set_gfid2path_separator (_private, gfid2path_sep) != 0) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, -                        "Length of separator exceeds 7: %s", gfid2path_sep); -                goto out; -        } - -#ifdef GF_DARWIN_HOST_OS - -        char  *xattr_user_namespace_mode_str = NULL; - -        GF_OPTION_INIT ("xattr-user-namespace-mode", -                        xattr_user_namespace_mode_str, str, out); - -        if (set_xattr_user_namespace_mode (_private, -                                           xattr_user_namespace_mode_str) != 0) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_INVALID_ARGUMENT, -                        "Unknown xattr user namespace mode string: %s", -                        xattr_user_namespace_mode_str); -                goto out; -        } -#endif - -        GF_OPTION_INIT ("batch-fsync-delay-usec", _private->batch_fsync_delay_usec, -                        uint32, out); -        GF_OPTION_INIT ("force-create-mode", force_create, int32, out); -        _private->force_create_mode = force_create; - -        GF_OPTION_INIT ("force-directory-mode", force_directory, int32, out); -        _private->force_directory_mode = force_directory; - -        GF_OPTION_INIT ("create-mask", -                        create_mask, int32, out); -        _private->create_mask = create_mask; - -        GF_OPTION_INIT ("create-directory-mask", -                        create_directory_mask, int32, out); -        _private->create_directory_mask = create_directory_mask; -out: -        if (ret) { -                if (_private) { -                        GF_FREE (_private->base_path); - -                        GF_FREE (_private->hostname); - -                        GF_FREE (_private->trash_path); - -                        GF_FREE (_private); -                } - -                this->private = NULL; -        } -        return ret; -} - -void -fini (xlator_t *this) -{ -        struct posix_private *priv = this->private; -        if (!priv) -                return; -        this->private = NULL; -        /*unlock brick dir*/ -        if (priv->mount_lock) -                (void) sys_closedir (priv->mount_lock); - -        GF_FREE (priv->base_path); -        GF_FREE (priv->hostname); -        GF_FREE (priv->trash_path); -        GF_FREE (priv); - -        return; -}  struct xlator_dumpops dumpops = {          .priv    = posix_priv,          .inode   = posix_inode, @@ -8081,8 +71,8 @@ struct xlator_fops fops = {          .fxattrop    = posix_fxattrop,          .setattr     = posix_setattr,          .fsetattr    = posix_fsetattr, -	.fallocate   = _posix_fallocate, -	.discard     = posix_discard, +	    .fallocate   = posix_glfallocate, +	    .discard     = posix_discard,          .zerofill    = posix_zerofill,          .ipc         = posix_ipc,  #ifdef HAVE_SEEK_HOLE @@ -8096,217 +86,3 @@ struct xlator_cbks cbks = {          .releasedir  = posix_releasedir,          .forget      = posix_forget  }; - -struct volume_options options[] = { -        { .key  = {"o-direct"}, -          .type = GF_OPTION_TYPE_BOOL }, -        { .key  = {"directory"}, -          .type = GF_OPTION_TYPE_PATH, -          .default_value = "{{brick.path}}" -        }, -        { .key  = {"hostname"}, -          .type = GF_OPTION_TYPE_ANY }, -        { .key  = {"export-statfs-size"}, -          .type = GF_OPTION_TYPE_BOOL }, -        { .key  = {"mandate-attribute"}, -          .type = GF_OPTION_TYPE_BOOL }, -        { .key  = {"background-unlink"}, -          .type = GF_OPTION_TYPE_BOOL }, -        { .key  = {"janitor-sleep-duration"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 1, -          .validate = GF_OPT_VALIDATE_MIN, -          .default_value = "10", -          .description = "Interval (in seconds) between times the internal " -                         "'landfill' directory is emptied." -        }, -        { .key  = {"volume-id"}, -          .type = GF_OPTION_TYPE_ANY, -          .default_value = "{{brick.volumeid}}" -        }, -        { .key  = {"glusterd-uuid"}, -          .type = GF_OPTION_TYPE_STR }, -	{ -	  .key  = {"linux-aio"}, -	  .type = GF_OPTION_TYPE_BOOL, -	  .default_value = "off", -          .description = "Support for native Linux AIO", -          .op_version = {1}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -	}, -        { -          .key = {"brick-uid"}, -          .type = GF_OPTION_TYPE_INT, -          .min = -1, -          .validate = GF_OPT_VALIDATE_MIN, -	  .default_value = "-1", -          .description = "Support for setting uid of brick's owner", -          .op_version = {1}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -        { -          .key = {"brick-gid"}, -          .type = GF_OPTION_TYPE_INT, -          .min = -1, -          .validate = GF_OPT_VALIDATE_MIN, -	  .default_value = "-1", -          .description = "Support for setting gid of brick's owner", -          .op_version = {1}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -        { .key = {"node-uuid-pathinfo"}, -          .type = GF_OPTION_TYPE_BOOL, -          .default_value = "off", -          .description = "return glusterd's node-uuid in pathinfo xattr" -                         " string instead of hostname", -          .op_version = {3}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -        { -          .key = {"health-check-interval"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0, -          .default_value = "30", -          .validate = GF_OPT_VALIDATE_MIN, -          .description = "Interval in seconds for a filesystem health check, " -                         "set to 0 to disable", -          .op_version = {3}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -        { -          .key = {"health-check-timeout"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0, -          .default_value = "10", -          .validate = GF_OPT_VALIDATE_MIN, -          .description = "Interval in seconds to wait aio_write finish for health check, " -                         "set to 0 to disable", -          .op_version = {GD_OP_VERSION_4_0_0}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -        { -          .key = {"reserve"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0, -          .default_value = "1", -          .validate = GF_OPT_VALIDATE_MIN, -          .description = "Percentage of disk space to be reserved." -           " Set to 0 to disable", -          .op_version = {GD_OP_VERSION_3_13_0}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -	{ .key = {"batch-fsync-mode"}, -	  .type = GF_OPTION_TYPE_STR, -	  .default_value = "reverse-fsync", -	  .description = "Possible values:\n" -	  "\t- syncfs: Perform one syncfs() on behalf oa batch" -	  "of fsyncs.\n" -	  "\t- syncfs-single-fsync: Perform one syncfs() on behalf of a batch" -	  " of fsyncs and one fsync() per batch.\n" -	  "\t- syncfs-reverse-fsync: Preform one syncfs() on behalf of a batch" -	  " of fsyncs and fsync() each file in the batch in reverse order.\n" -	  " in reverse order.\n" -	  "\t- reverse-fsync: Perform fsync() of each file in the batch in" -	  " reverse order.", -          .op_version = {3}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -	}, -	{ .key = {"batch-fsync-delay-usec"}, -	  .type = GF_OPTION_TYPE_INT, -	  .default_value = "0", -	  .description = "Num of usecs to wait for aggregating fsync" -	  " requests", -          .op_version = {3}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -	}, -        { .key = {"update-link-count-parent"}, -          .type = GF_OPTION_TYPE_BOOL, -          .default_value = "off", -          .description = "Enable placeholders for gfid to path conversion", -          .op_version = {GD_OP_VERSION_3_6_0}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -        { .key = {"gfid2path"}, -          .type = GF_OPTION_TYPE_BOOL, -#ifdef __NetBSD__ -          /* -           * NetBSD storage of extended attributes for UFS1 badly -           * scales when the list of extended attributes names rises. -           * This option can add as many extended attributes names -           * as we have files, hence we keep it disabled for performance -           * sake. -           */ -          .default_value = "off", -#else -          .default_value = "on", -#endif -          .description = "Enable logging metadata for gfid to path conversion", -          .op_version = {GD_OP_VERSION_3_12_0}, -          .flags = OPT_FLAG_SETTABLE -        }, -        { .key = {"gfid2path-separator"}, -          .type = GF_OPTION_TYPE_STR, -          .default_value = ":", -          .description = "Path separator for glusterfs.gfidtopath virt xattr", -          .op_version = {GD_OP_VERSION_3_12_0}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -#if GF_DARWIN_HOST_OS -        { .key = {"xattr-user-namespace-mode"}, -          .type = GF_OPTION_TYPE_STR, -          .default_value = "none", -          .description = "Option to control XATTR user namespace on the raw filesystem: " -	  "\t- None: Will use the user namespace, so files will be exchangable with Linux.\n" -	  " The raw filesystem will not be compatible with OS X Finder.\n" -	  "\t- Strip: Will strip the user namespace before setting. The raw filesystem will work in OS X.\n", -          .op_version = {GD_OP_VERSION_3_6_0}, -          .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC -        }, -#endif -        { .key  = {"shared-brick-count"}, -          .type = GF_OPTION_TYPE_INT, -          .default_value = "1", -          .description = "Number of bricks sharing the same backend export." -          " Useful for displaying the proper usable size through statvfs() " -          "call (df command)", -        }, -        { .key  = {"force-create-mode"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0000, -          .max = 0777, -          .default_value = "0000", -          .validate = GF_OPT_VALIDATE_MIN, -          .validate = GF_OPT_VALIDATE_MAX, -          .description = "Mode bit permission that will always be set on a file." -        }, -        { .key  = {"force-directory-mode"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0000, -          .max = 0777, -          .default_value = "0000", -          .validate = GF_OPT_VALIDATE_MIN, -          .validate = GF_OPT_VALIDATE_MAX, -          .description = "Mode bit permission that will be always set on directory" -        }, -        { .key  = {"create-mask"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0000, -          .max = 0777, -          .default_value = "0777", -          .validate = GF_OPT_VALIDATE_MIN, -          .validate = GF_OPT_VALIDATE_MAX, -          .description = "Any bit not set here will be removed from the" -          "modes set on a file when it is created" -        }, -        { .key  = {"create-directory-mask"}, -          .type = GF_OPTION_TYPE_INT, -          .min = 0000, -          .max = 0777, -          .default_value = "0777", -          .validate = GF_OPT_VALIDATE_MIN, -          .validate = GF_OPT_VALIDATE_MAX, -          .description = "Any bit not set here will be removed from the" -          "modes set on a directory when it is created" -        }, -        { .key  = {NULL} } -}; diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index e2f1dfa2dd1..36348767870 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -363,4 +363,247 @@ posix_fdget_objectsignature (int, dict_t *);  gf_boolean_t  posix_is_bulk_removexattr (char *name, dict_t *dict); + +int32_t +posix_set_iatt_in_dict (dict_t *, struct iatt *); + +mode_t +posix_override_umask (mode_t , mode_t); + +int32_t +posix_priv (xlator_t *this); + +int32_t +posix_inode (xlator_t *this); + +void +posix_fini (xlator_t *this); + +int +posix_init (xlator_t *this); + +int +posix_reconfigure (xlator_t *this, dict_t *options); + +int32_t +posix_notify (xlator_t *this, int32_t event, void *data, ...); + +/* posix-entry-ops.c FOP signatures */ +int32_t +posix_lookup (call_frame_t *frame, xlator_t *this, +              loc_t *loc, dict_t *xdata); + +int +posix_create (call_frame_t *frame, xlator_t *this, +              loc_t *loc, int32_t flags, mode_t mode, +              mode_t umask, fd_t *fd, dict_t *xdata); + +int +posix_symlink (call_frame_t *frame, xlator_t *this, +               const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata); + +int +posix_rename (call_frame_t *frame, xlator_t *this, +              loc_t *oldloc, loc_t *newloc, dict_t *xdata); + +int +posix_link (call_frame_t *frame, xlator_t *this, +            loc_t *oldloc, loc_t *newloc, dict_t *xdata); + +int +posix_mknod (call_frame_t *frame, xlator_t *this, +             loc_t *loc, mode_t mode, dev_t dev, mode_t umask, dict_t *xdata); + +int +posix_mkdir (call_frame_t *frame, xlator_t *this, +             loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata); + +int32_t +posix_unlink (call_frame_t *frame, xlator_t *this, +              loc_t *loc, int xflag, dict_t *xdata); + +int +posix_rmdir (call_frame_t *frame, xlator_t *this, +             loc_t *loc, int flags, dict_t *xdata); + +/* posix-inode-fs-ops.c FOP signatures */ +int +posix_forget (xlator_t *this, inode_t *inode); + +int32_t +posix_discover (call_frame_t *frame, xlator_t *this, +                loc_t *loc, dict_t *xdata); + +int32_t +posix_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); + +int +posix_setattr (call_frame_t *frame, xlator_t *this, +               loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int +posix_fsetattr (call_frame_t *frame, xlator_t *this, +                fd_t *fd, struct iatt *stbuf, int32_t valid, dict_t *xdata); + +int32_t +posix_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +              size_t len, dict_t *xdata); + +int32_t +posix_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +               off_t len, dict_t *xdata); + +int32_t +posix_glfallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, +                int32_t keep_size, off_t offset, size_t len, dict_t *xdata); + +int32_t +posix_ipc (call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata); + +int32_t +posix_seek (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +            gf_seek_what_t what, dict_t *xdata); + +int32_t +posix_opendir (call_frame_t *frame, xlator_t *this, +               loc_t *loc, fd_t *fd, dict_t *xdata); + +int32_t +posix_releasedir (xlator_t *this, +                  fd_t *fd); + +int32_t +posix_readlink (call_frame_t *frame, xlator_t *this, +                loc_t *loc, size_t size, dict_t *xdata); + +int32_t +posix_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, +                dict_t *xdata); + +int32_t +posix_open (call_frame_t *frame, xlator_t *this, +            loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata); + +int +posix_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, +             off_t offset, uint32_t flags, dict_t *xdata); + +int32_t +posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, +              struct iovec *vector, int32_t count, off_t offset, +              uint32_t flags, struct iobref *iobref, dict_t *xdata); + +int32_t +posix_statfs (call_frame_t *frame, xlator_t *this, +              loc_t *loc, dict_t *xdata); + +int32_t +posix_flush (call_frame_t *frame, xlator_t *this, +             fd_t *fd, dict_t *xdata); + +int32_t +posix_release (xlator_t *this, fd_t *fd); + +int32_t +posix_fsync (call_frame_t *frame, xlator_t *this, +             fd_t *fd, int32_t datasync, dict_t *xdata); + +int32_t +posix_setxattr (call_frame_t *frame, xlator_t *this, +                loc_t *loc, dict_t *dict, int flags, dict_t *xdata); + +int +posix_get_ancestry_non_directory (xlator_t *this, inode_t *leaf_inode, +                                  gf_dirent_t *head, char **path, int type, +                                  int32_t *op_errno, dict_t *xdata); + +int +posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, +                    gf_dirent_t *head, char **path, int type, int32_t *op_errno, +                    dict_t *xdata); + +int32_t +posix_getxattr (call_frame_t *frame, xlator_t *this, +                loc_t *loc, const char *name, dict_t *xdata); + +int32_t +posix_fgetxattr (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, const char *name, dict_t *xdata); + +int32_t +posix_fsetxattr (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, dict_t *dict, int flags, dict_t *xdata); + +int32_t +posix_removexattr (call_frame_t *frame, xlator_t *this, +                   loc_t *loc, const char *name, dict_t *xdata); + +int32_t +posix_fremovexattr (call_frame_t *frame, xlator_t *this, +                    fd_t *fd, const char *name, dict_t *xdata); + +int32_t +posix_fsyncdir (call_frame_t *frame, xlator_t *this, +                fd_t *fd, int datasync, dict_t *xdata); + +int +posix_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, +               gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata); + +int +posix_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, +                gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata); + +int +posix_access (call_frame_t *frame, xlator_t *this, +              loc_t *loc, int32_t mask, dict_t *xdata); + +int32_t +posix_ftruncate (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, off_t offset, dict_t *xdata); + +int32_t +posix_fstat (call_frame_t *frame, xlator_t *this, +             fd_t *fd, dict_t *xdata); + +int32_t +posix_lease (call_frame_t *frame, xlator_t *this, +             loc_t *loc, struct gf_lease *lease, dict_t *xdata); + +int32_t +posix_lk (call_frame_t *frame, xlator_t *this, +          fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata); + +int32_t +posix_inodelk (call_frame_t *frame, xlator_t *this, +               const char *volume, loc_t *loc, int32_t cmd, +               struct gf_flock *lock, dict_t *xdata); + +int32_t +posix_finodelk (call_frame_t *frame, xlator_t *this, +                const char *volume, fd_t *fd, int32_t cmd, +                struct gf_flock *lock, dict_t *xdata); + +int32_t +posix_entrylk (call_frame_t *frame, xlator_t *this, +               const char *volume, loc_t *loc, const char *basename, +               entrylk_cmd cmd, entrylk_type type, dict_t *xdata); + +int32_t +posix_fentrylk (call_frame_t *frame, xlator_t *this, +                const char *volume, fd_t *fd, const char *basename, +                entrylk_cmd cmd, entrylk_type type, dict_t *xdata); + +int32_t +posix_readdir (call_frame_t *frame, xlator_t *this, +               fd_t *fd, size_t size, off_t off, dict_t *xdata); + +int32_t +posix_readdirp (call_frame_t *frame, xlator_t *this, +                fd_t *fd, size_t size, off_t off, dict_t *dict); + +int32_t +posix_rchecksum (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, off_t offset, int32_t len, dict_t *xdata); +  #endif /* _POSIX_H */  | 
