Skip to content

Commit de0db42

Browse files
committed
Merge branch 'maint'
* maint: fsck: reduce stack footprint make sure packs to be replaced are closed beforehand
2 parents 07e62b7 + 04d3975 commit de0db42

File tree

4 files changed

+64
-7
lines changed

4 files changed

+64
-7
lines changed

builtin-fsck.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...)
6464
return (type == FSCK_WARN) ? 0 : 1;
6565
}
6666

67+
static struct object_array pending;
68+
6769
static int mark_object(struct object *obj, int type, void *data)
6870
{
69-
struct tree *tree = NULL;
7071
struct object *parent = data;
71-
int result;
7272

7373
if (!obj) {
7474
printf("broken link from %7s %s\n",
@@ -96,6 +96,20 @@ static int mark_object(struct object *obj, int type, void *data)
9696
return 1;
9797
}
9898

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+
99113
if (obj->type == OBJ_TREE) {
100114
obj->parsed = 0;
101115
tree = (struct tree *)obj;
@@ -107,15 +121,22 @@ static int mark_object(struct object *obj, int type, void *data)
107121
free(tree->buffer);
108122
tree->buffer = NULL;
109123
}
110-
if (result < 0)
111-
result = 1;
112-
113124
return result;
114125
}
115126

116-
static void mark_object_reachable(struct object *obj)
127+
static int traverse_reachable(void)
117128
{
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;
119140
}
120141

121142
static int mark_used(struct object *obj, int type, void *data)
@@ -237,6 +258,9 @@ static void check_connectivity(void)
237258
{
238259
int i, max;
239260

261+
/* Traverse the pending reachable objects */
262+
traverse_reachable();
263+
240264
/* Look up all the requirements, warn about missing objects.. */
241265
max = get_max_object_index();
242266
if (verbose)

builtin-pack-objects.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ static void write_pack_file(void)
535535

536536
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
537537
base_name, sha1_to_hex(sha1));
538+
free_pack_by_name(tmpname);
538539
if (adjust_perm(pack_tmp_name, mode))
539540
die("unable to make temporary pack file readable: %s",
540541
strerror(errno));

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ extern int open_pack_index(struct packed_git *);
820820
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
821821
extern void close_pack_windows(struct packed_git *);
822822
extern void unuse_pack(struct pack_window **);
823+
extern void free_pack_by_name(const char *);
823824
extern struct packed_git *add_packed_git(const char *, int, int);
824825
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
825826
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);

sha1_file.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,37 @@ void unuse_pack(struct pack_window **w_cursor)
672672
}
673673
}
674674

675+
/*
676+
* This is used by git-repack in case a newly created pack happens to
677+
* contain the same set of objects as an existing one. In that case
678+
* the resulting file might be different even if its name would be the
679+
* same. It is best to close any reference to the old pack before it is
680+
* replaced on disk. Of course no index pointers nor windows for given pack
681+
* must subsist at this point. If ever objects from this pack are requested
682+
* again, the new version of the pack will be reinitialized through
683+
* reprepare_packed_git().
684+
*/
685+
void free_pack_by_name(const char *pack_name)
686+
{
687+
struct packed_git *p, **pp = &packed_git;
688+
689+
while (*pp) {
690+
p = *pp;
691+
if (strcmp(pack_name, p->pack_name) == 0) {
692+
close_pack_windows(p);
693+
if (p->pack_fd != -1)
694+
close(p->pack_fd);
695+
if (p->index_data)
696+
munmap((void *)p->index_data, p->index_size);
697+
free(p->bad_object_sha1);
698+
*pp = p->next;
699+
free(p);
700+
return;
701+
}
702+
pp = &p->next;
703+
}
704+
}
705+
675706
/*
676707
* Do not call this directly as this leaks p->pack_fd on error return;
677708
* call open_packed_git() instead.

0 commit comments

Comments
 (0)