Skip to content

Commit

Permalink
commit: lookup payload link
Browse files Browse the repository at this point in the history
Whenever we add a new object file, in addition to lookup if the file is
already present with the same checksum we also check if an object with
the same payload is in the repository.

If a file with the same payload is already present in the repository, we
copy it with `glnx_regfile_copy_bytes` that internally attempts to
create a reflink (ioctl (..., FICLONE, ..)) to the target file if the
file system supports it.  This enables to have objects that share the
payload but have a different inode and xattrs.

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Feb 2, 2018
1 parent dc045ca commit 21fb989
Showing 1 changed file with 37 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/libostree/ostree-repo-commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,8 @@ write_content_object (OstreeRepo *self,
}
else
{
gboolean has_payload_object = FALSE;

/* Update size metadata if configured */
if (indexable && object_file_type == G_FILE_TYPE_REGULAR)
{
Expand All @@ -865,6 +867,41 @@ write_content_object (OstreeRepo *self,
repo_store_size_entry (self, actual_checksum, unpacked_size, stbuf.st_size);
}

if (actual_payload_checksum)
{

if (!ostree_repo_has_object (self, OSTREE_OBJECT_TYPE_PAYLOAD_LINK, actual_payload_checksum,
&has_payload_object, cancellable, error))
return FALSE;


/* We already have an object with the same payload. Clone it, if possible. */
if (has_payload_object)
{
glnx_autofd int fdf = -1;
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
char target_checksum[OSTREE_SHA256_STRING_LEN+1];

_ostree_loose_path (loose_path_buf, actual_payload_checksum, OSTREE_OBJECT_TYPE_PAYLOAD_LINK, self->mode);

if (readlinkat (self->objects_dir_fd, loose_path_buf, target_checksum, sizeof (target_checksum)) < 0)
return glnx_throw_errno (error);

_ostree_loose_path (loose_path_buf, target_checksum, OSTREE_OBJECT_TYPE_FILE, self->mode);
if (!ot_openat_ignore_enoent (self->objects_dir_fd, loose_path_buf, &fdf, error))
return FALSE;

if (fdf >= 0)
{
if (ftruncate (tmpf.fd, 0) < 0)
return glnx_throw_errno (error);

if (glnx_regfile_copy_bytes (fdf, tmpf.fd, -1) < 0)
return FALSE;
}
}
}

/* This path is for regular files */
if (!commit_loose_regfile_object (self, actual_checksum, &tmpf,
uid, gid, mode,
Expand Down

0 comments on commit 21fb989

Please sign in to comment.