Skip to content

cmake: detect availability of posix_fallocate(3)#5087

Closed
pks-t wants to merge 1 commit into
libgit2:masterfrom
pks-t:pks/cmake-posix-fallocate
Closed

cmake: detect availability of posix_fallocate(3)#5087
pks-t wants to merge 1 commit into
libgit2:masterfrom
pks-t:pks/cmake-posix-fallocate

Conversation

@pks-t

@pks-t pks-t commented May 24, 2019

Copy link
Copy Markdown
Member

Instead of having fragile checks for platform definitions to
guess whether posix_fallocate(3) is available or not, let's just
use CMake's CHECK_FUNCTION_EXISTS to detect that. This is both
more accurate and simpler.

@tiennou tiennou left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, and is clearly a better solution. Thanks for fixing this @pks-t.

(I do hope there's no such problem as the qsort/_r/_s conundrum, but I don't recall inconsistent signatures)

@pks-t

pks-t commented May 24, 2019 via email

Copy link
Copy Markdown
Member Author

@ethomson

Copy link
Copy Markdown
Member

Well, I'd definitely hope that if a function already has a
posix_ prefix, that implementers will in fact implement what
POSIX specifies. But you never know ;)

Indeed. The GCC builds are complaining about something, though I don't know what that is.

@pks-t

pks-t commented May 25, 2019 via email

Copy link
Copy Markdown
Member Author

@tiennou

tiennou commented May 25, 2019

Copy link
Copy Markdown
Contributor

I've pushed a fixup here. I've ended up doing a check for the posix_fallocate symbol, and if that fails, it'll check if we're on some kind of BSD.

This test is "looser" that the original NetBSD preprocessor checks provided by @jacquesg, but if I understood correctly, NetBSD gained posix_fallocate in v7, so doing the generic check first should handle all BSD (modulo Apple-specific modifications).

(edit I've also made more explicit that it's a BSD-specific implementation)

@jacquesg

Copy link
Copy Markdown
Contributor

FreeBSD has had posix_fallocate for many years, wouldn't worry about it.

@jacquesg

Copy link
Copy Markdown
Contributor

I would also check for it on Solaris, as I believe it is only available from 11 onwards. Version 10 is still in wide-spread use.

@tiennou

tiennou commented May 25, 2019

Copy link
Copy Markdown
Contributor

Thanks for the insight. I haven't been able to find a reference about what was supported on Solaris then. If it's the fcntl stuff as the BSDs need it's okay, but if it's not then (I'd really like to not have to implement a "stupid" write zeroes fallback)…

@jacquesg

Copy link
Copy Markdown
Contributor

Here is some guidance on how to implement it for Solaris: https://fossies.org/linux/dpkg/lib/dpkg/fdio.c

@jacquesg

Copy link
Copy Markdown
Contributor

Ok, so it doesn't seem like any version of NetBSD or OpenBSD has F_PREALLOCATE. So in summary:

  • FreeBSD: Has posix_fallocate since version 7 (added about 11 years ago)
  • OpenBSD: Doesn't have posix_fallocate or F_PREALLOCATE
  • NetBSD: Has posix_fallocate from version 7, doesn't have F_PREALLOCATE
  • macOS: Has F_PREALLOCATE
  • Solaris: Has F_ALLOCSP64.

@krytarowski

Copy link
Copy Markdown

This code is still not fully correct.

On NetBSD posix_fallocate(2) will report EOPNOTSUPP for frequently used filesystems (we need kernel support for each filesystem) and must have a fallback for the ftruncate(2) function.

@krytarowski

Copy link
Copy Markdown

@tiennou

tiennou commented May 27, 2019

Copy link
Copy Markdown
Contributor

Okay, I've updated my fixup commit to CMake checks all of those, choose the one available, and fallback to ftruncate on ENOTSUP/nothing being available.

@ethomson

Copy link
Copy Markdown
Member

/rebuild

@libgit2-azure-pipelines

Copy link
Copy Markdown

Sorry @ethomson, I was not able to find any builds to requeue.

@ethomson

Copy link
Copy Markdown
Member

Gah, the build expired. I'll have to figure out how to remove the build expirations. In the meantime, I queued a new build against this branch manually, and it's still failing, unfortunately.

@tiennou

tiennou commented Jun 12, 2019

Copy link
Copy Markdown
Contributor

@pks-t Do you mind if I take over this one ? I'm responsible for the half-working platform support, have a tentative fix handy which I forgot to point out here (there should be a lone commit I've added to my fork). As you wish, but since it impacts platforms not quite under CI, it feel best to fix it "fast" (maybe) ?

@pks-t

pks-t commented Jun 12, 2019 via email

Copy link
Copy Markdown
Member Author

@pks-t pks-t force-pushed the pks/cmake-posix-fallocate branch from 464d830 to 908e11f Compare June 13, 2019 14:44
@pks-t

pks-t commented Jun 13, 2019

Copy link
Copy Markdown
Member Author

Updated with @tiennou's changes

@tiennou

tiennou commented Jun 13, 2019

Copy link
Copy Markdown
Contributor

Okay, so the Linux test failed because I have inconsistent semantics, I believe because of the ftruncate fallback I've added without thinking.

My expectation of whatever POSIX describes as fallocate, is that a call to p_fallocate(fd, 0, 1024); cannot be assumed to mean that I want the file backed by fd to be truncated at 1024, only that I expect that part of the file to exist (else, what would happen with multiple calls, in case I wanted to zero parts of a file for some subsequent mmaps). So I've reimplemented the fallback as a dumb write loop (@pks-t if you can pull that, that'd be 🙏). Does anyone sees something wrong with that understanding ?

@pks-t pks-t force-pushed the pks/cmake-posix-fallocate branch from 908e11f to 4f717d6 Compare June 13, 2019 15:53
@ethomson

Copy link
Copy Markdown
Member

Okay, so the Linux test failed because I have inconsistent semantics, I believe because of the ftruncate fallback I've added without thinking.

Hmm, what version of Linux are we building on that's missing posix_fallocate and is thus falling into the ftruncate fallback?

@ethomson

Copy link
Copy Markdown
Member

In any case, yes, I agree that we need to avoid shrinking a file with ftruncate, but it should be much faster to just do arithmetic to determine if we would be shrinking or not, and only calling ftruncate opportunistically (or doing nothing). Is there something wrong with the code that was there from bd13204#diff-af200ec3b10b961c568b86610775effe ?

@tiennou

tiennou commented Jun 13, 2019

Copy link
Copy Markdown
Contributor

Hmm, what version of Linux are we building on that's missing posix_fallocate and is thus falling into the ftruncate fallback?

Dunno, but I'd wager it's also filesystem-specific, and we're in crazy vm shenanigans territory, so that could have been the fallback.

In any case, yes, I agree that we need to avoid shrinking a file with ftruncate, but it should be much faster to just do arithmetic to determine if we would be shrinking or not, and only calling ftruncate opportunistically (or doing nothing). Is there something wrong with the code that was there from bd13204#diff-af200ec3b10b961c568b86610775effe ?

Not per se, I could have just added a check to make sure we'd not cause the file to shrink. Would that work better ? It's just that I'm expecting I'll have to juggle offsets, lengths and seek positions to convert "fallocate hole" into "ftruncate complete file but don't make it smaller", and the dumb loop seemed safer…

Instead of having fragile checks for platform definitions to
guess whether posix_fallocate(3) is available or not, let's just
use CMake's `CHECK_FUNCTION_EXISTS` to detect that. This is both
more accurate and simpler.
@tiennou

tiennou commented Jun 14, 2019

Copy link
Copy Markdown
Contributor

@pks-t branch updated again (Xcode's renamer doesn't look inside #ifdefs). Do you have an opinion on the dump-write-loop vs. ftruncate-unless-it-would-shrink approach ?

@pks-t pks-t force-pushed the pks/cmake-posix-fallocate branch from 4f717d6 to efb2733 Compare June 14, 2019 08:09

@pks-t pks-t left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So... this seems mighty complex. And the funny thing is: we don't even use p_fallocate anywhere except for in our tests for the bigfile emulation. Is it really worth the effort? Shouldn't we just remove p_fallocate altogether and create a binary blob that explodes to a huge size upon uncompressing it?

Comment thread src/posix.c
goto fallback;
#endif

fallback:

Copy link
Copy Markdown
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
Copy Markdown
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.

Comment thread src/posix.c
#elif defined(GIT_USE_FALLOCATE)
do {
error = fallocate(fd, 0, offset, len);
} while (error < 0 && errno == EINTR);

Copy link
Copy Markdown
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
Copy Markdown
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…

Comment thread src/posix.c
goto fallback;
#else
return posix_fallocate(fd, offset, len);
goto fallback;

Copy link
Copy Markdown
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
Copy Markdown
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.

@tiennou tiennou left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So... this seems mighty complex.

God yes. Removing the fallback uncovered another "issue": macOS needs the fallback, because somehow after the call, its fstat size is still 0 (I've added a comment). So if there's any chance to drop that madness, I'm all for it now 😭.

Comment thread src/posix.c
goto fallback;
#endif

fallback:

Copy link
Copy Markdown
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.

Comment thread src/posix.c
goto fallback;
#else
return posix_fallocate(fd, offset, len);
goto fallback;

Copy link
Copy Markdown
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.

Comment thread src/posix.c
#elif defined(GIT_USE_FALLOCATE)
do {
error = fallocate(fd, 0, offset, len);
} while (error < 0 && errno == EINTR);

Copy link
Copy Markdown
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…

@pks-t

pks-t commented Jun 14, 2019

Copy link
Copy Markdown
Member Author

So if there's any chance to drop that madness, I'm all for it now

Yeah, seeing how this escalated quickly I'm all for dropping p_fallocate completely and using some other sorcery for the bigfile test.

@pks-t pks-t mentioned this pull request Jun 14, 2019
@ethomson

Copy link
Copy Markdown
Member

Yeah, seeing how this escalated quickly I'm all for dropping p_fallocate completely and using some other sorcery for the bigfile test.

+1

@pks-t

pks-t commented Jun 24, 2019

Copy link
Copy Markdown
Member Author

Closing, this has been fixed via #5114 by removing p_fallocate altogether.

@pks-t pks-t closed this Jun 24, 2019
@pks-t pks-t deleted the pks/cmake-posix-fallocate branch June 24, 2019 12:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants