diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-handle.c')
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 162 | 
1 files changed, 158 insertions, 4 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index 219a582c9f7..1d8e986314f 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -26,13 +26,167 @@  #include "xlator.h"  #include "syscall.h" +inode_t * +posix_resolve (xlator_t *this, inode_table_t *itable, inode_t *parent, +               char *bname, struct iatt *iabuf) +{ +        inode_t     *inode = NULL, *linked_inode = NULL; +        int          ret   = -1; + +        ret = posix_istat (this, parent->gfid, bname, iabuf); +        if (ret < 0) +                goto out; + +        inode = inode_find (itable, iabuf->ia_gfid); +        if (inode == NULL) { +                inode = inode_new (itable); +        } + +        linked_inode = inode_link (inode, parent, bname, iabuf); + +        inode_unref (inode); + +out: +        return linked_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) +{ +        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 (type & POSIX_ANCESTRY_DENTRY) { +                entry = gf_dirent_for_name (dir_name); +                if (!entry) { +                        gf_log (THIS->name, GF_LOG_ERROR, +                                "could not create gf_dirent for entry %s: (%s)", +                                dir_name, strerror (errno)); +                        goto out; +                } + +                entry->d_stat = *iabuf; +                entry->inode = inode_ref (inode); + +                list_add_tail (&entry->list, &head->list); +                strcpy (real_path, priv_base_path); +                strcat (real_path, "/"); +                strcat (real_path, path); +                loc.inode = inode_ref (inode); +                uuid_copy (loc.gfid, inode->gfid); + +                entry->dict = posix_lookup_xattr_fill (THIS, real_path, &loc, +                                                       xdata, iabuf); +                loc_wipe (&loc); +        } + +        ret = 0; + +out: +        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) +{ +        char        *linkname   = NULL; /* "../../<gfid[0]>/<gfid[1]/" +                                         "<gfidstr>/<NAME_MAX>" */ +        char        *dir_handle = NULL; +        char        *dir_name   = 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, }; + +        if (!path || !parent || !priv_base_path || uuid_is_null (gfid)) { +                goto out; +        } + +        if (__is_root_gfid (gfid)) { +                if (parent) { +                        if (*parent) { +                                inode_unref (*parent); +                        } + +                        *parent = inode_ref (itable->root); +                } + +                inode = itable->root; + +                memset (&iabuf, 0, sizeof (iabuf)); +                uuid_copy (iabuf.ia_gfid, inode->gfid); +                iabuf.ia_type = inode->ia_type; + +                ret = posix_make_ancestral_node (priv_base_path, path, pathsize, +                                                 head, "/", &iabuf, inode, type, +                                                 xdata); +                return ret; +        } + +        dir_handle = alloca (handle_size); +        linkname   = alloca (PATH_MAX); +        snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s", +                  priv_base_path, HANDLE_PFX, gfid[0], gfid[1], +                  uuid_utoa (gfid)); + +        len = readlink (dir_handle, linkname, PATH_MAX); +        if (len < 0) { +                gf_log (this->name, GF_LOG_ERROR, "could not read the link " +                        "from the gfid handle %s (%s)", dir_handle, +                        strerror (errno)); +                goto out; +        } + +        linkname[len] = '\0'; + +        pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), "/", &saveptr); +        dir_name = strtok_r (NULL, "/", &saveptr); +        strcat (dir_name, "/"); -#define HANDLE_PFX ".glusterfs" -#define TRASH_DIR "landfill" +        uuid_parse (pgfidstr, tmp_gfid); + +        ret = posix_make_ancestryfromgfid (this, path, pathsize, head, type, +                                           tmp_gfid, handle_size, +                                           priv_base_path, itable, parent, +                                           xdata); +        if (ret < 0) { +                goto out; +        } -#define UUID0_STR "00000000-0000-0000-0000-000000000000" -#define SLEN(str) (sizeof(str) - 1) +        memset (&iabuf, 0, sizeof (iabuf)); +        inode = posix_resolve (this, itable, *parent, dir_name, &iabuf); + +        ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head, +                                         dir_name, &iabuf, inode, type, xdata); +        if (*parent != NULL) { +                inode_unref (*parent); +        } + +        *parent = inode; + +out: +        return ret; +}  int  posix_handle_relpath (xlator_t *this, uuid_t gfid, const char *basename,  | 
