瀏覽代碼

bsdflags: use fd instead of path

this optimization is only needed for linux, the bsd-like platforms
do not need an open file to run a ioctl against, but have bsdflags
in the stat result already.

on linux, this optimization saves 1 file open/close per input file.
Thomas Waldmann 7 年之前
父節點
當前提交
018b62c845
共有 3 個文件被更改,包括 11 次插入8 次删除
  1. 1 1
      src/borg/archive.py
  2. 1 1
      src/borg/platform/base.py
  3. 9 6
      src/borg/platform/linux.pyx

+ 1 - 1
src/borg/archive.py

@@ -953,7 +953,7 @@ class MetadataCollector:
         with backup_io('extended stat'):
             xattrs = xattr.get_all(fd or path, follow_symlinks=False)
             if not self.nobsdflags:
-                bsdflags = get_flags(path, st)
+                bsdflags = get_flags(path, st, fd=fd)
             acl_get(path, attrs, st, self.numeric_owner, fd=fd)
         if xattrs:
             attrs['xattrs'] = StableDict(xattrs)

+ 1 - 1
src/borg/platform/base.py

@@ -88,7 +88,7 @@ except ImportError:
         pass
 
 
-def get_flags(path, st):
+def get_flags(path, st, fd=None):
     """Return BSD-style file flags for path or stat without following symlinks."""
     return getattr(st, 'st_flags', 0)
 

+ 9 - 6
src/borg/platform/linux.pyx

@@ -153,21 +153,24 @@ def set_flags(path, bsd_flags, fd=None):
             os.close(fd)
 
 
-def get_flags(path, st):
+def get_flags(path, st, fd=None):
     if stat.S_ISBLK(st.st_mode) or stat.S_ISCHR(st.st_mode) or stat.S_ISLNK(st.st_mode):
         # avoid opening devices files - trying to open non-present devices can be rather slow.
         # avoid opening symlinks, O_NOFOLLOW would make the open() fail anyway.
         return 0
     cdef int linux_flags
-    try:
-        fd = os.open(path, os.O_RDONLY|os.O_NONBLOCK|os.O_NOFOLLOW)
-    except OSError:
-        return 0
+    open_fd = fd is None
+    if open_fd:
+        try:
+            fd = os.open(path, os.O_RDONLY|os.O_NONBLOCK|os.O_NOFOLLOW)
+        except OSError:
+            return 0
     try:
         if ioctl(fd, FS_IOC_GETFLAGS, &linux_flags) == -1:
             return 0
     finally:
-        os.close(fd)
+        if open_fd:
+            os.close(fd)
     bsd_flags = 0
     for bsd_flag, linux_flag in BSD_TO_LINUX_FLAGS.items():
         if linux_flags & linux_flag: