commit, payload-reflink: do not write to the parent repo

reintroduce the feature that was reverted with commit:

28c7bc6d0e

Differently than the original implementation, now we don't attempt any
test for reflinks support on the parent repository, since the test
requires write access to the repository.

Additionally, also check that the two repositories are on the same
device before attempting any reflink.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>

Closes: #1525
Approved by: cgwalters
This commit is contained in:
Giuseppe Scrivano authored and Atomic Bot committed 2018-04-13 21:52:53 +00:00
1 parent fea9277020
commit cdaf7cd838
2 files changed
+98 -36

No files matched your search

+31 -20
View File
@@ -598,27 +598,26 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self,
}
static gboolean
_check_support_reflink (OstreeRepo *self, gboolean *supported, GError **error)
_check_support_reflink (OstreeRepo *dest, gboolean *supported, GError **error)
{
/* We have not checked yet if the file system supports reflinks, do it here */
if (g_atomic_int_get (&self->fs_support_reflink) == 0)
/* We have not checked yet if the destination file system supports reflinks, do it here */
if (g_atomic_int_get (&dest->fs_support_reflink) == 0)
{
g_auto(GLnxTmpfile) src_tmpf = { 0, };
glnx_autofd int src_fd = -1;
g_auto(GLnxTmpfile) dest_tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_RDWR|O_CLOEXEC,
&src_tmpf, error))
if (!glnx_openat_rdonly (dest->repo_dir_fd, "config", TRUE, &src_fd, error))
return FALSE;
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (dest), ".", O_WRONLY|O_CLOEXEC,
&dest_tmpf, error))
return FALSE;
if (ioctl (dest_tmpf.fd, FICLONE, src_tmpf.fd) == 0)
g_atomic_int_set (&self->fs_support_reflink, 1);
if (ioctl (dest_tmpf.fd, FICLONE, src_fd) == 0)
g_atomic_int_set (&dest->fs_support_reflink, 1);
else if (errno == EOPNOTSUPP) /* Ignore other kind of errors as they might be temporary failures */
g_atomic_int_set (&self->fs_support_reflink, -1);
g_atomic_int_set (&dest->fs_support_reflink, -1);
}
*supported = g_atomic_int_get (&self->fs_support_reflink) >= 0;
*supported = g_atomic_int_get (&dest->fs_support_reflink) >= 0;
return TRUE;
}
@@ -631,6 +630,7 @@ _create_payload_link (OstreeRepo *self,
GError **error)
{
gboolean reflinks_supported = FALSE;
if (!_check_support_reflink (self, &reflinks_supported, error))
return FALSE;
@@ -664,8 +664,8 @@ _create_payload_link (OstreeRepo *self,
}
static gboolean
_import_payload_link (OstreeRepo *self,
OstreeRepo *source,
_import_payload_link (OstreeRepo *dest_repo,
OstreeRepo *src_repo,
const char *checksum,
GCancellable *cancellable,
GError **error)
@@ -676,20 +676,24 @@ _import_payload_link (OstreeRepo *self,
glnx_unref_object OtChecksumInstream *checksum_payload = NULL;
g_autoptr(GFileInfo) file_info = NULL;
if (!_check_support_reflink (self, &reflinks_supported, error))
/* The two repositories are on different devices */
if (src_repo->device != dest_repo->device)
return TRUE;
if (!_check_support_reflink (dest_repo, &reflinks_supported, error))
return FALSE;
if (!reflinks_supported)
return TRUE;
if (!G_IN_SET(self->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY))
if (!G_IN_SET(dest_repo->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY))
return TRUE;
if (!ostree_repo_load_file (source, checksum, &is, &file_info, NULL, cancellable, error))
if (!ostree_repo_load_file (src_repo, checksum, &is, &file_info, NULL, cancellable, error))
return FALSE;
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR
|| g_file_info_get_size (file_info) < self->payload_link_threshold)
|| g_file_info_get_size (file_info) < dest_repo->payload_link_threshold)
return TRUE;
checksum_payload = ot_checksum_instream_new (is, G_CHECKSUM_SHA256);
@@ -706,11 +710,12 @@ _import_payload_link (OstreeRepo *self,
}
payload_checksum = ot_checksum_instream_get_string (checksum_payload);
return _create_payload_link (self, checksum, payload_checksum, file_info, cancellable, error);
return _create_payload_link (dest_repo, checksum, payload_checksum, file_info, cancellable, error);
}
static gboolean
_try_clone_from_payload_link (OstreeRepo *self,
OstreeRepo *dest_repo,
const char *payload_checksum,
GFileInfo *file_info,
GLnxTmpfile *tmpf,
@@ -722,7 +727,11 @@ _try_clone_from_payload_link (OstreeRepo *self,
if (self->commit_stagedir.initialized)
dfd_searches[0] = self->commit_stagedir.fd;
if (!_check_support_reflink (self, &reflinks_supported, error))
/* The two repositories are on different devices */
if (self->device != dest_repo->device)
return TRUE;
if (!_check_support_reflink (dest_repo, &reflinks_supported, error))
return FALSE;
if (!reflinks_supported)
@@ -777,6 +786,8 @@ _try_clone_from_payload_link (OstreeRepo *self,
return TRUE;
}
}
if (self->parent_repo)
return _try_clone_from_payload_link (self->parent_repo, dest_repo, payload_checksum, file_info, tmpf, cancellable, error);
return TRUE;
}
@@ -1071,7 +1082,7 @@ write_content_object (OstreeRepo *self,
/* Check if a file with the same payload is present in the repository,
and in case try to reflink it */
if (actual_payload_checksum && !_try_clone_from_payload_link (self, actual_payload_checksum, file_info, &tmpf, cancellable, error))
if (actual_payload_checksum && !_try_clone_from_payload_link (self, self, actual_payload_checksum, file_info, &tmpf, cancellable, error))
return FALSE;
/* This path is for regular files */