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,
|
OstreeRepoCheckoutMode mode,
|
||||||
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
||||||
GFile *source,
|
GFile *source,
|
||||||
GFile *destination,
|
|
||||||
int dirfd,
|
int dirfd,
|
||||||
|
const char *name,
|
||||||
gboolean *out_was_supported,
|
gboolean *out_was_supported,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
|
|
@ -337,11 +337,7 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||||
gboolean ret_was_supported = FALSE;
|
gboolean ret_was_supported = FALSE;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (dirfd != -1 &&
|
if (linkat (-1, gs_file_get_path_cached (source), dirfd, name, 0) != -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)
|
|
||||||
ret_was_supported = TRUE;
|
ret_was_supported = TRUE;
|
||||||
else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
|
else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
|
||||||
{
|
{
|
||||||
|
|
@ -360,7 +356,7 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||||
*
|
*
|
||||||
* So we can't make this atomic.
|
* So we can't make this atomic.
|
||||||
*/
|
*/
|
||||||
(void) unlink (gs_file_get_path_cached (destination));
|
(void) unlinkat (dirfd, name, 0);
|
||||||
goto again;
|
goto again;
|
||||||
ret_was_supported = TRUE;
|
ret_was_supported = TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -447,6 +443,8 @@ static gboolean
|
||||||
checkout_one_file (OstreeRepo *repo,
|
checkout_one_file (OstreeRepo *repo,
|
||||||
GFile *source,
|
GFile *source,
|
||||||
GFileInfo *source_info,
|
GFileInfo *source_info,
|
||||||
|
int destination_dfd,
|
||||||
|
const char *destination_name,
|
||||||
GFile *destination,
|
GFile *destination,
|
||||||
OstreeRepoCheckoutMode mode,
|
OstreeRepoCheckoutMode mode,
|
||||||
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
||||||
|
|
@ -547,7 +545,7 @@ checkout_one_file (OstreeRepo *repo,
|
||||||
/* If we found one, try hardlinking */
|
/* If we found one, try hardlinking */
|
||||||
if (!checkout_file_hardlink (repo, mode,
|
if (!checkout_file_hardlink (repo, mode,
|
||||||
overwrite_mode, loose_path,
|
overwrite_mode, loose_path,
|
||||||
destination, -1,
|
destination_dfd, destination_name,
|
||||||
&hardlink_supported, cancellable, error))
|
&hardlink_supported, cancellable, error))
|
||||||
{
|
{
|
||||||
g_prefix_error (error, "Hardlinking loose object %s to %s: ", checksum,
|
g_prefix_error (error, "Hardlinking loose object %s to %s: ", checksum,
|
||||||
|
|
@ -607,6 +605,7 @@ ostree_repo_checkout_tree (OstreeRepo *self,
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gs_unref_variant GVariant *xattrs = NULL;
|
gs_unref_variant GVariant *xattrs = NULL;
|
||||||
gs_unref_object GFileEnumerator *dir_enum = NULL;
|
gs_unref_object GFileEnumerator *dir_enum = NULL;
|
||||||
|
int destination_dfd = -1;
|
||||||
|
|
||||||
if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
|
if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
@ -629,6 +628,10 @@ ostree_repo_checkout_tree (OstreeRepo *self,
|
||||||
if (!dir_enum)
|
if (!dir_enum)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (!gs_file_open_dir_fd (destination, &destination_dfd,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
GFileInfo *file_info;
|
GFileInfo *file_info;
|
||||||
|
|
@ -654,7 +657,10 @@ ostree_repo_checkout_tree (OstreeRepo *self,
|
||||||
}
|
}
|
||||||
else
|
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,
|
mode, overwrite_mode,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
@ -663,6 +669,8 @@ ostree_repo_checkout_tree (OstreeRepo *self,
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
|
if (destination_dfd != -1)
|
||||||
|
(void) close (destination_dfd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue