@matheusbsbs / matheus-bagliano / commits / 04d3975937
Fork 0

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>

Linus Torvalds committed Dec 10, 2008 at 19:44 UTC 04d39759373e5de017e7c17ef4b762ac5ad3afcc
1 file changed +31 -7
builtin-fsck.c
+31 -7
@@ -64,11 +64,11 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...)
64 return (type == FSCK_WARN) ? 0 : 1;
65 }
66
67 +static struct object_array pending;
68 +
69 static int mark_object(struct object *obj, int type, void *data)
70 {
69 - struct tree *tree = NULL;
71 struct object *parent = data;
71 - int result;
72
73 if (!obj) {
74 printf("broken link from %7s %s\n",
@@ -96,6 +96,20 @@ static int mark_object(struct object *obj, int type, void *data)
96 return 1;
97 }
98
99 + add_object_array(obj, (void *) parent, &pending);
100 + return 0;
101 +}
102 +
103 +static void mark_object_reachable(struct object *obj)
104 +{
105 + mark_object(obj, OBJ_ANY, 0);
106 +}
107 +
108 +static int traverse_one_object(struct object *obj, struct object *parent)
109 +{
110 + int result;
111 + struct tree *tree = NULL;
112 +
113 if (obj->type == OBJ_TREE) {
114 obj->parsed = 0;
115 tree = (struct tree *)obj;
@@ -107,15 +121,22 @@ static int mark_object(struct object *obj, int type, void *data)
121 free(tree->buffer);
122 tree->buffer = NULL;
123 }
110 - if (result < 0)
111 - result = 1;
112 -
124 return result;
125 }
126
116 -static void mark_object_reachable(struct object *obj)
127 +static int traverse_reachable(void)
128 {
118 - mark_object(obj, OBJ_ANY, 0);
129 + int result = 0;
130 + while (pending.nr) {
131 + struct object_array_entry *entry;
132 + struct object *obj, *parent;
133 +
134 + entry = pending.objects + --pending.nr;
135 + obj = entry->item;
136 + parent = (struct object *) entry->name;
137 + result |= traverse_one_object(obj, parent);
138 + }
139 + return !!result;
140 }
141
142 static int mark_used(struct object *obj, int type, void *data)
@@ -233,6 +254,9 @@ static void check_connectivity(void)
254 {
255 int i, max;
256
257 + /* Traverse the pending reachable objects */
258 + traverse_reachable();
259 +
260 /* Look up all the requirements, warn about missing objects.. */
261 max = get_max_object_index();
262 if (verbose)