mirror of
https://github.com/ostreedev/ostree.git
synced 2025-03-19 22:50:35 +03:00
repo: After renaming in all loose objects, ensure metadata is stable
When a transaction is finished and we have moved all the staged loose objects into the repo we fsync all the object directory, to ensure the filenames are stable before we update the refs files to point to the new commits. With out this an unclean shutdown after the transaction is finished could result in a refs file that points to an incomplete commit. https://bugzilla.gnome.org/show_bug.cgi?id=759442 Closes: #918 Approved by: cgwalters
This commit is contained in:
parent
c81252c1e0
commit
2a3f17c7aa
@ -1202,7 +1202,9 @@ rename_pending_loose_objects (OstreeRepo *self,
|
||||
while (TRUE)
|
||||
{
|
||||
struct dirent *dent;
|
||||
gboolean renamed_some_object = FALSE;
|
||||
g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, };
|
||||
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
|
||||
return FALSE;
|
||||
@ -1220,21 +1222,20 @@ rename_pending_loose_objects (OstreeRepo *self,
|
||||
&child_dfd_iter, error))
|
||||
return FALSE;
|
||||
|
||||
loose_objpath[0] = dent->d_name[0];
|
||||
loose_objpath[1] = dent->d_name[1];
|
||||
loose_objpath[2] = '/';
|
||||
|
||||
/* Iterate over inner checksum dir */
|
||||
while (TRUE)
|
||||
{
|
||||
struct dirent *child_dent;
|
||||
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent (&child_dfd_iter, &child_dent, cancellable, error))
|
||||
return FALSE;
|
||||
if (child_dent == NULL)
|
||||
break;
|
||||
|
||||
loose_objpath[0] = dent->d_name[0];
|
||||
loose_objpath[1] = dent->d_name[1];
|
||||
loose_objpath[2] = '/';
|
||||
|
||||
g_strlcpy (loose_objpath + 3, child_dent->d_name, sizeof (loose_objpath)-3);
|
||||
|
||||
if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_objpath,
|
||||
@ -1244,9 +1245,34 @@ rename_pending_loose_objects (OstreeRepo *self,
|
||||
if (G_UNLIKELY (renameat (child_dfd_iter.fd, loose_objpath + 3,
|
||||
self->objects_dir_fd, loose_objpath) < 0))
|
||||
return glnx_throw_errno (error);
|
||||
|
||||
renamed_some_object = TRUE;
|
||||
}
|
||||
|
||||
if (renamed_some_object)
|
||||
{
|
||||
/* Ensure that in the case of a power cut all the directory metadata that
|
||||
we want has reached the disk. In particular, we want this before we
|
||||
update the refs to point to these objects. */
|
||||
glnx_fd_close int target_dir_fd = -1;
|
||||
|
||||
loose_objpath[2] = 0;
|
||||
|
||||
if (!glnx_opendirat (self->objects_dir_fd,
|
||||
loose_objpath, FALSE,
|
||||
&target_dir_fd,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (fsync (target_dir_fd) == -1)
|
||||
return glnx_throw_errno_prefix (error, "fsync");
|
||||
}
|
||||
}
|
||||
|
||||
/* In case we created any loose object subdirs, make sure they are on disk */
|
||||
if (fsync (self->objects_dir_fd) == -1)
|
||||
return glnx_throw_errno_prefix (error, "fsync");
|
||||
|
||||
if (!glnx_shutil_rm_rf_at (self->tmp_dir_fd, self->commit_stagedir_name,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user