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, |