From a8b52f6e21e052ed92b4ab3c9ab2104ca0522e8e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 14 Apr 2021 20:43:53 -0400 Subject: [PATCH] repo: Make locking APIs public Doing anything even somewhat sophisticated requires this; turns out our own `ostree prune` CLI wants this, e.g. https://github.com/ostreedev/ostree/issues/2337 Closes: https://github.com/ostreedev/ostree/issues/2286 (cherry picked from commit 0f36d8c2219decbb5794ff19b5259d15d3d8d791) The new symbols have been added to the released symbols file rather than the development symbols file as in the upstream PR since our package does a released build. Similarly, the upstream `LIBOSTREE_2021.3` symbol version has been used so that packages don't need to be rebuilt when we get to that version and drop our backported commits. https://phabricator.endlessm.com/T31868 --- apidoc/ostree-sections.txt | 6 +++ src/libostree/libostree-released.sym | 12 +++++ src/libostree/ostree-repo-commit.c | 8 +-- src/libostree/ostree-repo-private.h | 24 --------- src/libostree/ostree-repo-prune.c | 8 +-- src/libostree/ostree-repo-static-delta-core.c | 2 +- src/libostree/ostree-repo.c | 51 ++++++++++--------- src/libostree/ostree-repo.h | 50 ++++++++++++++++++ src/libostree/ostree-sysroot-cleanup.c | 2 +- tests/test-core.js | 8 +++ tests/test-repo.c | 27 +++++++++- tests/test-symbols.sh | 2 +- 12 files changed, 141 insertions(+), 59 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 64bc68d23..4904153fc 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -310,6 +310,12 @@ ostree_repo_get_min_free_space_bytes ostree_repo_get_config ostree_repo_get_dfd ostree_repo_get_default_repo_finders +OstreeRepoLockType +ostree_repo_lock_pop +ostree_repo_lock_push +OstreeRepoAutoLock +ostree_repo_auto_lock_push +ostree_repo_auto_lock_cleanup ostree_repo_hash ostree_repo_equal ostree_repo_copy_config diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index 4f80d7fc9..90d56babf 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -638,6 +638,18 @@ global: ostree_repo_gpg_sign_data; } LIBOSTREE_2020.7; +/* Endless backported symbols. Note that the upstream symbol version is + * used so that programs linking to the symbols don't need to be rebuilt + * when we get to the upstream release containing the symbols. + */ +LIBOSTREE_2021.3 { +global: + ostree_repo_auto_lock_push; + ostree_repo_auto_lock_cleanup; + ostree_repo_lock_push; + ostree_repo_lock_pop; +} LIBOSTREE_2020.8; + /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. */ diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 690075e12..2b2f6ccba 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1794,8 +1794,8 @@ ostree_repo_prepare_transaction (OstreeRepo *self, memset (&self->txn.stats, 0, sizeof (OstreeRepoTransactionStats)); - self->txn_locked = _ostree_repo_lock_push (self, OSTREE_REPO_LOCK_SHARED, - cancellable, error); + self->txn_locked = ostree_repo_lock_push (self, OSTREE_REPO_LOCK_SHARED, + cancellable, error); if (!self->txn_locked) return FALSE; @@ -2451,7 +2451,7 @@ ostree_repo_commit_transaction (OstreeRepo *self, if (self->txn_locked) { - if (!_ostree_repo_lock_pop (self, cancellable, error)) + if (!ostree_repo_lock_pop (self, cancellable, error)) return FALSE; self->txn_locked = FALSE; } @@ -2509,7 +2509,7 @@ ostree_repo_abort_transaction (OstreeRepo *self, if (self->txn_locked) { - if (!_ostree_repo_lock_pop (self, cancellable, error)) + if (!ostree_repo_lock_pop (self, cancellable, error)) return FALSE; self->txn_locked = FALSE; } diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 714fda8ba..5703db11b 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -496,30 +496,6 @@ _ostree_repo_maybe_regenerate_summary (OstreeRepo *self, GCancellable *cancellable, GError **error); -/* Locking APIs are currently private. - * See https://github.com/ostreedev/ostree/pull/1555 - */ -typedef enum { - OSTREE_REPO_LOCK_SHARED, - OSTREE_REPO_LOCK_EXCLUSIVE -} OstreeRepoLockType; - -gboolean _ostree_repo_lock_push (OstreeRepo *self, - OstreeRepoLockType lock_type, - GCancellable *cancellable, - GError **error); -gboolean _ostree_repo_lock_pop (OstreeRepo *self, - GCancellable *cancellable, - GError **error); - -typedef OstreeRepo OstreeRepoAutoLock; - -OstreeRepoAutoLock * _ostree_repo_auto_lock_push (OstreeRepo *self, - OstreeRepoLockType lock_type, - GCancellable *cancellable, - GError **error); -void _ostree_repo_auto_lock_cleanup (OstreeRepoAutoLock *lock); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoAutoLock, _ostree_repo_auto_lock_cleanup) gboolean _ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, diff --git a/src/libostree/ostree-repo-prune.c b/src/libostree/ostree-repo-prune.c index 0b9536281..c4ce64abc 100644 --- a/src/libostree/ostree-repo-prune.c +++ b/src/libostree/ostree-repo-prune.c @@ -204,7 +204,7 @@ ostree_repo_prune_static_deltas (OstreeRepo *self, const char *commit, GError **error) { g_autoptr(OstreeRepoAutoLock) lock = - _ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); + ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); if (!lock) return FALSE; @@ -325,7 +325,7 @@ ostree_repo_traverse_reachable_refs (OstreeRepo *self, GError **error) { g_autoptr(OstreeRepoAutoLock) lock = - _ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_SHARED, cancellable, error); + ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_SHARED, cancellable, error); if (!lock) return FALSE; @@ -400,7 +400,7 @@ ostree_repo_prune (OstreeRepo *self, GError **error) { g_autoptr(OstreeRepoAutoLock) lock = - _ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); + ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); if (!lock) return FALSE; @@ -486,7 +486,7 @@ ostree_repo_prune_from_reachable (OstreeRepo *self, GError **error) { g_autoptr(OstreeRepoAutoLock) lock = - _ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); + ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); if (!lock) return FALSE; diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c index c25367248..a71c749ea 100644 --- a/src/libostree/ostree-repo-static-delta-core.c +++ b/src/libostree/ostree-repo-static-delta-core.c @@ -1268,7 +1268,7 @@ ostree_repo_static_delta_reindex (OstreeRepo *repo, /* Protect against parallel prune operation */ g_autoptr(OstreeRepoAutoLock) lock = - _ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_SHARED, cancellable, error); + ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_SHARED, cancellable, error); if (!lock) return FALSE; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index ffb2e630a..553bfc3d0 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -444,7 +444,7 @@ pop_repo_lock (OstreeRepo *self, return TRUE; } -/* +/** * ostree_repo_lock_push: * @self: a #OstreeRepo * @lock_type: the type of lock to acquire @@ -470,12 +470,13 @@ pop_repo_lock (OstreeRepo *self, * %TRUE is returned. * * Returns: %TRUE on success, otherwise %FALSE with @error set + * Since: 2021.3 */ gboolean -_ostree_repo_lock_push (OstreeRepo *self, - OstreeRepoLockType lock_type, - GCancellable *cancellable, - GError **error) +ostree_repo_lock_push (OstreeRepo *self, + OstreeRepoLockType lock_type, + GCancellable *cancellable, + GError **error) { g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); @@ -538,8 +539,8 @@ _ostree_repo_lock_push (OstreeRepo *self, } } -/* - * _ostree_repo_lock_pop: +/** + * ostree_repo_lock_pop: * @self: a #OstreeRepo * @cancellable: a #GCancellable * @error: a #GError @@ -560,11 +561,12 @@ _ostree_repo_lock_push (OstreeRepo *self, * %TRUE is returned. * * Returns: %TRUE on success, otherwise %FALSE with @error set + * Since: 2021.3 */ gboolean -_ostree_repo_lock_pop (OstreeRepo *self, - GCancellable *cancellable, - GError **error) +ostree_repo_lock_pop (OstreeRepo *self, + GCancellable *cancellable, + GError **error) { g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); @@ -628,7 +630,7 @@ _ostree_repo_lock_pop (OstreeRepo *self, } /* - * _ostree_repo_auto_lock_push: (skip) + * ostree_repo_auto_lock_push: (skip) * @self: a #OstreeRepo * @lock_type: the type of lock to acquire * @cancellable: a #GCancellable @@ -642,34 +644,37 @@ _ostree_repo_lock_pop (OstreeRepo *self, * * |[ * g_autoptr(OstreeRepoAutoLock) lock = NULL; - * lock = _ostree_repo_auto_lock_push (repo, lock_type, cancellable, error); + * lock = ostree_repo_auto_lock_push (repo, lock_type, cancellable, error); * if (!lock) * return FALSE; * ]| * * Returns: @self on success, otherwise %NULL with @error set + * Since: 2021.3 */ OstreeRepoAutoLock * -_ostree_repo_auto_lock_push (OstreeRepo *self, - OstreeRepoLockType lock_type, - GCancellable *cancellable, - GError **error) +ostree_repo_auto_lock_push (OstreeRepo *self, + OstreeRepoLockType lock_type, + GCancellable *cancellable, + GError **error) { - if (!_ostree_repo_lock_push (self, lock_type, cancellable, error)) + if (!ostree_repo_lock_push (self, lock_type, cancellable, error)) return NULL; return (OstreeRepoAutoLock *)self; } -/* - * _ostree_repo_auto_lock_cleanup: (skip) +/** + * ostree_repo_auto_lock_cleanup: (skip) * @lock: a #OstreeRepoAutoLock * * A cleanup handler for use with ostree_repo_auto_lock_push(). If @lock is * not %NULL, ostree_repo_lock_pop() will be called on it. If * ostree_repo_lock_pop() fails, a critical warning will be emitted. + * + * Since: 2021.3 */ void -_ostree_repo_auto_lock_cleanup (OstreeRepoAutoLock *lock) +ostree_repo_auto_lock_cleanup (OstreeRepoAutoLock *lock) { OstreeRepo *repo = lock; if (repo) @@ -677,7 +682,7 @@ _ostree_repo_auto_lock_cleanup (OstreeRepoAutoLock *lock) g_autoptr(GError) error = NULL; int errsv = errno; - if (!_ostree_repo_lock_pop (repo, NULL, &error)) + if (!ostree_repo_lock_pop (repo, NULL, &error)) g_critical ("Cleanup repo lock failed: %s", error->message); errno = errsv; @@ -5831,8 +5836,8 @@ ostree_repo_regenerate_summary (OstreeRepo *self, g_autoptr(OstreeRepoAutoLock) lock = NULL; gboolean no_deltas_in_summary = FALSE; - lock = _ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, - cancellable, error); + lock = ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, + cancellable, error); if (!lock) return FALSE; diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index e64c3230c..ab2a37bfd 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -1466,6 +1466,56 @@ gboolean ostree_repo_regenerate_summary (OstreeRepo *self, GCancellable *cancellable, GError **error); + +/** + * OstreeRepoLockType: + * @OSTREE_REPO_LOCK_SHARED: A "read only" lock; multiple readers are allowed. + * @OSTREE_REPO_LOCK_EXCLUSIVE: A writable lock at most one writer can be active, and zero readers. + * + * Flags controlling repository locking. + * + * Since: 2021.3 + */ +typedef enum { + OSTREE_REPO_LOCK_SHARED, + OSTREE_REPO_LOCK_EXCLUSIVE +} OstreeRepoLockType; + +_OSTREE_PUBLIC +gboolean ostree_repo_lock_push (OstreeRepo *self, + OstreeRepoLockType lock_type, + GCancellable *cancellable, + GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_lock_pop (OstreeRepo *self, + GCancellable *cancellable, + GError **error); + +/* C convenience API only */ +#ifndef __GI_SCANNER__ + +/** + * OstreeRepoAutoLock: (skip) + * + * An opaque type for use with ostree_repo_auto_lock_push(). + * + * Since: 2021.3 + */ +typedef OstreeRepo OstreeRepoAutoLock; + +_OSTREE_PUBLIC +OstreeRepoAutoLock * ostree_repo_auto_lock_push (OstreeRepo *self, + OstreeRepoLockType lock_type, + GCancellable *cancellable, + GError **error); + +_OSTREE_PUBLIC +void ostree_repo_auto_lock_cleanup (OstreeRepoAutoLock *lock); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoAutoLock, ostree_repo_auto_lock_cleanup) + +#endif + + /** * OSTREE_REPO_METADATA_REF: * diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 271228340..91381cb0c 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -505,7 +505,7 @@ ostree_sysroot_cleanup_prune_repo (OstreeSysroot *sysroot, * the prune. */ g_autoptr(OstreeRepoAutoLock) lock = - _ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); + ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error); if (!lock) return FALSE; diff --git a/tests/test-core.js b/tests/test-core.js index a9ef89192..6e54ab082 100755 --- a/tests/test-core.js +++ b/tests/test-core.js @@ -70,4 +70,12 @@ repo.commit_transaction(null, null); [,readCommit] = repo.resolve_rev('someref', true); assertEquals(readCommit, null); +// Basic locking API sanity test +repo.lock_push(OSTree.RepoLockType.SHARED, null); +repo.lock_push(OSTree.RepoLockType.SHARED, null); +repo.lock_pop(null); +repo.lock_pop(null); +repo.lock_push(OSTree.RepoLockType.EXCLUSIVE, null); +repo.lock_pop(null); + print("ok test-core"); diff --git a/tests/test-repo.c b/tests/test-repo.c index 9857228e1..ae221ac0a 100644 --- a/tests/test-repo.c +++ b/tests/test-repo.c @@ -197,6 +197,30 @@ test_repo_get_min_free_space (Fixture *fixture, } } +/* Just a sanity check of the C autolocking API */ +static void +test_repo_autolock (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + g_autoptr(OstreeRepo) repo = ostree_repo_create_at (fixture->tmpdir.fd, ".", + OSTREE_REPO_MODE_ARCHIVE, + NULL, + NULL, &error); + g_assert_no_error (error); + + { + g_autoptr(OstreeRepoAutoLock) lock = ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_EXCLUSIVE, NULL, &error); + g_assert_no_error (error); + } + + g_autoptr(OstreeRepoAutoLock) lock1 = ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_SHARED, NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepoAutoLock) lock2 = ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_SHARED, NULL, &error); + g_assert_no_error (error); +} + int main (int argc, char **argv) @@ -212,7 +236,8 @@ main (int argc, test_repo_equal, teardown); g_test_add ("/repo/get_min_free_space", Fixture, NULL, setup, test_repo_get_min_free_space, teardown); - + g_test_add ("/repo/autolock", Fixture, NULL, setup, + test_repo_autolock, teardown); return g_test_run (); } diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh index 3072c2126..bad48620c 100755 --- a/tests/test-symbols.sh +++ b/tests/test-symbols.sh @@ -66,7 +66,7 @@ echo 'ok documented symbols' # ONLY update this checksum in release commits! cat > released-sha256.txt <