diff --git a/mercurial/osutil.c b/mercurial/osutil.c
--- a/mercurial/osutil.c
+++ b/mercurial/osutil.c
@@ -1106,7 +1106,7 @@ static PyObject *getfstype(PyObject *sel
 	memset(&buf, 0, sizeof(buf));
 	r = statfs(path, &buf);
 	if (r != 0)
-		Py_RETURN_NONE;
+		return PyErr_SetFromErrno(PyExc_OSError);
 	return Py_BuildValue("s", describefstype(&buf));
 }
 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1089,7 +1089,10 @@ def copyfile(src, dest, hardlink=False, 
     if hardlink:
         # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
         # unless we are confident that dest is on a whitelisted filesystem.
-        fstype = getfstype(os.path.dirname(dest))
+        try:
+            fstype = getfstype(os.path.dirname(dest))
+        except OSError:
+            fstype = None
         if fstype not in _hardlinkfswhitelist:
             hardlink = False
     if hardlink:
@@ -1372,7 +1375,7 @@ def fspath(name, root):
 def getfstype(dirpath):
     '''Get the filesystem type name from a directory (best-effort)
 
-    Returns None if we are unsure, or errors like ENOENT, EPERM happen.
+    Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc.
     '''
     return getattr(osutil, 'getfstype', lambda x: None)(dirpath)
 
diff --git a/tests/hghave.py b/tests/hghave.py
--- a/tests/hghave.py
+++ b/tests/hghave.py
@@ -349,7 +349,10 @@ def has_hardlink():
 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
 def has_hardlink_whitelisted():
     from mercurial import util
-    fstype = util.getfstype('.')
+    try:
+        fstype = util.getfstype('.')
+    except OSError:
+        return False
     return fstype in util._hardlinkfswhitelist
 
 @check("rmcwd", "can remove current working directory")