change UseDirectIO() to use_direct_io()

Summary:
also change variable name `direct_io_` to `use_direct_io_` in WritableFile to make it consistent with read path.
Closes https://github.com/facebook/rocksdb/pull/1770

Differential Revision: D4416435

Pulled By: lightmark

fbshipit-source-id: 4143c53
main
Aaron Gao 8 years ago committed by Facebook Github Bot
parent d4e07a8459
commit 3e6899d116
  1. 10
      include/rocksdb/env.h
  2. 14
      port/win/io_win.cc
  3. 10
      port/win/io_win.h
  4. 2
      util/env_test.cc
  5. 6
      util/file_reader_writer.cc
  6. 8
      util/file_reader_writer.h
  7. 6
      util/file_reader_writer_test.cc
  8. 24
      util/io_posix.cc
  9. 8
      util/io_posix.h
  10. 2
      utilities/env_librados.cc

@ -432,7 +432,7 @@ class SequentialFile {
// Indicates the upper layers if the current SequentialFile implementation // Indicates the upper layers if the current SequentialFile implementation
// uses direct IO. // uses direct IO.
virtual bool UseDirectIO() const { return false; } virtual bool use_direct_io() const { return false; }
// Use the returned alignment value to allocate // Use the returned alignment value to allocate
// aligned buffer for Direct I/O // aligned buffer for Direct I/O
@ -508,7 +508,7 @@ class RandomAccessFile {
// Indicates the upper layers if the current RandomAccessFile implementation // Indicates the upper layers if the current RandomAccessFile implementation
// uses direct IO. // uses direct IO.
virtual bool UseDirectIO() const { return false; } virtual bool use_direct_io() const { return false; }
// Use the returned alignment value to allocate // Use the returned alignment value to allocate
// aligned buffer for Direct I/O // aligned buffer for Direct I/O
@ -592,7 +592,7 @@ class WritableFile {
// Indicates the upper layers if the current WritableFile implementation // Indicates the upper layers if the current WritableFile implementation
// uses direct IO. // uses direct IO.
virtual bool UseDirectIO() const { return false; } virtual bool use_direct_io() const { return false; }
// Use the returned alignment value to allocate // Use the returned alignment value to allocate
// aligned buffer for Direct I/O // aligned buffer for Direct I/O
@ -707,7 +707,7 @@ class RandomRWFile {
// Indicates if the class makes use of direct I/O // Indicates if the class makes use of direct I/O
// If false you must pass aligned buffer to Write() // If false you must pass aligned buffer to Write()
virtual bool UseDirectIO() const { return false; } virtual bool use_direct_io() const { return false; }
// Use the returned alignment value to allocate // Use the returned alignment value to allocate
// aligned buffer for Direct I/O // aligned buffer for Direct I/O
@ -725,7 +725,7 @@ class RandomRWFile {
virtual void EnableReadAhead() {} virtual void EnableReadAhead() {}
// Write bytes in `data` at offset `offset`, Returns Status::OK() on success. // Write bytes in `data` at offset `offset`, Returns Status::OK() on success.
// Pass aligned buffer when UseDirectIO() returns true. // Pass aligned buffer when use_direct_io() returns true.
virtual Status Write(uint64_t offset, const Slice& data) = 0; virtual Status Write(uint64_t offset, const Slice& data) = 0;
// Read up to `n` bytes starting from offset `offset` and store them in // Read up to `n` bytes starting from offset `offset` and store them in

@ -688,7 +688,7 @@ WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base,
assert(!options.use_mmap_reads); assert(!options.use_mmap_reads);
// Direct access, use internal buffer for reads // Direct access, use internal buffer for reads
if (file_base_->UseDirectIO()) { if (file_base_->use_direct_io()) {
// Do not allocate the buffer either until the first request or // Do not allocate the buffer either until the first request or
// until there is a call to allocate a read-ahead buffer // until there is a call to allocate a read-ahead buffer
buffer_.Alignment(alignment); buffer_.Alignment(alignment);
@ -712,7 +712,7 @@ Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result,
// When in direct I/O mode we need to do the following changes: // When in direct I/O mode we need to do the following changes:
// - use our own aligned buffer // - use our own aligned buffer
// - always read at the offset of that is a multiple of alignment // - always read at the offset of that is a multiple of alignment
if (file_base_->UseDirectIO()) { if (file_base_->use_direct_io()) {
uint64_t first_page_start = 0; uint64_t first_page_start = 0;
size_t actual_bytes_toread = 0; size_t actual_bytes_toread = 0;
size_t bytes_requested = left; size_t bytes_requested = left;
@ -803,7 +803,7 @@ Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result,
inline inline
void WinRandomAccessImpl::HintImpl(RandomAccessFile::AccessPattern pattern) { void WinRandomAccessImpl::HintImpl(RandomAccessFile::AccessPattern pattern) {
if (pattern == RandomAccessFile::SEQUENTIAL && file_base_->UseDirectIO() && if (pattern == RandomAccessFile::SEQUENTIAL && file_base_->use_direct_io() &&
compaction_readahead_size_ > 0) { compaction_readahead_size_ > 0) {
std::lock_guard<std::mutex> lg(buffer_mut_); std::lock_guard<std::mutex> lg(buffer_mut_);
if (!read_ahead_) { if (!read_ahead_) {
@ -879,7 +879,7 @@ Status WinWritableImpl::AppendImpl(const Slice& data) {
uint64_t written = 0; uint64_t written = 0;
if (file_data_->UseDirectIO()) { if (file_data_->use_direct_io()) {
// With no offset specified we are appending // With no offset specified we are appending
// to the end of the file // to the end of the file
@ -925,7 +925,7 @@ Status WinWritableImpl::AppendImpl(const Slice& data) {
Status WinWritableImpl::PositionedAppendImpl(const Slice& data, uint64_t offset) { Status WinWritableImpl::PositionedAppendImpl(const Slice& data, uint64_t offset) {
if(file_data_->UseDirectIO()) { if(file_data_->use_direct_io()) {
assert(IsSectorAligned(offset)); assert(IsSectorAligned(offset));
assert(IsSectorAligned(data.size())); assert(IsSectorAligned(data.size()));
assert(IsAligned(GetAlignement(), data.data())); assert(IsAligned(GetAlignement(), data.data()));
@ -1036,7 +1036,7 @@ WinWritableFile::~WinWritableFile() {
} }
// Indicates if the class makes use of direct I/O // Indicates if the class makes use of direct I/O
bool WinWritableFile::UseDirectIO() const { return WinFileData::UseDirectIO(); } bool WinWritableFile::use_direct_io() const { return WinFileData::use_direct_io(); }
size_t WinWritableFile::GetRequiredBufferAlignment() const { size_t WinWritableFile::GetRequiredBufferAlignment() const {
return GetAlignement(); return GetAlignement();
@ -1094,7 +1094,7 @@ WinRandomRWFile::WinRandomRWFile(const std::string& fname, HANDLE hFile,
WinRandomAccessImpl(this, alignment, options), WinRandomAccessImpl(this, alignment, options),
WinWritableImpl(this, alignment) {} WinWritableImpl(this, alignment) {}
bool WinRandomRWFile::UseDirectIO() const { return WinFileData::UseDirectIO(); } bool WinRandomRWFile::use_direct_io() const { return WinFileData::use_direct_io(); }
size_t WinRandomRWFile::GetRequiredBufferAlignment() const { size_t WinRandomRWFile::GetRequiredBufferAlignment() const {
return GetAlignement(); return GetAlignement();

@ -95,7 +95,7 @@ class WinFileData {
HANDLE GetFileHandle() const { return hFile_; } HANDLE GetFileHandle() const { return hFile_; }
bool UseDirectIO() const { return use_direct_io_; } bool use_direct_io() const { return use_direct_io_; }
WinFileData(const WinFileData&) = delete; WinFileData(const WinFileData&) = delete;
WinFileData& operator=(const WinFileData&) = delete; WinFileData& operator=(const WinFileData&) = delete;
@ -384,7 +384,7 @@ class WinWritableFile : private WinFileData,
// Indicates if the class makes use of direct I/O // Indicates if the class makes use of direct I/O
// Use PositionedAppend // Use PositionedAppend
virtual bool UseDirectIO() const override; virtual bool use_direct_io() const override;
virtual size_t GetRequiredBufferAlignment() const override; virtual size_t GetRequiredBufferAlignment() const override;
@ -427,10 +427,10 @@ class WinRandomRWFile : private WinFileData,
// Indicates if the class makes use of direct I/O // Indicates if the class makes use of direct I/O
// If false you must pass aligned buffer to Write() // If false you must pass aligned buffer to Write()
virtual bool UseDirectIO() const override; virtual bool use_direct_io() const override;
// Use the returned alignment value to allocate aligned // Use the returned alignment value to allocate aligned
// buffer for Write() when UseDirectIO() returns true // buffer for Write() when use_direct_io() returns true
virtual size_t GetRequiredBufferAlignment() const override; virtual size_t GetRequiredBufferAlignment() const override;
// Used by the file_reader_writer to decide if the ReadAhead wrapper // Used by the file_reader_writer to decide if the ReadAhead wrapper
@ -444,7 +444,7 @@ class WinRandomRWFile : private WinFileData,
virtual void EnableReadAhead() override; virtual void EnableReadAhead() override;
// Write bytes in `data` at offset `offset`, Returns Status::OK() on success. // Write bytes in `data` at offset `offset`, Returns Status::OK() on success.
// Pass aligned buffer when UseDirectIO() returns true. // Pass aligned buffer when use_direct_io() returns true.
virtual Status Write(uint64_t offset, const Slice& data) override; virtual Status Write(uint64_t offset, const Slice& data) override;
// Read up to `n` bytes starting from offset `offset` and store them in // Read up to `n` bytes starting from offset `offset` and store them in

@ -969,7 +969,7 @@ TEST_P(EnvPosixTestWithParam, InvalidateCache) {
} }
#endif #endif
ASSERT_OK(env_->NewSequentialFile(fname, &file, soptions)); ASSERT_OK(env_->NewSequentialFile(fname, &file, soptions));
if (file->UseDirectIO()) { if (file->use_direct_io()) {
ASSERT_OK(file->PositionedRead(0, kSectorSize, &result, scratch.get())); ASSERT_OK(file->PositionedRead(0, kSectorSize, &result, scratch.get()));
} else { } else {
ASSERT_OK(file->Read(kSectorSize, &result, scratch.get())); ASSERT_OK(file->Read(kSectorSize, &result, scratch.get()));

@ -23,7 +23,7 @@ namespace rocksdb {
Status SequentialFileReader::Read(size_t n, Slice* result, char* scratch) { Status SequentialFileReader::Read(size_t n, Slice* result, char* scratch) {
Status s; Status s;
if (UseDirectIO()) { if (use_direct_io()) {
size_t offset = offset_.fetch_add(n); size_t offset = offset_.fetch_add(n);
size_t alignment = file_->GetRequiredBufferAlignment(); size_t alignment = file_->GetRequiredBufferAlignment();
size_t aligned_offset = TruncateToPageBoundary(alignment, offset); size_t aligned_offset = TruncateToPageBoundary(alignment, offset);
@ -73,7 +73,7 @@ Status SequentialFileReader::DirectRead(size_t n, Slice* result,
} }
Status SequentialFileReader::Skip(uint64_t n) { Status SequentialFileReader::Skip(uint64_t n) {
if (UseDirectIO()) { if (use_direct_io()) {
offset_ += n; offset_ += n;
return Status::OK(); return Status::OK();
} else { } else {
@ -89,7 +89,7 @@ Status RandomAccessFileReader::Read(uint64_t offset, size_t n, Slice* result,
StopWatch sw(env_, stats_, hist_type_, StopWatch sw(env_, stats_, hist_type_,
(stats_ != nullptr) ? &elapsed : nullptr); (stats_ != nullptr) ? &elapsed : nullptr);
IOSTATS_TIMER_GUARD(read_nanos); IOSTATS_TIMER_GUARD(read_nanos);
if (UseDirectIO()) { if (use_direct_io()) {
size_t alignment = file_->GetRequiredBufferAlignment(); size_t alignment = file_->GetRequiredBufferAlignment();
size_t aligned_offset = TruncateToPageBoundary(alignment, offset); size_t aligned_offset = TruncateToPageBoundary(alignment, offset);
size_t offset_advance = offset - aligned_offset; size_t offset_advance = offset - aligned_offset;

@ -48,7 +48,7 @@ class SequentialFileReader {
SequentialFile* file() { return file_.get(); } SequentialFile* file() { return file_.get(); }
bool UseDirectIO() const { return file_->UseDirectIO(); } bool use_direct_io() const { return file_->use_direct_io(); }
protected: protected:
Status DirectRead(size_t n, Slice* result, char* scratch); Status DirectRead(size_t n, Slice* result, char* scratch);
@ -94,7 +94,7 @@ class RandomAccessFileReader {
RandomAccessFile* file() { return file_.get(); } RandomAccessFile* file() { return file_.get(); }
bool UseDirectIO() const { return file_->UseDirectIO(); } bool use_direct_io() const { return file_->use_direct_io(); }
protected: protected:
Status DirectRead(uint64_t offset, size_t n, Slice* result, Status DirectRead(uint64_t offset, size_t n, Slice* result,
@ -129,7 +129,7 @@ class WritableFileWriter {
filesize_(0), filesize_(0),
next_write_offset_(0), next_write_offset_(0),
pending_sync_(false), pending_sync_(false),
direct_io_(writable_file_->UseDirectIO()), direct_io_(writable_file_->use_direct_io()),
last_sync_size_(0), last_sync_size_(0),
bytes_per_sync_(options.bytes_per_sync), bytes_per_sync_(options.bytes_per_sync),
rate_limiter_(options.rate_limiter) { rate_limiter_(options.rate_limiter) {
@ -165,7 +165,7 @@ class WritableFileWriter {
WritableFile* writable_file() const { return writable_file_.get(); } WritableFile* writable_file() const { return writable_file_.get(); }
bool UseDirectIO() { return writable_file_->UseDirectIO(); } bool use_direct_io() { return writable_file_->use_direct_io(); }
private: private:
// Used when os buffering is OFF and we are writing // Used when os buffering is OFF and we are writing

@ -90,7 +90,7 @@ TEST_F(WritableFileWriterTest, AppendStatusReturn) {
public: public:
explicit FakeWF() : use_direct_io_(false), io_error_(false) {} explicit FakeWF() : use_direct_io_(false), io_error_(false) {}
virtual bool UseDirectIO() const override { return use_direct_io_; } virtual bool use_direct_io() const override { return use_direct_io_; }
Status Append(const Slice& data) override { Status Append(const Slice& data) override {
if (io_error_) { if (io_error_) {
return Status::IOError("Fake IO error"); return Status::IOError("Fake IO error");
@ -106,7 +106,7 @@ TEST_F(WritableFileWriterTest, AppendStatusReturn) {
Status Close() override { return Status::OK(); } Status Close() override { return Status::OK(); }
Status Flush() override { return Status::OK(); } Status Flush() override { return Status::OK(); }
Status Sync() override { return Status::OK(); } Status Sync() override { return Status::OK(); }
void SetUseDirectIO(bool val) { use_direct_io_ = val; } void Setuse_direct_io(bool val) { use_direct_io_ = val; }
void SetIOError(bool val) { io_error_ = val; } void SetIOError(bool val) { io_error_ = val; }
protected: protected:
@ -114,7 +114,7 @@ TEST_F(WritableFileWriterTest, AppendStatusReturn) {
bool io_error_; bool io_error_;
}; };
unique_ptr<FakeWF> wf(new FakeWF()); unique_ptr<FakeWF> wf(new FakeWF());
wf->SetUseDirectIO(true); wf->Setuse_direct_io(true);
unique_ptr<WritableFileWriter> writer( unique_ptr<WritableFileWriter> writer(
new WritableFileWriter(std::move(wf), EnvOptions())); new WritableFileWriter(std::move(wf), EnvOptions()));

@ -82,7 +82,7 @@ PosixSequentialFile::PosixSequentialFile(const std::string& fname, FILE* file,
} }
PosixSequentialFile::~PosixSequentialFile() { PosixSequentialFile::~PosixSequentialFile() {
if (!UseDirectIO()) { if (!use_direct_io()) {
assert(file_); assert(file_);
fclose(file_); fclose(file_);
} else { } else {
@ -92,7 +92,7 @@ PosixSequentialFile::~PosixSequentialFile() {
} }
Status PosixSequentialFile::Read(size_t n, Slice* result, char* scratch) { Status PosixSequentialFile::Read(size_t n, Slice* result, char* scratch) {
assert(result != nullptr && !UseDirectIO()); assert(result != nullptr && !use_direct_io());
Status s; Status s;
size_t r = 0; size_t r = 0;
do { do {
@ -122,7 +122,7 @@ Status PosixSequentialFile::PositionedRead(uint64_t offset, size_t n,
ssize_t r = -1; ssize_t r = -1;
size_t left = n; size_t left = n;
char* ptr = scratch; char* ptr = scratch;
assert(UseDirectIO()); assert(use_direct_io());
while (left > 0) { while (left > 0) {
r = pread(fd_, ptr, left, static_cast<off_t>(offset)); r = pread(fd_, ptr, left, static_cast<off_t>(offset));
if (r <= 0) { if (r <= 0) {
@ -159,7 +159,7 @@ Status PosixSequentialFile::InvalidateCache(size_t offset, size_t length) {
#ifndef OS_LINUX #ifndef OS_LINUX
return Status::OK(); return Status::OK();
#else #else
if (!UseDirectIO()) { if (!use_direct_io()) {
// free OS pages // free OS pages
int ret = Fadvise(fd_, offset, length, POSIX_FADV_DONTNEED); int ret = Fadvise(fd_, offset, length, POSIX_FADV_DONTNEED);
if (ret != 0) { if (ret != 0) {
@ -254,7 +254,7 @@ Status PosixRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result,
ptr += r; ptr += r;
offset += r; offset += r;
left -= r; left -= r;
if (UseDirectIO() && if (use_direct_io() &&
r % static_cast<ssize_t>(GetRequiredBufferAlignment()) != 0) { r % static_cast<ssize_t>(GetRequiredBufferAlignment()) != 0) {
// Bytes reads don't fill sectors. Should only happen at the end // Bytes reads don't fill sectors. Should only happen at the end
// of the file. // of the file.
@ -265,7 +265,7 @@ Status PosixRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result,
// An error: return a non-ok status // An error: return a non-ok status
s = IOError(filename_, errno); s = IOError(filename_, errno);
} }
if (!UseDirectIO()) { if (!use_direct_io()) {
// we need to fadvise away the entire range of pages because // we need to fadvise away the entire range of pages because
// we do not want readahead pages to be cached. // we do not want readahead pages to be cached.
Fadvise(fd_, 0, 0, POSIX_FADV_DONTNEED); // free OS pages Fadvise(fd_, 0, 0, POSIX_FADV_DONTNEED); // free OS pages
@ -281,7 +281,7 @@ size_t PosixRandomAccessFile::GetUniqueId(char* id, size_t max_size) const {
#endif #endif
void PosixRandomAccessFile::Hint(AccessPattern pattern) { void PosixRandomAccessFile::Hint(AccessPattern pattern) {
if (UseDirectIO()) { if (use_direct_io()) {
return; return;
} }
switch (pattern) { switch (pattern) {
@ -307,7 +307,7 @@ void PosixRandomAccessFile::Hint(AccessPattern pattern) {
} }
Status PosixRandomAccessFile::InvalidateCache(size_t offset, size_t length) { Status PosixRandomAccessFile::InvalidateCache(size_t offset, size_t length) {
if (UseDirectIO()) { if (use_direct_io()) {
return Status::OK(); return Status::OK();
} }
#ifndef OS_LINUX #ifndef OS_LINUX
@ -604,7 +604,7 @@ Status PosixMmapFile::Allocate(uint64_t offset, uint64_t len) {
PosixWritableFile::PosixWritableFile(const std::string& fname, int fd, PosixWritableFile::PosixWritableFile(const std::string& fname, int fd,
const EnvOptions& options) const EnvOptions& options)
: filename_(fname), : filename_(fname),
direct_io_(options.use_direct_writes), use_direct_io_(options.use_direct_writes),
fd_(fd), fd_(fd),
filesize_(0) { filesize_(0) {
#ifdef ROCKSDB_FALLOCATE_PRESENT #ifdef ROCKSDB_FALLOCATE_PRESENT
@ -621,7 +621,7 @@ PosixWritableFile::~PosixWritableFile() {
} }
Status PosixWritableFile::Append(const Slice& data) { Status PosixWritableFile::Append(const Slice& data) {
assert(!direct_io_|| (IsSectorAligned(data.size()) && IsPageAligned(data.data()))); assert(!use_direct_io() || (IsSectorAligned(data.size()) && IsPageAligned(data.data())));
const char* src = data.data(); const char* src = data.data();
size_t left = data.size(); size_t left = data.size();
while (left != 0) { while (left != 0) {
@ -640,7 +640,7 @@ Status PosixWritableFile::Append(const Slice& data) {
} }
Status PosixWritableFile::PositionedAppend(const Slice& data, uint64_t offset) { Status PosixWritableFile::PositionedAppend(const Slice& data, uint64_t offset) {
assert(direct_io_ && IsSectorAligned(offset) && assert(use_direct_io() && IsSectorAligned(offset) &&
IsSectorAligned(data.size()) && IsPageAligned(data.data())); IsSectorAligned(data.size()) && IsPageAligned(data.data()));
assert(offset <= std::numeric_limits<off_t>::max()); assert(offset <= std::numeric_limits<off_t>::max());
const char* src = data.data(); const char* src = data.data();
@ -727,7 +727,7 @@ bool PosixWritableFile::IsSyncThreadSafe() const { return true; }
uint64_t PosixWritableFile::GetFileSize() { return filesize_; } uint64_t PosixWritableFile::GetFileSize() { return filesize_; }
Status PosixWritableFile::InvalidateCache(size_t offset, size_t length) { Status PosixWritableFile::InvalidateCache(size_t offset, size_t length) {
if (direct_io_) { if (use_direct_io()) {
return Status::OK(); return Status::OK();
} }
#ifndef OS_LINUX #ifndef OS_LINUX

@ -53,7 +53,7 @@ class PosixSequentialFile : public SequentialFile {
char* scratch) override; char* scratch) override;
virtual Status Skip(uint64_t n) override; virtual Status Skip(uint64_t n) override;
virtual Status InvalidateCache(size_t offset, size_t length) override; virtual Status InvalidateCache(size_t offset, size_t length) override;
virtual bool UseDirectIO() const override { return use_direct_io_; } virtual bool use_direct_io() const override { return use_direct_io_; }
}; };
class PosixRandomAccessFile : public RandomAccessFile { class PosixRandomAccessFile : public RandomAccessFile {
@ -74,13 +74,13 @@ class PosixRandomAccessFile : public RandomAccessFile {
#endif #endif
virtual void Hint(AccessPattern pattern) override; virtual void Hint(AccessPattern pattern) override;
virtual Status InvalidateCache(size_t offset, size_t length) override; virtual Status InvalidateCache(size_t offset, size_t length) override;
virtual bool UseDirectIO() const override { return use_direct_io_; } virtual bool use_direct_io() const override { return use_direct_io_; }
}; };
class PosixWritableFile : public WritableFile { class PosixWritableFile : public WritableFile {
protected: protected:
const std::string filename_; const std::string filename_;
const bool direct_io_; const bool use_direct_io_;
int fd_; int fd_;
uint64_t filesize_; uint64_t filesize_;
#ifdef ROCKSDB_FALLOCATE_PRESENT #ifdef ROCKSDB_FALLOCATE_PRESENT
@ -103,7 +103,7 @@ class PosixWritableFile : public WritableFile {
virtual Status Sync() override; virtual Status Sync() override;
virtual Status Fsync() override; virtual Status Fsync() override;
virtual bool IsSyncThreadSafe() const override; virtual bool IsSyncThreadSafe() const override;
virtual bool UseDirectIO() const override { return direct_io_; } virtual bool use_direct_io() const override { return use_direct_io_; }
virtual uint64_t GetFileSize() override; virtual uint64_t GetFileSize() override;
virtual size_t GetRequiredBufferAlignment() const override { virtual size_t GetRequiredBufferAlignment() const override {
// TODO(gzh): It should be the logical sector size/filesystem block size // TODO(gzh): It should be the logical sector size/filesystem block size

@ -454,7 +454,7 @@ public:
* @details [long description] * @details [long description]
* @return [description] * @return [description]
*/ */
bool UseDirectIO() const { bool use_direct_io() const {
return false; return false;
} }

Loading…
Cancel
Save