Patchwork [1,of,4,V2] util: disable hardlink for copyfile if fstype is outside a whitelist

login
register
mail settings
Submitter Jun Wu
Date March 22, 2017, 2 a.m.
Message ID <8891617ca43282810a8e.1490148053@localhost.localdomain>
Download mbox | patch
Permalink /patch/19544/
State Accepted
Headers show

Comments

Jun Wu - March 22, 2017, 2 a.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1489306987 28800
#      Sun Mar 12 00:23:07 2017 -0800
# Node ID 8891617ca43282810a8e758e53d6968f8138f0ca
# Parent  102f291807c92864a2231e5e925d6cd64783bb59
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r 8891617ca432
util: disable hardlink for copyfile if fstype is outside a whitelist

Since osutil.getfstype is available, use it to detect filesystem types. The
whitelist currently includes common local filesystems on Linux where they
should have good hardlink support. We may add new filesystems for other
platforms later.

Patch

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1062,4 +1062,16 @@  def checksignature(func):
 allowhardlinks = False
 
+# a whilelist of known filesystems where hardlink works reliably
+_hardlinkfswhitelist = set([
+    'btrfs',
+    'ext2',
+    'ext3',
+    'ext4',
+    'jfs',
+    'reiserfs',
+    'tmpfs',
+    'xfs',
+])
+
 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
     '''copy a file, preserving mode and optionally other stat info like
@@ -1078,4 +1090,11 @@  def copyfile(src, dest, hardlink=False, 
             oldstat = checkambig and filestat(dest)
         unlink(dest)
+    if hardlink:
+        # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
+        # unless we are confident that dest is on a whitelisted filesystem.
+        destdir = os.path.dirname(dest)
+        fstype = getattr(osutil, 'getfstype', lambda x: None)(destdir)
+        if fstype not in _hardlinkfswhitelist:
+            hardlink = False
     if allowhardlinks and hardlink:
         try: