Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ IF (HAVE_FUTIMENS)
SET(GIT_USE_FUTIMENS 1)
ENDIF ()

CHECK_SYMBOL_EXISTS(posix_fallocate fcntl.h HAVE_POSIX_FALLOCATE)
CHECK_SYMBOL_EXISTS(fallocate fcntl.h HAVE_FALLOCATE)
CHECK_C_SOURCE_COMPILES(
"#include <fcntl.h>
int main(void) { return F_PREALLOCATE; }"
HAVE_F_PREALLOCATE)
CHECK_C_SOURCE_COMPILES(
"#include <fcntl.h>
int main(void) { return F_ALLOCSP64; }"
HAVE_F_ALLOCSP64)
IF(HAVE_F_PREALLOCATE)
# APPLE OR FREEBSD OR NETBSD
SET(GIT_USE_FALLOCATE_BSD 1)
ELSEIF(HAVE_F_ALLOCSP64)
SET(GIT_USE_FALLOCATE_SOLARIS 1)
ELSEIF(HAVE_FALLOCATE)
SET(GIT_USE_FALLOCATE 1)
ELSEIF (HAVE_POSIX_FALLOCATE)
SET(GIT_USE_FALLOCATE_POSIX 1)
ENDIF ()

CHECK_PROTOTYPE_DEFINITION(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" HAVE_QSORT_R_BSD)
Expand Down
4 changes: 4 additions & 0 deletions src/features.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#cmakedefine GIT_USE_STAT_MTIMESPEC 1
#cmakedefine GIT_USE_STAT_MTIME_NSEC 1
#cmakedefine GIT_USE_FUTIMENS 1
#cmakedefine GIT_USE_FALLOCATE 1
#cmakedefine GIT_USE_FALLOCATE_BSD 1
#cmakedefine GIT_USE_FALLOCATE_POSIX 1
#cmakedefine GIT_USE_FALLOCATE_SOLARIS 1

#cmakedefine GIT_REGEX_REGCOMP_L
#cmakedefine GIT_REGEX_REGCOMP
Expand Down
62 changes: 54 additions & 8 deletions src/posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,30 @@ int p_rename(const char *from, const char *to)

int p_fallocate(int fd, off_t offset, off_t len)
{
#if defined (__APPLE__) || (defined (__NetBSD__) && __NetBSD_Version__ < 700000000)
int error = 0, cur;
char buf[BUFSIZ];
off_t pos = 0;

#if defined(GIT_USE_FALLOCATE_POSIX)
if ((error = posix_fallocate(fd, offset, len)) < 0)
if (errno == ENOTSUP)
goto fallback;
#elif defined(GIT_USE_FALLOCATE_SOLARIS)
struct flock64 fl;

fl.l_whence = SEEK_SET;
fl.l_start = offset;
fl.l_len = len;

if ((error = fcntl(fd, F_ALLOCSP64, &fl)) < 0)
goto fallback;
#elif defined(GIT_USE_FALLOCATE_BSD)
fstore_t prealloc;
struct stat st;
size_t newsize;
int error;

if ((error = p_fstat(fd, &st)) < 0)
return error;
return -1;

if (git__add_sizet_overflow(&newsize, offset, len)) {
errno = EINVAL;
Expand All @@ -182,15 +198,45 @@ int p_fallocate(int fd, off_t offset, off_t len)

/*
* fcntl will often error when the file already exists; ignore
* this error since ftruncate will also resize the file (although
* this error since our fallback will also resize the file (although
* likely slower).
*/
fcntl(fd, F_PREALLOCATE, &prealloc);

return ftruncate(fd, (offset + len));
if ((error = fcntl(fd, F_PREALLOCATE, &prealloc)) < 0)
goto fallback;
#elif defined(GIT_USE_FALLOCATE)
do {
error = fallocate(fd, 0, offset, len);
} while (error < 0 && errno == EINTR);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can fallocate set EAGAIN?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's copy-pasted from #5087 (comment), actually. And isn't EAGAIN usually async network stuff ? I'm scared now…

if (error < 0 && errno == ENOTSUP)
goto fallback;
#else
return posix_fallocate(fd, offset, len);
goto fallback;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just remove the else block, but that's a matter of taste

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's protecting against an "unused label" warning on macOS case, actually.

#endif

fallback:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite get it. Aren't we now always executing the fallback, regardless of whether the platform-specific implementation succeeded or not?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, true, I seem to have forgot a few returns when whatever platform-specific version succeeded. IOW, only failures of the (potential) platform fallocate would cause the fallback to run.

/* save offset, seek, write zeroes, restore */
if ((error = p_lseek(fd, 0, SEEK_CUR)) < 0)
return -1;

cur = error;

memset(&buf, '\0', sizeof(buf));

if ((error = p_lseek(fd, offset, SEEK_SET)) < 0)
goto cleanup;

while (pos < len) {
size_t wlen = MIN(len - pos, (off_t)sizeof(buf));
if ((error = p_write(fd, buf, wlen)) < 0)
goto cleanup;
pos += wlen;
}

cleanup:
if ((error = p_lseek(fd, cur, SEEK_SET)) < 0)
return error;

return error;
}

#endif /* GIT_WIN32 */
Expand Down
2 changes: 2 additions & 0 deletions tests/core/posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,5 +302,7 @@ void test_core_posix__fallocate(void)
cl_must_pass(p_lseek(fd, 42, SEEK_SET));
cl_must_pass(p_fallocate(fd, 0, 200));
cl_assert_equal_i(42, p_lseek(fd, 0, SEEK_CUR));
cl_must_pass(p_fallocate(fd, 190, 128));
cl_assert_equal_i(42, p_lseek(fd, 0, SEEK_CUR));
p_close(fd);
}