Skip to content

Commit

Permalink
ostree/prune: Calculate reachability under exclusive lock
Browse files Browse the repository at this point in the history
When we calculate the reachability set in `ostree prune`, we do this
without any locking. This means that between the time we build the set
and when we call `ostree_repo_prune_from_reachable`, new content
might've been added. This then causes us to immediately prune that
content since it's not in the now outdated set.

Fix this by calculating the set under an exclusive lock.

I think this is what happened in
fedora-silverblue/issue-tracker#405. While
the pruner was running, the `new-updates-sync` script[1] was importing
content into the repo. The newly imported commits were immediately
deleted by the many `ostree prune --commit-only` calls the pruner does,
breaking the refs.

[1] https://pagure.io/fedora-infra/ansible/blob/35b35127e444/f/roles/bodhi2/backend/files/new-updates-sync#_18
  • Loading branch information
jlebon committed Jan 30, 2023
1 parent af50533 commit fb63f7a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/ostree/ot-builtin-prune.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ ostree_builtin_prune (int argc, char **argv, OstreeCommandInvocation *invocation
}
else
{
/* In this branch, we need to compute the reachability set manually.
* While we do this, we can't let new content in since it'll race with
* reachability calculations and we may immediately nuke it. So push an
* exclusive lock now. */
g_autoptr(OstreeRepoAutoLock) lock =
ostree_repo_auto_lock_push (repo, OSTREE_REPO_LOCK_EXCLUSIVE, cancellable, error);
if (!lock)
return FALSE;

g_autoptr(GHashTable) all_refs = NULL;
g_autoptr(GHashTable) reachable = ostree_repo_traverse_new_reachable ();
g_autoptr(GHashTable) retain_branch_depth = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
Expand Down
12 changes: 12 additions & 0 deletions tests/test-prune.sh
Original file line number Diff line number Diff line change
Expand Up @@ -363,4 +363,16 @@ ${CMD_PREFIX} ostree --repo=repo prune --commit-only --keep-younger-than="1 week
assert_repo_has_n_commits repo 4
assert_repo_has_n_non_commit_objects repo ${orig_obj_count}
tap_ok --commit-only and --keep-younger-than

reinitialize_commit_only_test_repo
for i in {1..10}; do
${CMD_PREFIX} ostree --repo=repo prune --commit-only --keep-younger-than="1 week ago" &
commit=$(${CMD_PREFIX} ostree --repo=repo commit --branch foobar tree)
wait $!
if ! ostree show --repo=repo ${commit}; then
assert_not_reached "commit ${commit} on branch foobar was pruned?"
fi
done
tap_ok commit and prune together

tap_end

0 comments on commit fb63f7a

Please sign in to comment.