summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2008-10-09 22:08:51 -0400
committerShawn O. Pearce <spearce@spearce.org>2008-10-10 07:09:30 -0700
commit838cd34664422863096f1a089f779bed1f00edf6 (patch)
treebe36986d2f3b6e64e0770f4fc5045b3390cfeec9
parent44c33a5b9603fba7c9556512a72e4e392ba4ae2d (diff)
downloadgit-838cd34664422863096f1a089f779bed1f00edf6.tar.gz
fix pread()'s short read in index-pack
Since v1.6.0.2~13^2~ the completion of a thin pack uses sha1write() for its ability to compute a SHA1 on the written data. This also provides data buffering which, along with commit 92392b4a45, will confuse pread() whenever an appended object is 1) freed due to memory pressure because of the depth-first delta processing, and 2) needed again because it has many delta children, and 3) its data is still buffered by sha1write(). Let's fix the issue by simply forcing cached data out when such an object is written so it can be pread()'d at leisure. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--csum-file.c18
-rw-r--r--csum-file.h1
-rw-r--r--index-pack.c1
3 files changed, 14 insertions, 6 deletions
diff --git a/csum-file.c b/csum-file.c
index 28389541a3..cfc1ac42b9 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -11,7 +11,7 @@
#include "progress.h"
#include "csum-file.h"
-static void sha1flush(struct sha1file *f, unsigned int count)
+static void flush(struct sha1file *f, unsigned int count)
{
void *buf = f->buffer;
@@ -32,22 +32,28 @@ static void sha1flush(struct sha1file *f, unsigned int count)
}
}
-int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
+void sha1flush(struct sha1file *f)
{
- int fd;
unsigned offset = f->offset;
if (offset) {
SHA1_Update(&f->ctx, f->buffer, offset);
- sha1flush(f, offset);
+ flush(f, offset);
f->offset = 0;
}
+}
+
+int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
+{
+ int fd;
+
+ sha1flush(f);
SHA1_Final(f->buffer, &f->ctx);
if (result)
hashcpy(result, f->buffer);
if (flags & (CSUM_CLOSE | CSUM_FSYNC)) {
/* write checksum and close fd */
- sha1flush(f, 20);
+ flush(f, 20);
if (flags & CSUM_FSYNC)
fsync_or_die(f->fd, f->name);
if (close(f->fd))
@@ -76,7 +82,7 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count)
left -= nr;
if (!left) {
SHA1_Update(&f->ctx, f->buffer, offset);
- sha1flush(f, offset);
+ flush(f, offset);
offset = 0;
}
f->offset = offset;
diff --git a/csum-file.h b/csum-file.h
index 72c9487f4f..01f13b5501 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -24,6 +24,7 @@ extern struct sha1file *sha1fd(int fd, const char *name);
extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
extern int sha1close(struct sha1file *, unsigned char *, unsigned int);
extern int sha1write(struct sha1file *, void *, unsigned int);
+extern void sha1flush(struct sha1file *f);
extern void crc32_begin(struct sha1file *);
extern uint32_t crc32_end(struct sha1file *);
diff --git a/index-pack.c b/index-pack.c
index c45ae20e8f..2a366206a4 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -707,6 +707,7 @@ static struct object_entry *append_obj_to_pack(struct sha1file *f,
obj[1].idx.offset = obj[0].idx.offset + n;
obj[1].idx.offset += write_compressed(f, buf, size);
obj[0].idx.crc32 = crc32_end(f);
+ sha1flush(f);
hashcpy(obj->idx.sha1, sha1);
return obj;
}