14f8ab
From 161a039f8088bf8ce7000d8175e3793219525179 Mon Sep 17 00:00:00 2001
14f8ab
From: Kotresh HR <khiremat@redhat.com>
14f8ab
Date: Thu, 28 Mar 2019 07:17:16 -0400
14f8ab
Subject: [PATCH 50/52] geo-rep: Fix syncing multiple rename of symlink
14f8ab
14f8ab
Problem:
14f8ab
Geo-rep fails to sync rename of symlink if it's
14f8ab
renamed multiple times if creation and rename
14f8ab
happened successively
14f8ab
14f8ab
Worker crash at slave:
14f8ab
Traceback (most recent call last):
14f8ab
  File "/usr/libexec/glusterfs/python/syncdaemon/repce.py",  in worker
14f8ab
    res = getattr(self.obj, rmeth)(*in_data[2:])
14f8ab
  File "/usr/libexec/glusterfs/python/syncdaemon/resource.py", in entry_ops
14f8ab
    [ESTALE, EINVAL, EBUSY])
14f8ab
  File "/usr/libexec/glusterfs/python/syncdaemon/syncdutils.py", in errno_wrap
14f8ab
    return call(*arg)
14f8ab
  File "/usr/libexec/glusterfs/python/syncdaemon/libcxattr.py", in lsetxattr
14f8ab
    cls.raise_oserr()
14f8ab
  File "/usr/libexec/glusterfs/python/syncdaemon/libcxattr.py", in raise_oserr
14f8ab
    raise OSError(errn, os.strerror(errn))
14f8ab
OSError: [Errno 12] Cannot allocate memory
14f8ab
14f8ab
Geo-rep Behaviour:
14f8ab
1. SYMLINK doesn't record target path in changelog.
14f8ab
   So while syncing SYMLINK, readlink is done on
14f8ab
   master to get target path.
14f8ab
14f8ab
2. Geo-rep will create destination if source is not
14f8ab
   present while syncing RENAME. Hence while syncing
14f8ab
   RENAME of SYMLINK, target path is collected from
14f8ab
   destination.
14f8ab
14f8ab
Cause:
14f8ab
If symlink is created and renamed multiple times, creation of
14f8ab
symlink is ignored, as it's no longer present on master at
14f8ab
that path. While symlink is renamed multiple times at master,
14f8ab
when syncing first RENAME of SYMLINK, both source and destination
14f8ab
is not present, hence target path is not known.  In this case,
14f8ab
while creating destination directly at slave,  regular file
14f8ab
attributes were encoded into blob instead of symlink,
14f8ab
causing failure in gfid-access translator while decoding
14f8ab
blob.
14f8ab
14f8ab
Solution:
14f8ab
While syncing of RENAME of SYMLINK, when target is not known
14f8ab
and when src and destination is not present on the master,
14f8ab
don't create destination. Ignore the rename. It's ok to ignore.
14f8ab
If it's unliked, it's fine.  If it's renamed to something else,
14f8ab
it will be synced then.
14f8ab
14f8ab
Backport of:
14f8ab
> Patch: https://review.gluster.org/22438
14f8ab
> Change-Id: Ibdfa495513b7c05b5370ab0b89c69a6802338d87
14f8ab
> BUG: 1693648
14f8ab
> Signed-off-by: Kotresh HR <khiremat@redhat.com>
14f8ab
14f8ab
Change-Id: Ibdfa495513b7c05b5370ab0b89c69a6802338d87
14f8ab
fixes: bz#1670429
14f8ab
Signed-off-by: Kotresh HR <khiremat@redhat.com>
14f8ab
Reviewed-on: https://code.engineering.redhat.com/gerrit/167122
14f8ab
Tested-by: RHGS Build Bot <nigelb@redhat.com>
14f8ab
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
14f8ab
---
14f8ab
 geo-replication/syncdaemon/resource.py   | 23 ++++++++++++++---------
14f8ab
 tests/00-geo-rep/georep-basic-dr-rsync.t |  1 +
14f8ab
 tests/geo-rep.rc                         | 12 ++++++++++++
14f8ab
 3 files changed, 27 insertions(+), 9 deletions(-)
14f8ab
14f8ab
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
14f8ab
index a2d0b16..c290d86 100644
14f8ab
--- a/geo-replication/syncdaemon/resource.py
14f8ab
+++ b/geo-replication/syncdaemon/resource.py
14f8ab
@@ -625,15 +625,20 @@ class Server(object):
14f8ab
                 # exist with different gfid.
14f8ab
                 if not matching_disk_gfid(gfid, entry):
14f8ab
                     if e['stat'] and not stat.S_ISDIR(e['stat']['mode']):
14f8ab
-                        if stat.S_ISLNK(e['stat']['mode']) and \
14f8ab
-                           e['link'] is not None:
14f8ab
-                            st1 = lstat(en)
14f8ab
-                            if isinstance(st1, int):
14f8ab
-                                (pg, bname) = entry2pb(en)
14f8ab
-                                blob = entry_pack_symlink(cls, gfid, bname,
14f8ab
-                                                          e['link'], e['stat'])
14f8ab
-                            elif not matching_disk_gfid(gfid, en):
14f8ab
-                                collect_failure(e, EEXIST, uid, gid, True)
14f8ab
+                        if stat.S_ISLNK(e['stat']['mode']):
14f8ab
+                            # src is not present, so don't sync symlink as
14f8ab
+                            # we don't know target. It's ok to ignore. If
14f8ab
+                            # it's unliked, it's fine. If it's renamed to
14f8ab
+                            # something else, it will be synced then.
14f8ab
+                            if e['link'] is not None:
14f8ab
+                                st1 = lstat(en)
14f8ab
+                                if isinstance(st1, int):
14f8ab
+                                    (pg, bname) = entry2pb(en)
14f8ab
+                                    blob = entry_pack_symlink(cls, gfid, bname,
14f8ab
+                                                              e['link'],
14f8ab
+                                                              e['stat'])
14f8ab
+                                elif not matching_disk_gfid(gfid, en):
14f8ab
+                                    collect_failure(e, EEXIST, uid, gid, True)
14f8ab
                         else:
14f8ab
                             slink = os.path.join(pfx, gfid)
14f8ab
                             st = lstat(slink)
14f8ab
diff --git a/tests/00-geo-rep/georep-basic-dr-rsync.t b/tests/00-geo-rep/georep-basic-dr-rsync.t
14f8ab
index 4a03930..8b64370 100644
14f8ab
--- a/tests/00-geo-rep/georep-basic-dr-rsync.t
14f8ab
+++ b/tests/00-geo-rep/georep-basic-dr-rsync.t
14f8ab
@@ -110,6 +110,7 @@ EXPECT_WITHIN $GEO_REP_TIMEOUT 0 chown_file_ok ${slave_mnt}/hybrid_chown_f1
14f8ab
 #Check History Crawl.
14f8ab
 TEST $GEOREP_CLI $master $slave stop
14f8ab
 TEST create_data "history"
14f8ab
+TEST create_rename_symlink_case
14f8ab
 TEST $GEOREP_CLI $master $slave start
14f8ab
 EXPECT_WITHIN $GEO_REP_TIMEOUT  2 check_status_num_rows "Active"
14f8ab
 EXPECT_WITHIN $GEO_REP_TIMEOUT  2 check_status_num_rows "Passive"
14f8ab
diff --git a/tests/geo-rep.rc b/tests/geo-rep.rc
14f8ab
index 396b4c4..d723129 100644
14f8ab
--- a/tests/geo-rep.rc
14f8ab
+++ b/tests/geo-rep.rc
14f8ab
@@ -19,6 +19,18 @@ function check_common_secret_file()
14f8ab
     echo $?
14f8ab
 }
14f8ab
 
14f8ab
+function create_rename_symlink_case()
14f8ab
+{
14f8ab
+    mkdir ${mastermnt}/MUL_REN_SYMLINK
14f8ab
+    cd ${mastermnt}/MUL_REN_SYMLINK
14f8ab
+    mkdir sym_dir1
14f8ab
+    ln -s "sym_dir1" sym1
14f8ab
+    mv sym1 sym2
14f8ab
+    mv sym2 sym3
14f8ab
+    mv sym3 sym4
14f8ab
+    cd -
14f8ab
+}
14f8ab
+
14f8ab
 function create_data()
14f8ab
 {
14f8ab
     prefix=$1
14f8ab
-- 
14f8ab
1.8.3.1
14f8ab