Skip to content

Commit d1bf1a0

Browse files
pks-tgitster
authored andcommitted
reftable/stack: handle outdated stacks when compacting
When we compact the reftable stack we first acquire the lock for the "tables.list" file and then reload the stack to check that it is still up-to-date. This is done by calling `stack_uptodate()`, which knows to return zero in case the stack is up-to-date, a positive value if it is not and a negative error code on unexpected conditions. We don't do proper error checking though, but instead we only check whether the returned error code is non-zero. If so, we simply bubble it up the calling stack, which means that callers may see an unexpected positive value. Fix this issue by translating to `REFTABLE_OUTDATED_ERROR` instead. Handle this situation in `reftable_addition_commit()`, where we perform a best-effort auto-compaction. All other callsites of `stack_uptodate()` know to handle a positive return value and thus don't need to be fixed. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1f70354 commit d1bf1a0

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

reftable/stack.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,11 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
579579
return err;
580580
}
581581

582-
/* -1 = error
583-
0 = up to date
584-
1 = changed. */
582+
/*
583+
* Check whether the given stack is up-to-date with what we have in memory.
584+
* Returns 0 if so, 1 if the stack is out-of-date or a negative error code
585+
* otherwise.
586+
*/
585587
static int stack_uptodate(struct reftable_stack *st)
586588
{
587589
char **names = NULL;
@@ -849,10 +851,13 @@ int reftable_addition_commit(struct reftable_addition *add)
849851
* control. It is possible that a concurrent writer is already
850852
* trying to compact parts of the stack, which would lead to a
851853
* `REFTABLE_LOCK_ERROR` because parts of the stack are locked
852-
* already. This is a benign error though, so we ignore it.
854+
* already. Similarly, the stack may have been rewritten by a
855+
* concurrent writer, which causes `REFTABLE_OUTDATED_ERROR`.
856+
* Both of these errors are benign, so we simply ignore them.
853857
*/
854858
err = reftable_stack_auto_compact(add->stack);
855-
if (err < 0 && err != REFTABLE_LOCK_ERROR)
859+
if (err < 0 && err != REFTABLE_LOCK_ERROR &&
860+
err != REFTABLE_OUTDATED_ERROR)
856861
goto done;
857862
err = 0;
858863
}
@@ -1215,9 +1220,24 @@ static int stack_compact_range(struct reftable_stack *st,
12151220
goto done;
12161221
}
12171222

1223+
/*
1224+
* Check whether the stack is up-to-date. We unfortunately cannot
1225+
* handle the situation gracefully in case it's _not_ up-to-date
1226+
* because the range of tables that the user has requested us to
1227+
* compact may have been changed. So instead we abort.
1228+
*
1229+
* We could in theory improve the situation by having the caller not
1230+
* pass in a range, but instead the list of tables to compact. If so,
1231+
* we could check that relevant tables still exist. But for now it's
1232+
* good enough to just abort.
1233+
*/
12181234
err = stack_uptodate(st);
1219-
if (err)
1235+
if (err < 0)
12201236
goto done;
1237+
if (err > 0) {
1238+
err = REFTABLE_OUTDATED_ERROR;
1239+
goto done;
1240+
}
12211241

12221242
/*
12231243
* Lock all tables in the user-provided range. This is the slice of our

0 commit comments

Comments
 (0)