diff options
| author | Milind Changire <mchangir@redhat.com> | 2016-01-06 21:23:51 +0530 | 
|---|---|---|
| committer | Aravinda VK <avishwan@redhat.com> | 2016-03-09 00:25:15 -0800 | 
| commit | bf03543388c39e4b5162ff5866ba4754fb4fdfc1 (patch) | |
| tree | 3e4fa666fdaf70759d7d0e63a3f9a19c121e3e2a | |
| parent | 5cb80ac63b17a3c34d4deef1816e1782757687d9 (diff) | |
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: 1296174
Signed-off-by: Milind Changire <mchangir@redhat.com>
Reviewed-on: http://review.gluster.org/13189
Smoke: Gluster Build System <jenkins@build.gluster.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Aravinda VK <avishwan@redhat.com>
| -rw-r--r-- | geo-replication/syncdaemon/resource.py | 28 | 
1 files changed, 24 insertions, 4 deletions
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],  | 
