diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-handle.c')
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 1607 | 
1 files changed, 777 insertions, 830 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index 802dcf1cc2a..bc34e3e5dba 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -28,366 +28,358 @@  #include "compat-errno.h"  int -posix_handle_mkdir_hashes (xlator_t *this, const char *newpath); +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) +posix_resolve(xlator_t *this, inode_table_t *itable, inode_t *parent, +              char *bname, struct iatt *iabuf)  { -        inode_t     *inode = NULL; -        int          ret   = -1; - -        ret = posix_istat (this, NULL, parent->gfid, bname, iabuf); -        if (ret < 0) { -                gf_log (this->name, GF_LOG_WARNING, "gfid: %s, bname: %s " -                        "failed", uuid_utoa (parent->gfid), bname); -                goto out; -        } - -        if (__is_root_gfid (iabuf->ia_gfid) && !strcmp (bname, "/")) { -                inode = itable->root; -        } else { -                inode = inode_find (itable, iabuf->ia_gfid); -                if (inode == NULL) { -                        inode = inode_new (itable); -                        gf_uuid_copy (inode->gfid, iabuf->ia_gfid); -                } -        } - -        /* posix_istat wouldn't have fetched posix_mdata_t i.e., -         * time attributes as inode is passed as NULL, hence get -         * here once you got the inode -         */ -        ret = posix_get_mdata_xattr (this, NULL, -1, inode, iabuf); -        if (ret) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_GETMDATA_FAILED, -                        "posix get mdata failed on gfid:%s", -                        uuid_utoa (inode->gfid)); -                goto out; -        } - -        /* 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 - -        if (__is_root_gfid (iabuf->ia_gfid) && !strcmp (bname, "/")) -                linked_inode = itable->root; -        else -                linked_inode = inode_link (inode, parent, bname, iabuf); - -        inode_unref (inode);*/ +    inode_t *inode = NULL; +    int ret = -1; + +    ret = posix_istat(this, NULL, parent->gfid, bname, iabuf); +    if (ret < 0) { +        gf_log(this->name, GF_LOG_WARNING, +               "gfid: %s, bname: %s " +               "failed", +               uuid_utoa(parent->gfid), bname); +        goto out; +    } + +    if (__is_root_gfid(iabuf->ia_gfid) && !strcmp(bname, "/")) { +        inode = itable->root; +    } else { +        inode = inode_find(itable, iabuf->ia_gfid); +        if (inode == NULL) { +            inode = inode_new(itable); +            gf_uuid_copy(inode->gfid, iabuf->ia_gfid); +        } +    } + +    /* posix_istat wouldn't have fetched posix_mdata_t i.e., +     * time attributes as inode is passed as NULL, hence get +     * here once you got the inode +     */ +    ret = posix_get_mdata_xattr(this, NULL, -1, inode, iabuf); +    if (ret) { +        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_GETMDATA_FAILED, +               "posix get mdata failed on gfid:%s", uuid_utoa(inode->gfid)); +        goto out; +    } + +    /* 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 + +    if (__is_root_gfid (iabuf->ia_gfid) && !strcmp (bname, "/")) +            linked_inode = itable->root; +    else +            linked_inode = inode_link (inode, parent, bname, iabuf); + +    inode_unref (inode);*/  out: -        return inode; +    return inode;  }  int -posix_make_ancestral_node (const char *priv_base_path, char *path, int pathsize, -                           gf_dirent_t *head, -                           char *dir_name, struct iatt *iabuf, inode_t *inode, -                           int type, dict_t *xdata) +posix_make_ancestral_node(const char *priv_base_path, char *path, int pathsize, +                          gf_dirent_t *head, char *dir_name, struct iatt *iabuf, +                          inode_t *inode, int type, dict_t *xdata)  { -        gf_dirent_t *entry           = NULL; -        char real_path[PATH_MAX + 1] = {0, }, len = 0; -        loc_t        loc             = {0, }; -        int          ret             = -1; - -        len = strlen (path) + strlen (dir_name) + 1; -        if (len > pathsize) { -                goto out; -        } - -        strcat (path, dir_name); -        if (*dir_name != '/') -                strcat (path, "/"); - -        if (type & POSIX_ANCESTRY_DENTRY) { -                entry = gf_dirent_for_name (dir_name); -                if (!entry) -                        goto out; - -                entry->d_stat = *iabuf; -                entry->inode = inode_ref (inode); - -                list_add_tail (&entry->list, &head->list); -                snprintf(real_path, sizeof (real_path), "%s/%s", priv_base_path, path); -                loc.inode = inode_ref (inode); -                gf_uuid_copy (loc.gfid, inode->gfid); - -                entry->dict = posix_xattr_fill (THIS, real_path, &loc, NULL, -1, -                                                xdata, iabuf); -                loc_wipe (&loc); -        } - -        ret = 0; +    gf_dirent_t *entry = NULL; +    char real_path[PATH_MAX + 1] = +        { +            0, +        }, +                              len = 0; +    loc_t loc = { +        0, +    }; +    int ret = -1; + +    len = strlen(path) + strlen(dir_name) + 1; +    if (len > pathsize) { +        goto out; +    } + +    strcat(path, dir_name); +    if (*dir_name != '/') +        strcat(path, "/"); + +    if (type & POSIX_ANCESTRY_DENTRY) { +        entry = gf_dirent_for_name(dir_name); +        if (!entry) +            goto out; + +        entry->d_stat = *iabuf; +        entry->inode = inode_ref(inode); + +        list_add_tail(&entry->list, &head->list); +        snprintf(real_path, sizeof(real_path), "%s/%s", priv_base_path, path); +        loc.inode = inode_ref(inode); +        gf_uuid_copy(loc.gfid, inode->gfid); + +        entry->dict = posix_xattr_fill(THIS, real_path, &loc, NULL, -1, xdata, +                                       iabuf); +        loc_wipe(&loc); +    } + +    ret = 0;  out: -        return ret; +    return ret;  }  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 *itable, -                             inode_t **parent, dict_t *xdata, int32_t *op_errno) +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 *itable, +                            inode_t **parent, dict_t *xdata, int32_t *op_errno)  { -        char        *linkname   = NULL; /* "../../<gfid[0]>/<gfid[1]/" -                                         "<gfidstr>/<NAME_MAX>" */ -        char        *dir_handle = NULL; -        char        *pgfidstr   = NULL; -        char        *saveptr    = NULL; -        ssize_t       len        = 0; -        inode_t     *inode      = NULL; -        struct iatt  iabuf      = {0, }; -        int          ret        = -1; -        uuid_t       tmp_gfid   = {0, }; -        char        *dir_stack[PATH_MAX/2 + 1]; /* Since PATH_MAX/2 also gives -                                                 an upper bound on depth of -                                                 directories tree */ -        uuid_t       gfid_stack[PATH_MAX/2 + 1]; - -        char        *dir_name   = NULL; -        char        *saved_dir  = NULL; -        int          top = -1; - -        if (!path || !parent || !priv_base_path || gf_uuid_is_null (gfid)) { -                *op_errno = EINVAL; -                goto out; -        } - -        dir_handle = alloca (handle_size); -        linkname   = alloca (PATH_MAX); -        gf_uuid_copy(tmp_gfid, gfid); - -        while (top < PATH_MAX/2) { - -                gf_uuid_copy(gfid_stack[++top], tmp_gfid); -                if (__is_root_gfid (tmp_gfid)) { - -                        *parent = inode_ref (itable->root); - -                        saved_dir = alloca(sizeof ("/")); -                        strcpy(saved_dir, "/"); -                        dir_stack[top] = saved_dir; -                        break; -                } else { -                        snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s", -                                  priv_base_path, GF_HIDDEN_PATH, tmp_gfid[0], -                                  tmp_gfid[1], uuid_utoa (tmp_gfid)); - -                        len = sys_readlink (dir_handle, linkname, PATH_MAX); -                        if (len < 0) { -                                *op_errno = errno; -                                gf_msg (this->name, (errno == ENOENT || -                                                      errno == ESTALE) -                                        ? GF_LOG_DEBUG:GF_LOG_ERROR, errno, -                                        P_MSG_READLINK_FAILED, "could not read" -                                        " the link from the gfid handle %s ", -                                         dir_handle); -                                ret = -1; -                                goto out; -                        } - -                        linkname[len] = '\0'; - -                        pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), -                                              "/", &saveptr); -                        dir_name = strtok_r (NULL, "/", &saveptr); -                        saved_dir = alloca(strlen(dir_name) + 1); -                        gf_uuid_parse (pgfidstr, tmp_gfid); -                        strcpy(saved_dir, dir_name); -                        dir_stack[top] = saved_dir; -                } -        } -        if (top == PATH_MAX/2) { -                gf_msg (this->name, GF_LOG_ERROR, -                        P_MSG_ANCESTORY_FAILED, -                        0, "build ancestry failed due to " -                        "deep directory hierarchy, depth: %d.", top); -                *op_errno = EINVAL; +    char *linkname = NULL; /* "../../<gfid[0]>/<gfid[1]/" +                            "<gfidstr>/<NAME_MAX>" */ +    char *dir_handle = NULL; +    char *pgfidstr = NULL; +    char *saveptr = NULL; +    ssize_t len = 0; +    inode_t *inode = NULL; +    struct iatt iabuf = { +        0, +    }; +    int ret = -1; +    uuid_t tmp_gfid = { +        0, +    }; +    char *dir_stack[PATH_MAX / 2 + 1]; /* Since PATH_MAX/2 also gives +                                        an upper bound on depth of +                                        directories tree */ +    uuid_t gfid_stack[PATH_MAX / 2 + 1]; + +    char *dir_name = NULL; +    char *saved_dir = NULL; +    int top = -1; + +    if (!path || !parent || !priv_base_path || gf_uuid_is_null(gfid)) { +        *op_errno = EINVAL; +        goto out; +    } + +    dir_handle = alloca(handle_size); +    linkname = alloca(PATH_MAX); +    gf_uuid_copy(tmp_gfid, gfid); + +    while (top < PATH_MAX / 2) { +        gf_uuid_copy(gfid_stack[++top], tmp_gfid); +        if (__is_root_gfid(tmp_gfid)) { +            *parent = inode_ref(itable->root); + +            saved_dir = alloca(sizeof("/")); +            strcpy(saved_dir, "/"); +            dir_stack[top] = saved_dir; +            break; +        } else { +            snprintf(dir_handle, handle_size, "%s/%s/%02x/%02x/%s", +                     priv_base_path, GF_HIDDEN_PATH, tmp_gfid[0], tmp_gfid[1], +                     uuid_utoa(tmp_gfid)); + +            len = sys_readlink(dir_handle, linkname, PATH_MAX); +            if (len < 0) { +                *op_errno = errno; +                gf_msg(this->name, +                       (errno == ENOENT || errno == ESTALE) ? GF_LOG_DEBUG +                                                            : GF_LOG_ERROR, +                       errno, P_MSG_READLINK_FAILED, +                       "could not read" +                       " the link from the gfid handle %s ", +                       dir_handle);                  ret = -1;                  goto out; +            } + +            linkname[len] = '\0'; + +            pgfidstr = strtok_r(linkname + SLEN("../../00/00/"), "/", &saveptr); +            dir_name = strtok_r(NULL, "/", &saveptr); +            saved_dir = alloca(strlen(dir_name) + 1); +            gf_uuid_parse(pgfidstr, tmp_gfid); +            strcpy(saved_dir, dir_name); +            dir_stack[top] = saved_dir; +        } +    } +    if (top == PATH_MAX / 2) { +        gf_msg(this->name, GF_LOG_ERROR, P_MSG_ANCESTORY_FAILED, 0, +               "build ancestry failed due to " +               "deep directory hierarchy, depth: %d.", +               top); +        *op_errno = EINVAL; +        ret = -1; +        goto out; +    } + +    while (top >= 0) { +        if (!*parent) { +            /* There's no real "root" cause for how we end up here, +             * so for now let's log this and bail out to prevent +             * crashes. +             */ +            gf_msg(this->name, GF_LOG_WARNING, P_MSG_INODE_RESOLVE_FAILED, 0, +                   "OOPS: *parent is null (path: %s), bailing!", path); +            goto out; +        } + +        memset(&iabuf, 0, sizeof(iabuf)); +        inode = posix_resolve(this, itable, *parent, dir_stack[top], &iabuf); +        if (inode == NULL) { +            gf_msg(this->name, GF_LOG_ERROR, P_MSG_INODE_RESOLVE_FAILED, 0, +                   "posix resolve on the inode %s failed", +                   uuid_utoa(gfid_stack[top])); +            *op_errno = ESTALE; +            ret = -1; +            goto out; +        } + +        ret = posix_make_ancestral_node(priv_base_path, path, pathsize, head, +                                        dir_stack[top], &iabuf, inode, type, +                                        xdata); +        if (ret < 0) { +            *op_errno = ENOMEM; +            goto out;          } -        while (top >= 0) { - -                if (!*parent) { -                        /* There's no real "root" cause for how we end up here, -                         * so for now let's log this and bail out to prevent -                         * crashes. -                         */ -                        gf_msg (this->name, GF_LOG_WARNING, -                                P_MSG_INODE_RESOLVE_FAILED, 0, -                                "OOPS: *parent is null (path: %s), bailing!", -                                path); -                        goto out; -                } - -                memset (&iabuf, 0, sizeof (iabuf)); -                inode = posix_resolve (this, itable, *parent, -                                       dir_stack[top], &iabuf); -                if (inode == NULL) { -                        gf_msg (this->name, GF_LOG_ERROR, -                                 P_MSG_INODE_RESOLVE_FAILED, -                                0, "posix resolve on the inode %s failed", -                                uuid_utoa (gfid_stack[top])); -                        *op_errno = ESTALE; -                        ret = -1; -                        goto out; -                } - -                ret = posix_make_ancestral_node (priv_base_path, path, -                                                 pathsize, head, -                                                 dir_stack[top], &iabuf, -                                                 inode, type, xdata); -                if (ret < 0) { -                        *op_errno = ENOMEM; -                        goto out; -                } - -                inode_unref (*parent); -                *parent = inode; -                top--; -        } +        inode_unref(*parent); +        *parent = inode; +        top--; +    }  out: -        return ret; +    return ret;  }  int -posix_handle_relpath (xlator_t *this, uuid_t gfid, const char *basename, -                      char *buf, size_t buflen) +posix_handle_relpath(xlator_t *this, uuid_t gfid, const char *basename, +                     char *buf, size_t buflen)  { -        char *uuid_str = NULL; -        int   len      = 0; +    char *uuid_str = NULL; +    int len = 0; -        len = SLEN("../") -                + SLEN("../") -                + SLEN("00/") -                + SLEN("00/") -                + SLEN(UUID0_STR) -                + 1 /* '\0' */ -                ; +    len = SLEN("../") + SLEN("../") + SLEN("00/") + SLEN("00/") + +          SLEN(UUID0_STR) + 1 /* '\0' */ +        ; -        if (basename) { -                len += (strlen (basename) + 1); -        } +    if (basename) { +        len += (strlen(basename) + 1); +    } -        if (buflen < len || !buf) -                return len; +    if (buflen < len || !buf) +        return len; -        uuid_str = uuid_utoa (gfid); +    uuid_str = uuid_utoa(gfid); -        if (basename) { -                len = snprintf (buf, buflen, "../../%02x/%02x/%s/%s", -                                gfid[0], gfid[1], uuid_str, basename); -        } else { -                len = snprintf (buf, buflen, "../../%02x/%02x/%s", -                                gfid[0], gfid[1], uuid_str); -        } +    if (basename) { +        len = snprintf(buf, buflen, "../../%02x/%02x/%s/%s", gfid[0], gfid[1], +                       uuid_str, basename); +    } else { +        len = snprintf(buf, buflen, "../../%02x/%02x/%s", gfid[0], gfid[1], +                       uuid_str); +    } -        return len; +    return len;  } -  /*    TODO: explain how this pump fixes ELOOP  */  gf_boolean_t -posix_is_malformed_link (xlator_t *this, char *base_str, char *linkname, -                         size_t len) +posix_is_malformed_link(xlator_t *this, char *base_str, char *linkname, +                        size_t len)  { -        if ((len == 8) && strcmp (linkname, "../../..")) /*for root*/ -                goto err; +    if ((len == 8) && strcmp(linkname, "../../..")) /*for root*/ +        goto err; -        if (len < 50 || len >= 512) -                goto err; +    if (len < 50 || len >= 512) +        goto err; -        if (memcmp (linkname, "../../", 6) != 0) -                goto err; +    if (memcmp(linkname, "../../", 6) != 0) +        goto err; -        if ((linkname[2] != '/') || -            (linkname[5] != '/') || -            (linkname[8] != '/') || -            (linkname[11] != '/') || -            (linkname[48] != '/')) { -                goto err; -        } +    if ((linkname[2] != '/') || (linkname[5] != '/') || (linkname[8] != '/') || +        (linkname[11] != '/') || (linkname[48] != '/')) { +        goto err; +    } -        if ((linkname[20] != '-') || -            (linkname[25] != '-') || -            (linkname[30] != '-') || -            (linkname[35] != '-')) { -                goto err; -        } +    if ((linkname[20] != '-') || (linkname[25] != '-') || +        (linkname[30] != '-') || (linkname[35] != '-')) { +        goto err; +    } -        return _gf_false; +    return _gf_false;  err: -        gf_log_callingfn (this->name, GF_LOG_ERROR, "malformed internal link " -                          "%s for %s", linkname, base_str); -        return _gf_true; +    gf_log_callingfn(this->name, GF_LOG_ERROR, +                     "malformed internal link " +                     "%s for %s", +                     linkname, base_str); +    return _gf_true;  }  int -posix_handle_pump (xlator_t *this, char *buf, int len, int maxlen, -                   char *base_str, int base_len, int pfx_len) +posix_handle_pump(xlator_t *this, char *buf, int len, int maxlen, +                  char *base_str, int base_len, int pfx_len)  { -        char       linkname[512] = {0,}; /* "../../<gfid>/<NAME_MAX>" */ -        int        ret = 0; -        int        blen = 0; -        int        link_len = 0; - -        /* is a directory's symlink-handle */ -        ret = sys_readlink (base_str, linkname, 512); -        if (ret == -1) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_READLINK_FAILED, -                        "internal readlink failed on %s ", -                        base_str); -                goto err; -        } +    char linkname[512] = { +        0, +    }; /* "../../<gfid>/<NAME_MAX>" */ +    int ret = 0; +    int blen = 0; +    int link_len = 0; -        if (ret < 512) -                linkname[ret] = 0; +    /* is a directory's symlink-handle */ +    ret = sys_readlink(base_str, linkname, 512); +    if (ret == -1) { +        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_READLINK_FAILED, +               "internal readlink failed on %s ", base_str); +        goto err; +    } -        link_len = ret; +    if (ret < 512) +        linkname[ret] = 0; -        if ((ret == 8) && memcmp (linkname, "../../..", 8) == 0) { -                if (strcmp (base_str, buf) == 0) { -                        strcpy (buf + pfx_len, ".."); -                } -                goto out; +    link_len = ret; + +    if ((ret == 8) && memcmp(linkname, "../../..", 8) == 0) { +        if (strcmp(base_str, buf) == 0) { +            strcpy(buf + pfx_len, "..");          } +        goto out; +    } -        if (posix_is_malformed_link (this, base_str, linkname, ret)) -                goto err; +    if (posix_is_malformed_link(this, base_str, linkname, ret)) +        goto err; -        blen = link_len - 48; +    blen = link_len - 48; -        if (len + blen >= maxlen) { -                gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_HANDLEPATH_FAILED, -                        "Unable to form handle path for %s (maxlen = %d)", -                        buf, maxlen); -                goto err; -        } +    if (len + blen >= maxlen) { +        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLEPATH_FAILED, +               "Unable to form handle path for %s (maxlen = %d)", buf, maxlen); +        goto err; +    } -        memmove (buf + base_len + blen, buf + base_len, -                 (strlen (buf) - base_len) + 1); +    memmove(buf + base_len + blen, buf + base_len, +            (strlen(buf) - base_len) + 1); -        strncpy (base_str + pfx_len, linkname + 6, 42); +    strncpy(base_str + pfx_len, linkname + 6, 42); -        strncpy (buf + pfx_len, linkname + 6, link_len - 6); +    strncpy(buf + pfx_len, linkname + 6, link_len - 6);  out: -        return len + blen; +    return len + blen;  err: -        return -1; +    return -1;  } -  /*    posix_handle_path differs from posix_handle_gfid_path in the way that the    path filled in @buf by posix_handle_path will return type IA_IFDIR when @@ -398,651 +390,606 @@ err:  */  int -posix_handle_path (xlator_t *this, uuid_t gfid, const char *basename, -                   char *ubuf, size_t size) +posix_handle_path(xlator_t *this, uuid_t gfid, const char *basename, char *ubuf, +                  size_t size)  { -        struct posix_private *priv = NULL; -        char                 *uuid_str = NULL; -        int                   len = 0; -        int                   ret = -1; -        struct stat           stat; -        char                 *base_str = NULL; -        int                   base_len = 0; -        int                   pfx_len; -        int                   maxlen; -        char                 *buf; - -        priv = this->private; - -        uuid_str = uuid_utoa (gfid); - -        if (ubuf) { -                buf = ubuf; -                maxlen = size; -        } else { -                maxlen = PATH_MAX; -                buf = alloca (maxlen); -        } - -        base_len = (priv->base_path_length + SLEN(GF_HIDDEN_PATH) + 45); -        base_str = alloca (base_len + 1); -        base_len = snprintf (base_str, base_len + 1, "%s/%s/%02x/%02x/%s", -                             priv->base_path, GF_HIDDEN_PATH, gfid[0], gfid[1], -                             uuid_str); - -        pfx_len = priv->base_path_length + 1 + SLEN(GF_HIDDEN_PATH) + 1; - -        if (basename) { -                len = snprintf (buf, maxlen, "%s/%s", base_str, basename); -        } else { -                len = snprintf (buf, maxlen, "%s", base_str); -        } - -        ret = sys_lstat (base_str, &stat); - -        if (!(ret == 0 && S_ISLNK(stat.st_mode) && stat.st_nlink == 1)) -                goto out; - -        do { -                errno = 0; -                ret = posix_handle_pump (this, buf, len, maxlen, -                                         base_str, base_len, pfx_len); -                len = ret; - -                if (ret == -1) -                        break; - -                ret = sys_lstat (buf, &stat); -        } while ((ret == -1) && errno == ELOOP); +    struct posix_private *priv = NULL; +    char *uuid_str = NULL; +    int len = 0; +    int ret = -1; +    struct stat stat; +    char *base_str = NULL; +    int base_len = 0; +    int pfx_len; +    int maxlen; +    char *buf; + +    priv = this->private; + +    uuid_str = uuid_utoa(gfid); + +    if (ubuf) { +        buf = ubuf; +        maxlen = size; +    } else { +        maxlen = PATH_MAX; +        buf = alloca(maxlen); +    } + +    base_len = (priv->base_path_length + SLEN(GF_HIDDEN_PATH) + 45); +    base_str = alloca(base_len + 1); +    base_len = snprintf(base_str, base_len + 1, "%s/%s/%02x/%02x/%s", +                        priv->base_path, GF_HIDDEN_PATH, gfid[0], gfid[1], +                        uuid_str); + +    pfx_len = priv->base_path_length + 1 + SLEN(GF_HIDDEN_PATH) + 1; + +    if (basename) { +        len = snprintf(buf, maxlen, "%s/%s", base_str, basename); +    } else { +        len = snprintf(buf, maxlen, "%s", base_str); +    } + +    ret = sys_lstat(base_str, &stat); + +    if (!(ret == 0 && S_ISLNK(stat.st_mode) && stat.st_nlink == 1)) +        goto out; + +    do { +        errno = 0; +        ret = posix_handle_pump(this, buf, len, maxlen, base_str, base_len, +                                pfx_len); +        len = ret; + +        if (ret == -1) +            break; + +        ret = sys_lstat(buf, &stat); +    } while ((ret == -1) && errno == ELOOP);  out: -        return len + 1; +    return len + 1;  } -  int -posix_handle_gfid_path (xlator_t *this, uuid_t gfid, const char *basename, -                        char *buf, size_t buflen) +posix_handle_gfid_path(xlator_t *this, uuid_t gfid, const char *basename, +                       char *buf, size_t buflen)  { -        struct posix_private *priv = NULL; -        char                 *uuid_str = NULL; -        int                   len = 0; - -        priv = this->private; - -        len = priv->base_path_length  /* option directory "/export" */ -                + SLEN("/") -                + SLEN(GF_HIDDEN_PATH) -                + SLEN("/") -                + SLEN("00/") -                + SLEN("00/") -                + SLEN(UUID0_STR) -                + 1 /* '\0' */ -                ; +    struct posix_private *priv = NULL; +    char *uuid_str = NULL; +    int len = 0; -        if (basename) { -                len += (strlen (basename) + 1); -        } else { -                len += 256;  /* worst-case for directory's symlink-handle expansion */ -        } +    priv = this->private; -        if ((buflen < len) || !buf) -                return len; +    len = priv->base_path_length /* option directory "/export" */ +          + SLEN("/") + SLEN(GF_HIDDEN_PATH) + SLEN("/") + SLEN("00/") + +          SLEN("00/") + SLEN(UUID0_STR) + 1 /* '\0' */ +        ; -        uuid_str = uuid_utoa (gfid); +    if (basename) { +        len += (strlen(basename) + 1); +    } else { +        len += 256; /* worst-case for directory's symlink-handle expansion */ +    } -        if (__is_root_gfid (gfid)) { -                if (basename) { -                        len = snprintf (buf, buflen, "%s/%s", priv->base_path, -                                        basename); -                } else { -                        len = snprintf (buf, buflen, "%s", priv->base_path); -                } -                goto out; -        } +    if ((buflen < len) || !buf) +        return len; +    uuid_str = uuid_utoa(gfid); + +    if (__is_root_gfid(gfid)) {          if (basename) { -                len = snprintf (buf, buflen, "%s/%s/%02x/%02x/%s/%s", priv->base_path, -                                GF_HIDDEN_PATH, gfid[0], gfid[1], uuid_str, basename); +            len = snprintf(buf, buflen, "%s/%s", priv->base_path, basename);          } else { -                len = snprintf (buf, buflen, "%s/%s/%02x/%02x/%s", priv->base_path, -                                GF_HIDDEN_PATH, gfid[0], gfid[1], uuid_str); -        } +            len = snprintf(buf, buflen, "%s", priv->base_path); +        } +        goto out; +    } + +    if (basename) { +        len = snprintf(buf, buflen, "%s/%s/%02x/%02x/%s/%s", priv->base_path, +                       GF_HIDDEN_PATH, gfid[0], gfid[1], uuid_str, basename); +    } else { +        len = snprintf(buf, buflen, "%s/%s/%02x/%02x/%s", priv->base_path, +                       GF_HIDDEN_PATH, gfid[0], gfid[1], uuid_str); +    }  out: -        return len; +    return len;  }  int -posix_handle_init (xlator_t *this) +posix_handle_init(xlator_t *this)  { -        struct posix_private *priv = NULL; -        char                 *handle_pfx = NULL; -        int                   ret = 0; -        struct stat           stbuf; -        struct stat           rootbuf; -        struct stat           exportbuf; -        char                 *rootstr = NULL; -        uuid_t                gfid = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - -        priv = this->private; - -        ret = sys_stat (priv->base_path, &exportbuf); -        if (ret || !S_ISDIR (exportbuf.st_mode)) { -                gf_msg (this->name, GF_LOG_ERROR, 0, -                        P_MSG_HANDLE_CREATE, -                        "Not a directory: %s", priv->base_path); -                return -1; -        } +    struct posix_private *priv = NULL; +    char *handle_pfx = NULL; +    int ret = 0; +    struct stat stbuf; +    struct stat rootbuf; +    struct stat exportbuf; +    char *rootstr = NULL; +    uuid_t gfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + +    priv = this->private; + +    ret = sys_stat(priv->base_path, &exportbuf); +    if (ret || !S_ISDIR(exportbuf.st_mode)) { +        gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE, +               "Not a directory: %s", priv->base_path); +        return -1; +    } -        handle_pfx = alloca (priv->base_path_length + 1 + -                             SLEN (GF_HIDDEN_PATH) + 1); +    handle_pfx = alloca(priv->base_path_length + 1 + SLEN(GF_HIDDEN_PATH) + 1); -        sprintf (handle_pfx, "%s/%s", priv->base_path, GF_HIDDEN_PATH); +    sprintf(handle_pfx, "%s/%s", priv->base_path, GF_HIDDEN_PATH); -        ret = sys_stat (handle_pfx, &stbuf); -        switch (ret) { +    ret = sys_stat(handle_pfx, &stbuf); +    switch (ret) {          case -1: -                if (errno == ENOENT) { -                        ret = sys_mkdir (handle_pfx, 0600); -                        if (ret != 0) { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_HANDLE_CREATE, -                                        "Creating directory %s failed", -                                        handle_pfx); -                                return -1; -                        } -                } else { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_HANDLE_CREATE, -                                "Checking for %s failed", -                                handle_pfx); -                        return -1; +            if (errno == ENOENT) { +                ret = sys_mkdir(handle_pfx, 0600); +                if (ret != 0) { +                    gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +                           "Creating directory %s failed", handle_pfx); +                    return -1;                  } -                break; +            } else { +                gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +                       "Checking for %s failed", handle_pfx); +                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", -                                handle_pfx); -                        return -1; -                } -                break; +            if (!S_ISDIR(stbuf.st_mode)) { +                gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE, +                       "Not a directory: %s", handle_pfx); +                return -1; +            } +            break;          default: -                break; -        } - -        ret = sys_stat (handle_pfx, &priv->handledir); +            break; +    } -        if (ret) { -                gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, -                        "stat for %s failed", handle_pfx); -                return -1; -        } +    ret = sys_stat(handle_pfx, &priv->handledir); +    if (ret) { +        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +               "stat for %s failed", handle_pfx); +        return -1; +    } -        MAKE_HANDLE_ABSPATH(rootstr, this, gfid); +    MAKE_HANDLE_ABSPATH(rootstr, this, gfid); -        ret = sys_stat (rootstr, &rootbuf); -        switch (ret) { +    ret = sys_stat(rootstr, &rootbuf); +    switch (ret) {          case -1: -                if (errno != ENOENT) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_HANDLE_CREATE, -                                "%s", priv->base_path); -                        return -1; -                } +            if (errno != ENOENT) { +                gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +                       "%s", priv->base_path); +                return -1; +            } -                ret = posix_handle_mkdir_hashes (this, rootstr); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, -                                "mkdir %s failed", rootstr); -                        return -1; -                } +            ret = posix_handle_mkdir_hashes(this, rootstr); +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                       "mkdir %s failed", rootstr); +                return -1; +            } -                ret = sys_symlink ("../../..", rootstr); -                if (ret) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_HANDLE_CREATE, -                                "symlink %s creation failed", -                                rootstr); -                        return -1; -                } -                break; -        case 0: -                if ((exportbuf.st_ino == rootbuf.st_ino) && -                    (exportbuf.st_dev == rootbuf.st_dev)) -                        return 0; - -                gf_msg (this->name, GF_LOG_ERROR, 0, -                        P_MSG_HANDLE_CREATE, -                        "Different dirs %s (%lld/%lld) != %s (%lld/%lld)", -                        priv->base_path, (long long) exportbuf.st_ino, -                        (long long) exportbuf.st_dev, rootstr, -                        (long long) rootbuf.st_ino, (long long) rootbuf.st_dev); +            ret = sys_symlink("../../..", rootstr); +            if (ret) { +                gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +                       "symlink %s creation failed", rootstr);                  return -1; +            } +            break; +        case 0: +            if ((exportbuf.st_ino == rootbuf.st_ino) && +                (exportbuf.st_dev == rootbuf.st_dev)) +                return 0; -                break; -        } +            gf_msg(this->name, GF_LOG_ERROR, 0, P_MSG_HANDLE_CREATE, +                   "Different dirs %s (%lld/%lld) != %s (%lld/%lld)", +                   priv->base_path, (long long)exportbuf.st_ino, +                   (long long)exportbuf.st_dev, rootstr, +                   (long long)rootbuf.st_ino, (long long)rootbuf.st_dev); +            return -1; -        return 0; +            break; +    } + +    return 0;  }  gf_boolean_t -posix_does_old_trash_exists (char *old_trash) +posix_does_old_trash_exists(char *old_trash)  { -        uuid_t                gfid = {0}; -        gf_boolean_t          exists = _gf_false; -        struct stat           stbuf = {0}; -        int                   ret = 0; - -        ret = sys_lstat (old_trash, &stbuf); -        if ((ret == 0) && S_ISDIR (stbuf.st_mode)) { -                ret = sys_lgetxattr (old_trash, "trusted.gfid", gfid, 16); -                if ((ret < 0) && (errno == ENODATA || errno == ENOATTR) ) -                        exists = _gf_true; -        } -        return exists; +    uuid_t gfid = {0}; +    gf_boolean_t exists = _gf_false; +    struct stat stbuf = {0}; +    int ret = 0; + +    ret = sys_lstat(old_trash, &stbuf); +    if ((ret == 0) && S_ISDIR(stbuf.st_mode)) { +        ret = sys_lgetxattr(old_trash, "trusted.gfid", gfid, 16); +        if ((ret < 0) && (errno == ENODATA || errno == ENOATTR)) +            exists = _gf_true; +    } +    return exists;  }  int -posix_handle_new_trash_init (xlator_t *this, char *trash) +posix_handle_new_trash_init(xlator_t *this, char *trash)  { -        int                     ret = 0; -        struct stat             stbuf = {0}; +    int ret = 0; +    struct stat stbuf = {0}; -        ret = sys_lstat (trash, &stbuf); -        switch (ret) { +    ret = sys_lstat(trash, &stbuf); +    switch (ret) {          case -1: -                if (errno == ENOENT) { -                        ret = sys_mkdir (trash, 0755); -                        if (ret != 0) { -                                gf_msg (this->name, GF_LOG_ERROR, errno, -                                        P_MSG_HANDLE_TRASH_CREATE, -                                        "Creating directory %s failed", -                                        trash); -                        } -                } else { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_HANDLE_TRASH_CREATE, -                                "Checking for %s failed", trash); +            if (errno == ENOENT) { +                ret = sys_mkdir(trash, 0755); +                if (ret != 0) { +                    gf_msg(this->name, GF_LOG_ERROR, errno, +                           P_MSG_HANDLE_TRASH_CREATE, +                           "Creating directory %s failed", trash);                  } -                break; +            } else { +                gf_msg(this->name, GF_LOG_ERROR, errno, +                       P_MSG_HANDLE_TRASH_CREATE, "Checking for %s failed", +                       trash); +            } +            break;          case 0: -                if (!S_ISDIR (stbuf.st_mode)) { -                        gf_msg (this->name, GF_LOG_ERROR, errno, -                                P_MSG_HANDLE_TRASH_CREATE, -                                "Not a directory: %s", trash); -                        ret = -1; -                } -                break; +            if (!S_ISDIR(stbuf.st_mode)) { +                gf_msg(this->name, GF_LOG_ERROR, errno, +                       P_MSG_HANDLE_TRASH_CREATE, "Not a directory: %s", trash); +                ret = -1; +            } +            break;          default: -                break; -        } -        return ret; +            break; +    } +    return ret;  }  int -posix_mv_old_trash_into_new_trash (xlator_t *this, char *old, char *new) +posix_mv_old_trash_into_new_trash(xlator_t *this, char *old, char *new)  { -        char                  dest_old[PATH_MAX] = {0}; -        int                   ret = 0; -        uuid_t                dest_name = {0}; - -        if (!posix_does_old_trash_exists (old)) -                goto out; -        gf_uuid_generate (dest_name); -        snprintf (dest_old, sizeof (dest_old), "%s/%s", new, -                  uuid_utoa (dest_name)); -        ret = sys_rename (old, dest_old); -        if (ret < 0) { -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_HANDLE_TRASH_CREATE, -                        "Not able to move %s -> %s ", old, dest_old); -        } +    char dest_old[PATH_MAX] = {0}; +    int ret = 0; +    uuid_t dest_name = {0}; + +    if (!posix_does_old_trash_exists(old)) +        goto out; +    gf_uuid_generate(dest_name); +    snprintf(dest_old, sizeof(dest_old), "%s/%s", new, uuid_utoa(dest_name)); +    ret = sys_rename(old, dest_old); +    if (ret < 0) { +        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_TRASH_CREATE, +               "Not able to move %s -> %s ", old, dest_old); +    }  out: -        return ret; +    return ret;  }  int -posix_handle_trash_init (xlator_t *this) +posix_handle_trash_init(xlator_t *this)  { -        int                   ret = -1; -        struct posix_private  *priv = NULL; -        char                  old_trash[PATH_MAX] = {0}; - -        priv = this->private; - -        priv->trash_path = GF_MALLOC (priv->base_path_length + SLEN ("/") -                                      + SLEN (GF_HIDDEN_PATH) + SLEN ("/") -                                      + SLEN (TRASH_DIR) + 1, -                                      gf_posix_mt_trash_path); - -        if (!priv->trash_path) -                goto out; - -        snprintf (priv->trash_path, priv->base_path_length -                  + SLEN (GF_HIDDEN_PATH) + SLEN (TRASH_DIR) + 3, -                  "%s/%s/%s", priv->base_path, GF_HIDDEN_PATH, TRASH_DIR); - -        ret = posix_handle_new_trash_init (this, priv->trash_path); -        if (ret) -                goto out; -        snprintf (old_trash, sizeof (old_trash), "%s/.landfill", -                  priv->base_path); -        ret = posix_mv_old_trash_into_new_trash (this, old_trash, -                                                 priv->trash_path); +    int ret = -1; +    struct posix_private *priv = NULL; +    char old_trash[PATH_MAX] = {0}; + +    priv = this->private; + +    priv->trash_path = GF_MALLOC(priv->base_path_length + SLEN("/") + +                                     SLEN(GF_HIDDEN_PATH) + SLEN("/") + +                                     SLEN(TRASH_DIR) + 1, +                                 gf_posix_mt_trash_path); + +    if (!priv->trash_path) +        goto out; + +    snprintf( +        priv->trash_path, +        priv->base_path_length + SLEN(GF_HIDDEN_PATH) + SLEN(TRASH_DIR) + 3, +        "%s/%s/%s", priv->base_path, GF_HIDDEN_PATH, TRASH_DIR); + +    ret = posix_handle_new_trash_init(this, priv->trash_path); +    if (ret) +        goto out; +    snprintf(old_trash, sizeof(old_trash), "%s/.landfill", priv->base_path); +    ret = posix_mv_old_trash_into_new_trash(this, old_trash, priv->trash_path);  out: -        return ret; +    return ret;  }  int -posix_handle_mkdir_hashes (xlator_t *this, const char *newpath) +posix_handle_mkdir_hashes(xlator_t *this, const char *newpath)  { -        char        *duppath = NULL; -        char        *parpath = NULL; -        int          ret = 0; - -        duppath = strdupa (newpath); -        parpath = dirname (duppath); -        parpath = dirname (duppath); - -        ret = sys_mkdir (parpath, 0700); -        if (ret == -1 && errno != EEXIST) { -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_HANDLE_CREATE, -                        "error mkdir hash-1 %s ", parpath); -                return -1; -        } +    char *duppath = NULL; +    char *parpath = NULL; +    int ret = 0; + +    duppath = strdupa(newpath); +    parpath = dirname(duppath); +    parpath = dirname(duppath); + +    ret = sys_mkdir(parpath, 0700); +    if (ret == -1 && errno != EEXIST) { +        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +               "error mkdir hash-1 %s ", parpath); +        return -1; +    } -        strcpy (duppath, newpath); -        parpath = dirname (duppath); +    strcpy(duppath, newpath); +    parpath = dirname(duppath); -        ret = sys_mkdir (parpath, 0700); -        if (ret == -1 && errno != EEXIST) { -                gf_msg (this->name, GF_LOG_ERROR, errno, -                        P_MSG_HANDLE_CREATE, -                        "error mkdir hash-2 %s ", parpath); -                return -1; -        } +    ret = sys_mkdir(parpath, 0700); +    if (ret == -1 && errno != EEXIST) { +        gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_HANDLE_CREATE, +               "error mkdir hash-2 %s ", parpath); +        return -1; +    } -        return 0; +    return 0;  } -  int -posix_handle_hard (xlator_t *this, const char *oldpath, uuid_t gfid, struct stat *oldbuf) +posix_handle_hard(xlator_t *this, const char *oldpath, uuid_t gfid, +                  struct stat *oldbuf)  { -        char        *newpath = NULL; -        struct stat  newbuf; -        int          ret = -1; +    char *newpath = NULL; +    struct stat newbuf; +    int ret = -1; +    MAKE_HANDLE_ABSPATH(newpath, this, gfid); -        MAKE_HANDLE_ABSPATH (newpath, this, gfid); +    ret = sys_lstat(newpath, &newbuf); +    if (ret == -1 && errno != ENOENT) { +        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, "%s", +               newpath); +        return -1; +    } -        ret = sys_lstat (newpath, &newbuf); -        if (ret == -1 && errno != ENOENT) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_HANDLE_CREATE, -                        "%s", newpath); -                return -1; +    if (ret == -1 && errno == ENOENT) { +        ret = posix_handle_mkdir_hashes(this, newpath); +        if (ret) { +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                   "mkdir %s failed ", newpath); +            return -1;          } -        if (ret == -1 && errno == ENOENT) { -                ret = posix_handle_mkdir_hashes (this, newpath); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, "mkdir %s failed ", -                                newpath); -                        return -1; -                } - -                ret = sys_link (oldpath, newpath); - -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, "link %s -> %s" -                                "failed ", oldpath, newpath); -                        return -1; -                } +        ret = sys_link(oldpath, newpath); -                ret = sys_lstat (newpath, &newbuf); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, -                                "lstat on %s failed", newpath); -                        return -1; -                } -        } - -        if (newbuf.st_ino != oldbuf->st_ino || -            newbuf.st_dev != oldbuf->st_dev) { -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_HANDLE_CREATE, -                        "mismatching ino/dev between file %s (%lld/%lld) " -                        "and handle %s (%lld/%lld)", -                        oldpath, (long long) oldbuf->st_ino, (long long) oldbuf->st_dev, -                        newpath, (long long) newbuf.st_ino, (long long) newbuf.st_dev); -                ret = -1; +        if (ret) { +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                   "link %s -> %s" +                   "failed ", +                   oldpath, newpath); +            return -1;          } -        return ret; +        ret = sys_lstat(newpath, &newbuf); +        if (ret) { +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                   "lstat on %s failed", newpath); +            return -1; +        } +    } + +    if (newbuf.st_ino != oldbuf->st_ino || newbuf.st_dev != oldbuf->st_dev) { +        gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_HANDLE_CREATE, +               "mismatching ino/dev between file %s (%lld/%lld) " +               "and handle %s (%lld/%lld)", +               oldpath, (long long)oldbuf->st_ino, (long long)oldbuf->st_dev, +               newpath, (long long)newbuf.st_ino, (long long)newbuf.st_dev); +        ret = -1; +    } + +    return ret;  } -  int -posix_handle_soft (xlator_t *this, const char *real_path, loc_t *loc, -                   uuid_t gfid, struct stat *oldbuf) +posix_handle_soft(xlator_t *this, const char *real_path, loc_t *loc, +                  uuid_t gfid, struct stat *oldbuf)  { -        char        *oldpath = NULL; -        char        *newpath = NULL; -        struct stat  newbuf; -        int          ret = -1; - -        MAKE_HANDLE_ABSPATH (newpath, this, gfid); -        MAKE_HANDLE_RELPATH (oldpath, this, loc->pargfid, loc->name); - -        ret = sys_lstat (newpath, &newbuf); -        if (ret == -1 && errno != ENOENT) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_HANDLE_CREATE, "%s", newpath); -                return -1; -        } - -        if (ret == -1 && errno == ENOENT) { -                if (posix_is_malformed_link (this, newpath, oldpath, -                                             strlen (oldpath))) { -                        GF_ASSERT (!"Malformed link"); -                        errno = EINVAL; -                        return -1; -                } -                ret = posix_handle_mkdir_hashes (this, newpath); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, -                                "mkdir %s failed ", newpath); -                        return -1; -                } - -                ret = sys_symlink (oldpath, newpath); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, -                                "symlink %s -> %s failed", -                                oldpath, newpath); -                        return -1; -                } +    char *oldpath = NULL; +    char *newpath = NULL; +    struct stat newbuf; +    int ret = -1; + +    MAKE_HANDLE_ABSPATH(newpath, this, gfid); +    MAKE_HANDLE_RELPATH(oldpath, this, loc->pargfid, loc->name); + +    ret = sys_lstat(newpath, &newbuf); +    if (ret == -1 && errno != ENOENT) { +        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, "%s", +               newpath); +        return -1; +    } -                ret = sys_lstat (newpath, &newbuf); -                if (ret) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_CREATE, -                                "stat on %s failed ", newpath); -                        return -1; -                } +    if (ret == -1 && errno == ENOENT) { +        if (posix_is_malformed_link(this, newpath, oldpath, strlen(oldpath))) { +            GF_ASSERT(!"Malformed link"); +            errno = EINVAL; +            return -1; +        } +        ret = posix_handle_mkdir_hashes(this, newpath); +        if (ret) { +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                   "mkdir %s failed ", newpath); +            return -1;          } -        ret = sys_stat (real_path, &newbuf); +        ret = sys_symlink(oldpath, newpath);          if (ret) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_HANDLE_CREATE, -                        "stat on %s failed ", newpath); -                return -1; +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                   "symlink %s -> %s failed", oldpath, newpath); +            return -1;          } -        if (!oldbuf) -                return ret; - -        if (newbuf.st_ino != oldbuf->st_ino || -            newbuf.st_dev != oldbuf->st_dev) { -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_HANDLE_CREATE, -                        "mismatching ino/dev between file %s (%lld/%lld) " -                        "and handle %s (%lld/%lld)", -                        oldpath, (long long) oldbuf->st_ino, (long long) oldbuf->st_dev, -                        newpath, (long long) newbuf.st_ino, (long long) newbuf.st_dev); -                ret = -1; +        ret = sys_lstat(newpath, &newbuf); +        if (ret) { +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                   "stat on %s failed ", newpath); +            return -1;          } +    } +    ret = sys_stat(real_path, &newbuf); +    if (ret) { +        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +               "stat on %s failed ", newpath); +        return -1; +    } + +    if (!oldbuf)          return ret; -} +    if (newbuf.st_ino != oldbuf->st_ino || newbuf.st_dev != oldbuf->st_dev) { +        gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_HANDLE_CREATE, +               "mismatching ino/dev between file %s (%lld/%lld) " +               "and handle %s (%lld/%lld)", +               oldpath, (long long)oldbuf->st_ino, (long long)oldbuf->st_dev, +               newpath, (long long)newbuf.st_ino, (long long)newbuf.st_dev); +        ret = -1; +    } + +    return ret; +}  int -posix_handle_unset_gfid (xlator_t *this, uuid_t gfid) +posix_handle_unset_gfid(xlator_t *this, uuid_t gfid)  { -        char        *path = NULL; -        int          ret = 0; -        struct stat  stat; +    char *path = NULL; +    int ret = 0; +    struct stat stat; -        MAKE_HANDLE_GFID_PATH (path, this, gfid, NULL); +    MAKE_HANDLE_GFID_PATH(path, this, gfid, NULL); -        ret = sys_lstat (path, &stat); +    ret = sys_lstat(path, &stat); -        if (ret == -1) { -                if (errno != ENOENT) { -                        gf_msg (this->name, GF_LOG_WARNING, errno, -                                P_MSG_HANDLE_DELETE, "%s", path); -                } -                goto out; +    if (ret == -1) { +        if (errno != ENOENT) { +            gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_DELETE, "%s", +                   path);          } +        goto out; +    } -        ret = sys_unlink (path); -        if (ret == -1) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_HANDLE_DELETE, "unlink %s failed ", path); -        } +    ret = sys_unlink(path); +    if (ret == -1) { +        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_DELETE, +               "unlink %s failed ", path); +    }  out: -        return ret; +    return ret;  } -  int -posix_handle_unset (xlator_t *this, uuid_t gfid, const char *basename) +posix_handle_unset(xlator_t *this, uuid_t gfid, const char *basename)  { -        int          ret; -        struct iatt  stat; -        char        *path = NULL; - -        if (!basename) { -                ret = posix_handle_unset_gfid (this, gfid); -                return ret; -        } +    int ret; +    struct iatt stat; +    char *path = NULL; -        MAKE_HANDLE_PATH (path, this, gfid, basename); -        if (!path) { -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_HANDLE_DELETE, -                        "Failed to create handle path for %s (%s)", -                        basename, uuid_utoa(gfid)); -                return -1; -        } +    if (!basename) { +        ret = posix_handle_unset_gfid(this, gfid); +        return ret; +    } -        /* stat is being used only for gfid, so passing a NULL inode -         * doesn't fetch time attributes which is fine -         */ -        ret = posix_istat (this, NULL, gfid, basename, &stat); -        if (ret == -1) { -                gf_msg (this->name, GF_LOG_WARNING, errno, -                        P_MSG_HANDLE_DELETE, "%s", path); -                return -1; -        } +    MAKE_HANDLE_PATH(path, this, gfid, basename); +    if (!path) { +        gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_HANDLE_DELETE, +               "Failed to create handle path for %s (%s)", basename, +               uuid_utoa(gfid)); +        return -1; +    } + +    /* stat is being used only for gfid, so passing a NULL inode +     * doesn't fetch time attributes which is fine +     */ +    ret = posix_istat(this, NULL, gfid, basename, &stat); +    if (ret == -1) { +        gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_DELETE, "%s", +               path); +        return -1; +    } -        ret = posix_handle_unset_gfid (this, stat.ia_gfid); +    ret = posix_handle_unset_gfid(this, stat.ia_gfid); -        return ret; +    return ret;  } -  int -posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid, char *real_path, -                                  inode_table_t *itable) +posix_create_link_if_gfid_exists(xlator_t *this, uuid_t gfid, char *real_path, +                                 inode_table_t *itable)  { -        int                    ret         = -1; -        char                  *newpath     = NULL; -        char                  *unlink_path = NULL; -        uint64_t               ctx_int     = 0; -        inode_t               *inode       = NULL; -        struct stat            stbuf       = {0,}; -        struct posix_private  *priv        = NULL; -        posix_inode_ctx_t     *ctx         = NULL; - -        priv = this->private; - -        MAKE_HANDLE_PATH (newpath, this, gfid, NULL); -        if (!newpath) { -                gf_msg (this->name, GF_LOG_WARNING, 0, -                        P_MSG_HANDLE_CREATE, -                        "Failed to create handle path (%s)", uuid_utoa(gfid)); -                return ret; -        } - -        ret = sys_lstat (newpath, &stbuf); -        if (!ret) { -                ret = sys_link (newpath, real_path); -        } else { -                inode = inode_find (itable, gfid); -                if (!inode) -                        return -1; - -                LOCK (&inode->lock); -                { -                        ret = __posix_inode_ctx_get_all (inode, this, &ctx); -                        if (ret) -                                goto unlock; - -                        if (ctx->unlink_flag != GF_UNLINK_TRUE) { -                                ret = -1; -                                goto unlock; -                        } - -                        POSIX_GET_FILE_UNLINK_PATH (priv->base_path, gfid, -                                                    unlink_path); -                        ret = sys_link (unlink_path, real_path); -                        if (ret) { -                                gf_msg (this->name, GF_LOG_WARNING, errno, -                                        P_MSG_HANDLE_CREATE, "Failed to link " -                                        "%s with %s", real_path, unlink_path); -                                goto unlock; -                        } -                        ret = sys_rename (unlink_path, newpath); -                        if (ret) { -                                gf_msg (this->name, GF_LOG_WARNING, errno, -                                        P_MSG_HANDLE_CREATE, "Failed to link " -                                        "%s with %s", real_path, unlink_path); -                                goto unlock; -                        } -                        ctx_int = GF_UNLINK_FALSE; -                        ret = __posix_inode_ctx_set_unlink_flag (inode, this, -                                                                 ctx_int); -                } -unlock: -                UNLOCK (&inode->lock); - -                inode_unref (inode); -        } - +    int ret = -1; +    char *newpath = NULL; +    char *unlink_path = NULL; +    uint64_t ctx_int = 0; +    inode_t *inode = NULL; +    struct stat stbuf = { +        0, +    }; +    struct posix_private *priv = NULL; +    posix_inode_ctx_t *ctx = NULL; + +    priv = this->private; + +    MAKE_HANDLE_PATH(newpath, this, gfid, NULL); +    if (!newpath) { +        gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_HANDLE_CREATE, +               "Failed to create handle path (%s)", uuid_utoa(gfid));          return ret; +    } + +    ret = sys_lstat(newpath, &stbuf); +    if (!ret) { +        ret = sys_link(newpath, real_path); +    } else { +        inode = inode_find(itable, gfid); +        if (!inode) +            return -1; + +        LOCK(&inode->lock); +        { +            ret = __posix_inode_ctx_get_all(inode, this, &ctx); +            if (ret) +                goto unlock; + +            if (ctx->unlink_flag != GF_UNLINK_TRUE) { +                ret = -1; +                goto unlock; +            } + +            POSIX_GET_FILE_UNLINK_PATH(priv->base_path, gfid, unlink_path); +            ret = sys_link(unlink_path, real_path); +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                       "Failed to link " +                       "%s with %s", +                       real_path, unlink_path); +                goto unlock; +            } +            ret = sys_rename(unlink_path, newpath); +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE, +                       "Failed to link " +                       "%s with %s", +                       real_path, unlink_path); +                goto unlock; +            } +            ctx_int = GF_UNLINK_FALSE; +            ret = __posix_inode_ctx_set_unlink_flag(inode, this, ctx_int); +        } +    unlock: +        UNLOCK(&inode->lock); + +        inode_unref(inode); +    } + +    return ret;  }  | 
