Skip to content

Commit

Permalink
Fix problem with posix_fallocate on AWS Lambda
Browse files Browse the repository at this point in the history
  • Loading branch information
jedelbo committed Dec 13, 2018
1 parent 48bbc05 commit 938f752
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 21 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* None.

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
* None.
* On AWS Lambda we may throw an "Operation not permitted" exception when calling posix_fallocate().
A slower workaround has been supplied.
([#3193](https://github.com/realm/realm-core/issues/3293))

### Breaking changes
* None.
Expand Down
32 changes: 14 additions & 18 deletions src/realm/util/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,12 +681,6 @@ void File::prealloc(size_t size)
{
REALM_ASSERT_RELEASE(is_attached());

#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L // POSIX.1-2001 version
// Mostly Linux only
prealloc_if_supported(0, size);

#else // Non-atomic fallback

if (size <= to_size_t(get_size())) {
return;
}
Expand All @@ -713,6 +707,12 @@ void File::prealloc(size_t size)
}
};

#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L // POSIX.1-2001 version
// Mostly Linux only
if (!prealloc_if_supported(0, new_size)) {
manually_consume_space();
}
#else // Non-atomic fallback
#if REALM_PLATFORM_APPLE
// posix_fallocate() is not supported on MacOS or iOS, so use a combination of fcntl(F_PREALLOCATE) and ftruncate().

Expand Down Expand Up @@ -783,42 +783,38 @@ void File::prealloc(size_t size)
}


void File::prealloc_if_supported(SizeType offset, size_t size)
bool File::prealloc_if_supported(SizeType offset, size_t size)
{
REALM_ASSERT_RELEASE(is_attached());

#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L // POSIX.1-2001 version

REALM_ASSERT_RELEASE(is_prealloc_supported());

if (m_encryption_key)
size = data_size_to_encrypted_size(size);

off_t size2;
if (int_cast_with_overflow_detect(size, size2))
throw util::overflow_error("File size overflow");

if (size2 == 0) {
if (size == 0) {
// calling posix_fallocate with a size of 0 will cause a return of EINVAL
// since this is a meaningless operation anyway, we just return early here
return;
return true;
}

// posix_fallocate() does not set errno, it returns the error (if any) or zero.
// It is also possible for it to be interrupted by EINTR according to some man pages (ex fedora 24)
int status;
do {
status = ::posix_fallocate(m_fd, offset, size2);
status = ::posix_fallocate(m_fd, offset, size);
} while (status == EINTR);

if (REALM_LIKELY(status == 0)) {
return;
return true;
}

if (status == ENOSPC || status == EDQUOT) {
std::string msg = get_errno_msg("posix_fallocate() failed: ", status);
throw OutOfDiskSpace(msg);
}
if (status == EINVAL) {
return false; // Retry with non-atomic version
}
throw std::system_error(status, std::system_category(), "posix_fallocate() failed");

// FIXME: OS X does not have any version of fallocate, but see
Expand Down
2 changes: 1 addition & 1 deletion src/realm/util/file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ class File {
///
/// \sa prealloc()
/// \sa is_prealloc_supported()
void prealloc_if_supported(SizeType offset, size_t size);
bool prealloc_if_supported(SizeType offset, size_t size);

/// See prealloc_if_supported().
static bool is_prealloc_supported();
Expand Down

0 comments on commit 938f752

Please sign in to comment.