repo: Use per-transaction staging dir
Concurrent pulls break since we're sharing the staging directory for all transactions in the repo. This makes us use a per-transaction directory. However, in order for resumes to work we first look for existing staging directories and try to aquire an exclusive lock for them. If we can't find any staging directory or they are all already locked, then we create a new one. https://bugzilla.gnome.org/show_bug.cgi?id=757611
This commit is contained in:
parent
be19c88861
commit
f771461b4a
|
|
@ -1161,45 +1161,26 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gboolean ret_transaction_resume = FALSE;
|
gboolean ret_transaction_resume = FALSE;
|
||||||
struct stat stbuf;
|
g_autofree char *stagedir_boot_id_prefix = NULL;
|
||||||
|
g_autofree char *stagedir_name = NULL;
|
||||||
|
glnx_fd_close int stagedir_fd = -1;
|
||||||
|
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||||
|
|
||||||
g_return_val_if_fail (self->in_transaction == FALSE, FALSE);
|
g_return_val_if_fail (self->in_transaction == FALSE, FALSE);
|
||||||
|
|
||||||
/* We used to create a `transaction` symbolic link, but it's now
|
|
||||||
* obsoleted by the per-commit .commitpartial files. We no longer
|
|
||||||
* create it, but let's still read it if it exists, as well as
|
|
||||||
* unlink it when we're done.
|
|
||||||
*/
|
|
||||||
if (fstatat (self->repo_dir_fd, "transaction", &stbuf, AT_SYMLINK_NOFOLLOW) != 0)
|
|
||||||
{
|
|
||||||
if (errno == ENOENT)
|
|
||||||
ret_transaction_resume = FALSE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glnx_set_error_from_errno (error);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret_transaction_resume = TRUE;
|
|
||||||
|
|
||||||
memset (&self->txn_stats, 0, sizeof (OstreeRepoTransactionStats));
|
memset (&self->txn_stats, 0, sizeof (OstreeRepoTransactionStats));
|
||||||
|
|
||||||
self->in_transaction = TRUE;
|
self->in_transaction = TRUE;
|
||||||
|
|
||||||
self->commit_stagedir_name = g_strconcat ("tmpobjects-", self->boot_id, NULL);
|
stagedir_boot_id_prefix = g_strconcat ("staging-", self->boot_id, "-", NULL);
|
||||||
if (mkdirat (self->tmp_dir_fd, self->commit_stagedir_name, 0777) == -1)
|
|
||||||
{
|
|
||||||
int errsv = errno;
|
|
||||||
if (G_UNLIKELY (errsv != EEXIST))
|
|
||||||
{
|
|
||||||
gs_set_error_from_errno (error, errsv);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gs_opendirat (self->tmp_dir_fd, self->commit_stagedir_name, FALSE,
|
if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd,
|
||||||
&self->commit_stagedir_fd, error))
|
stagedir_boot_id_prefix,
|
||||||
|
&self->commit_stagedir_name,
|
||||||
|
&self->commit_stagedir_fd,
|
||||||
|
&self->commit_stagedir_lock,
|
||||||
|
&ret_transaction_resume,
|
||||||
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
@ -1485,6 +1466,8 @@ ostree_repo_commit_transaction (OstreeRepo *self,
|
||||||
{
|
{
|
||||||
(void) close (self->commit_stagedir_fd);
|
(void) close (self->commit_stagedir_fd);
|
||||||
self->commit_stagedir_fd = -1;
|
self->commit_stagedir_fd = -1;
|
||||||
|
|
||||||
|
glnx_release_lock_file (&self->commit_stagedir_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&self->commit_stagedir_name, g_free);
|
g_clear_pointer (&self->commit_stagedir_name, g_free);
|
||||||
|
|
@ -1524,6 +1507,8 @@ ostree_repo_abort_transaction (OstreeRepo *self,
|
||||||
{
|
{
|
||||||
(void) close (self->commit_stagedir_fd);
|
(void) close (self->commit_stagedir_fd);
|
||||||
self->commit_stagedir_fd = -1;
|
self->commit_stagedir_fd = -1;
|
||||||
|
|
||||||
|
glnx_release_lock_file (&self->commit_stagedir_lock);
|
||||||
}
|
}
|
||||||
g_clear_pointer (&self->commit_stagedir_name, g_free);
|
g_clear_pointer (&self->commit_stagedir_name, g_free);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ostree-repo.h"
|
#include "ostree-repo.h"
|
||||||
|
#include "libglnx.h"
|
||||||
|
|
||||||
#ifdef HAVE_LIBSOUP
|
#ifdef HAVE_LIBSOUP
|
||||||
#include "ostree-fetcher.h"
|
#include "ostree-fetcher.h"
|
||||||
|
|
@ -43,6 +44,7 @@ struct OstreeRepo {
|
||||||
char *boot_id;
|
char *boot_id;
|
||||||
int commit_stagedir_fd;
|
int commit_stagedir_fd;
|
||||||
char *commit_stagedir_name;
|
char *commit_stagedir_name;
|
||||||
|
GLnxLockFile commit_stagedir_lock;
|
||||||
|
|
||||||
GFile *repodir;
|
GFile *repodir;
|
||||||
int repo_dir_fd;
|
int repo_dir_fd;
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,7 @@ ostree_repo_finalize (GObject *object)
|
||||||
if (self->commit_stagedir_fd != -1)
|
if (self->commit_stagedir_fd != -1)
|
||||||
(void) close (self->commit_stagedir_fd);
|
(void) close (self->commit_stagedir_fd);
|
||||||
g_free (self->commit_stagedir_name);
|
g_free (self->commit_stagedir_name);
|
||||||
|
glnx_release_lock_file (&self->commit_stagedir_lock);
|
||||||
g_clear_object (&self->tmp_dir);
|
g_clear_object (&self->tmp_dir);
|
||||||
if (self->tmp_dir_fd)
|
if (self->tmp_dir_fd)
|
||||||
(void) close (self->tmp_dir_fd);
|
(void) close (self->tmp_dir_fd);
|
||||||
|
|
@ -674,6 +675,7 @@ static void
|
||||||
ostree_repo_init (OstreeRepo *self)
|
ostree_repo_init (OstreeRepo *self)
|
||||||
{
|
{
|
||||||
static gsize gpgme_initialized;
|
static gsize gpgme_initialized;
|
||||||
|
GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT;
|
||||||
|
|
||||||
if (g_once_init_enter (&gpgme_initialized))
|
if (g_once_init_enter (&gpgme_initialized))
|
||||||
{
|
{
|
||||||
|
|
@ -694,6 +696,7 @@ ostree_repo_init (OstreeRepo *self)
|
||||||
self->commit_stagedir_fd = -1;
|
self->commit_stagedir_fd = -1;
|
||||||
self->objects_dir_fd = -1;
|
self->objects_dir_fd = -1;
|
||||||
self->uncompressed_objects_dir_fd = -1;
|
self->uncompressed_objects_dir_fd = -1;
|
||||||
|
self->commit_stagedir_lock = empty_lockfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue