diff options
author | Edward Thomson <ethomson@github.com> | 2017-01-21 23:55:21 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-21 23:55:21 +0000 |
commit | 048c5ea7c084508358bc49e7f8131ebd6250a756 (patch) | |
tree | 4ed69758fc9b4306a81693a7ff95846a02008444 | |
parent | 8d3b39a6ad325fe1d08e17281803e26359756fc6 (diff) | |
parent | c7a1535f3202ccc38bbdf9e5084c1d6e589e2dd0 (diff) | |
download | libgit2-048c5ea7c084508358bc49e7f8131ebd6250a756.tar.gz |
Merge pull request #4053 from chescock/extend-packfile-by-pages
Extend packfile in increments of page_size.
-rw-r--r-- | src/indexer.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/indexer.c b/src/indexer.c index 951d7179c..606de2ef6 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -483,13 +483,29 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t static int append_to_pack(git_indexer *idx, const void *data, size_t size) { + git_off_t new_size; + size_t mmap_alignment; + size_t page_offset; + git_off_t page_start; git_off_t current_size = idx->pack->mwf.size; int fd = idx->pack->mwf.fd; + int error; if (!size) return 0; - if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 || + if ((error = git__mmap_alignment(&mmap_alignment)) < 0) + return error; + + /* Write a single byte to force the file system to allocate space now or + * report an error, since we can't report errors when writing using mmap. + * Round the size up to the nearest page so that we only need to perform file + * I/O when we add a page, instead of whenever we write even a single byte. */ + new_size = current_size + size; + page_offset = new_size % mmap_alignment; + page_start = new_size - page_offset; + + if (p_lseek(fd, page_start + mmap_alignment - 1, SEEK_SET) < 0 || p_write(idx->pack->mwf.fd, data, 1) < 0) { giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name); return -1; @@ -1047,6 +1063,13 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) goto on_error; git_mwindow_free_all(&idx->pack->mwf); + + /* Truncate file to undo rounding up to next page_size in append_to_pack */ + if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) { + giterr_set(GITERR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name); + return -1; + } + /* We need to close the descriptor here so Windows doesn't choke on commit_at */ if (p_close(idx->pack->mwf.fd) < 0) { giterr_set(GITERR_OS, "failed to close packfile"); |