mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Front ported support for fallocate() call on Linux.
Front ported improvement CORE-4443 : Use fast file grow on those Linux systems which supports it
This commit is contained in:
parent
6a2016235a
commit
02e898741a
@ -690,6 +690,7 @@ AC_CHECK_HEADERS(poll.h)
|
||||
AC_CHECK_HEADERS(langinfo.h)
|
||||
AC_CHECK_HEADERS(iconv.h)
|
||||
AC_CHECK_HEADERS(libio.h)
|
||||
AC_CHECK_HEADERS(linux/falloc.h)
|
||||
|
||||
dnl check for ICU presence
|
||||
AC_CHECK_HEADER(unicode/ucnv.h,,AC_MSG_ERROR(ICU support not found - please install development ICU package))
|
||||
|
@ -94,6 +94,7 @@ const USHORT FIL_force_write = 1;
|
||||
const USHORT FIL_no_fs_cache = 2; // not using file system cache
|
||||
const USHORT FIL_readonly = 4; // file opened in readonly mode
|
||||
const USHORT FIL_sh_write = 8; // file opened in shared write mode
|
||||
const USHORT FIL_no_fast_extend = 16; // file not supports fast extending
|
||||
|
||||
// Physical IO trace events
|
||||
|
||||
|
@ -45,6 +45,9 @@
|
||||
#ifdef HAVE_AIO_H
|
||||
#include <aio.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_FALLOC_H
|
||||
#include <linux/falloc.h>
|
||||
#endif
|
||||
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/os/pio.h"
|
||||
@ -291,7 +294,7 @@ bool PIO_expand(const TEXT* file_name, USHORT file_length, TEXT* expanded_name,
|
||||
}
|
||||
|
||||
|
||||
void PIO_extend(Database* dbb, jrd_file* /*main_file*/, const ULONG /*extPages*/, const USHORT /*pageSize*/)
|
||||
void PIO_extend(Database* dbb, jrd_file* main_file, const ULONG extPages, const USHORT pageSize)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -303,6 +306,56 @@ void PIO_extend(Database* dbb, jrd_file* /*main_file*/, const ULONG /*extPages*/
|
||||
* Extend file by extPages pages of pageSize size.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
#ifdef HAVE_LINUX_FALLOC_H
|
||||
ULONG leftPages = extPages;
|
||||
for (jrd_file* file = main_file; file && leftPages; file = file->fil_next)
|
||||
{
|
||||
const ULONG filePages = PIO_get_number_of_pages(file, pageSize);
|
||||
const ULONG fileMaxPages = (file->fil_max_page == MAX_ULONG) ?
|
||||
MAX_ULONG : file->fil_max_page - file->fil_min_page + 1;
|
||||
if (filePages < fileMaxPages)
|
||||
{
|
||||
if (file->fil_flags & FIL_no_fast_extend)
|
||||
return;
|
||||
|
||||
const ULONG extendBy = MIN(fileMaxPages - filePages + file->fil_fudge, leftPages);
|
||||
|
||||
int r;
|
||||
for (r = 0; r < IO_RETRY; r++)
|
||||
{
|
||||
int err = fallocate(file->fil_desc, 0, filePages * pageSize, extendBy * pageSize);
|
||||
if (err == 0)
|
||||
break;
|
||||
|
||||
err = errno;
|
||||
if (SYSCALL_INTERRUPTED(err))
|
||||
continue;
|
||||
|
||||
if (err == EOPNOTSUPP || err == ENOSYS)
|
||||
file->fil_flags |= FIL_no_fast_extend;
|
||||
else
|
||||
unix_error("fallocate", file, isc_io_write_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == IO_RETRY)
|
||||
{
|
||||
#ifdef DEV_BUILD
|
||||
fprintf(stderr, "PIO_extend: retry count exceeded\n");
|
||||
fflush(stderr);
|
||||
#endif
|
||||
unix_error("fallocate_retry", file, isc_io_write_err);
|
||||
return;
|
||||
}
|
||||
|
||||
leftPages -= extendBy;
|
||||
}
|
||||
}
|
||||
#else
|
||||
main_file->fil_flags |= FIL_no_fast_extend;
|
||||
#endif // HAVE_LINUX_FALLOC_H
|
||||
|
||||
// not implemented
|
||||
return;
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ PAG PAG_allocate(thread_db* tdbb, WIN* window)
|
||||
// At this point we ensure database has at least "initialized" pages
|
||||
// allocated. To avoid file growth by few pages when all this space
|
||||
// will be used, extend file up to initialized + next_init_pages now
|
||||
pageSpace->extend(tdbb, initialized + next_init_pages);
|
||||
pageSpace->extend(tdbb, initialized + next_init_pages, false);
|
||||
}
|
||||
|
||||
break; // Found a page and successfully fake-ed it
|
||||
@ -2039,7 +2039,7 @@ ULONG PageSpace::lastUsedPage(const Database* dbb)
|
||||
return pgSpace->lastUsedPage();
|
||||
}
|
||||
|
||||
bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum)
|
||||
bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum, const bool forceSize)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2051,12 +2051,16 @@ bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum)
|
||||
* If "DatabaseGrowthIncrement" is less than MIN_EXTEND_BYTES then don't
|
||||
* extend file(s)
|
||||
*
|
||||
* If forceSize is true, extend file up to pageNum pages (despite of value
|
||||
* of "DatabaseGrowthIncrement") and don't make attempts to extend by less
|
||||
* pages.
|
||||
*
|
||||
**************************************/
|
||||
fb_assert(dbb == tdbb->getDatabase());
|
||||
|
||||
const int MAX_EXTEND_BYTES = dbb->dbb_config->getDatabaseGrowthIncrement();
|
||||
|
||||
if (pageNum < maxPageNumber || MAX_EXTEND_BYTES < MIN_EXTEND_BYTES)
|
||||
if (pageNum < maxPageNumber || MAX_EXTEND_BYTES < MIN_EXTEND_BYTES && !forceSize)
|
||||
return true;
|
||||
|
||||
if (pageNum >= maxAlloc())
|
||||
@ -2071,6 +2075,7 @@ bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum)
|
||||
|
||||
while (true)
|
||||
{
|
||||
const ULONG oldMaxPageNumber = maxPageNumber;
|
||||
try
|
||||
{
|
||||
PIO_extend(dbb, file, extPages, dbb->dbb_page_size);
|
||||
@ -2078,10 +2083,16 @@ bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum)
|
||||
}
|
||||
catch (const status_exception&)
|
||||
{
|
||||
if (extPages > reqPages)
|
||||
if (extPages > reqPages && !forceSize)
|
||||
{
|
||||
extPages = MAX(reqPages, extPages / 2);
|
||||
fb_utils::init_status(tdbb->tdbb_status_vector);
|
||||
|
||||
// if file was extended, return, else try to extend by less pages
|
||||
|
||||
if (oldMaxPageNumber < maxAlloc())
|
||||
return true;
|
||||
|
||||
extPages = MAX(reqPages, extPages / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -120,7 +120,7 @@ public:
|
||||
static ULONG lastUsedPage(const Database* dbb);
|
||||
|
||||
// extend page space
|
||||
bool extend(thread_db*, const ULONG);
|
||||
bool extend(thread_db*, const ULONG, const bool);
|
||||
|
||||
// get SCN's page number
|
||||
ULONG getSCNPageNum(ULONG sequence);
|
||||
|
Loading…
Reference in New Issue
Block a user