Support dynamic sector size in alignment validation for Windows. (#8613)

Summary:
- Use dynamic section size when calling IsSectorAligned()
- Support relative path for GetSectorSize().
- Move buffer and sector alignment check to assert for better retail performance.
- Typo fixes.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/8613

Reviewed By: ajkr

Differential Revision: D30136082

Pulled By: mrambacher

fbshipit-source-id: e8cb849befdcae4fea99de5ed5dd6565e612425f
This commit is contained in:
Burton Li 2021-08-16 07:30:57 -07:00 committed by Facebook GitHub Bot
parent 48c468c22e
commit 9b0a32f802
3 changed files with 56 additions and 47 deletions

View File

@ -347,8 +347,7 @@ IOStatus WinFileSystem::NewRandomAccessFile(
fileGuard.release();
}
} else {
result->reset(new WinRandomAccessFile(
fname, hFile, std::max(GetSectorSize(fname), page_size_), options));
result->reset(new WinRandomAccessFile(fname, hFile, page_size_, options));
fileGuard.release();
}
return s;
@ -433,9 +432,8 @@ IOStatus WinFileSystem::OpenWritableFile(
} else {
// Here we want the buffer allocation to be aligned by the SSD page size
// and to be a multiple of it
result->reset(new WinWritableFile(
fname, hFile, std::max(GetSectorSize(fname), GetPageSize()),
c_BufferCapacity, local_options));
result->reset(new WinWritableFile(fname, hFile, GetPageSize(),
c_BufferCapacity, local_options));
}
return s;
}
@ -487,8 +485,7 @@ IOStatus WinFileSystem::NewRandomRWFile(const std::string& fname,
}
UniqueCloseHandlePtr fileGuard(hFile, CloseHandleFunc);
result->reset(new WinRandomRWFile(
fname, hFile, std::max(GetSectorSize(fname), GetPageSize()), options));
result->reset(new WinRandomRWFile(fname, hFile, GetPageSize(), options));
fileGuard.release();
return s;
@ -1183,13 +1180,23 @@ bool WinFileSystem::DirExists(const std::string& dname) {
size_t WinFileSystem::GetSectorSize(const std::string& fname) {
size_t sector_size = kSectorSize;
if (RX_PathIsRelative(RX_FN(fname).c_str())) {
return sector_size;
}
// obtain device handle
char devicename[7] = "\\\\.\\";
int erresult = strncat_s(devicename, sizeof(devicename), fname.c_str(), 2);
int erresult = 0;
if (RX_PathIsRelative(RX_FN(fname).c_str())) {
RX_FILESTRING rx_current_dir;
rx_current_dir.resize(MAX_PATH);
DWORD len = RX_GetCurrentDirectory(MAX_PATH, &rx_current_dir[0]);
if (len == 0) {
return sector_size;
}
rx_current_dir.resize(len);
std::string current_dir = FN_TO_RX(rx_current_dir);
erresult =
strncat_s(devicename, sizeof(devicename), current_dir.c_str(), 2);
} else {
erresult = strncat_s(devicename, sizeof(devicename), fname.c_str(), 2);
}
if (erresult) {
assert(false);

View File

@ -11,6 +11,7 @@
#include "port/win/io_win.h"
#include "env_win.h"
#include "monitoring/iostats_context_imp.h"
#include "test_util/sync_point.h"
#include "util/aligned_buffer.h"
@ -30,10 +31,6 @@ inline bool IsPowerOfTwo(const size_t alignment) {
return ((alignment) & (alignment - 1)) == 0;
}
inline bool IsSectorAligned(const size_t off) {
return (off & (kSectorSize - 1)) == 0;
}
inline bool IsAligned(size_t alignment, const void* ptr) {
return ((uintptr_t(ptr)) & (alignment - 1)) == 0;
}
@ -186,6 +183,17 @@ size_t GetUniqueIdFromFile(HANDLE /*hFile*/, char* /*id*/,
return 0;
}
WinFileData::WinFileData(const std::string& filename, HANDLE hFile,
bool direct_io)
: filename_(filename),
hFile_(hFile),
use_direct_io_(direct_io),
sector_size_(WinFileSystem::GetSectorSize(filename)) {}
bool WinFileData::IsSectorAligned(const size_t off) const {
return (off & (sector_size_ - 1)) == 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// WinMmapReadableFile
@ -624,10 +632,8 @@ IOStatus WinSequentialFile::PositionedRead(uint64_t offset, size_t n,
return IOStatus::NotSupported("This function is only used for direct_io");
}
if (!IsSectorAligned(static_cast<size_t>(offset)) || !IsSectorAligned(n)) {
return IOStatus::InvalidArgument(
"WinSequentialFile::PositionedRead: offset is not properly aligned");
}
assert(IsSectorAligned(static_cast<size_t>(offset)));
assert(IsSectorAligned(static_cast<size_t>(n)));
size_t bytes_read = 0; // out param
IOStatus s = PositionedReadInternal(scratch, static_cast<size_t>(n), offset,
@ -671,7 +677,8 @@ inline IOStatus WinRandomAccessImpl::PositionedReadInternal(
inline WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base,
size_t alignment,
const FileOptions& options)
: file_base_(file_base), alignment_(alignment) {
: file_base_(file_base),
alignment_(std::max(alignment, file_base->GetSectorSize())) {
assert(!options.use_mmap_reads);
}
@ -680,12 +687,8 @@ inline IOStatus WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n,
char* scratch) const {
// Check buffer alignment
if (file_base_->use_direct_io()) {
if (!IsSectorAligned(static_cast<size_t>(offset)) ||
!IsAligned(alignment_, scratch)) {
return IOStatus::InvalidArgument(
"WinRandomAccessImpl::ReadImpl: offset or scratch is not properly "
"aligned");
}
assert(file_base_->IsSectorAligned(static_cast<size_t>(offset)));
assert(IsAligned(alignment_, scratch));
}
if (n == 0) {
@ -741,7 +744,7 @@ inline IOStatus WinWritableImpl::PreallocateInternal(uint64_t spaceToReserve) {
inline WinWritableImpl::WinWritableImpl(WinFileData* file_data,
size_t alignment)
: file_data_(file_data),
alignment_(alignment),
alignment_(std::max(alignment, file_data->GetSectorSize())),
next_write_offset_(0),
reservedsize_(0) {
// Query current position in case ReopenWritableFile is called
@ -774,14 +777,10 @@ inline IOStatus WinWritableImpl::AppendImpl(const Slice& data) {
if (file_data_->use_direct_io()) {
// With no offset specified we are appending
// to the end of the file
assert(IsSectorAligned(next_write_offset_));
if (!IsSectorAligned(data.size()) ||
!IsAligned(static_cast<size_t>(GetAlignement()), data.data())) {
s = IOStatus::InvalidArgument(
"WriteData must be page aligned, size must be sector aligned");
} else {
s = pwrite(file_data_, data, next_write_offset_, bytes_written);
}
assert(file_data_->IsSectorAligned(next_write_offset_));
assert(file_data_->IsSectorAligned(data.size()));
assert(IsAligned(static_cast<size_t>(GetAlignment()), data.data()));
s = pwrite(file_data_, data, next_write_offset_, bytes_written);
} else {
DWORD bytesWritten = 0;
if (!WriteFile(file_data_->GetFileHandle(), data.data(),
@ -812,12 +811,9 @@ inline IOStatus WinWritableImpl::AppendImpl(const Slice& data) {
inline IOStatus WinWritableImpl::PositionedAppendImpl(const Slice& data,
uint64_t offset) {
if (file_data_->use_direct_io()) {
if (!IsSectorAligned(static_cast<size_t>(offset)) ||
!IsSectorAligned(data.size()) ||
!IsAligned(static_cast<size_t>(GetAlignement()), data.data())) {
return IOStatus::InvalidArgument(
"Data and offset must be page aligned, size must be sector aligned");
}
assert(file_data_->IsSectorAligned(static_cast<size_t>(offset)));
assert(file_data_->IsSectorAligned(data.size()));
assert(IsAligned(static_cast<size_t>(GetAlignment()), data.data()));
}
size_t bytes_written = 0;
@ -929,7 +925,7 @@ bool WinWritableFile::use_direct_io() const {
}
size_t WinWritableFile::GetRequiredBufferAlignment() const {
return static_cast<size_t>(GetAlignement());
return static_cast<size_t>(GetAlignment());
}
IOStatus WinWritableFile::Append(const Slice& data,
@ -1003,7 +999,9 @@ bool WinRandomRWFile::use_direct_io() const {
}
size_t WinRandomRWFile::GetRequiredBufferAlignment() const {
return static_cast<size_t>(GetAlignement());
assert(WinRandomAccessImpl::GetAlignment() ==
WinWritableImpl::GetAlignment());
return static_cast<size_t>(WinRandomAccessImpl::GetAlignment());
}
IOStatus WinRandomRWFile::Write(uint64_t offset, const Slice& data,

View File

@ -67,12 +67,12 @@ class WinFileData {
// will need to be aligned (not sure there is a guarantee that the buffer
// passed in is aligned).
const bool use_direct_io_;
const size_t sector_size_;
public:
// We want this class be usable both for inheritance (prive
// or protected) and for containment so __ctor and __dtor public
WinFileData(const std::string& filename, HANDLE hFile, bool direct_io)
: filename_(filename), hFile_(hFile), use_direct_io_(direct_io) {}
WinFileData(const std::string& filename, HANDLE hFile, bool direct_io);
virtual ~WinFileData() { this->CloseFile(); }
@ -93,6 +93,10 @@ class WinFileData {
bool use_direct_io() const { return use_direct_io_; }
size_t GetSectorSize() const { return sector_size_; }
bool IsSectorAligned(const size_t off) const;
WinFileData(const WinFileData&) = delete;
WinFileData& operator=(const WinFileData&) = delete;
};
@ -321,7 +325,7 @@ class WinWritableImpl {
~WinWritableImpl() {}
uint64_t GetAlignement() const { return alignment_; }
uint64_t GetAlignment() const { return alignment_; }
IOStatus AppendImpl(const Slice& data);