Re: [PATCH 08/11] builtin/maintenance: let tasks do maintenance before and after detach

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> Le 27 mai 2025 à 10:05, Patrick Steinhardt <ps@xxxxxx> a écrit :
> 
> Both git-gc(1) and git-maintenance(1) have logic to daemonize so that
> the maintenance tasks are performed in the background. git-gc(1) has
> some special logic though to not perform _all_ housekeeping tasks in the
> background: both references and reflogs are still handled synchronously
> ni the foreground.
> 
> This split exists because otherwise it may easily happen that git-gc(1)
> keeps for the "packed-refs" file locked for an extended amount of time,
> where the next Git command that wants to modify any reference could now
> fail. This was especially important in the past, where git-gc(1) was
> still executed directly as part of our automatic maintenance: git-gc(1)
> was invoked via `git gc --auto --detach`, so we knew to handle most of
> the maintenance tasks in the background while doing those parts that may
> cause locking issues in the foreground.
> 
> We have since moved to git-maintenance(1), which is a more flexible
> replacement for git-gc(1). By default this command runs git-gc(1), only,
> but it can be configured to run different tasks, as well. This command
> does not know about the split between maintenance tasks that should run
> before and after detach though, and this has led to several bug reports
> about spurious locking errors for the "packed-refs" file.
> 
> Prepare for a fix by introducing this split for maintenance tasks. Note
> that this commit does not yet change any of the tasks, so there should
> not (yet) be a change in behaviour.
> 
> Signed-off-by: Patrick Steinhardt <ps@xxxxxx>
> ---
> builtin/gc.c | 40 +++++++++++++++++++++++++---------------
> 1 file changed, 25 insertions(+), 15 deletions(-)
> 
> diff --git a/builtin/gc.c b/builtin/gc.c
> index 447e5800846..57f3bbf5344 100644
> --- a/builtin/gc.c
> +++ b/builtin/gc.c
> @@ -1545,53 +1545,54 @@ typedef int (*maintenance_auto_fn)(struct gc_config *cfg);
> 
> struct maintenance_task {
>   const char *name;
> -    maintenance_task_fn fn;
> +    maintenance_task_fn before_detach;
> +    maintenance_task_fn after_detach;
>   maintenance_auto_fn auto_condition;
> };
> 
> static const struct maintenance_task tasks[] = {
>   [TASK_PREFETCH] = {
>       .name = "prefetch",
> -        .fn = maintenance_task_prefetch,
> +        .after_detach = maintenance_task_prefetch,
>   },
>   [TASK_LOOSE_OBJECTS] = {
>       .name = "loose-objects",
> -        .fn = maintenance_task_loose_objects,
> +        .after_detach = maintenance_task_loose_objects,
>       .auto_condition = loose_object_auto_condition,
>   },
>   [TASK_INCREMENTAL_REPACK] = {
>       .name = "incremental-repack",
> -        .fn = maintenance_task_incremental_repack,
> +        .after_detach = maintenance_task_incremental_repack,
>       .auto_condition = incremental_repack_auto_condition,
>   },
>   [TASK_GC] = {
>       .name = "gc",
> -        .fn = maintenance_task_gc,
> +        .after_detach = maintenance_task_gc,
>       .auto_condition = need_to_gc,
>   },
>   [TASK_COMMIT_GRAPH] = {
>       .name = "commit-graph",
> -        .fn = maintenance_task_commit_graph,
> +        .after_detach = maintenance_task_commit_graph,
>       .auto_condition = should_write_commit_graph,
>   },
>   [TASK_PACK_REFS] = {
>       .name = "pack-refs",
> -        .fn = maintenance_task_pack_refs,
> +        .after_detach = maintenance_task_pack_refs,
>       .auto_condition = pack_refs_condition,
>   },
>   [TASK_REFLOG_EXPIRE] = {
>       .name = "reflog-expire",
> -        .fn = maintenance_task_reflog_expire,
> +        .after_detach = maintenance_task_reflog_expire,
>       .auto_condition = reflog_expire_condition,
>   },
>   [TASK_WORKTREE_PRUNE] = {
>       .name = "worktree-prune",
> -        .fn = maintenance_task_worktree_prune,
> +        .after_detach = maintenance_task_worktree_prune,
>       .auto_condition = worktree_prune_condition,
>   },
>   [TASK_RERERE_GC] = {
>       .name = "rerere-gc",
> -        .fn = maintenance_task_rerere_gc,
> +        .after_detach = maintenance_task_rerere_gc,
>       .auto_condition = rerere_gc_condition,
>   },
> };
> @@ -1599,20 +1600,25 @@ static const struct maintenance_task tasks[] = {
> static int maybe_run_task(const struct maintenance_task *task,
>             struct repository *repo,
>             struct maintenance_run_opts *opts,
> -              struct gc_config *cfg)
> +              struct gc_config *cfg,
> +              int before)

Perhaps we can use a small enum…

> {
> +    maintenance_task_fn fn = before ? task->before_detach : task->after_detach;
> +    const char *region = before ? "maintenance before" : "maintenance";
>   int ret = 0;
> 
> +    if (!fn)
> +        return 0;
>   if (opts->auto_flag &&
>       (!task->auto_condition || !task->auto_condition(cfg)))
>       return 0;
> 
> -    trace2_region_enter("maintenance", task->name, repo);
> -    if (task->fn(opts, cfg)) {
> +    trace2_region_enter(region, task->name, repo);
> +    if (fn(opts, cfg)) {
>       error(_("task '%s' failed"), task->name);
>       ret = 1;
>   }
> -    trace2_region_leave("maintenance", task->name, repo);
> +    trace2_region_leave(region, task->name, repo);
> 
>   return ret;
> }
> @@ -1641,6 +1647,10 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
>   }
>   free(lock_path);
> 
> +    for (size_t i = 0; i < opts->tasks_nr; i++)
> +        if (maybe_run_task(&tasks[opts->tasks[i]], r, opts, cfg, 1))

So that is clear what « 1 » (« BEFORE ») does here…

> +            result = 1;
> +
>   /* Failure to daemonize is ok, we'll continue in foreground. */
>   if (opts->detach > 0) {
>       trace2_region_enter("maintenance", "detach", the_repository);
> @@ -1649,7 +1659,7 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
>   }
> 
>   for (size_t i = 0; i < opts->tasks_nr; i++)
> -        if (maybe_run_task(&tasks[opts->tasks[i]], r, opts, cfg))
> +        if (maybe_run_task(&tasks[opts->tasks[i]], r, opts, cfg, 0))

And « 0 » (« AFTER ») does here?

>           result = 1;
> 
>   rollback_lock_file(&lk);
> 
> --
> 2.49.0.1266.g31b7d2e469.dirty





[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux