mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 09:20:39 +01:00
Fixed bug #7873 : IO error reading file, The parameter is incorrect.
This commit is contained in:
parent
8789caf2b1
commit
f8571de6ec
@ -68,6 +68,8 @@
|
|||||||
#define FLOCK flock
|
#define FLOCK flock
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const ULONG DEFAULT_SECTOR_SIZE = 4096;
|
||||||
|
|
||||||
namespace os_utils
|
namespace os_utils
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -88,6 +90,8 @@ namespace os_utils
|
|||||||
void setCloseOnExec(int fd); // posix only
|
void setCloseOnExec(int fd); // posix only
|
||||||
FILE* fopen(const char* pathname, const char* mode);
|
FILE* fopen(const char* pathname, const char* mode);
|
||||||
|
|
||||||
|
ULONG getPhysicalSectorSize(const Firebird::PathName& fileName);
|
||||||
|
|
||||||
// return a binary string that uniquely identifies the file
|
// return a binary string that uniquely identifies the file
|
||||||
#ifdef WIN_NT
|
#ifdef WIN_NT
|
||||||
void getUniqueFileId(HANDLE fd, Firebird::UCharBuffer& id);
|
void getUniqueFileId(HANDLE fd, Firebird::UCharBuffer& id);
|
||||||
|
@ -399,6 +399,12 @@ FILE* fopen(const char* pathname, const char* mode)
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG getPhysicalSectorSize(const PathName& fileName)
|
||||||
|
{
|
||||||
|
// return safe value
|
||||||
|
return DEFAULT_SECTOR_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
static void makeUniqueFileId(const struct STAT& statistics, UCharBuffer& id)
|
static void makeUniqueFileId(const struct STAT& statistics, UCharBuffer& id)
|
||||||
{
|
{
|
||||||
const size_t len1 = sizeof(statistics.st_dev);
|
const size_t len1 = sizeof(statistics.st_dev);
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include <aclapi.h>
|
#include <aclapi.h>
|
||||||
#include <Winsock2.h>
|
#include <Winsock2.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
|
||||||
using namespace Firebird;
|
using namespace Firebird;
|
||||||
|
|
||||||
@ -408,6 +409,47 @@ FILE* fopen(const char* pathname, const char* mode)
|
|||||||
return ::fopen(pathname, mode);
|
return ::fopen(pathname, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG getPhysicalSectorSize(const PathName& fileName)
|
||||||
|
{
|
||||||
|
// Fallback to the safe value
|
||||||
|
ULONG ret = DEFAULT_SECTOR_SIZE;
|
||||||
|
|
||||||
|
// Device name could be set as \\.\PhysicalDrive0 or as \\.\a:
|
||||||
|
// The second form is used below for simplicity.
|
||||||
|
|
||||||
|
string deviceName = "\\\\.\\";
|
||||||
|
deviceName.append(fileName.c_str(), 2);
|
||||||
|
|
||||||
|
HANDLE hDevice = CreateFile(deviceName.c_str(),
|
||||||
|
0,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
|
if (hDevice != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
STORAGE_PROPERTY_QUERY qry;
|
||||||
|
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc;
|
||||||
|
DWORD readSize = 0;
|
||||||
|
|
||||||
|
qry.PropertyId = StorageAccessAlignmentProperty;
|
||||||
|
qry.QueryType = PropertyStandardQuery;
|
||||||
|
|
||||||
|
if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
|
||||||
|
&qry, sizeof(qry),
|
||||||
|
&desc, sizeof(desc),
|
||||||
|
&readSize, NULL))
|
||||||
|
{
|
||||||
|
ret = desc.BytesPerPhysicalSector;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void getUniqueFileId(HANDLE fd, UCharBuffer& id)
|
void getUniqueFileId(HANDLE fd, UCharBuffer& id)
|
||||||
{
|
{
|
||||||
entryLoader.init();
|
entryLoader.init();
|
||||||
|
@ -7592,11 +7592,21 @@ static JAttachment* create_attachment(const PathName& alias_name,
|
|||||||
|
|
||||||
static void check_single_maintenance(thread_db* tdbb)
|
static void check_single_maintenance(thread_db* tdbb)
|
||||||
{
|
{
|
||||||
UCHAR spare_memory[RAW_HEADER_SIZE + PAGE_ALIGNMENT];
|
Database* const dbb = tdbb->getDatabase();
|
||||||
UCHAR* header_page_buffer = FB_ALIGN(spare_memory, PAGE_ALIGNMENT);
|
|
||||||
|
const ULONG sectorSize = (dbb->dbb_flags & DBB_no_fs_cache) ?
|
||||||
|
os_utils::getPhysicalSectorSize(dbb->dbb_filename) :
|
||||||
|
PAGE_ALIGNMENT;
|
||||||
|
|
||||||
|
const ULONG headerSize = MAX(RAW_HEADER_SIZE, sectorSize);
|
||||||
|
|
||||||
|
HalfStaticArray<UCHAR, RAW_HEADER_SIZE + PAGE_ALIGNMENT> temp;
|
||||||
|
UCHAR* header_page_buffer = temp.getBuffer(headerSize + sectorSize);
|
||||||
|
|
||||||
|
header_page_buffer = FB_ALIGN(header_page_buffer, PAGE_ALIGNMENT);
|
||||||
Ods::header_page* const header_page = reinterpret_cast<Ods::header_page*>(header_page_buffer);
|
Ods::header_page* const header_page = reinterpret_cast<Ods::header_page*>(header_page_buffer);
|
||||||
|
|
||||||
PIO_header(tdbb, header_page_buffer, RAW_HEADER_SIZE);
|
PIO_header(tdbb, header_page_buffer, headerSize);
|
||||||
|
|
||||||
if ((header_page->hdr_flags & Ods::hdr_shutdown_mask) == Ods::hdr_shutdown_single)
|
if ((header_page->hdr_flags & Ods::hdr_shutdown_mask) == Ods::hdr_shutdown_single)
|
||||||
{
|
{
|
||||||
|
@ -1261,10 +1261,17 @@ void PAG_header_init(thread_db* tdbb)
|
|||||||
// and unit of transfer is a multiple of physical disk
|
// and unit of transfer is a multiple of physical disk
|
||||||
// sector for raw disk access.
|
// sector for raw disk access.
|
||||||
|
|
||||||
UCHAR temp_buffer[RAW_HEADER_SIZE + PAGE_ALIGNMENT];
|
const ULONG sectorSize = (dbb->dbb_flags & DBB_no_fs_cache) ?
|
||||||
UCHAR* const temp_page = FB_ALIGN(temp_buffer, PAGE_ALIGNMENT);
|
os_utils::getPhysicalSectorSize(dbb->dbb_filename) :
|
||||||
|
PAGE_ALIGNMENT;
|
||||||
|
|
||||||
PIO_header(tdbb, temp_page, RAW_HEADER_SIZE);
|
const ULONG headerSize = MAX(RAW_HEADER_SIZE, sectorSize);
|
||||||
|
|
||||||
|
HalfStaticArray<UCHAR, RAW_HEADER_SIZE + PAGE_ALIGNMENT> temp;
|
||||||
|
UCHAR* temp_buffer = temp.getBuffer(headerSize + sectorSize);
|
||||||
|
UCHAR* const temp_page = FB_ALIGN(temp_buffer, sectorSize);
|
||||||
|
|
||||||
|
PIO_header(tdbb, temp_page, headerSize);
|
||||||
const header_page* header = (header_page*) temp_page;
|
const header_page* header = (header_page*) temp_page;
|
||||||
|
|
||||||
if (header->hdr_header.pag_type != pag_header || header->hdr_sequence)
|
if (header->hdr_header.pag_type != pag_header || header->hdr_sequence)
|
||||||
|
@ -610,6 +610,10 @@ int gstat(Firebird::UtilSvc* uSvc)
|
|||||||
expandDatabaseName(fileName, tempStr, NULL);
|
expandDatabaseName(fileName, tempStr, NULL);
|
||||||
fileName = tempStr;
|
fileName = tempStr;
|
||||||
|
|
||||||
|
// If file will be opened with no buffering (direct IO), make sure that
|
||||||
|
// temp buffer is aligned on the disk physical sector size and IO size
|
||||||
|
// is multiply of sector size.
|
||||||
|
|
||||||
dba_fil* current = db_open(fileName.c_str(), fileName.length());
|
dba_fil* current = db_open(fileName.c_str(), fileName.length());
|
||||||
|
|
||||||
SCHAR temp[RAW_HEADER_SIZE];
|
SCHAR temp[RAW_HEADER_SIZE];
|
||||||
|
@ -79,12 +79,6 @@
|
|||||||
#define O_LARGEFILE 0
|
#define O_LARGEFILE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// How much we align memory when reading database header.
|
|
||||||
// Sector alignment of memory is necessary to use unbuffered IO on Windows.
|
|
||||||
// Actually, sectors may be bigger than 1K, but let's be consistent with
|
|
||||||
// JRD regarding the matter for the moment.
|
|
||||||
const FB_SIZE_T SECTOR_ALIGNMENT = PAGE_ALIGNMENT;
|
|
||||||
|
|
||||||
using namespace Firebird;
|
using namespace Firebird;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -1199,7 +1193,7 @@ void NBackup::backup_database(int level, Guid& guid, const PathName& fname)
|
|||||||
ULONG prev_scn = 0;
|
ULONG prev_scn = 0;
|
||||||
char prev_guid[GUID_BUFF_SIZE] = "";
|
char prev_guid[GUID_BUFF_SIZE] = "";
|
||||||
char str_guid[GUID_BUFF_SIZE] = "";
|
char str_guid[GUID_BUFF_SIZE] = "";
|
||||||
Ods::pag* page_buff = NULL;
|
|
||||||
attach_database();
|
attach_database();
|
||||||
ULONG page_writes = 0, page_reads = 0;
|
ULONG page_writes = 0, page_reads = 0;
|
||||||
|
|
||||||
@ -1339,12 +1333,18 @@ void NBackup::backup_database(int level, Guid& guid, const PathName& fname)
|
|||||||
open_database_scan();
|
open_database_scan();
|
||||||
|
|
||||||
// Read database header
|
// Read database header
|
||||||
char unaligned_header_buffer[RAW_HEADER_SIZE + SECTOR_ALIGNMENT];
|
|
||||||
|
|
||||||
auto header = reinterpret_cast<Ods::header_page*>(
|
const ULONG sectorSize = os_utils::getPhysicalSectorSize(dbname);
|
||||||
FB_ALIGN(unaligned_header_buffer, SECTOR_ALIGNMENT));
|
const ULONG headerSize = MAX(RAW_HEADER_SIZE, sectorSize);
|
||||||
|
|
||||||
if (read_file(dbase, header, RAW_HEADER_SIZE) != RAW_HEADER_SIZE)
|
Array<UCHAR> unaligned_header_buffer;
|
||||||
|
Ods::header_page* header = nullptr;
|
||||||
|
{ // scope
|
||||||
|
UCHAR* buf = unaligned_header_buffer.getBuffer(headerSize + sectorSize);
|
||||||
|
header = reinterpret_cast<Ods::header_page*>(FB_ALIGN(buf, sectorSize));
|
||||||
|
} // end scope
|
||||||
|
|
||||||
|
if (read_file(dbase, header, headerSize) != headerSize)
|
||||||
status_exception::raise(Arg::Gds(isc_nbackup_err_eofhdrdb) << dbname.c_str() << Arg::Num(1));
|
status_exception::raise(Arg::Gds(isc_nbackup_err_eofhdrdb) << dbname.c_str() << Arg::Num(1));
|
||||||
|
|
||||||
if (!Ods::isSupported(header))
|
if (!Ods::isSupported(header))
|
||||||
@ -1361,9 +1361,10 @@ void NBackup::backup_database(int level, Guid& guid, const PathName& fname)
|
|||||||
status_exception::raise(Arg::Gds(isc_nbackup_db_notlock) << Arg::Num(header->hdr_flags));
|
status_exception::raise(Arg::Gds(isc_nbackup_db_notlock) << Arg::Num(header->hdr_flags));
|
||||||
|
|
||||||
Array<UCHAR> unaligned_page_buffer;
|
Array<UCHAR> unaligned_page_buffer;
|
||||||
|
Ods::pag* page_buff = nullptr;
|
||||||
{ // scope
|
{ // scope
|
||||||
UCHAR* buf = unaligned_page_buffer.getBuffer(header->hdr_page_size + SECTOR_ALIGNMENT);
|
UCHAR* buf = unaligned_page_buffer.getBuffer(header->hdr_page_size + sectorSize);
|
||||||
page_buff = reinterpret_cast<Ods::pag*>(FB_ALIGN(buf, SECTOR_ALIGNMENT));
|
page_buff = reinterpret_cast<Ods::pag*>(FB_ALIGN(buf, sectorSize));
|
||||||
} // end scope
|
} // end scope
|
||||||
|
|
||||||
ULONG db_size = db_size_pages;
|
ULONG db_size = db_size_pages;
|
||||||
@ -1430,8 +1431,8 @@ void NBackup::backup_database(int level, Guid& guid, const PathName& fname)
|
|||||||
Array<UCHAR> unaligned_scns_buffer;
|
Array<UCHAR> unaligned_scns_buffer;
|
||||||
Ods::scns_page* scns = NULL, *scns_buf = NULL;
|
Ods::scns_page* scns = NULL, *scns_buf = NULL;
|
||||||
{ // scope
|
{ // scope
|
||||||
UCHAR* buf = unaligned_scns_buffer.getBuffer(header->hdr_page_size + SECTOR_ALIGNMENT);
|
UCHAR* buf = unaligned_scns_buffer.getBuffer(header->hdr_page_size + sectorSize);
|
||||||
scns_buf = reinterpret_cast<Ods::scns_page*>(FB_ALIGN(buf, SECTOR_ALIGNMENT));
|
scns_buf = reinterpret_cast<Ods::scns_page*>(FB_ALIGN(buf, sectorSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
Loading…
Reference in New Issue
Block a user