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