mdbx: чуть больше контроля и паранойи для страховки от дефектов mremap().

Есть основание полагать, что mremap() может возвращать MAP_FAILED, но НЕ
устанавливать errno в некоторых пограничных ситуациях. Например, когда
системных ресурсов не хватает на актуализацию/копирование/клонирование
состояния отображения на финальной стадии, в том числе из-за раскраски
исходного отображения разными флагами через madvise().
This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2022-10-14 00:20:37 +03:00
parent 51a765a5a7
commit 80f9f73a5e

View File

@ -2166,6 +2166,7 @@ MDBX_INTERNAL_FUNC int osal_mmap(const int flags, osal_mmap_t *map,
map->limit = 0;
map->current = 0;
map->address = nullptr;
assert(errno != 0);
return errno;
}
map->limit = limit;
@ -2204,8 +2205,10 @@ MDBX_INTERNAL_FUNC int osal_munmap(osal_mmap_t *map) {
if (!NT_SUCCESS(rc))
ntstatus2errcode(rc);
#else
if (unlikely(munmap(map->address, map->limit)))
if (unlikely(munmap(map->address, map->limit))) {
assert(errno != 0);
return errno;
}
#endif /* ! Windows */
map->limit = 0;
@ -2428,8 +2431,10 @@ retry_mapview:;
if (limit < map->limit) {
/* unmap an excess at end of mapping. */
// coverity[offset_free : FALSE]
if (unlikely(munmap(map->dxb + limit, map->limit - limit)))
if (unlikely(munmap(map->dxb + limit, map->limit - limit))) {
assert(errno != 0);
return errno;
}
map->limit = limit;
return rc;
}
@ -2441,14 +2446,19 @@ retry_mapview:;
assert(limit > map->limit);
uint8_t *ptr = MAP_FAILED;
#if defined(MREMAP_MAYMOVE)
#if (defined(__linux__) || defined(__gnu_linux__)) && defined(_GNU_SOURCE)
ptr = mremap(map->address, map->limit, limit,
(flags & MDBX_MRESIZE_MAY_MOVE) ? MREMAP_MAYMOVE : 0);
#if defined(MREMAP_MAYMOVE)
(flags & MDBX_MRESIZE_MAY_MOVE) ? MREMAP_MAYMOVE :
#endif /* MREMAP_MAYMOVE */
0);
if (ptr == MAP_FAILED) {
err = errno;
assert(err != 0);
switch (err) {
default:
return err;
case 0 /* paranoia */:
case EAGAIN:
case ENOMEM:
return MDBX_UNABLE_EXTEND_MAPSIZE;
@ -2456,7 +2466,7 @@ retry_mapview:;
break;
}
}
#endif /* MREMAP_MAYMOVE */
#endif /* Linux & _GNU_SOURCE */
const unsigned mmap_flags =
MAP_CONCEAL | MAP_SHARED | MAP_FILE | MAP_NORESERVE |
@ -2469,17 +2479,22 @@ retry_mapview:;
ptr = mmap(map->dxb + map->limit, limit - map->limit, mmap_prot,
mmap_flags | MAP_FIXED_NOREPLACE, map->fd, map->limit);
if (ptr == map->dxb + map->limit)
/* успешно прилепили отображение в конец */
ptr = map->dxb;
else if (ptr != MAP_FAILED) {
/* the desired address is busy, unmap unsuitable one */
if (unlikely(munmap(ptr, limit - map->limit)))
if (unlikely(munmap(ptr, limit - map->limit))) {
assert(errno != 0);
return errno;
}
ptr = MAP_FAILED;
} else {
err = errno;
assert(err != 0);
switch (err) {
default:
return err;
case 0 /* paranoia */:
case EAGAIN:
case ENOMEM:
return MDBX_UNABLE_EXTEND_MAPSIZE;
@ -2498,8 +2513,10 @@ retry_mapview:;
return MDBX_UNABLE_EXTEND_MAPSIZE;
}
if (unlikely(munmap(map->address, map->limit)))
if (unlikely(munmap(map->address, map->limit))) {
assert(errno != 0);
return errno;
}
// coverity[pass_freed_arg : FALSE]
ptr = mmap(map->address, limit, mmap_prot,
@ -2543,6 +2560,7 @@ retry_mapview:;
map->limit = 0;
map->current = 0;
map->address = nullptr;
assert(errno != 0);
return errno;
}
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
@ -2569,8 +2587,10 @@ retry_mapview:;
#if MDBX_ENABLE_MADVISE
#ifdef MADV_DONTFORK
if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0))
if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0)) {
assert(errno != 0);
return errno;
}
#endif /* MADV_DONTFORK */
#ifdef MADV_NOHUGEPAGE
(void)madvise(map->address, map->limit, MADV_NOHUGEPAGE);
@ -2579,6 +2599,9 @@ retry_mapview:;
#endif /* POSIX / Windows */
assert(rc != MDBX_SUCCESS ||
(map->address != nullptr && map->address != MAP_FAILED &&
map->current == size && map->limit == limit));
return rc;
}