core: Attempt direct link() and fallback on EEXIST

Rather than always doing:

1) make temporary link
2) unlink() target
3) rename()

Just try making the link, and only do the second two if the file
already exists.  This reduces system call traffic a lot.
This commit is contained in:
Colin Walters 2012-05-24 20:14:51 -04:00
parent f7bbf41132
commit fb71519cd6
1 changed files with 18 additions and 30 deletions

View File

@ -4120,37 +4120,27 @@ checkout_file_hardlink (OstreeRepo *self,
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
ot_lobj GFile *dir = NULL; ot_lobj GFile *dir = NULL;
ot_lobj GFile *temp_file = NULL;
if (overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES) if (link (ot_gfile_get_path_cached (source), ot_gfile_get_path_cached (destination)) < 0)
{ {
dir = g_file_get_parent (destination); if (errno == EEXIST && overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
if (!ostree_create_temp_hardlink (dir, (GFile*)source, NULL, "link", {
&temp_file, cancellable, error)) /* Idiocy, from man rename(2)
goto out; *
* "If oldpath and newpath are existing hard links referring to
/* Idiocy, from man rename(2) * the same file, then rename() does nothing, and returns a
* * success status."
* "If oldpath and newpath are existing hard links referring to *
* the same file, then rename() does nothing, and returns a * So we can't make this atomic.
* success status." */
* (void) unlink (ot_gfile_get_path_cached (destination));
* So we can't make this atomic. if (link (ot_gfile_get_path_cached (source), ot_gfile_get_path_cached (destination)) < 0)
*/ {
ot_util_set_error_from_errno (error, errno);
(void) unlink (ot_gfile_get_path_cached (destination)); goto out;
}
if (rename (ot_gfile_get_path_cached (temp_file),
ot_gfile_get_path_cached (destination)) < 0)
{
ot_util_set_error_from_errno (error, errno);
goto out;
} }
g_clear_object (&temp_file); else
}
else
{
if (link (ot_gfile_get_path_cached (source), ot_gfile_get_path_cached (destination)) < 0)
{ {
ot_util_set_error_from_errno (error, errno); ot_util_set_error_from_errno (error, errno);
goto out; goto out;
@ -4159,8 +4149,6 @@ checkout_file_hardlink (OstreeRepo *self,
ret = TRUE; ret = TRUE;
out: out:
if (temp_file)
(void) unlink (ot_gfile_get_path_cached (temp_file));
return ret; return ret;
} }