diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-gfid-path.c')
| -rw-r--r-- | xlators/storage/posix/src/posix-gfid-path.c | 184 | 
1 files changed, 184 insertions, 0 deletions
diff --git a/xlators/storage/posix/src/posix-gfid-path.c b/xlators/storage/posix/src/posix-gfid-path.c index 7529f559fc7..2834c2fc4fd 100644 --- a/xlators/storage/posix/src/posix-gfid-path.c +++ b/xlators/storage/posix/src/posix-gfid-path.c @@ -13,6 +13,9 @@  #include "syscall.h"  #include "logging.h"  #include "posix-messages.h" +#include "posix-mem-types.h" +#include "posix-gfid-path.h" +#include "posix.h"  int32_t  posix_set_gfid2path_xattr (xlator_t *this, const char *path, uuid_t pgfid, @@ -96,3 +99,184 @@ posix_is_gfid2path_xattr (const char *name)                  return _gf_false;          }  } + +static int gf_posix_xattr_enotsup_log; + +int32_t +posix_get_gfid2path (xlator_t *this, inode_t *inode, const char *real_path, +                     int *op_errno, dict_t *dict) +{ +        int                    ret                             = 0; +        char                  *path                            = NULL; +        ssize_t                size                            = 0; +        char                  *list                            = NULL; +        int32_t                list_offset                     = 0; +        int32_t                i                               = 0; +        int32_t                j                               = 0; +        char                  *paths[MAX_GFID2PATH_LINK_SUP]   = {NULL,}; +        char                  *value                           = NULL; +        size_t                 remaining_size                  = 0; +        size_t                 bytes                           = 0; +        char                   keybuffer[4096]                 = {0,}; +        char                   value_buf[8192]                 = {0,}; +        uuid_t                 pargfid                         = {0,}; +        gf_boolean_t           have_val                        = _gf_false; +        struct posix_private  *priv                            = NULL; +        char                   pargfid_str[UUID_CANONICAL_FORM_LEN + 1] = {0,}; + +        priv = this->private; + +        if (IA_ISDIR (inode->ia_type)) { +                ret = posix_resolve_dirgfid_to_path (inode->gfid, +                                                     priv->base_path, +                                                     NULL, &path); +                if (ret < 0) { +                        ret = -1; +                        goto err; +                } +                ret = dict_set_dynstr (dict, GFID2PATH_VIRT_XATTR_KEY, path); +                if (ret < 0) { +                        gf_msg (this->name, GF_LOG_WARNING, -ret, +                                P_MSG_DICT_SET_FAILED, "could not set " +                                "value for key (%s)", GFID2PATH_VIRT_XATTR_KEY); +                        goto err; +                } +        } else { +                have_val = _gf_false; +                memset (value_buf, '\0', sizeof(value_buf)); +                size = sys_llistxattr (real_path, value_buf, +                                       sizeof (value_buf) - 1); +                if (size > 0) { +                        have_val = _gf_true; +                } else { +                        if (errno == ERANGE) { +                                gf_msg (this->name, GF_LOG_DEBUG, 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 err; +                        } +                        if (size == 0) +                                goto done; +                } +                list = alloca (size); +                if (!list) { +                        *op_errno = errno; +                        goto err; +                } +                if (have_val) { +                        memcpy (list, value_buf, size); +                } else { +                        size = sys_llistxattr (real_path, list, size); +                        if (size < 0) { +                                ret = -1; +                                *op_errno = errno; +                                goto err; +                        } +                } +                remaining_size = size; +                list_offset = 0; +                while (remaining_size > 0) { +                        strncpy (keybuffer, list + list_offset, +                                 sizeof(keybuffer)); + +                        if (!posix_is_gfid2path_xattr (keybuffer)) { +                                goto ignore; +                        } + +                        memset (value_buf, '\0', sizeof(value_buf)); +                        size = sys_lgetxattr (real_path, keybuffer, value_buf, +                                              sizeof (value_buf) - 1); +                        if (size == -1) { +                                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, keybuffer); +                                break; +                        } + +                        /* Parse pargfid from xattr value*/ +                        strncpy (pargfid_str, value_buf, 36); +                        pargfid_str[36] = '\0'; +                        gf_uuid_parse (pargfid_str, pargfid); + +                        /* Convert pargfid to path */ +                        ret = posix_resolve_dirgfid_to_path (pargfid, +                                                             priv->base_path, +                                                             &value_buf[37], +                                                             &paths[i]); +                        i++; + +ignore: +                        remaining_size -= strlen (keybuffer) + 1; +                        list_offset += strlen (keybuffer) + 1; +                } /* while (remaining_size > 0) */ + +                /* Calculate memory to be allocated */ +                for (j = 0; j < i; j++) { +                        bytes += strlen(paths[j]); +                        if (j < i-1) +                                bytes += strlen(priv->gfid2path_sep); +                } +                value = GF_CALLOC (bytes + 1, sizeof(char), gf_posix_mt_char); +                if (!value) { +                        ret = -1; +                        *op_errno = errno; +                        goto err; +                } + +                for (j = 0; j < i; j++) { +                        strcat (value, paths[j]); +                        if (j != i - 1) +                                strcat (value, priv->gfid2path_sep); +                } +                value[bytes] = '\0'; + +                ret = dict_set_dynptr (dict, GFID2PATH_VIRT_XATTR_KEY, +                                       value, bytes); +                if (ret < 0) { +                        *op_errno = -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, GFID2PATH_VIRT_XATTR_KEY); +                        GF_FREE (value); +                        goto err; +                } +        } + +done: +        for (j = 0; j < i; j++) { +                if (paths[j]) +                        GF_FREE (paths[j]); +        } +        ret = 0; +        return ret; +err: +        if (path) +                GF_FREE (path); +        for (j = 0; j < i; j++) { +                if (paths[j]) +                        GF_FREE (paths[j]); +        } +        return ret; +}  | 
