From 324e81d6fea324d512431a2604086326b8848e9b Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Thu, 25 May 2017 07:28:07 -0400 Subject: 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 Reviewed-on: https://review.gluster.org/17389 NetBSD-regression: NetBSD Build System Reviewed-by: Aravinda VK Smoke: Gluster Build System Reviewed-by: Amar Tumballi CentOS-regression: Gluster Build System --- geo-replication/syncdaemon/resource.py | 48 ++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 11 deletions(-) (limited to 'geo-replication') diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py index 9cbe92a93c5..5d7234358fb 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 -- cgit