e7a346
From a47d863ea4501d3d0daceacb194c9f900cefe1a7 Mon Sep 17 00:00:00 2001
e7a346
From: Kotresh HR <khiremat@redhat.com>
e7a346
Date: Mon, 13 Nov 2017 05:27:50 -0500
e7a346
Subject: [PATCH 119/128] geo-rep: Fix data sync issue during hardlink, rename
e7a346
e7a346
Problem:
e7a346
The data is not getting synced if master witnessed
e7a346
IO as below.
e7a346
e7a346
1. echo "test_data" > f1
e7a346
2. ln f1 f2
e7a346
3. mv f2 f3
e7a346
4. unlink f1
e7a346
e7a346
On master, 'f3' exists with data "test_data" but on
e7a346
slave, only f3 exists with zero byte file without
e7a346
backend gfid link.
e7a346
e7a346
Cause:
e7a346
On master, since 'f2' no longer exists, the hardlink
e7a346
is skipped during processing. Later, on trying to sync
e7a346
rename, since source ('f2') doesn't exist, dst ('f3')
e7a346
is created with same gfid. But in this use case, it
e7a346
succeeds but backend gfid would not have linked as 'f1'
e7a346
exists with the same gfid. So, rsync would fail with
e7a346
ENOENT as backend gfid is not linked with 'f3' and 'f1'
e7a346
is unlinked.
e7a346
e7a346
Fix:
e7a346
On processing rename, if src doesn't exist on slave,
e7a346
don't blindly create dst with same gfid. The gfid
e7a346
needs to be checked, if it exists, hardlink needs
e7a346
to be created instead of mknod.
e7a346
e7a346
Thanks Aravinda for helping in RCA :)
e7a346
e7a346
Upstream Reference:
e7a346
> Patch: https://review.gluster.org/18731
e7a346
> BUG: 1512483
e7a346
e7a346
Change-Id: I5af4f99798ed1bcb297598a4bc796b701d1e0130
e7a346
BUG: 1512496
e7a346
Signed-off-by: Kotresh HR <khiremat@redhat.com>
e7a346
Reviewed-on: https://code.engineering.redhat.com/gerrit/126728
e7a346
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e7a346
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e7a346
---
e7a346
 geo-replication/syncdaemon/resource.py | 13 +++++++++++--
e7a346
 1 file changed, 11 insertions(+), 2 deletions(-)
e7a346
e7a346
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
e7a346
index 22aaf85..5ad5b97 100644
e7a346
--- a/geo-replication/syncdaemon/resource.py
e7a346
+++ b/geo-replication/syncdaemon/resource.py
e7a346
@@ -814,8 +814,17 @@ class Server(object):
e7a346
                             elif not matching_disk_gfid(gfid, en):
e7a346
                                 collect_failure(e, EEXIST, True)
e7a346
                         else:
e7a346
-                            (pg, bname) = entry2pb(en)
e7a346
-                            blob = entry_pack_reg_stat(gfid, bname, e['stat'])
e7a346
+                            slink = os.path.join(pfx, gfid)
e7a346
+                            st = lstat(slink)
e7a346
+                            # don't create multiple entries with same gfid
e7a346
+                            if isinstance(st, int):
e7a346
+                                (pg, bname) = entry2pb(en)
e7a346
+                                blob = entry_pack_reg_stat(gfid, bname,
e7a346
+                                                           e['stat'])
e7a346
+                            else:
e7a346
+                                cmd_ret = errno_wrap(os.link, [slink, en],
e7a346
+                                                    [ENOENT, EEXIST], [ESTALE])
e7a346
+                                collect_failure(e, cmd_ret)
e7a346
                 else:
e7a346
                     st1 = lstat(en)
e7a346
                     if isinstance(st1, int):
e7a346
-- 
e7a346
1.8.3.1
e7a346