]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rocksdb/port/win/io_win.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / port / win / io_win.cc
index f8d1c3dbb83cf67e745409b342a203b5e8f958bc..4fa735518f7b49226594df7ab51ebab5219c9421 100644 (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"
@@ -20,39 +21,34 @@ namespace ROCKSDB_NAMESPACE {
 namespace port {
 
 /*
-* DirectIOHelper
-*/
+ * DirectIOHelper
+ */
 namespace {
 
 const size_t kSectorSize = 512;
 
-inline
-bool IsPowerOfTwo(const size_t alignment) {
+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) {
+inline bool IsAligned(size_t alignment, const void* ptr) {
   return ((uintptr_t(ptr)) & (alignment - 1)) == 0;
 }
-}
-
+}  // namespace
 
 std::string GetWindowsErrSz(DWORD err) {
-  LPSTR lpMsgBuf;
+  std::string Err;
+  LPSTR lpMsgBuf = nullptr;
   FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
-    FORMAT_MESSAGE_IGNORE_INSERTS,
-    NULL, err,
-    0,  // Default language
-    reinterpret_cast<LPSTR>(&lpMsgBuf), 0, NULL);
-
-  std::string Err = lpMsgBuf;
-  LocalFree(lpMsgBuf);
+                     FORMAT_MESSAGE_IGNORE_INSERTS,
+                 NULL, err,
+                 0,  // Default language
+                 reinterpret_cast<LPSTR>(&lpMsgBuf), 0, NULL);
+
+  if (lpMsgBuf) {
+    Err = lpMsgBuf;
+    LocalFree(lpMsgBuf);
+  }
   return Err;
 }
 
@@ -69,21 +65,20 @@ std::string GetWindowsErrSz(DWORD err) {
 // Because all the reads/writes happen by the specified offset, the caller in
 // theory should not
 // rely on the current file offset.
-Status pwrite(const WinFileData* file_data, const Slice& data,
-  uint64_t offset, size_t& bytes_written) {
-
-  Status s;
+IOStatus pwrite(const WinFileData* file_data, const Slice& data,
+                uint64_t offset, size_t& bytes_written) {
+  IOStatus s;
   bytes_written = 0;
 
   size_t num_bytes = data.size();
   if (num_bytes > std::numeric_limits<DWORD>::max()) {
     // May happen in 64-bit builds where size_t is 64-bits but
     // long is still 32-bit, but that's the API here at the moment
-    return Status::InvalidArgument("num_bytes is too large for a single write: " +
-          file_data->GetName());
+    return IOStatus::InvalidArgument(
+        "num_bytes is too large for a single write: " + file_data->GetName());
   }
 
-  OVERLAPPED overlapped = { 0 };
+  OVERLAPPED overlapped = {0};
   ULARGE_INTEGER offsetUnion;
   offsetUnion.QuadPart = offset;
 
@@ -92,11 +87,12 @@ Status pwrite(const WinFileData* file_data, const Slice& data,
 
   DWORD bytesWritten = 0;
 
-  if (FALSE == WriteFile(file_data->GetFileHandle(), data.data(), static_cast<DWORD>(num_bytes),
-    &bytesWritten, &overlapped)) {
+  if (FALSE == WriteFile(file_data->GetFileHandle(), data.data(),
+                         static_cast<DWORD>(num_bytes), &bytesWritten,
+                         &overlapped)) {
     auto lastError = GetLastError();
     s = IOErrorFromWindowsError("WriteFile failed: " + file_data->GetName(),
-      lastError);
+                                lastError);
   } else {
     bytes_written = bytesWritten;
   }
@@ -105,18 +101,17 @@ Status pwrite(const WinFileData* file_data, const Slice& data,
 }
 
 // See comments for pwrite above
-Status pread(const WinFileData* file_data, char* src, size_t num_bytes,
-  uint64_t offset, size_t& bytes_read) {
-
-  Status s;
+IOStatus pread(const WinFileData* file_data, char* src, size_t num_bytes,
+               uint64_t offset, size_t& bytes_read) {
+  IOStatus s;
   bytes_read = 0;
 
   if (num_bytes > std::numeric_limits<DWORD>::max()) {
-    return Status::InvalidArgument("num_bytes is too large for a single read: " +
-      file_data->GetName());
+    return IOStatus::InvalidArgument(
+        "num_bytes is too large for a single read: " + file_data->GetName());
   }
 
-  OVERLAPPED overlapped = { 0 };
+  OVERLAPPED overlapped = {0};
   ULARGE_INTEGER offsetUnion;
   offsetUnion.QuadPart = offset;
 
@@ -125,13 +120,14 @@ Status pread(const WinFileData* file_data, char* src, size_t num_bytes,
 
   DWORD bytesRead = 0;
 
-  if (FALSE == ReadFile(file_data->GetFileHandle(), src, static_cast<DWORD>(num_bytes),
-    &bytesRead, &overlapped)) {
+  if (FALSE == ReadFile(file_data->GetFileHandle(), src,
+                        static_cast<DWORD>(num_bytes), &bytesRead,
+                        &overlapped)) {
     auto lastError = GetLastError();
     // EOF is OK with zero bytes read
     if (lastError != ERROR_HANDLE_EOF) {
       s = IOErrorFromWindowsError("ReadFile failed: " + file_data->GetName(),
-        lastError);
+                                  lastError);
     }
   } else {
     bytes_read = bytesRead;
@@ -143,35 +139,34 @@ Status pread(const WinFileData* file_data, char* src, size_t num_bytes,
 // SetFileInformationByHandle() is capable of fast pre-allocates.
 // However, this does not change the file end position unless the file is
 // truncated and the pre-allocated space is not considered filled with zeros.
-Status fallocate(const std::string& filename, HANDLE hFile,
-  uint64_t to_size) {
-  Status status;
+IOStatus fallocate(const std::string& filename, HANDLE hFile,
+                   uint64_t to_size) {
+  IOStatus status;
 
   FILE_ALLOCATION_INFO alloc_info;
   alloc_info.AllocationSize.QuadPart = to_size;
 
   if (!SetFileInformationByHandle(hFile, FileAllocationInfo, &alloc_info,
-    sizeof(FILE_ALLOCATION_INFO))) {
+                                  sizeof(FILE_ALLOCATION_INFO))) {
     auto lastError = GetLastError();
     status = IOErrorFromWindowsError(
-      "Failed to pre-allocate space: " + filename, lastError);
+        "Failed to pre-allocate space: " + filename, lastError);
   }
 
   return status;
 }
 
-Status ftruncate(const std::string& filename, HANDLE hFile,
-  uint64_t toSize) {
-  Status status;
+IOStatus ftruncate(const std::string& filename, HANDLE hFile, uint64_t toSize) {
+  IOStatus status;
 
   FILE_END_OF_FILE_INFO end_of_file;
   end_of_file.EndOfFile.QuadPart = toSize;
 
   if (!SetFileInformationByHandle(hFile, FileEndOfFileInfo, &end_of_file,
-    sizeof(FILE_END_OF_FILE_INFO))) {
+                                  sizeof(FILE_END_OF_FILE_INFO))) {
     auto lastError = GetLastError();
     status = IOErrorFromWindowsError("Failed to Set end of file: " + filename,
-      lastError);
+                                     lastError);
   }
 
   return status;
@@ -191,6 +186,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
 
@@ -212,9 +218,11 @@ WinMmapReadableFile::~WinMmapReadableFile() {
   assert(ret);
 }
 
-Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result,
-  char* scratch) const {
-  Status s;
+IOStatus WinMmapReadableFile::Read(uint64_t offset, size_t n,
+                                   const IOOptions& /*options*/, Slice* result,
+                                   char* scratch,
+                                   IODebugContext* /*dbg*/) const {
+  IOStatus s;
 
   if (offset > length_) {
     *result = Slice();
@@ -222,13 +230,12 @@ Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result,
   } else if (offset + n > length_) {
     n = length_ - static_cast<size_t>(offset);
   }
-  *result =
-    Slice(reinterpret_cast<const char*>(mapped_region_)+offset, n);
+  *result = Slice(reinterpret_cast<const char*>(mapped_region_) + offset, n);
   return s;
 }
 
-Status WinMmapReadableFile::InvalidateCache(size_t offset, size_t length) {
-  return Status::OK();
+IOStatus WinMmapReadableFile::InvalidateCache(size_t offset, size_t length) {
+  return IOStatus::OK();
 }
 
 size_t WinMmapReadableFile::GetUniqueId(char* id, size_t max_size) const {
@@ -238,20 +245,19 @@ size_t WinMmapReadableFile::GetUniqueId(char* id, size_t max_size) const {
 ///////////////////////////////////////////////////////////////////////////////
 /// WinMmapFile
 
-
 // Can only truncate or reserve to a sector size aligned if
 // used on files that are opened with Unbuffered I/O
-Status WinMmapFile::TruncateFile(uint64_t toSize) {
+IOStatus WinMmapFile::TruncateFile(uint64_t toSize) {
   return ftruncate(filename_, hFile_, toSize);
 }
 
-Status WinMmapFile::UnmapCurrentRegion() {
-  Status status;
+IOStatus WinMmapFile::UnmapCurrentRegion() {
+  IOStatus status;
 
   if (mapped_begin_ != nullptr) {
     if (!::UnmapViewOfFile(mapped_begin_)) {
       status = IOErrorFromWindowsError(
-        "Failed to unmap file view: " + filename_, GetLastError());
+          "Failed to unmap file view: " + filename_, GetLastError());
     }
 
     // Move on to the next portion of the file
@@ -271,16 +277,16 @@ Status WinMmapFile::UnmapCurrentRegion() {
   return status;
 }
 
-Status WinMmapFile::MapNewRegion() {
-
-  Status status;
+IOStatus WinMmapFile::MapNewRegion(const IOOptions& options,
+                                   IODebugContext* dbg) {
+  IOStatus status;
 
   assert(mapped_begin_ == nullptr);
 
   size_t minDiskSize = static_cast<size_t>(file_offset_) + view_size_;
 
   if (minDiskSize > reserved_size_) {
-    status = Allocate(file_offset_, view_size_);
+    status = Allocate(file_offset_, view_size_, options, dbg);
     if (!status.ok()) {
       return status;
     }
@@ -288,7 +294,6 @@ Status WinMmapFile::MapNewRegion() {
 
   // Need to remap
   if (hMap_ == NULL || reserved_size_ > mapping_size_) {
-
     if (hMap_ != NULL) {
       // Unmap the previous one
       BOOL ret __attribute__((__unused__));
@@ -301,18 +306,18 @@ Status WinMmapFile::MapNewRegion() {
     mappingSize.QuadPart = reserved_size_;
 
     hMap_ = CreateFileMappingA(
-      hFile_,
-      NULL,                  // Security attributes
-      PAGE_READWRITE,        // There is not a write only mode for mapping
-      mappingSize.HighPart,  // Enable mapping the whole file but the actual
-      // amount mapped is determined by MapViewOfFile
-      mappingSize.LowPart,
-      NULL);  // Mapping name
+        hFile_,
+        NULL,                  // Security attributes
+        PAGE_READWRITE,        // There is not a write only mode for mapping
+        mappingSize.HighPart,  // Enable mapping the whole file but the actual
+        // amount mapped is determined by MapViewOfFile
+        mappingSize.LowPart,
+        NULL);  // Mapping name
 
     if (NULL == hMap_) {
       return IOErrorFromWindowsError(
-        "WindowsMmapFile failed to create file mapping for: " + filename_,
-        GetLastError());
+          "WindowsMmapFile failed to create file mapping for: " + filename_,
+          GetLastError());
     }
 
     mapping_size_ = reserved_size_;
@@ -323,13 +328,13 @@ Status WinMmapFile::MapNewRegion() {
 
   // View must begin at the granularity aligned offset
   mapped_begin_ = reinterpret_cast<char*>(
-    MapViewOfFileEx(hMap_, FILE_MAP_WRITE, offset.HighPart, offset.LowPart,
-    view_size_, NULL));
+      MapViewOfFileEx(hMap_, FILE_MAP_WRITE, offset.HighPart, offset.LowPart,
+                      view_size_, NULL));
 
   if (!mapped_begin_) {
     status = IOErrorFromWindowsError(
-      "WindowsMmapFile failed to map file view: " + filename_,
-      GetLastError());
+        "WindowsMmapFile failed to map file view: " + filename_,
+        GetLastError());
   } else {
     mapped_end_ = mapped_begin_ + view_size_;
     dst_ = mapped_begin_;
@@ -339,15 +344,15 @@ Status WinMmapFile::MapNewRegion() {
   return status;
 }
 
-Status WinMmapFile::PreallocateInternal(uint64_t spaceToReserve) {
+IOStatus WinMmapFile::PreallocateInternal(uint64_t spaceToReserve) {
   return fallocate(filename_, hFile_, spaceToReserve);
 }
 
 WinMmapFile::WinMmapFile(const std::string& fname, HANDLE hFile,
                          size_t page_size, size_t allocation_granularity,
-                         const EnvOptions& options)
+                         const FileOptions& options)
     : WinFileData(fname, hFile, false),
-      WritableFile(options),
+      FSWritableFile(options),
       hMap_(NULL),
       page_size_(page_size),
       allocation_granularity_(allocation_granularity),
@@ -373,17 +378,19 @@ WinMmapFile::WinMmapFile(const std::string& fname, HANDLE hFile,
 
   // View size must be both the multiple of allocation_granularity AND the
   // page size and the granularity is usually a multiple of a page size.
-  const size_t viewSize = 32 * 1024; // 32Kb similar to the Windows File Cache in buffered mode
+  const size_t viewSize =
+      32 * 1024;  // 32Kb similar to the Windows File Cache in buffered mode
   view_size_ = Roundup(viewSize, allocation_granularity_);
 }
 
 WinMmapFile::~WinMmapFile() {
   if (hFile_) {
-    this->Close();
+    this->Close(IOOptions(), nullptr);
   }
 }
 
-Status WinMmapFile::Append(const Slice& data) {
+IOStatus WinMmapFile::Append(const Slice& data, const IOOptions& options,
+                             IODebugContext* dbg) {
   const char* src = data.data();
   size_t left = data.size();
 
@@ -392,9 +399,9 @@ Status WinMmapFile::Append(const Slice& data) {
     size_t avail = mapped_end_ - dst_;
 
     if (avail == 0) {
-      Status s = UnmapCurrentRegion();
+      IOStatus s = UnmapCurrentRegion();
       if (s.ok()) {
-        s = MapNewRegion();
+        s = MapNewRegion(options, dbg);
       }
 
       if (!s.ok()) {
@@ -416,30 +423,31 @@ Status WinMmapFile::Append(const Slice& data) {
     memset(dst_, 0, bytesToPad);
   }
 
-  return Status::OK();
+  return IOStatus::OK();
 }
 
 // Means Close() will properly take care of truncate
 // and it does not need any additional information
-Status WinMmapFile::Truncate(uint64_t size) {
-  return Status::OK();
+IOStatus WinMmapFile::Truncate(uint64_t size, const IOOptions& /*options*/,
+                               IODebugContext* /*dbg*/) {
+  return IOStatus::OK();
 }
 
-Status WinMmapFile::Close() {
-  Status s;
+IOStatus WinMmapFile::Close(const IOOptions& options, IODebugContext* dbg) {
+  IOStatus s;
 
   assert(NULL != hFile_);
 
   // We truncate to the precise size so no
   // uninitialized data at the end. SetEndOfFile
   // which we use does not write zeros and it is good.
-  uint64_t targetSize = GetFileSize();
+  uint64_t targetSize = GetFileSize(options, dbg);
 
   if (mapped_begin_ != nullptr) {
     // Sync before unmapping to make sure everything
     // is on disk and there is not a lazy writing
     // so we are deterministic with the tests
-    Sync();
+    Sync(options, dbg);
     s = UnmapCurrentRegion();
   }
 
@@ -448,14 +456,13 @@ Status WinMmapFile::Close() {
     if (!ret && s.ok()) {
       auto lastError = GetLastError();
       s = IOErrorFromWindowsError(
-        "Failed to Close mapping for file: " + filename_, lastError);
+          "Failed to Close mapping for file: " + filename_, lastError);
     }
 
     hMap_ = NULL;
   }
 
   if (hFile_ != NULL) {
-
     TruncateFile(targetSize);
 
     BOOL ret = ::CloseHandle(hFile_);
@@ -464,18 +471,22 @@ Status WinMmapFile::Close() {
     if (!ret && s.ok()) {
       auto lastError = GetLastError();
       s = IOErrorFromWindowsError(
-        "Failed to close file map handle: " + filename_, lastError);
+          "Failed to close file map handle: " + filename_, lastError);
     }
   }
 
   return s;
 }
 
-Status WinMmapFile::Flush() { return Status::OK(); }
+IOStatus WinMmapFile::Flush(const IOOptions& /*options*/,
+                            IODebugContext* /*dbg*/) {
+  return IOStatus::OK();
+}
 
 // Flush only data
-Status WinMmapFile::Sync() {
-  Status s;
+IOStatus WinMmapFile::Sync(const IOOptions& /*options*/,
+                           IODebugContext* /*dbg*/) {
+  IOStatus s;
 
   // Some writes occurred since last sync
   if (dst_ > last_sync_) {
@@ -485,15 +496,15 @@ Status WinMmapFile::Sync() {
     assert(dst_ < mapped_end_);
 
     size_t page_begin =
-      TruncateToPageBoundary(page_size_, last_sync_ - mapped_begin_);
+        TruncateToPageBoundary(page_size_, last_sync_ - mapped_begin_);
     size_t page_end =
-      TruncateToPageBoundary(page_size_, dst_ - mapped_begin_ - 1);
+        TruncateToPageBoundary(page_size_, dst_ - mapped_begin_ - 1);
 
     // Flush only the amount of that is a multiple of pages
     if (!::FlushViewOfFile(mapped_begin_ + page_begin,
-      (page_end - page_begin) + page_size_)) {
+                           (page_end - page_begin) + page_size_)) {
       s = IOErrorFromWindowsError("Failed to FlushViewOfFile: " + filename_,
-        GetLastError());
+                                  GetLastError());
     } else {
       last_sync_ = dst_;
     }
@@ -503,16 +514,16 @@ Status WinMmapFile::Sync() {
 }
 
 /**
-* Flush data as well as metadata to stable storage.
-*/
-Status WinMmapFile::Fsync() {
-  Status s = Sync();
+ * Flush data as well as metadata to stable storage.
+ */
+IOStatus WinMmapFile::Fsync(const IOOptions& options, IODebugContext* dbg) {
+  IOStatus s = Sync(options, dbg);
 
   // Flush metadata
   if (s.ok() && pending_sync_) {
     if (!::FlushFileBuffers(hFile_)) {
       s = IOErrorFromWindowsError("Failed to FlushFileBuffers: " + filename_,
-        GetLastError());
+                                  GetLastError());
     }
     pending_sync_ = false;
   }
@@ -521,27 +532,31 @@ Status WinMmapFile::Fsync() {
 }
 
 /**
-* Get the size of valid data in the file. This will not match the
-* size that is returned from the filesystem because we use mmap
-* to extend file by map_size every time.
-*/
-uint64_t WinMmapFile::GetFileSize() {
+ * Get the size of valid data in the file. This will not match the
+ * size that is returned from the filesystem because we use mmap
+ * to extend file by map_size every time.
+ */
+uint64_t WinMmapFile::GetFileSize(const IOOptions& /*options*/,
+                                  IODebugContext* /*dbg*/) {
   size_t used = dst_ - mapped_begin_;
   return file_offset_ + used;
 }
 
-Status WinMmapFile::InvalidateCache(size_t offset, size_t length) {
-  return Status::OK();
+IOStatus WinMmapFile::InvalidateCache(size_t offset, size_t length) {
+  return IOStatus::OK();
 }
 
-Status WinMmapFile::Allocate(uint64_t offset, uint64_t len) {
-  Status status;
-  TEST_KILL_RANDOM("WinMmapFile::Allocate", rocksdb_kill_odds);
+IOStatus WinMmapFile::Allocate(uint64_t offset, uint64_t len,
+                               const IOOptions& /*options*/,
+                               IODebugContext* /*dbg*/) {
+  IOStatus status;
+  TEST_KILL_RANDOM("WinMmapFile::Allocate");
 
   // Make sure that we reserve an aligned amount of space
   // since the reservation block size is driven outside so we want
   // to check if we are ok with reservation here
-  size_t spaceToReserve = Roundup(static_cast<size_t>(offset + len), view_size_);
+  size_t spaceToReserve =
+      Roundup(static_cast<size_t>(offset + len), view_size_);
   // Nothing to do
   if (spaceToReserve <= reserved_size_) {
     return status;
@@ -563,31 +578,34 @@ size_t WinMmapFile::GetUniqueId(char* id, size_t max_size) const {
 // WinSequentialFile
 
 WinSequentialFile::WinSequentialFile(const std::string& fname, HANDLE f,
-                                     const EnvOptions& options)
+                                     const FileOptions& options)
     : WinFileData(fname, f, options.use_direct_reads) {}
 
 WinSequentialFile::~WinSequentialFile() {
   assert(hFile_ != INVALID_HANDLE_VALUE);
 }
 
-Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
-  Status s;
+IOStatus WinSequentialFile::Read(size_t n, const IOOptions& /*opts*/,
+                                 Slice* result, char* scratch,
+                                 IODebugContext* /*dbg*/) {
+  IOStatus s;
   size_t r = 0;
 
   assert(result != nullptr);
   if (WinFileData::use_direct_io()) {
-    return Status::NotSupported("Read() does not support direct_io");
+    return IOStatus::NotSupported("Read() does not support direct_io");
   }
 
   // Windows ReadFile API accepts a DWORD.
   // While it is possible to read in a loop if n is too big
   // it is an unlikely case.
   if (n > std::numeric_limits<DWORD>::max()) {
-    return Status::InvalidArgument("n is too big for a single ReadFile: "
-      + filename_);
+    return IOStatus::InvalidArgument("n is too big for a single ReadFile: " +
+                                     filename_);
   }
 
-  DWORD bytesToRead = static_cast<DWORD>(n); //cast is safe due to the check above
+  DWORD bytesToRead =
+      static_cast<DWORD>(n);  // cast is safe due to the check above
   DWORD bytesRead = 0;
   BOOL ret = ReadFile(hFile_, scratch, bytesToRead, &bytesRead, NULL);
   if (ret != FALSE) {
@@ -595,8 +613,7 @@ Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
   } else {
     auto lastError = GetLastError();
     if (lastError != ERROR_HANDLE_EOF) {
-      s = IOErrorFromWindowsError("ReadFile failed: " + filename_,
-        lastError);
+      s = IOErrorFromWindowsError("ReadFile failed: " + filename_, lastError);
     }
   }
 
@@ -604,99 +621,86 @@ Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
   return s;
 }
 
-Status WinSequentialFile::PositionedReadInternal(char* src, size_t numBytes,
-  uint64_t offset, size_t& bytes_read) const {
+IOStatus WinSequentialFile::PositionedReadInternal(char* src, size_t numBytes,
+                                                   uint64_t offset,
+                                                   size_t& bytes_read) const {
   return pread(this, src, numBytes, offset, bytes_read);
 }
 
-Status WinSequentialFile::PositionedRead(uint64_t offset, size_t n, Slice* result,
-  char* scratch) {
-
-  Status s;
-
+IOStatus WinSequentialFile::PositionedRead(uint64_t offset, size_t n,
+                                           const IOOptions& /*opts*/,
+                                           Slice* result, char* scratch,
+                                           IODebugContext* /*dbg*/) {
   if (!WinFileData::use_direct_io()) {
-    return Status::NotSupported("This function is only used for direct_io");
+    return IOStatus::NotSupported("This function is only used for direct_io");
   }
 
-  if (!IsSectorAligned(static_cast<size_t>(offset)) ||
-      !IsSectorAligned(n)) {
-      return Status::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
-  s = PositionedReadInternal(scratch, static_cast<size_t>(n), offset, bytes_read);
+  size_t bytes_read = 0;  // out param
+  IOStatus s = PositionedReadInternal(scratch, static_cast<size_t>(n), offset,
+                                      bytes_read);
   *result = Slice(scratch, bytes_read);
   return s;
 }
 
-
-Status WinSequentialFile::Skip(uint64_t n) {
-  // Can't handle more than signed max as SetFilePointerEx accepts a signed 64-bit
-  // integer. As such it is a highly unlikley case to have n so large.
+IOStatus WinSequentialFile::Skip(uint64_t n) {
+  // Can't handle more than signed max as SetFilePointerEx accepts a signed
+  // 64-bit integer. As such it is a highly unlikley case to have n so large.
   if (n > static_cast<uint64_t>(std::numeric_limits<LONGLONG>::max())) {
-    return Status::InvalidArgument("n is too large for a single SetFilePointerEx() call" +
-      filename_);
+    return IOStatus::InvalidArgument(
+        "n is too large for a single SetFilePointerEx() call" + filename_);
   }
 
   LARGE_INTEGER li;
-  li.QuadPart = static_cast<LONGLONG>(n); //cast is safe due to the check above
+  li.QuadPart = static_cast<LONGLONG>(n);  // cast is safe due to the check
+                                           // above
   BOOL ret = SetFilePointerEx(hFile_, li, NULL, FILE_CURRENT);
   if (ret == FALSE) {
     auto lastError = GetLastError();
     return IOErrorFromWindowsError("Skip SetFilePointerEx():" + filename_,
                                    lastError);
   }
-  return Status::OK();
+  return IOStatus::OK();
 }
 
-Status WinSequentialFile::InvalidateCache(size_t offset, size_t length) {
-  return Status::OK();
+IOStatus WinSequentialFile::InvalidateCache(size_t offset, size_t length) {
+  return IOStatus::OK();
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 /// WinRandomAccessBase
 
-inline
-Status WinRandomAccessImpl::PositionedReadInternal(char* src,
-  size_t numBytes,
-  uint64_t offset,
-  size_t& bytes_read) const {
+inline IOStatus WinRandomAccessImpl::PositionedReadInternal(
+    char* src, size_t numBytes, uint64_t offset, size_t& bytes_read) const {
   return pread(file_base_, src, numBytes, offset, bytes_read);
 }
 
-inline
-WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base,
-  size_t alignment,
-  const EnvOptions& options) :
-    file_base_(file_base),
-    alignment_(alignment) {
-
+inline WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base,
+                                                size_t alignment,
+                                                const FileOptions& options)
+    : file_base_(file_base),
+      alignment_(std::max(alignment, file_base->GetSectorSize())) {
   assert(!options.use_mmap_reads);
 }
 
-inline
-Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result,
-  char* scratch) const {
-
-  Status s;
-
+inline IOStatus WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n,
+                                              Slice* result,
+                                              char* scratch) const {
   // Check buffer alignment
   if (file_base_->use_direct_io()) {
-    if (!IsSectorAligned(static_cast<size_t>(offset)) ||
-        !IsAligned(alignment_, scratch)) {
-      return Status::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) {
     *result = Slice(scratch, 0);
-    return s;
+    return IOStatus::OK();
   }
 
   size_t bytes_read = 0;
-  s = PositionedReadInternal(scratch, n, offset, bytes_read);
+  IOStatus s = PositionedReadInternal(scratch, n, offset, bytes_read);
   *result = Slice(scratch, bytes_read);
   return s;
 }
@@ -706,20 +710,21 @@ Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result,
 
 WinRandomAccessFile::WinRandomAccessFile(const std::string& fname, HANDLE hFile,
                                          size_t alignment,
-                                         const EnvOptions& options)
+                                         const FileOptions& options)
     : WinFileData(fname, hFile, options.use_direct_reads),
       WinRandomAccessImpl(this, alignment, options) {}
 
-WinRandomAccessFile::~WinRandomAccessFile() {
-}
+WinRandomAccessFile::~WinRandomAccessFile() {}
 
-Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result,
-  char* scratch) const {
+IOStatus WinRandomAccessFile::Read(uint64_t offset, size_t n,
+                                   const IOOptions& /*options*/, Slice* result,
+                                   char* scratch,
+                                   IODebugContext* /*dbg*/) const {
   return ReadImpl(offset, n, result, scratch);
 }
 
-Status WinRandomAccessFile::InvalidateCache(size_t offset, size_t length) {
-  return Status::OK();
+IOStatus WinRandomAccessFile::InvalidateCache(size_t offset, size_t length) {
+  return IOStatus::OK();
 }
 
 size_t WinRandomAccessFile::GetUniqueId(char* id, size_t max_size) const {
@@ -734,27 +739,26 @@ size_t WinRandomAccessFile::GetRequiredBufferAlignment() const {
 // WinWritableImpl
 //
 
-inline
-Status WinWritableImpl::PreallocateInternal(uint64_t spaceToReserve) {
-  return fallocate(file_data_->GetName(), file_data_->GetFileHandle(), spaceToReserve);
+inline IOStatus WinWritableImpl::PreallocateInternal(uint64_t spaceToReserve) {
+  return fallocate(file_data_->GetName(), file_data_->GetFileHandle(),
+                   spaceToReserve);
 }
 
-inline
-WinWritableImpl::WinWritableImpl(WinFileData* file_data, size_t alignment)
-  : file_data_(file_data),
-  alignment_(alignment),
-  next_write_offset_(0),
-  reservedsize_(0) {
-
+inline WinWritableImpl::WinWritableImpl(WinFileData* file_data,
+                                        size_t alignment)
+    : file_data_(file_data),
+      alignment_(std::max(alignment, file_data->GetSectorSize())),
+      next_write_offset_(0),
+      reservedsize_(0) {
   // Query current position in case ReopenWritableFile is called
   // This position is only important for buffered writes
   // for unbuffered writes we explicitely specify the position.
   LARGE_INTEGER zero_move;
-  zero_move.QuadPart = 0; // Do not move
+  zero_move.QuadPart = 0;  // Do not move
   LARGE_INTEGER pos;
   pos.QuadPart = 0;
   BOOL ret = SetFilePointerEx(file_data_->GetFileHandle(), zero_move, &pos,
-      FILE_CURRENT);
+                              FILE_CURRENT);
   // Querying no supped to fail
   if (ret != 0) {
     next_write_offset_ = pos.QuadPart;
@@ -763,74 +767,62 @@ WinWritableImpl::WinWritableImpl(WinFileData* file_data, size_t alignment)
   }
 }
 
-inline
-Status WinWritableImpl::AppendImpl(const Slice& data) {
-
-  Status s;
+inline IOStatus WinWritableImpl::AppendImpl(const Slice& data) {
+  IOStatus s;
 
   if (data.size() > std::numeric_limits<DWORD>::max()) {
-    return Status::InvalidArgument("data is too long for a single write" +
-                                   file_data_->GetName());
+    return IOStatus::InvalidArgument("data is too long for a single write" +
+                                     file_data_->GetName());
   }
 
-  size_t bytes_written = 0; // out param
+  size_t bytes_written = 0;  // out param
 
   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 = Status::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(),
-      static_cast<DWORD>(data.size()), &bytesWritten, NULL)) {
+                   static_cast<DWORD>(data.size()), &bytesWritten, NULL)) {
       auto lastError = GetLastError();
       s = IOErrorFromWindowsError(
-        "Failed to WriteFile: " + file_data_->GetName(),
-        lastError);
+          "Failed to WriteFile: " + file_data_->GetName(), lastError);
     } else {
       bytes_written = bytesWritten;
     }
   }
 
-  if(s.ok()) {
+  if (s.ok()) {
     if (bytes_written == data.size()) {
       // This matters for direct_io cases where
       // we rely on the fact that next_write_offset_
       // is sector aligned
       next_write_offset_ += bytes_written;
     } else {
-      s = Status::IOError("Failed to write all bytes: " +
-                          file_data_->GetName());
+      s = IOStatus::IOError("Failed to write all bytes: " +
+                            file_data_->GetName());
     }
   }
 
   return s;
 }
 
-inline
-Status 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 Status::InvalidArgument(
-        "Data and offset must be page aligned, size must be sector aligned");
-    }
+inline IOStatus WinWritableImpl::PositionedAppendImpl(const Slice& data,
+                                                      uint64_t offset) {
+  if (file_data_->use_direct_io()) {
+    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;
-  Status s = pwrite(file_data_, data, offset, bytes_written);
+  IOStatus s = pwrite(file_data_, data, offset, bytes_written);
 
-  if(s.ok()) {
+  if (s.ok()) {
     if (bytes_written == data.size()) {
       // For sequential write this would be simple
       // size extension by data.size()
@@ -839,23 +831,21 @@ Status WinWritableImpl::PositionedAppendImpl(const Slice& data, uint64_t offset)
         next_write_offset_ = write_end;
       }
     } else {
-      s = Status::IOError("Failed to write all of the requested data: " +
-        file_data_->GetName());
+      s = IOStatus::IOError("Failed to write all of the requested data: " +
+                            file_data_->GetName());
     }
   }
   return s;
 }
 
-inline
-Status WinWritableImpl::TruncateImpl(uint64_t size) {
-
+inline IOStatus WinWritableImpl::TruncateImpl(uint64_t size) {
   // It is tempting to check for the size for sector alignment
   // but truncation may come at the end and there is not a requirement
   // for this to be sector aligned so long as we do not attempt to write
   // after that. The interface docs state that the behavior is undefined
   // in that case.
-  Status s = ftruncate(file_data_->GetName(), file_data_->GetFileHandle(),
-    size);
+  IOStatus s =
+      ftruncate(file_data_->GetName(), file_data_->GetFileHandle(), size);
 
   if (s.ok()) {
     next_write_offset_ = size;
@@ -863,50 +853,48 @@ Status WinWritableImpl::TruncateImpl(uint64_t size) {
   return s;
 }
 
-inline
-Status WinWritableImpl::CloseImpl() {
-
-  Status s;
+inline IOStatus WinWritableImpl::CloseImpl() {
+  IOStatus s;
 
   auto hFile = file_data_->GetFileHandle();
   assert(INVALID_HANDLE_VALUE != hFile);
 
   if (!::FlushFileBuffers(hFile)) {
     auto lastError = GetLastError();
-    s = IOErrorFromWindowsError("FlushFileBuffers failed at Close() for: " +
-      file_data_->GetName(),
-      lastError);
+    s = IOErrorFromWindowsError(
+        "FlushFileBuffers failed at Close() for: " + file_data_->GetName(),
+        lastError);
   }
 
-  if(!file_data_->CloseFile() && s.ok()) {
+  if (!file_data_->CloseFile() && s.ok()) {
     auto lastError = GetLastError();
-    s = IOErrorFromWindowsError("CloseHandle failed for: " + file_data_->GetName(),
-      lastError);
+    s = IOErrorFromWindowsError(
+        "CloseHandle failed for: " + file_data_->GetName(), lastError);
   }
   return s;
 }
 
-inline
-Status WinWritableImpl::SyncImpl() {
-  Status s;
-  if (!::FlushFileBuffers (file_data_->GetFileHandle())) {
+inline IOStatus WinWritableImpl::SyncImpl(const IOOptions& /*options*/,
+                                          IODebugContext* /*dbg*/) {
+  IOStatus s;
+  if (!::FlushFileBuffers(file_data_->GetFileHandle())) {
     auto lastError = GetLastError();
     s = IOErrorFromWindowsError(
-        "FlushFileBuffers failed at Sync() for: " + file_data_->GetName(), lastError);
+        "FlushFileBuffers failed at Sync() for: " + file_data_->GetName(),
+        lastError);
   }
   return s;
 }
 
-
-inline
-Status WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) {
-  Status status;
-  TEST_KILL_RANDOM("WinWritableFile::Allocate", rocksdb_kill_odds);
+inline IOStatus WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) {
+  IOStatus status;
+  TEST_KILL_RANDOM("WinWritableFile::Allocate");
 
   // Make sure that we reserve an aligned amount of space
   // since the reservation block size is driven outside so we want
   // to check if we are ok with reservation here
-  size_t spaceToReserve = Roundup(static_cast<size_t>(offset + len), static_cast<size_t>(alignment_));
+  size_t spaceToReserve = Roundup(static_cast<size_t>(offset + len),
+                                  static_cast<size_t>(alignment_));
   // Nothing to do
   if (spaceToReserve <= reservedsize_) {
     return status;
@@ -920,66 +908,78 @@ Status WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) {
   return status;
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////
 /// WinWritableFile
 
 WinWritableFile::WinWritableFile(const std::string& fname, HANDLE hFile,
                                  size_t alignment, size_t /* capacity */,
-                                 const EnvOptions& options)
+                                 const FileOptions& options)
     : WinFileData(fname, hFile, options.use_direct_writes),
       WinWritableImpl(this, alignment),
-      WritableFile(options) {
+      FSWritableFile(options) {
   assert(!options.use_mmap_writes);
 }
 
-WinWritableFile::~WinWritableFile() {
-}
+WinWritableFile::~WinWritableFile() {}
 
 // Indicates if the class makes use of direct I/O
-bool WinWritableFile::use_direct_io() const { return WinFileData::use_direct_io(); }
+bool WinWritableFile::use_direct_io() const {
+  return WinFileData::use_direct_io();
+}
 
 size_t WinWritableFile::GetRequiredBufferAlignment() const {
-  return static_cast<size_t>(GetAlignement());
+  return static_cast<size_t>(GetAlignment());
 }
 
-Status WinWritableFile::Append(const Slice& data) {
+IOStatus WinWritableFile::Append(const Slice& data,
+                                 const IOOptions& /*options*/,
+                                 IODebugContext* /*dbg*/) {
   return AppendImpl(data);
 }
 
-Status WinWritableFile::PositionedAppend(const Slice& data, uint64_t offset) {
+IOStatus WinWritableFile::PositionedAppend(const Slice& data, uint64_t offset,
+                                           const IOOptions& /*options*/,
+                                           IODebugContext* /*dbg*/) {
   return PositionedAppendImpl(data, offset);
 }
 
 // Need to implement this so the file is truncated correctly
 // when buffered and unbuffered mode
-Status WinWritableFile::Truncate(uint64_t size) {
+IOStatus WinWritableFile::Truncate(uint64_t size, const IOOptions& /*options*/,
+                                   IODebugContext* /*dbg*/) {
   return TruncateImpl(size);
 }
 
-Status WinWritableFile::Close() {
+IOStatus WinWritableFile::Close(const IOOptions& /*options*/,
+                                IODebugContext* /*dbg*/) {
   return CloseImpl();
 }
 
-  // write out the cached data to the OS cache
-  // This is now taken care of the WritableFileWriter
-Status WinWritableFile::Flush() {
-  return Status::OK();
+// write out the cached data to the OS cache
+// This is now taken care of the WritableFileWriter
+IOStatus WinWritableFile::Flush(const IOOptions& /*options*/,
+                                IODebugContext* /*dbg*/) {
+  return IOStatus::OK();
 }
 
-Status WinWritableFile::Sync() {
-  return SyncImpl();
+IOStatus WinWritableFile::Sync(const IOOptions& options, IODebugContext* dbg) {
+  return SyncImpl(options, dbg);
 }
 
-Status WinWritableFile::Fsync() { return SyncImpl(); }
+IOStatus WinWritableFile::Fsync(const IOOptions& options, IODebugContext* dbg) {
+  return SyncImpl(options, dbg);
+}
 
 bool WinWritableFile::IsSyncThreadSafe() const { return true; }
 
-uint64_t WinWritableFile::GetFileSize() {
+uint64_t WinWritableFile::GetFileSize(const IOOptions& /*options*/,
+                                      IODebugContext* /*dbg*/) {
   return GetFileNextWriteOffset();
 }
 
-Status WinWritableFile::Allocate(uint64_t offset, uint64_t len) {
+IOStatus WinWritableFile::Allocate(uint64_t offset, uint64_t len,
+                                   const IOOptions& /*options*/,
+                                   IODebugContext* /*dbg*/) {
   return AllocateImpl(offset, len);
 }
 
@@ -991,36 +991,45 @@ size_t WinWritableFile::GetUniqueId(char* id, size_t max_size) const {
 /// WinRandomRWFile
 
 WinRandomRWFile::WinRandomRWFile(const std::string& fname, HANDLE hFile,
-                                 size_t alignment, const EnvOptions& options)
+                                 size_t alignment, const FileOptions& options)
     : WinFileData(fname, hFile,
                   options.use_direct_reads && options.use_direct_writes),
       WinRandomAccessImpl(this, alignment, options),
       WinWritableImpl(this, alignment) {}
 
-bool WinRandomRWFile::use_direct_io() const { return WinFileData::use_direct_io(); }
+bool WinRandomRWFile::use_direct_io() const {
+  return WinFileData::use_direct_io();
+}
 
 size_t WinRandomRWFile::GetRequiredBufferAlignment() const {
-  return static_cast<size_t>(GetAlignement());
+  assert(WinRandomAccessImpl::GetAlignment() ==
+         WinWritableImpl::GetAlignment());
+  return static_cast<size_t>(WinRandomAccessImpl::GetAlignment());
 }
 
-Status WinRandomRWFile::Write(uint64_t offset, const Slice & data) {
+IOStatus WinRandomRWFile::Write(uint64_t offset, const Slice& data,
+                                const IOOptions& /*options*/,
+                                IODebugContext* /*dbg*/) {
   return PositionedAppendImpl(data, offset);
 }
 
-Status WinRandomRWFile::Read(uint64_t offset, size_t n, Slice* result,
-                             char* scratch) const {
+IOStatus WinRandomRWFile::Read(uint64_t offset, size_t n,
+                               const IOOptions& /*options*/, Slice* result,
+                               char* scratch, IODebugContext* /*dbg*/) const {
   return ReadImpl(offset, n, result, scratch);
 }
 
-Status WinRandomRWFile::Flush() {
-  return Status::OK();
+IOStatus WinRandomRWFile::Flush(const IOOptions& /*options*/,
+                                IODebugContext* /*dbg*/) {
+  return IOStatus::OK();
 }
 
-Status WinRandomRWFile::Sync() {
-  return SyncImpl();
+IOStatus WinRandomRWFile::Sync(const IOOptions& options, IODebugContext* dbg) {
+  return SyncImpl(options, dbg);
 }
 
-Status WinRandomRWFile::Close() {
+IOStatus WinRandomRWFile::Close(const IOOptions& /*options*/,
+                                IODebugContext* /*dbg*/) {
   return CloseImpl();
 }
 
@@ -1029,9 +1038,9 @@ Status WinRandomRWFile::Close() {
 WinMemoryMappedBuffer::~WinMemoryMappedBuffer() {
   BOOL ret
 #if defined(_MSC_VER)
-    = FALSE;
+      = FALSE;
 #else
-    __attribute__((__unused__));
+      __attribute__((__unused__));
 #endif
   if (base_ != nullptr) {
     ret = ::UnmapViewOfFile(base_);
@@ -1053,7 +1062,26 @@ WinMemoryMappedBuffer::~WinMemoryMappedBuffer() {
 //////////////////////////////////////////////////////////////////////////
 /// WinDirectory
 
-Status WinDirectory::Fsync() { return Status::OK(); }
+IOStatus WinDirectory::Fsync(const IOOptions& /*options*/,
+                             IODebugContext* /*dbg*/) {
+  return IOStatus::OK();
+}
+
+IOStatus WinDirectory::Close(const IOOptions& /*options*/,
+                             IODebugContext* /*dbg*/) {
+  IOStatus s = IOStatus::OK();
+  BOOL ret __attribute__((__unused__));
+  if (handle_ != INVALID_HANDLE_VALUE) {
+    ret = ::CloseHandle(handle_);
+    if (!ret) {
+      auto lastError = GetLastError();
+      s = IOErrorFromWindowsError("Directory closes failed for : " + GetName(),
+                                  lastError);
+    }
+    handle_ = NULL;
+  }
+  return s;
+}
 
 size_t WinDirectory::GetUniqueId(char* id, size_t max_size) const {
   return GetUniqueIdFromFile(handle_, id, max_size);
@@ -1067,7 +1095,7 @@ WinFileLock::~WinFileLock() {
   assert(ret);
 }
 
-}
+}  // namespace port
 }  // namespace ROCKSDB_NAMESPACE
 
 #endif