diff options
| author | Brodie Rao <brodie@sf.io> | 2013-08-13 10:55:37 -0700 |
|---|---|---|
| committer | Brodie Rao <brodie@sf.io> | 2013-08-13 10:55:37 -0700 |
| commit | 9ccdb21155b3c9650acf58c55b2596c3503ea14d (patch) | |
| tree | ce304d88b61c99aaa8c73ff7894512882ac64174 /src | |
| parent | 14da618260be02c63b4f08dca8e6ab479f7449d7 (diff) | |
| download | libgit2-9ccdb21155b3c9650acf58c55b2596c3503ea14d.tar.gz | |
fileops: stat() before open()ing in git_futils_readbuffer_updated()
This reverts refactoring done in 13224ea4aad9a1b3c9cc4c992ceaea9af623e047
that introduces a performance regression for NFS when reading files that
don't exist. open() forces a cache invalidation on NFS, while stat()ing a
file just uses the cache and is very quick.
To give a specific example, say you have a repo with a thousand packed
refs. Before this change, looking up every single one ould incur a thousand
slow open() calls. With this change, it's a thousand fast stat() calls.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileops.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/src/fileops.c b/src/fileops.c index 7f8418d7a..e367ac244 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -147,6 +147,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) int git_futils_readbuffer_updated( git_buf *buf, const char *path, time_t *mtime, size_t *size, int *updated) { + int error = 0; git_file fd; struct stat st; bool changed = false; @@ -156,11 +157,15 @@ int git_futils_readbuffer_updated( if (updated != NULL) *updated = 0; - if ((fd = git_futils_open_ro(path)) < 0) - return fd; + if (p_stat(path, &st) < 0) { + error = errno; + giterr_set(GITERR_OS, "Failed to stat '%s'", path); + if (error == ENOENT || error == ENOTDIR) + return GIT_ENOTFOUND; + return -1; + } - if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { - p_close(fd); + if (S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); return -1; } @@ -177,7 +182,6 @@ int git_futils_readbuffer_updated( changed = true; if (!changed) { - p_close(fd); return 0; } @@ -186,6 +190,9 @@ int git_futils_readbuffer_updated( if (size != NULL) *size = (size_t)st.st_size; + if ((fd = git_futils_open_ro(path)) < 0) + return fd; + if (git_futils_readbuffer_fd(buf, fd, (size_t)st.st_size) < 0) { p_close(fd); return -1; |
