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