diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-handle.c')
-rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index aad7db61430..d9086530322 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -35,24 +35,42 @@ 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; + inode_t *inode = NULL; int ret = -1; ret = posix_istat (this, parent->gfid, bname, iabuf); - if (ret < 0) + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "gfid: %s, bname: %s " + "failed", uuid_utoa (parent->gfid), bname); goto out; + } - inode = inode_find (itable, iabuf->ia_gfid); - if (inode == NULL) { - inode = inode_new (itable); + 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); + } } - linked_inode = inode_link (inode, parent, bname, iabuf); + /* 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_unref (inode);*/ out: - return linked_inode; + return inode; } int @@ -72,6 +90,8 @@ posix_make_ancestral_node (const char *priv_base_path, char *path, int pathsize, } strcat (path, dir_name); + if (*dir_name != '/') + strcat (path, "/"); if (type & POSIX_ANCESTRY_DENTRY) { entry = gf_dirent_for_name (dir_name); @@ -132,11 +152,16 @@ posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, *parent = inode_ref (itable->root); } - inode = itable->root; - memset (&iabuf, 0, sizeof (iabuf)); - gf_uuid_copy (iabuf.ia_gfid, inode->gfid); - iabuf.ia_type = inode->ia_type; + inode = posix_resolve (this, itable, *parent, "/", &iabuf); + if (!inode) { + gf_msg (this->name, GF_LOG_ERROR, + P_MSG_INODE_RESOLVE_FAILED, 0, + "posix resolve on the root inode %s failed", + uuid_utoa (gfid)); + *op_errno = ESTALE; + goto out; + } ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head, "/", &iabuf, inode, type, @@ -182,12 +207,14 @@ posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, inode = posix_resolve (this, itable, *parent, dir_name, &iabuf); if (inode == NULL) { + gf_msg (this->name, GF_LOG_ERROR, P_MSG_INODE_RESOLVE_FAILED, + 0, "posix resolve on the root inode %s failed", + uuid_utoa (gfid)); *op_errno = ESTALE; ret = -1; goto out; } - strcat (dir_name, "/"); ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head, dir_name, &iabuf, inode, type, xdata); if (*parent != NULL) { |