git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 8/8] refs/reftable: always reload stacks when creating lock

From
Patrick Steinhardt <ps@pks.im>
Date
Aug 12, 2025, 09:54 UTC
Message-ID
<20250812-pks-reftable-fixes-for-libgit2-v3-8-cf3b2267867e@pks.im>
In-Reply-To
<20250812-pks-reftable-fixes-for-libgit2-v3-0-cf3b2267867e@pks.im>

When creating a new addition via either `reftable_stack_new_addition()` or its convenince wrapper `reftable_stack_add()` we:

  1. Create the "tables.list.lock" file.
  2. Verify that the current version of the "tables.list" file is
     up-to-date.
  3. Write the new table records if so.

By default, the second step would cause us to bail out if we see that there has been a concurrent write to the stack that made our in-memory copy of the stack out-of-date. This is a safety mechanism to not write records to the stack based on outdated information.

The downside though is that concurrent writes may now cause us to bail out, which is not a good user experience. In addition, this isn't even necessary for us, as Git knows to perform all checks for the old state of references under the lock. (Well, in all except one case: when we expire the reflog we first create the log iterator before we create the lock, but this ordering is fixed as part of this commit.)

Consequently, most writers pass the `REFTABLE_STACK_NEW_ADDITION_RELOAD` flag. The effect of this flag is that we reload the stack after having acquired the lock in case the stack is out-of-date. This plugs the race with concurrent writers, but we continue performing the verifications of the expected old state to catch actual conflicts in the references we are about to write.

Adapt the remaining callsites that don't yet pass this flag to do so. While at it, drop a needless manual reload.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs/reftable-backend.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 3f0deab338..66d25411f1 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1006,10 +1006,6 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out,
 	if (!arg) {
 		struct reftable_addition *addition;
 
-		ret = reftable_stack_reload(be->stack);
-		if (ret)
-			return ret;
-
 		ret = reftable_stack_new_addition(&addition, be->stack,
 						  REFTABLE_STACK_NEW_ADDITION_RELOAD);
 		if (ret) {
@@ -1960,7 +1956,8 @@ static int reftable_be_rename_ref(struct ref_store *ref_store,
 	ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
 	if (ret)
 		goto done;
-	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg, 0);
+	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 done:
 	assert(ret != REFTABLE_API_ERROR);
@@ -1989,7 +1986,8 @@ static int reftable_be_copy_ref(struct ref_store *ref_store,
 	ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
 	if (ret)
 		goto done;
-	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg, 0);
+	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 done:
 	assert(ret != REFTABLE_API_ERROR);
@@ -2360,7 +2358,8 @@ static int reftable_be_create_reflog(struct ref_store *ref_store,
 		goto done;
 	arg.stack = be->stack;
 
-	ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg, 0);
+	ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 done:
 	return ret;
@@ -2431,7 +2430,8 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
 		return ret;
 	arg.stack = be->stack;
 
-	ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg, 0);
+	ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg,
+				 REFTABLE_STACK_NEW_ADDITION_RELOAD);
 
 	assert(ret != REFTABLE_API_ERROR);
 	return ret;
@@ -2552,15 +2552,16 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
 	if (ret < 0)
 		goto done;
 
-	ret = reftable_stack_init_log_iterator(be->stack, &it);
+	ret = reftable_stack_new_addition(&add, be->stack,
+					  REFTABLE_STACK_NEW_ADDITION_RELOAD);
 	if (ret < 0)
 		goto done;
 
-	ret = reftable_iterator_seek_log(&it, refname);
+	ret = reftable_stack_init_log_iterator(be->stack, &it);
 	if (ret < 0)
 		goto done;
 
-	ret = reftable_stack_new_addition(&add, be->stack, 0);
+	ret = reftable_iterator_seek_log(&it, refname);
 	if (ret < 0)
 		goto done;
 
-- 
2.51.0.rc1.163.g2494970778.dirty
Previous: Justin ToblerNext: Justin Tobler
Message 38 of 52 in “reftable: a couple of improvements for libgit2”
  1. 0/5 reftable: a couple of improvements for libgit2Patrick Steinhardt, Aug 1, 2025
  2. 1/5 reftable/writer: fix type used for number of recordsPatrick Steinhardt, Aug 1, 2025
  3. 2/5 reftable/writer: drop Git-specific `QSORT()` macroPatrick Steinhardt, Aug 1, 2025
  4. 3/5 reftable/stack: fix compiler warning due to missing bracesPatrick Steinhardt, Aug 1, 2025
  5. Eric SunshineAug 1, 2025
  6. Patrick SteinhardtAug 4, 2025
  7. Junio C HamanoAug 4, 2025
  8. Patrick SteinhardtAug 5, 2025
  9. Carlo ArenasAug 12, 2025
  10. Patrick SteinhardtAug 12, 2025
  11. Junio C HamanoAug 12, 2025
  12. 4/5 reftable/stack: reorder code to avoid forward declarationsPatrick Steinhardt, Aug 1, 2025
  13. 5/5 reftable/stack: allow passing flags to `reftable_stack_add()`Patrick Steinhardt, Aug 1, 2025
  14. 0/6 reftable: a couple of improvements for libgit2Patrick Steinhardt, Aug 4, 2025
  15. 1/6 reftable/writer: fix type used for number of recordsPatrick Steinhardt, Aug 4, 2025
  16. 2/6 reftable/writer: drop Git-specific `QSORT()` macroPatrick Steinhardt, Aug 4, 2025
  17. 3/6 reftable/stack: fix compiler warning due to missing bracesPatrick Steinhardt, Aug 4, 2025
  18. 4/6 reftable/stack: reorder code to avoid forward declarationsPatrick Steinhardt, Aug 4, 2025
  19. Justin ToblerAug 11, 2025
  20. 5/6 reftable/stack: allow passing flags to `reftable_stack_add()`Patrick Steinhardt, Aug 4, 2025
  21. Justin ToblerAug 11, 2025
  22. Patrick SteinhardtAug 12, 2025
  23. 6/6 reftable/stack: handle outdated stacks when compactingPatrick Steinhardt, Aug 4, 2025
  24. Justin ToblerAug 11, 2025
  25. Patrick SteinhardtAug 12, 2025
  26. 0/8 reftable: a couple of improvements for libgit2Patrick Steinhardt, Aug 12, 2025
  27. 1/8 reftable/writer: fix type used for number of recordsPatrick Steinhardt, Aug 12, 2025
  28. 2/8 reftable/writer: drop Git-specific `QSORT()` macroPatrick Steinhardt, Aug 12, 2025
  29. 3/8 reftable/stack: reorder code to avoid forward declarationsPatrick Steinhardt, Aug 12, 2025
  30. 4/8 reftable/stack: fix compiler warning due to missing bracesPatrick Steinhardt, Aug 12, 2025
  31. Justin ToblerAug 12, 2025
  32. 5/8 reftable/stack: allow passing flags to `reftable_stack_add()`Patrick Steinhardt, Aug 12, 2025
  33. Justin ToblerAug 12, 2025
  34. Patrick SteinhardtAug 13, 2025
  35. 6/8 reftable/stack: handle outdated stacks when compactingPatrick Steinhardt, Aug 12, 2025
  36. 7/8 reftable: don't second-guess errors from flock interfacePatrick Steinhardt, Aug 12, 2025
  37. Justin ToblerAug 12, 2025
  38. 8/8 refs/reftable: always reload stacks when creating lockPatrick Steinhardt, Aug 12, 2025
  39. Justin ToblerAug 12, 2025
  40. Carlo ArenasAug 12, 2025
  41. Patrick SteinhardtAug 13, 2025
  42. Junio C HamanoAug 13, 2025
  43. 0/8 reftable: a couple of improvements for libgit2Patrick Steinhardt, Aug 13, 2025
  44. 1/8 reftable/writer: fix type used for number of recordsPatrick Steinhardt, Aug 13, 2025
  45. 2/8 reftable/writer: drop Git-specific `QSORT()` macroPatrick Steinhardt, Aug 13, 2025
  46. 3/8 reftable/stack: reorder code to avoid forward declarationsPatrick Steinhardt, Aug 13, 2025
  47. 4/8 reftable/stack: fix compiler warning due to missing bracesPatrick Steinhardt, Aug 13, 2025
  48. 5/8 reftable/stack: allow passing flags to `reftable_stack_add()`Patrick Steinhardt, Aug 13, 2025
  49. 6/8 reftable/stack: handle outdated stacks when compactingPatrick Steinhardt, Aug 13, 2025
  50. 7/8 reftable: don't second-guess errors from flock interfacePatrick Steinhardt, Aug 13, 2025
  51. 8/8 refs/reftable: always reload stacks when creating lockPatrick Steinhardt, Aug 13, 2025
  52. Justin ToblerAug 13, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.