8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:00:38 +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:
hvlad 2014-06-10 09:00:58 +00:00
parent 6a2016235a
commit 02e898741a
5 changed files with 73 additions and 7 deletions

View File

@ -690,6 +690,7 @@ AC_CHECK_HEADERS(poll.h)
AC_CHECK_HEADERS(langinfo.h) AC_CHECK_HEADERS(langinfo.h)
AC_CHECK_HEADERS(iconv.h) AC_CHECK_HEADERS(iconv.h)
AC_CHECK_HEADERS(libio.h) AC_CHECK_HEADERS(libio.h)
AC_CHECK_HEADERS(linux/falloc.h)
dnl check for ICU presence dnl check for ICU presence
AC_CHECK_HEADER(unicode/ucnv.h,,AC_MSG_ERROR(ICU support not found - please install development ICU package)) AC_CHECK_HEADER(unicode/ucnv.h,,AC_MSG_ERROR(ICU support not found - please install development ICU package))

View File

@ -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_no_fs_cache = 2; // not using file system cache
const USHORT FIL_readonly = 4; // file opened in readonly mode 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_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 // Physical IO trace events

View File

@ -45,6 +45,9 @@
#ifdef HAVE_AIO_H #ifdef HAVE_AIO_H
#include <aio.h> #include <aio.h>
#endif #endif
#ifdef HAVE_LINUX_FALLOC_H
#include <linux/falloc.h>
#endif
#include "../jrd/jrd.h" #include "../jrd/jrd.h"
#include "../jrd/os/pio.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. * 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 // not implemented
return; return;
} }

View File

@ -640,7 +640,7 @@ PAG PAG_allocate(thread_db* tdbb, WIN* window)
// At this point we ensure database has at least "initialized" pages // At this point we ensure database has at least "initialized" pages
// allocated. To avoid file growth by few pages when all this space // allocated. To avoid file growth by few pages when all this space
// will be used, extend file up to initialized + next_init_pages now // 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 break; // Found a page and successfully fake-ed it
@ -2039,7 +2039,7 @@ ULONG PageSpace::lastUsedPage(const Database* dbb)
return pgSpace->lastUsedPage(); 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 * If "DatabaseGrowthIncrement" is less than MIN_EXTEND_BYTES then don't
* extend file(s) * 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()); fb_assert(dbb == tdbb->getDatabase());
const int MAX_EXTEND_BYTES = dbb->dbb_config->getDatabaseGrowthIncrement(); 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; return true;
if (pageNum >= maxAlloc()) if (pageNum >= maxAlloc())
@ -2071,6 +2075,7 @@ bool PageSpace::extend(thread_db* tdbb, const ULONG pageNum)
while (true) while (true)
{ {
const ULONG oldMaxPageNumber = maxPageNumber;
try try
{ {
PIO_extend(dbb, file, extPages, dbb->dbb_page_size); 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&) catch (const status_exception&)
{ {
if (extPages > reqPages) if (extPages > reqPages && !forceSize)
{ {
extPages = MAX(reqPages, extPages / 2);
fb_utils::init_status(tdbb->tdbb_status_vector); 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 else
{ {

View File

@ -120,7 +120,7 @@ public:
static ULONG lastUsedPage(const Database* dbb); static ULONG lastUsedPage(const Database* dbb);
// extend page space // extend page space
bool extend(thread_db*, const ULONG); bool extend(thread_db*, const ULONG, const bool);
// get SCN's page number // get SCN's page number
ULONG getSCNPageNum(ULONG sequence); ULONG getSCNPageNum(ULONG sequence);