summaryrefslogtreecommitdiffstats
path: root/geo-replication
diff options
context:
space:
mode:
authorKotresh HR <khiremat@redhat.com>2017-05-25 07:28:07 -0400
committerShyamsundar Ranganathan <srangana@redhat.com>2017-06-06 12:58:43 +0000
commit5d49ff1f8b41f5babb2f6d484b3f1e1e6bb51ec8 (patch)
tree6d4c87bd914b20632813aac95f486a54df5996d3 /geo-replication
parentcced21a21528cebee7220b732fd26191ea5a83c3 (diff)
geo-rep: Fix meta data sync on symlink
chmod doesn't support 'no dereference' option. It always deference the symlink. But 'chown' does support metadata changes on symlink itself, which was not taken care while syncing. This patch fixes the same. > Change-Id: Ic9985f4e39d15b5a9deb379841bcfb2c263d3e6c > BUG: 1455559 > Signed-off-by: Kotresh HR <khiremat@redhat.com> > Reviewed-on: https://review.gluster.org/17389 > NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> > Reviewed-by: Aravinda VK <avishwan@redhat.com> > Smoke: Gluster Build System <jenkins@build.gluster.org> > Reviewed-by: Amar Tumballi <amarts@redhat.com> > CentOS-regression: Gluster Build System <jenkins@build.gluster.org> (cherry picked from commit 324e81d6fea324d512431a2604086326b8848e9b) Change-Id: Ic9985f4e39d15b5a9deb379841bcfb2c263d3e6c BUG: 1458664 Signed-off-by: Kotresh HR <khiremat@redhat.com> Reviewed-on: https://review.gluster.org/17463 Smoke: Gluster Build System <jenkins@build.gluster.org> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com>
Diffstat (limited to 'geo-replication')
-rw-r--r--geo-replication/syncdaemon/resource.py48
1 files changed, 37 insertions, 11 deletions
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
index 2fb6d5f1cdf..19e16910dfd 100644
--- a/geo-replication/syncdaemon/resource.py
+++ b/geo-replication/syncdaemon/resource.py
@@ -23,8 +23,8 @@ import logging
import tempfile
import threading
import subprocess
-from errno import EEXIST, ENOENT, ENODATA, ENOTDIR, ELOOP
-from errno import EISDIR, ENOTEMPTY, ESTALE, EINVAL, EBUSY
+from errno import EEXIST, ENOENT, ENODATA, ENOTDIR, ELOOP, EACCES
+from errno import EISDIR, ENOTEMPTY, ESTALE, EINVAL, EBUSY, EPERM
from select import error as SelectError
import shutil
@@ -880,17 +880,43 @@ class Server(object):
atime = e['stat']['atime']
mtime = e['stat']['mtime']
go = e['go']
- cmd_ret = errno_wrap(os.chmod, [go, mode],
- [ENOENT], [ESTALE, EINVAL])
- # This is a fail fast mechanism
- # We do this for failing fops on Slave
- # Master should be logging this
+ # Linux doesn't support chmod on symlink itself.
+ # It is always applied to the target file. So
+ # changelog would record target file's gfid
+ # and we are good. But 'chown' is supported on
+ # symlink file. So changelog would record symlink
+ # gfid in such cases. Since we do 'chown' 'chmod'
+ # 'utime' for each gfid recorded for metadata, and
+ # we know from changelog the metadata is on symlink's
+ # gfid or target file's gfid, we should be doing
+ # 'lchown' 'lchmod' 'utime with no-deference' blindly.
+ # But since 'lchmod' and 'utime with no de-reference' is
+ # not supported in python3, we have to rely on 'chmod'
+ # and 'utime with de-reference'. But 'chmod'
+ # de-reference the symlink and gets ENOENT, EACCES,
+ # EPERM errors, hence ignoring those errors if it's on
+ # symlink file.
+
+ is_symlink = False
+ cmd_ret = errno_wrap(os.lchown, [go, uid, gid], [ENOENT],
+ [ESTALE, EINVAL])
if isinstance(cmd_ret, int):
- failures.append((e, cmd_ret))
continue
- errno_wrap(os.chown, [go, uid, gid], [ENOENT], [ESTALE, EINVAL])
- errno_wrap(os.utime, [go, (atime, mtime)],
- [ENOENT], [ESTALE, EINVAL])
+
+ cmd_ret = errno_wrap(os.chmod, [go, mode],
+ [ENOENT, EACCES, EPERM], [ESTALE, EINVAL])
+ if isinstance(cmd_ret, int):
+ is_symlink = os.path.islink(go)
+ if not is_symlink:
+ failures.append((e, cmd_ret, "chmod"))
+
+ cmd_ret = errno_wrap(os.utime, [go, (atime, mtime)],
+ [ENOENT, EACCES, EPERM], [ESTALE, EINVAL])
+ if isinstance(cmd_ret, int):
+ if not is_symlink:
+ is_symlink = os.path.islink(go)
+ if not is_symlink:
+ failures.append((e, cmd_ret, "utime"))
return failures
@classmethod