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

Skip to content

Conversation

pks-t
Copy link
Member

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

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.

Copy link
Contributor

@tiennou tiennou left a comment

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
Copy link
Member Author

pks-t commented May 24, 2019 via email

@ethomson
Copy link
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
Copy link
Member Author

pks-t commented May 25, 2019 via email

@tiennou
Copy link
Contributor

tiennou commented May 25, 2019

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
Contributor

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

@jacquesg
Copy link
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
Copy link
Contributor

tiennou commented May 25, 2019

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
Contributor

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

@jacquesg
Copy link
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

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

@tiennou
Copy link
Contributor

tiennou commented May 27, 2019

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
Member

/rebuild

@libgit2-azure-pipelines
Copy link

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

@ethomson
Copy link
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
Copy link
Contributor

tiennou commented Jun 12, 2019

@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
Copy link
Member Author

pks-t commented Jun 12, 2019 via email

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

pks-t commented Jun 13, 2019

Updated with @tiennou's changes

@tiennou
Copy link
Contributor

tiennou commented Jun 13, 2019

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
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
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
Copy link
Contributor

tiennou commented Jun 13, 2019

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
Copy link
Contributor

tiennou commented Jun 14, 2019

@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
Copy link
Member Author

@pks-t pks-t left a comment

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?

#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.

#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…

#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.

Copy link
Contributor

@tiennou tiennou left a comment

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 😭.

#endif

fallback:
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.

#else
return posix_fallocate(fd, offset, len);
goto fallback;
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.

#elif defined(GIT_USE_FALLOCATE)
do {
error = fallocate(fd, 0, offset, len);
} while (error < 0 && errno == EINTR);
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…

@pks-t
Copy link
Member Author

pks-t commented Jun 14, 2019

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
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
Copy link
Member Author

pks-t commented Jun 24, 2019

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