[ostree] core: When using hardlinks, always use linkat() for destination



commit 4dcf1a42824695dd8c14c61e5aad74d4a6e6b47a
Author: Colin Walters <walters verbum org>
Date:   Fri Sep 6 18:28:20 2013 -0400

    core: When using hardlinks, always use linkat() for destination
    
    This avoids repeatedly traversing the target pathname, and is just
    more efficient.
    
    Part of a prelude to using fd-relative API for the source object path
    too.

 src/libostree/ostree-repo-checkout.c |   26 +++++++++++++++++---------
 1 files changed, 17 insertions(+), 9 deletions(-)
---
diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c
index 239df4a..ffd1c27 100644
--- a/src/libostree/ostree-repo-checkout.c
+++ b/src/libostree/ostree-repo-checkout.c
@@ -327,8 +327,8 @@ checkout_file_hardlink (OstreeRepo                  *self,
                         OstreeRepoCheckoutMode    mode,
                         OstreeRepoCheckoutOverwriteMode    overwrite_mode,
                         GFile                    *source,
-                        GFile                    *destination,
                         int                       dirfd,
+                        const char               *name,
                         gboolean                 *out_was_supported,
                         GCancellable             *cancellable,
                         GError                  **error)
@@ -337,11 +337,7 @@ checkout_file_hardlink (OstreeRepo                  *self,
   gboolean ret_was_supported = FALSE;
 
  again:
-  if (dirfd != -1 &&
-      linkat (-1, gs_file_get_path_cached (source),
-              dirfd, gs_file_get_basename_cached (destination), 0) != -1)
-    ret_was_supported = TRUE;
-  else if (link (gs_file_get_path_cached (source), gs_file_get_path_cached (destination)) != -1)
+  if (linkat (-1, gs_file_get_path_cached (source), dirfd, name, 0) != -1)
     ret_was_supported = TRUE;
   else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
     {
@@ -360,7 +356,7 @@ checkout_file_hardlink (OstreeRepo                  *self,
        *
        * So we can't make this atomic.  
        */
-      (void) unlink (gs_file_get_path_cached (destination));
+      (void) unlinkat (dirfd, name, 0);
       goto again;
       ret_was_supported = TRUE;
     }
@@ -447,6 +443,8 @@ static gboolean
 checkout_one_file (OstreeRepo                        *repo,
                    GFile                             *source,
                    GFileInfo                         *source_info,
+                   int                                destination_dfd,
+                   const char                        *destination_name,
                    GFile                             *destination,
                    OstreeRepoCheckoutMode             mode,
                    OstreeRepoCheckoutOverwriteMode    overwrite_mode,
@@ -547,7 +545,7 @@ checkout_one_file (OstreeRepo                        *repo,
       /* If we found one, try hardlinking */
       if (!checkout_file_hardlink (repo, mode,
                                    overwrite_mode, loose_path,
-                                   destination, -1,
+                                   destination_dfd, destination_name,
                                    &hardlink_supported, cancellable, error))
         {
           g_prefix_error (error, "Hardlinking loose object %s to %s: ", checksum,
@@ -607,6 +605,7 @@ ostree_repo_checkout_tree (OstreeRepo               *self,
   gboolean ret = FALSE;
   gs_unref_variant GVariant *xattrs = NULL;
   gs_unref_object GFileEnumerator *dir_enum = NULL;
+  int destination_dfd = -1;
 
   if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
     goto out;
@@ -629,6 +628,10 @@ ostree_repo_checkout_tree (OstreeRepo               *self,
   if (!dir_enum)
     goto out;
 
+  if (!gs_file_open_dir_fd (destination, &destination_dfd,
+                            cancellable, error))
+    goto out;
+
   while (TRUE)
     {
       GFileInfo *file_info;
@@ -654,7 +657,10 @@ ostree_repo_checkout_tree (OstreeRepo               *self,
         }
       else
         {
-          if (!checkout_one_file (self, src_child, file_info, dest_path,
+          if (!checkout_one_file (self, src_child, file_info,
+                                  destination_dfd,
+                                  name,
+                                  dest_path,
                                   mode, overwrite_mode,
                                   cancellable, error))
             goto out;
@@ -663,6 +669,8 @@ ostree_repo_checkout_tree (OstreeRepo               *self,
 
   ret = TRUE;
  out:
+  if (destination_dfd != -1)
+    (void) close (destination_dfd);
   return ret;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]