Make pack creation always fsync() the result
This means that we can depend on packs always being stable on disk, simplifying a lot of the object serialization worries. And unlike loose objects, serializing pack creation IO isn't going to be a performance killer. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Linus Torvalds committed
May 30, 2008 at 08:42 UTC
4c81b03e30d13dbc93ea7071438ef2da0acd4189
8 files changed
+24
-6
builtin-pack-objects.c
+3
-1
@@ -515,10 +515,12 @@ static void write_pack_file(void)
515
* If so, rewrite it like in fast-import
516
*/
517
if (pack_to_stdout || nr_written == nr_remaining) {
518
- sha1close(f, sha1, 1);
518
+ unsigned flags = pack_to_stdout ? CSUM_CLOSE : CSUM_FSYNC;
519
+ sha1close(f, sha1, flags);
520
} else {
521
int fd = sha1close(f, NULL, 0);
522
fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written);
523
+ fsync_or_die(fd, pack_tmp_name);
524
close(fd);
525
}
526
cache.h
+1
@@ -761,6 +761,7 @@ extern ssize_t write_in_full(int fd, const void *buf, size_t count);
761
extern void write_or_die(int fd, const void *buf, size_t count);
762
extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
763
extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
764
+extern void fsync_or_die(int fd, const char *);
765
766
/* pager.c */
767
extern void setup_pager(void);
csum-file.c
+5
-2
@@ -32,21 +32,24 @@ static void sha1flush(struct sha1file *f, unsigned int count)
32
}
33
}
34
35
-int sha1close(struct sha1file *f, unsigned char *result, int final)
35
+int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
36
{
37
int fd;
38
unsigned offset = f->offset;
39
+
40
if (offset) {
41
SHA1_Update(&f->ctx, f->buffer, offset);
42
sha1flush(f, offset);
43
f->offset = 0;
44
}
44
- if (final) {
45
+ if (flags & (CSUM_CLOSE | CSUM_FSYNC)) {
46
/* write checksum and close fd */
47
SHA1_Final(f->buffer, &f->ctx);
48
if (result)
49
hashcpy(result, f->buffer);
50
sha1flush(f, 20);
51
+ if (flags & CSUM_FSYNC)
52
+ fsync_or_die(f->fd, f->name);
53
if (close(f->fd))
54
die("%s: sha1 file error on close (%s)",
55
f->name, strerror(errno));
csum-file.h
+5
-1
@@ -16,9 +16,13 @@ struct sha1file {
16
unsigned char buffer[8192];
17
};
18
19
+/* sha1close flags */
20
+#define CSUM_CLOSE 1
21
+#define CSUM_FSYNC 2
22
+
23
extern struct sha1file *sha1fd(int fd, const char *name);
24
extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
21
-extern int sha1close(struct sha1file *, unsigned char *, int);
25
+extern int sha1close(struct sha1file *, unsigned char *, unsigned int);
26
extern int sha1write(struct sha1file *, void *, unsigned int);
27
extern void crc32_begin(struct sha1file *);
28
extern uint32_t crc32_end(struct sha1file *);
fast-import.c
+1
-1
@@ -890,7 +890,7 @@ static char *create_index(void)
890
SHA1_Update(&ctx, (*c)->sha1, 20);
891
}
892
sha1write(f, pack_data->sha1, sizeof(pack_data->sha1));
893
- sha1close(f, NULL, 1);
893
+ sha1close(f, NULL, CSUM_FSYNC);
894
free(idx);
895
SHA1_Final(pack_data->sha1, &ctx);
896
return tmpfile;
index-pack.c
+1
@@ -694,6 +694,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
694
if (!from_stdin) {
695
close(input_fd);
696
} else {
697
+ fsync_or_die(output_fd, curr_pack_name);
698
err = close(output_fd);
699
if (err)
700
die("error while closing pack file: %s", strerror(errno));
pack-write.c
+1
-1
@@ -139,7 +139,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects,
139
}
140
141
sha1write(f, sha1, 20);
142
- sha1close(f, NULL, 1);
142
+ sha1close(f, NULL, CSUM_FSYNC);
143
SHA1_Final(sha1, &ctx);
144
return index_name;
145
}
write_or_die.c
+7
@@ -78,6 +78,13 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
78
return total;
79
}
80
81
+void fsync_or_die(int fd, const char *msg)
82
+{
83
+ if (fsync(fd) < 0) {
84
+ die("%s: fsync error (%s)", msg, strerror(errno));
85
+ }
86
+}
87
+
88
void write_or_die(int fd, const void *buf, size_t count)
89
{
90
if (write_in_full(fd, buf, count) < 0) {