Пример #1
0
void ida_inode_unassign(inode_t ** dst)
{
    if (*dst != NULL)
    {
        inode_unref(*dst);
        *dst = NULL;
    }
}
Пример #2
0
struct glfs_object *
glfs_h_lookupat (struct glfs *fs, struct glfs_object *parent,
		 const char *path, struct stat *stat)
{
	int                      ret = 0;
	xlator_t                *subvol = NULL;
	inode_t                 *inode = NULL;
	struct iatt              iatt = {0, };
	struct glfs_object      *object = NULL;
	loc_t                    loc = {0, };

	/* validate in args */
	if ((fs == NULL) || (path == NULL)) {
		errno = EINVAL;
		return NULL;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	if (parent) {
		inode = glfs_resolve_inode (fs, subvol, parent);
		if (!inode) {
			errno = ESTALE;
			goto out;
		}
	}

	/* fop/op */
	ret = glfs_resolve_at (fs, subvol, inode, path, &loc, &iatt,
			       0 /*TODO: links? */, 0);

	/* populate out args */
	if (!ret) {
		if (stat)
			glfs_iatt_to_stat (fs, &iatt, stat);

		ret = glfs_create_object (&loc, &object);
	}

out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	glfs_subvol_done (fs, subvol);

	return object;
}
Пример #3
0
int
glfs_h_close (struct glfs_object *object)
{
	/* Release the held reference */
	inode_unref (object->inode);
	GF_FREE (object);

	return 0;
}
Пример #4
0
int
glfs_h_setxattrs (struct glfs *fs, struct glfs_object *object, const char *name,
		 const void *value, size_t size, int flags)
{
	int              ret = -1;
	xlator_t        *subvol = NULL;
	inode_t         *inode = NULL;
	loc_t            loc = {0, };
	dict_t          *xattr = NULL;

	/* validate in args */
	if ((fs == NULL) || (object == NULL) || (stat == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, object);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	xattr = dict_for_key_value (name, value, size);
	if (!xattr) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	/* populate loc */
	GLFS_LOC_FILL_INODE (inode, loc, out);

	/* fop/op */
	ret = syncop_setxattr (subvol, &loc, xattr, flags);
        DECODE_SYNCOP_ERR (ret);

out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #5
0
int
glfs_h_readlink (struct glfs *fs, struct glfs_object *object, char *buf,
		 size_t bufsiz)
{
	loc_t               loc = {0, };
	int                 ret = -1;
	xlator_t           *subvol = NULL;
	inode_t            *inode = NULL;
	char               *linkval = NULL;

	/* validate in args */
	if ((fs == NULL) || (object == NULL) || (buf == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, object);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	GLFS_LOC_FILL_INODE (inode, loc, out);

	/* fop/op */
	ret = syncop_readlink (subvol, &loc, &linkval, bufsiz);
        DECODE_SYNCOP_ERR (ret);

	/* populate out args */
	if (ret > 0)
		memcpy (buf, linkval, ret);

out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	if (linkval)
		GF_FREE (linkval);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #6
0
int
glfs_h_setattrs (struct glfs *fs, struct glfs_object *object, struct stat *stat,
		 int valid)
{
	int              ret = -1;
	xlator_t        *subvol = NULL;
	inode_t         *inode = NULL;
	loc_t            loc = {0, };
	struct iatt      iatt = {0, };
	int              glvalid = 0;

	/* validate in args */
	if ((fs == NULL) || (object == NULL) || (stat == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, object);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	/* map valid masks from in args */
	glfs_iatt_from_stat (stat, valid, &iatt, &glvalid);

	/* populate loc */
	GLFS_LOC_FILL_INODE (inode, loc, out);

	/* fop/op */
	ret = syncop_setattr (subvol, &loc, &iatt, glvalid, 0, 0);
        DECODE_SYNCOP_ERR (ret);
out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #7
0
int
glfs_h_truncate (struct glfs *fs, struct glfs_object *object, off_t offset)
{
	loc_t               loc = {0, };
	int                 ret = -1;
	xlator_t           *subvol = NULL;
	inode_t            *inode = NULL;

	/* validate in args */
	if ((fs == NULL) || (object == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, object);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	GLFS_LOC_FILL_INODE (inode, loc, out);

	/* fop/op */
	ret = syncop_truncate (subvol, &loc, (off_t)offset);
        DECODE_SYNCOP_ERR (ret);

	/* populate out args */
	if (ret == 0)
		ret = glfs_loc_unlink (&loc);

out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #8
0
int
nfs_inode_loc_fill (inode_t *inode, loc_t *loc, int how)
{
        char            *resolvedpath = NULL;
        inode_t         *parent = NULL;
        int             ret = -EFAULT;

        if ((!inode) || (!loc))
                return ret;

        /* If gfid is not null, then the inode is already linked to
         * the inode table, and not a newly created one. For newly
         * created inode, inode_path returns null gfid as the path.
         */
        if (!gf_uuid_is_null (inode->gfid)) {
                ret = inode_path (inode, NULL, &resolvedpath);
                if (ret < 0) {
                        gf_msg (GF_NFS, GF_LOG_ERROR, 0,
                                NFS_MSG_PATH_RESOLVE_FAIL, "path resolution "
                                "failed %s", resolvedpath);
                        goto err;
                }
        }

        if (resolvedpath == NULL) {
                char tmp_path[GFID_STR_PFX_LEN + 1] = {0,};
                snprintf (tmp_path, sizeof (tmp_path), "<gfid:%s>",
                          uuid_utoa (loc->gfid));
                resolvedpath = gf_strdup (tmp_path);
        } else {
                parent = inode_parent (inode, loc->pargfid, NULL);
        }

        ret = nfs_loc_fill (loc, inode, parent, resolvedpath);
        if (ret < 0) {
                gf_msg (GF_NFS, GF_LOG_ERROR, -ret,
                        NFS_MSG_LOC_FILL_RESOLVE_FAIL,
                        "loc fill resolution failed %s", resolvedpath);
                goto err;
        }

        ret = 0;
err:
        if (parent)
                inode_unref (parent);

        GF_FREE (resolvedpath);

        return ret;
}
Пример #9
0
int
nfs_gfid_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *loc, int how)
{
        int             ret = -EFAULT;
        inode_t         *inode = NULL;

        if (!loc)
                return ret;

        inode = inode_find (itable, gfid);
        if (!inode) {
		gf_msg_trace (GF_NFS, 0, "Inode not found in itable, will "
                              "try to create one.");
                if (how == NFS_RESOLVE_CREATE) {
			gf_msg_trace (GF_NFS, 0, "Inode needs to be created.");
                        inode = inode_new (itable);
                        if (!inode) {
                                gf_msg (GF_NFS, GF_LOG_ERROR, ENOMEM,
                                        NFS_MSG_NO_MEMORY, "Failed to "
                                        "allocate memory");
                                ret = -ENOMEM;
                                goto err;
                        }

                } else {
			gf_msg (GF_NFS, GF_LOG_ERROR, ENOENT,
                                NFS_MSG_INODE_NOT_FOUND, "Inode not found in "
                                "itable and no creation was requested.");
                        ret = -ENOENT;
                        goto err;
                }
        } else {
		gf_msg_trace (GF_NFS, 0, "Inode was found in the itable.");
	}

        gf_uuid_copy (loc->gfid, gfid);

        ret = nfs_inode_loc_fill (inode, loc, how);
	if (ret < 0) {
		gf_msg (GF_NFS, GF_LOG_ERROR, -ret,
                        NFS_MSG_INODE_LOC_FILL_ERROR,
                        "Inode loc filling failed.: %s", strerror (-ret));
		goto err;
	}

err:
        if (inode)
                inode_unref (inode);
        return ret;
}
Пример #10
0
int
glfsh_link_inode_update_loc (loc_t *loc, struct iatt *iattr)
{
        inode_t       *link_inode = NULL;
        int           ret = -1;

        link_inode = inode_link (loc->inode, NULL, NULL, iattr);
        if (link_inode == NULL)
                goto out;

        inode_unref (loc->inode);
        loc->inode = link_inode;
        ret = 0;
out:
        return ret;
}
Пример #11
0
int
glfs_h_getattrs (struct glfs *fs, struct glfs_object *object, struct stat *stat)
{
	int                      ret = 0;
	xlator_t                *subvol = NULL;
	inode_t                 *inode = NULL;
	struct iatt              iatt = {0, };

	/* validate in args */
	if ((fs == NULL) || (object == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, object);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	/* fop/op */
	ret = glfs_resolve_base (fs, subvol, inode, &iatt);

	/* populate out args */
	if (!ret && stat) {
		glfs_iatt_to_stat (fs, &iatt, stat);
	}

out:
	if (inode)
		inode_unref (inode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #12
0
void
stripe_local_wipe (stripe_local_t *local)
{
        if (!local)
                goto out;

        loc_wipe (&local->loc);
        loc_wipe (&local->loc2);

        if (local->fd)
                fd_unref (local->fd);

        if (local->inode)
                inode_unref (local->inode);

        if (local->xattr)
                dict_unref (local->xattr);

        if (local->xdata)
                dict_unref (local->xdata);

out:
        return;
}
Пример #13
0
static void del_file(file_t *file)
{
    inode_unref(file->node);
    file->node = NULL;
}
Пример #14
0
int
glfs_h_link (struct glfs *fs, struct glfs_object *linksrc,
	     struct glfs_object *parent, const char *name)
{
	int                 ret = -1;
	xlator_t           *subvol = NULL;
	inode_t            *inode = NULL;
	inode_t            *pinode = NULL;
	loc_t               oldloc = {0, };
	loc_t               newloc = {0, };

	/* validate in args */
	if ((fs == NULL) || (linksrc == NULL) || (parent == NULL) ||
		(name == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, linksrc);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	if (inode->ia_type == IA_IFDIR) {
		ret = -1;
		errno = EISDIR;
		goto out;
	}

	GLFS_LOC_FILL_INODE (inode, oldloc, out);

	/* get/refresh the in arg objects inode in correlation to the xlator */
	pinode = glfs_resolve_inode (fs, subvol, parent);
	if (!pinode) {
		errno = ESTALE;
		goto out;
	}

	/* setup newloc based on parent */
	newloc.parent = inode_ref (pinode);
	newloc.name = name;
	ret = glfs_loc_touchup (&newloc);
	if (ret != 0) {
		errno = EINVAL;
		goto out;
	}

	/* Filling the inode of the hard link to be same as that of the
	 * original file
	 */
	newloc.inode = inode_ref (inode);

	/* fop/op */
	ret = syncop_link (subvol, &oldloc, &newloc);
        DECODE_SYNCOP_ERR (ret);

	if (ret == 0)
		/* TODO: No iatt to pass as there has been no lookup */
		ret = glfs_loc_link (&newloc, NULL);
out:
	loc_wipe (&oldloc);
	loc_wipe (&newloc);

	if (inode)
		inode_unref (inode);

	if (pinode)
		inode_unref (pinode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #15
0
int
glfs_h_rename (struct glfs *fs, struct glfs_object *olddir, const char *oldname,
	       struct glfs_object *newdir, const char *newname)
{
	int                 ret = -1;
	xlator_t           *subvol = NULL;
	inode_t            *oldpinode = NULL;
	inode_t            *newpinode = NULL;
	loc_t               oldloc = {0, };
	loc_t               newloc = {0, };
	struct iatt         oldiatt = {0, };
	struct iatt         newiatt = {0, };

	/* validate in args */
	if ((fs == NULL) || (olddir == NULL) || (oldname == NULL) ||
		(newdir == NULL) || (newname == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if ( !subvol ) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	oldpinode = glfs_resolve_inode (fs, subvol, olddir);
	if (!oldpinode) {
		errno = ESTALE;
		goto out;
	}

	ret = glfs_resolve_at (fs, subvol, oldpinode, oldname, &oldloc,
			       &oldiatt, 0 , 0);
	if (ret != 0) {
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	newpinode = glfs_resolve_inode (fs, subvol, newdir);
	if (!newpinode) {
		errno = ESTALE;
		goto out;
	}

	ret = glfs_resolve_at (fs, subvol, newpinode, newname, &newloc,
			       &newiatt, 0, 0);

	if (ret && errno != ENOENT && newloc.parent)
		goto out;

	if (newiatt.ia_type != IA_INVAL) {
		if ((oldiatt.ia_type == IA_IFDIR) !=
			(newiatt.ia_type == IA_IFDIR)) {
			/* Either both old and new must be dirs,
			 * or both must be non-dirs. Else, fail.
			 */
			ret = -1;
			errno = EEXIST;
			goto out;
		}
	}

	/* TODO: check if new or old is a prefix of the other, and fail EINVAL */

	ret = syncop_rename (subvol, &oldloc, &newloc);
        DECODE_SYNCOP_ERR (ret);

	if (ret == 0)
		inode_rename (oldloc.parent->table, oldloc.parent, oldloc.name,
			      newloc.parent, newloc.name, oldloc.inode,
			      &oldiatt);

out:
	loc_wipe (&oldloc);
	loc_wipe (&newloc);

	if (oldpinode)
		inode_unref (oldpinode);

	if (newpinode)
		inode_unref (newpinode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #16
0
struct glfs_fd *
glfs_h_opendir (struct glfs *fs, struct glfs_object *object)
{
	int              ret = -1;
	struct glfs_fd  *glfd = NULL;
	xlator_t        *subvol = NULL;
	inode_t         *inode = NULL;
	loc_t            loc = {0, };

	/* validate in args */
	if ((fs == NULL) || (object == NULL)) {
		errno = EINVAL;
		return NULL;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, object);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	if (!IA_ISDIR (inode->ia_type)) {
		ret = -1;
		errno = ENOTDIR;
		goto out;
	}

	glfd = glfs_fd_new (fs);
	if (!glfd)
		goto out;

	INIT_LIST_HEAD (&glfd->entries);

	glfd->fd = fd_create (inode, getpid());
	if (!glfd->fd) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	GLFS_LOC_FILL_INODE (inode, loc, out);

	/* fop/op */
	ret = syncop_opendir (subvol, &loc, glfd->fd);
        DECODE_SYNCOP_ERR (ret);

out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	if (ret && glfd) {
		glfs_fd_destroy (glfd);
		glfd = NULL;
	} else {
		fd_bind (glfd->fd);
		glfs_fd_bind (glfd);
	}

	glfs_subvol_done (fs, subvol);

	return glfd;
}
Пример #17
0
int
glfs_h_unlink (struct glfs *fs, struct glfs_object *parent, const char *path)
{
	int                 ret = -1;
	xlator_t           *subvol = NULL;
	inode_t            *inode = NULL;
	loc_t               loc = {0, };

	/* validate in args */
	if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
		errno = EINVAL;
		return -1;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if ( !subvol ) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, parent);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	ret = glfs_resolve_at (fs, subvol, inode, path, &loc, NULL, 0 , 0);
	if (ret != 0) {
		goto out;
	}

	if (!IA_ISDIR(loc.inode->ia_type)) {
		ret = syncop_unlink (subvol, &loc);
                DECODE_SYNCOP_ERR (ret);
		if (ret != 0) {
			goto out;
		}
	} else {
		ret = syncop_rmdir (subvol, &loc, 0);
                DECODE_SYNCOP_ERR (ret);
		if (ret != 0) {
			goto out;
		}
	}

	if (ret == 0)
		ret = glfs_loc_unlink (&loc);

out:
	loc_wipe (&loc);

	if (inode)
		inode_unref (inode);

	glfs_subvol_done (fs, subvol);

	return ret;
}
Пример #18
0
struct glfs_object *
glfs_h_mknod (struct glfs *fs, struct glfs_object *parent, const char *path,
	      mode_t mode, dev_t dev, struct stat *stat)
{
	int                 ret = -1;
	xlator_t           *subvol = NULL;
	inode_t            *inode = NULL;
	loc_t               loc = {0, };
	struct iatt         iatt = {0, };
	uuid_t              gfid;
	dict_t             *xattr_req = NULL;
	struct glfs_object *object = NULL;

	/* validate in args */
	if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
		errno = EINVAL;
		return NULL;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, parent);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	xattr_req = dict_new ();
	if (!xattr_req) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	uuid_generate (gfid);
	ret = dict_set_static_bin (xattr_req, "gfid-req", gfid, 16);
	if (ret) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	GLFS_LOC_FILL_PINODE (inode, loc, ret, errno, out, path);

	/* fop/op */
	ret = syncop_mknod (subvol, &loc, mode, dev, xattr_req, &iatt);
        DECODE_SYNCOP_ERR (ret);

	/* populate out args */
	if (ret == 0) {
		ret = glfs_loc_link (&loc, &iatt);
		if (ret != 0) {
			goto out;
		}

		if (stat)
			glfs_iatt_to_stat (fs, &iatt, stat);

		ret = glfs_create_object (&loc, &object);
	}
out:
	if (ret && object != NULL) {
		glfs_h_close (object);
		object = NULL;
	}

	loc_wipe(&loc);

	if (inode)
		inode_unref (inode);

	if (xattr_req)
		dict_unref (xattr_req);

	glfs_subvol_done (fs, subvol);

	return object;
}
Пример #19
0
struct glfs_object *
glfs_h_creat (struct glfs *fs, struct glfs_object *parent, const char *path,
	      int flags, mode_t mode, struct stat *stat)
{
	int                 ret = -1;
	struct glfs_fd     *glfd = NULL;
	xlator_t           *subvol = NULL;
	inode_t            *inode = NULL;
	loc_t               loc = {0, };
	struct iatt         iatt = {0, };
	uuid_t              gfid;
	dict_t             *xattr_req = NULL;
	struct glfs_object *object = NULL;

	/* validate in args */
	if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
		errno = EINVAL;
		return NULL;
	}

	__glfs_entry_fs (fs);

	/* get the active volume */
	subvol = glfs_active_subvol (fs);
	if (!subvol) {
		ret = -1;
		errno = EIO;
		goto out;
	}

	/* get/refresh the in arg objects inode in correlation to the xlator */
	inode = glfs_resolve_inode (fs, subvol, parent);
	if (!inode) {
		errno = ESTALE;
		goto out;
	}

	xattr_req = dict_new ();
	if (!xattr_req) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	uuid_generate (gfid);
	ret = dict_set_static_bin (xattr_req, "gfid-req", gfid, 16);
	if (ret) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	GLFS_LOC_FILL_PINODE (inode, loc, ret, errno, out, path);

	glfd = glfs_fd_new (fs);
	if (!glfd)
		goto out;

	glfd->fd = fd_create (loc.inode, getpid());
	if (!glfd->fd) {
		ret = -1;
		errno = ENOMEM;
		goto out;
	}

	/* fop/op */
	ret = syncop_create (subvol, &loc, flags, mode, glfd->fd,
			     xattr_req, &iatt);
        DECODE_SYNCOP_ERR (ret);

	/* populate out args */
	if (ret == 0) {
		/* TODO: If the inode existed in the cache (say file already
		   exists), then the glfs_loc_link will not update the
		   loc.inode, as a result we will have a 0000 GFID that we
		   would copy out to the object, this needs to be fixed.
		*/
		ret = glfs_loc_link (&loc, &iatt);
		if (ret != 0) {
			goto out;
		}

		if (stat)
			glfs_iatt_to_stat (fs, &iatt, stat);

		ret = glfs_create_object (&loc, &object);
	}

out:
	if (ret && object != NULL) {
		glfs_h_close (object);
		object = NULL;
	}

	loc_wipe(&loc);

	if (inode)
		inode_unref (inode);

	if (xattr_req)
		dict_unref (xattr_req);

	if (glfd) {
		glfs_fd_destroy (glfd);
		glfd = NULL;
	}

	glfs_subvol_done (fs, subvol);

	return object;
}