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.
This commit is contained in:
parent
2b61caa2fe
commit
4dcf1a4282
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue