[ostree] repo: Use per-transaction staging dir



commit f771461b4a048d2fb9acde9d38f833438bc51a29
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Dec 11 15:48:29 2015 +0100

    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

 src/libostree/ostree-repo-commit.c  |   51 ++++++++++++----------------------
 src/libostree/ostree-repo-private.h |    2 +
 src/libostree/ostree-repo.c         |    3 ++
 3 files changed, 23 insertions(+), 33 deletions(-)
---
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c
index 6afc54a..d861e62 100644
--- a/src/libostree/ostree-repo-commit.c
+++ b/src/libostree/ostree-repo-commit.c
@@ -1161,47 +1161,28 @@ ostree_repo_prepare_transaction (OstreeRepo     *self,
 {
   gboolean ret = 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);
 
-  /* 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));
 
   self->in_transaction = TRUE;
 
-  self->commit_stagedir_name = g_strconcat ("tmpobjects-", 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;
-        }
-    }
+  stagedir_boot_id_prefix = g_strconcat ("staging-", self->boot_id, "-", NULL);
 
-  if (!gs_opendirat (self->tmp_dir_fd, self->commit_stagedir_name, FALSE,
-                     &self->commit_stagedir_fd, error))
+  if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd,
+                                     stagedir_boot_id_prefix,
+                                     &self->commit_stagedir_name,
+                                     &self->commit_stagedir_fd,
+                                     &self->commit_stagedir_lock,
+                                     &ret_transaction_resume,
+                                     cancellable, error))
     goto out;
-  
+
   ret = TRUE;
   if (out_transaction_resume)
     *out_transaction_resume = ret_transaction_resume;
@@ -1485,6 +1466,8 @@ ostree_repo_commit_transaction (OstreeRepo                  *self,
     {
       (void) close (self->commit_stagedir_fd);
       self->commit_stagedir_fd = -1;
+
+      glnx_release_lock_file (&self->commit_stagedir_lock);
     }
 
   g_clear_pointer (&self->commit_stagedir_name, g_free);
@@ -1519,11 +1502,13 @@ ostree_repo_abort_transaction (OstreeRepo     *self,
     g_hash_table_remove_all (self->loose_object_devino_hash);
 
   g_clear_pointer (&self->txn_refs, g_hash_table_destroy);
-  
+
   if (self->commit_stagedir_fd != -1)
     {
       (void) close (self->commit_stagedir_fd);
       self->commit_stagedir_fd = -1;
+
+      glnx_release_lock_file (&self->commit_stagedir_lock);
     }
   g_clear_pointer (&self->commit_stagedir_name, g_free);
 
diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h
index 8f57f95..1985b2e 100644
--- a/src/libostree/ostree-repo-private.h
+++ b/src/libostree/ostree-repo-private.h
@@ -21,6 +21,7 @@
 #pragma once
 
 #include "ostree-repo.h"
+#include "libglnx.h"
 
 #ifdef HAVE_LIBSOUP
 #include "ostree-fetcher.h"
@@ -43,6 +44,7 @@ struct OstreeRepo {
   char *boot_id;
   int commit_stagedir_fd;
   char *commit_stagedir_name;
+  GLnxLockFile commit_stagedir_lock;
 
   GFile *repodir;
   int    repo_dir_fd;
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index bc03719..57d81c6 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -514,6 +514,7 @@ ostree_repo_finalize (GObject *object)
   if (self->commit_stagedir_fd != -1)
     (void) close (self->commit_stagedir_fd);
   g_free (self->commit_stagedir_name);
+  glnx_release_lock_file (&self->commit_stagedir_lock);
   g_clear_object (&self->tmp_dir);
   if (self->tmp_dir_fd)
     (void) close (self->tmp_dir_fd);
@@ -674,6 +675,7 @@ static void
 ostree_repo_init (OstreeRepo *self)
 {
   static gsize gpgme_initialized;
+  GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT;
 
   if (g_once_init_enter (&gpgme_initialized))
     {
@@ -694,6 +696,7 @@ ostree_repo_init (OstreeRepo *self)
   self->commit_stagedir_fd = -1;
   self->objects_dir_fd = -1;
   self->uncompressed_objects_dir_fd = -1;
+  self->commit_stagedir_lock = empty_lockfile;
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]