From 0cb6e6e7020c5a4f2e5c34c6b8cbfa4fdeb45191 Mon Sep 17 00:00:00 2001 From: Milind Changire Date: Wed, 6 Jan 2016 21:23:51 +0530 Subject: geo-rep: hard-link rename issues on changelog replay Problem: LINK + RENAME changelog when replayed after worker restart causes stale hard-links to persist since VFS returns success for RENAME if hard-links point to same inode. Solution: Worker detects RENAME being issued on hard-links to the same inode and unlinks the source file-name. Conditionally rename by verifying that the source gfid matches with the on-disk gfid on the slave. Change-Id: I3ff1c30ef79e77503c8b246d46dab8ac3059ccf2 BUG: 1296175 Reviewed-on: http://review.gluster.org/13189 Signed-off-by: Milind Changire Reviewed-on: http://review.gluster.org/13638 Smoke: Gluster Build System Tested-by: Aravinda VK NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Aravinda VK --- geo-replication/syncdaemon/resource.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'geo-replication/syncdaemon') diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py index c26054ad9df..81edfaa4a49 100644 --- a/geo-replication/syncdaemon/resource.py +++ b/geo-replication/syncdaemon/resource.py @@ -670,6 +670,21 @@ class Server(object): errno_wrap(os.rmdir, [path], [ENOENT, ESTALE]) + def rename_with_disk_gfid_confirmation(gfid, entry, en): + if not matching_disk_gfid(gfid, entry): + logging.error("RENAME ignored: " + "source entry:%s(gfid:%s) does not match with " + "on-disk gfid(%s), when attempting to rename " + "to %s" % + (entry, gfid, cls.gfid_mnt(entry), en)) + return + + cmd_ret = errno_wrap(os.rename, + [entry, en], + [ENOENT, EEXIST], [ESTALE]) + collect_failure(e, cmd_ret) + + for e in entries: blob = None op = e['op'] @@ -738,10 +753,15 @@ class Server(object): (pg, bname) = entry2pb(en) blob = entry_pack_reg_stat(gfid, bname, e['stat']) else: - cmd_ret = errno_wrap(os.rename, - [entry, en], - [ENOENT, EEXIST], [ESTALE]) - collect_failure(e, cmd_ret) + st1 = lstat(en) + if isinstance(st1, int): + rename_with_disk_gfid_confirmation(gfid, entry, en) + else: + if st.st_ino == st1.st_ino: + # we have a hard link, we can now unlink source + os.unlink(entry) + else: + rename_with_disk_gfid_confirmation(gfid, entry, en) if blob: cmd_ret = errno_wrap(Xattr.lsetxattr, [pg, 'glusterfs.gfid.newfile', blob], -- cgit