fsck: reduce stack footprint

The logic to mark all objects that are reachable from tips of refs were
implemented as a set of recursive functions.  In a repository with a deep
enough history, this can easily eat up all the available stack space.

Restructure the code to require less stackspace by using an object array
to keep track of the objects that still need to be processed.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Linus Torvalds 2008-12-10 19:44:37 -08:00 committed by Junio C Hamano
parent c74faea19e
commit 04d3975937

View File

@ -64,11 +64,11 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...)
return (type == FSCK_WARN) ? 0 : 1; return (type == FSCK_WARN) ? 0 : 1;
} }
static struct object_array pending;
static int mark_object(struct object *obj, int type, void *data) static int mark_object(struct object *obj, int type, void *data)
{ {
struct tree *tree = NULL;
struct object *parent = data; struct object *parent = data;
int result;
if (!obj) { if (!obj) {
printf("broken link from %7s %s\n", printf("broken link from %7s %s\n",
@ -96,6 +96,20 @@ static int mark_object(struct object *obj, int type, void *data)
return 1; return 1;
} }
add_object_array(obj, (void *) parent, &pending);
return 0;
}
static void mark_object_reachable(struct object *obj)
{
mark_object(obj, OBJ_ANY, 0);
}
static int traverse_one_object(struct object *obj, struct object *parent)
{
int result;
struct tree *tree = NULL;
if (obj->type == OBJ_TREE) { if (obj->type == OBJ_TREE) {
obj->parsed = 0; obj->parsed = 0;
tree = (struct tree *)obj; tree = (struct tree *)obj;
@ -107,15 +121,22 @@ static int mark_object(struct object *obj, int type, void *data)
free(tree->buffer); free(tree->buffer);
tree->buffer = NULL; tree->buffer = NULL;
} }
if (result < 0)
result = 1;
return result; return result;
} }
static void mark_object_reachable(struct object *obj) static int traverse_reachable(void)
{ {
mark_object(obj, OBJ_ANY, 0); int result = 0;
while (pending.nr) {
struct object_array_entry *entry;
struct object *obj, *parent;
entry = pending.objects + --pending.nr;
obj = entry->item;
parent = (struct object *) entry->name;
result |= traverse_one_object(obj, parent);
}
return !!result;
} }
static int mark_used(struct object *obj, int type, void *data) static int mark_used(struct object *obj, int type, void *data)
@ -233,6 +254,9 @@ static void check_connectivity(void)
{ {
int i, max; int i, max;
/* Traverse the pending reachable objects */
traverse_reachable();
/* Look up all the requirements, warn about missing objects.. */ /* Look up all the requirements, warn about missing objects.. */
max = get_max_object_index(); max = get_max_object_index();
if (verbose) if (verbose)