summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src/posix-handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/storage/posix/src/posix-handle.c')
-rw-r--r--xlators/storage/posix/src/posix-handle.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c
index 5a8f180b9f4..7f5cd5237ae 100644
--- a/xlators/storage/posix/src/posix-handle.c
+++ b/xlators/storage/posix/src/posix-handle.c
@@ -903,12 +903,18 @@ posix_handle_unset (xlator_t *this, uuid_t gfid, const char *basename)
int
-posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid,
- char *real_path)
+posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid, char *real_path,
+ inode_table_t *itable)
{
- int ret = -1;
- struct stat stbuf = {0,};
- char *newpath = NULL;
+ 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;
+
+ priv = this->private;
MAKE_HANDLE_PATH (newpath, this, gfid, NULL);
if (!newpath) {
@@ -921,6 +927,41 @@ posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid,
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 = __inode_ctx_get0 (inode, this, &ctx_int);
+ if (ret)
+ goto unlock;
+
+ if (ctx_int != GF_UNLINK_TRUE)
+ 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 = __inode_ctx_set0 (inode, this, &ctx_int);
+ }
+unlock:
+ UNLOCK (&inode->lock);
}
return ret;