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

Re: [PATCH v2 9/9] reftable/stack: handle locked tables during auto-compaction

From
Karthik Nayak <karthik.188@gmail.com>
Date
Aug 8, 2024, 12:25 UTC
Message-ID
<CAOLa=ZSJXdH-C6VcWoFbPV6z7Rb1_TFx-6N=nseeNP320xubzA@mail.gmail.com>
In-Reply-To
<1ef560feb1906c160ad7c81a30e9bd4fc92d2eca.1722862822.git.ps@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
Show 24 quoted lines
> When compacting tables, it may happen that we want to compact a set of
> tables which are already locked by a concurrent process that compacts
> them. In the case where we wanted to perform a full compaction of all
> tables it is sensible to bail out in this case, as we cannot fulfill the
> requested action.
>
> But when performing auto-compaction it isn't necessarily in our best
> interest of us to abort the whole operation. For example, due to the
> geometric compacting schema that we use, it may be that process A takes
> a lot of time to compact the bulk of all tables whereas process B
> appends a bunch of new tables to the stack. B would in this case also
> notice that it has to compact the tables that process A is compacting
> already and thus also try to compact the same range, probably including
> the new tables it has appended. But because those tables are locked
> already, it will fail and thus abort the complete auto-compaction. The
> consequence is that the stack will grow longer and longer while A isn't
> yet done with compaction, which will lead to a growing performance
> impact.
>
> Instead of aborting auto-compaction altogether, let's gracefully handle
> this situation by instead compacting tables which aren't locked. To do
> so, instead of locking from the beginning of the slice-to-be-compacted,
> we start locking tables from the end of the slice. Once we hit the first
> table that is locked already, we abort. If we succeded to lock two or
s/succeded/succeeded
Show 8 quoted lines
> more tables, then we simply reduce the slice of tables that we're about
> to compact to those which we managed to lock.
>
> This ensures that we can at least make some progress for compaction in
> said scenario. It also helps in other scenarios, like for example when a
> process died and left a stale lockfile behind. In such a case we can at
> least ensure some compaction on a best-effort basis.
>
Right. This is really well written.
[snip]
Show 40 quoted lines
> @@ -1052,19 +1062,47 @@ static int stack_compact_range(struct reftable_stack *st,
>  	/*
>  	 * Lock all tables in the user-provided range. This is the slice of our
>  	 * stack which we'll compact.
> +	 *
> +	 * Note that we lock tables in reverse order from last to first. The
> +	 * intent behind this is to allow a newer process to perform best
> +	 * effort compaction of tables that it has added in the case where an
> +	 * older process is still busy compacting tables which are preexisting
> +	 * from the point of view of the newer process.
>  	 */
>  	REFTABLE_CALLOC_ARRAY(table_locks, last - first + 1);
> -	for (i = first; i <= last; i++) {
> -		stack_filename(&table_name, st, reader_name(st->readers[i]));
> +	for (i = last + 1; i > first; i--) {
> +		stack_filename(&table_name, st, reader_name(st->readers[i - 1]));
>
>  		err = hold_lock_file_for_update(&table_locks[nlocks],
>  						table_name.buf, LOCK_NO_DEREF);
>  		if (err < 0) {
> -			if (errno == EEXIST)
> +			/*
> +			 * When the table is locked already we may do a
> +			 * best-effort compaction and compact only the tables
> +			 * that we have managed to lock so far. This of course
> +			 * requires that we have been able to lock at least two
> +			 * tables, otherwise there would be nothing to compact.
> +			 * In that case, we return a lock error to our caller.
> +			 */
> +			if (errno == EEXIST && last - (i - 1) >= 2 &&
> +			    flags & STACK_COMPACT_RANGE_BEST_EFFORT) {
> +				err = 0;
> +				/*
> +				 * The subtraction is to offset the index, the
> +				 * addition is to only compact up to the table
> +				 * of the preceding iteration. They obviously
> +				 * cancel each other out, but that may be
> +				 * non-obvious when it was omitted.
> +				 */
> +				first = (i - 1) + 1;

I remember thinking about this and how to fix it, I'm happy how you've done it. It's simple and sufficient. Kudos.

[snip]

Overall this patch looked great. I have nothing to add, I really like it that we use a flag and this means this would only come into play for auto-compaction.

Previous: Justin ToblerNext: Karthik Nayak
Message 38 of 50 in “reftable: improvements and fixes for compaction”
  1. 0/8 reftable: improvements and fixes for compactionPatrick Steinhardt, Jul 31, 2024
  2. 1/8 reftable/stack: refactor function to gather table sizesPatrick Steinhardt, Jul 31, 2024
  3. Junio C HamanoAug 2, 2024
  4. 2/8 reftable/stack: test compaction with already-locked tablesPatrick Steinhardt, Jul 31, 2024
  5. Junio C HamanoAug 2, 2024
  6. Patrick SteinhardtAug 5, 2024
  7. 3/8 reftable/stack: update stats on failed full compactionPatrick Steinhardt, Jul 31, 2024
  8. 4/8 reftable/stack: simplify tracking of table locksPatrick Steinhardt, Jul 31, 2024
  9. Justin ToblerJul 31, 2024
  10. Junio C HamanoAug 2, 2024
  11. Patrick SteinhardtAug 5, 2024
  12. 5/8 reftable/stack: do not die when fsyncing lock file filesPatrick Steinhardt, Jul 31, 2024
  13. 6/8 reftable/stack: use lock_file when adding table to "tables.list"Patrick Steinhardt, Jul 31, 2024
  14. Justin ToblerJul 31, 2024
  15. Patrick SteinhardtAug 1, 2024
  16. 7/8 reftable/stack: fix corruption on concurrent compactionPatrick Steinhardt, Jul 31, 2024
  17. Justin ToblerAug 1, 2024
  18. Patrick SteinhardtAug 1, 2024
  19. 8/8 reftable/stack: handle locked tables during auto-compactionPatrick Steinhardt, Jul 31, 2024
  20. Junio C HamanoAug 2, 2024
  21. Patrick SteinhardtAug 5, 2024
  22. 0/9 reftable: improvements and fixes for compactionPatrick Steinhardt, Aug 5, 2024
  23. 1/9 reftable/stack: refactor function to gather table sizesPatrick Steinhardt, Aug 5, 2024
  24. 2/9 reftable/stack: extract function to setup stack with N tablesPatrick Steinhardt, Aug 5, 2024
  25. 3/9 reftable/stack: test compaction with already-locked tablesPatrick Steinhardt, Aug 5, 2024
  26. Karthik NayakAug 8, 2024
  27. 4/9 reftable/stack: update stats on failed full compactionPatrick Steinhardt, Aug 5, 2024
  28. 5/9 reftable/stack: simplify tracking of table locksPatrick Steinhardt, Aug 5, 2024
  29. 6/9 reftable/stack: do not die when fsyncing lock file filesPatrick Steinhardt, Aug 5, 2024
  30. 7/9 reftable/stack: use lock_file when adding table to "tables.list"Patrick Steinhardt, Aug 5, 2024
  31. 8/9 reftable/stack: fix corruption on concurrent compactionPatrick Steinhardt, Aug 5, 2024
  32. Karthik NayakAug 8, 2024
  33. Patrick SteinhardtAug 8, 2024
  34. 9/9 reftable/stack: handle locked tables during auto-compactionPatrick Steinhardt, Aug 5, 2024
  35. Justin ToblerAug 6, 2024
  36. Patrick SteinhardtAug 7, 2024
  37. Justin ToblerAug 7, 2024
  38. Karthik NayakAug 8, 2024
  39. Karthik NayakAug 8, 2024
  40. 0/9 reftable: improvements and fixes for compactionPatrick Steinhardt, Aug 8, 2024
  41. 1/9 reftable/stack: refactor function to gather table sizesPatrick Steinhardt, Aug 8, 2024
  42. 2/9 reftable/stack: extract function to setup stack with N tablesPatrick Steinhardt, Aug 8, 2024
  43. 3/9 reftable/stack: test compaction with already-locked tablesPatrick Steinhardt, Aug 8, 2024
  44. 4/9 reftable/stack: update stats on failed full compactionPatrick Steinhardt, Aug 8, 2024
  45. 5/9 reftable/stack: simplify tracking of table locksPatrick Steinhardt, Aug 8, 2024
  46. 6/9 reftable/stack: do not die when fsyncing lock file filesPatrick Steinhardt, Aug 8, 2024
  47. 7/9 reftable/stack: use lock_file when adding table to "tables.list"Patrick Steinhardt, Aug 8, 2024
  48. 8/9 reftable/stack: fix corruption on concurrent compactionPatrick Steinhardt, Aug 8, 2024
  49. 9/9 reftable/stack: handle locked tables during auto-compactionPatrick Steinhardt, Aug 8, 2024
  50. Karthik NayakAug 8, 2024

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.