Skip to content

Commit 5f59990

Browse files
laramielcopybara-github
authored andcommitted
Fix incorrect offset in ::mmap call
This would likely have caused issues for users who set file_io_memmap and were using ocdbt where the coalescing didn't trigger a read of the entire file. PiperOrigin-RevId: 716363648 Change-Id: I3d2ffd5b200307c5f0e80ad07f947d9b1fcd7535
1 parent 5d64c23 commit 5f59990

File tree

4 files changed

+57
-25
lines changed

4 files changed

+57
-25
lines changed

tensorstore/internal/os/file_util_posix.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ Result<MemoryRegion> MemmapFileReadOnly(FileDescriptor fd, size_t offset,
416416
}
417417
}
418418

419-
void* address = ::mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
419+
void* address = ::mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, offset);
420420
if (address == MAP_FAILED) {
421421
return std::move(tspan).EndWithStatus(
422422
StatusFromOsError(errno, "Failed to mmap"));

tensorstore/internal/os/file_util_test.cc

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414

1515
#include "tensorstore/internal/os/file_util.h"
1616

17+
#include <stdint.h>
18+
19+
#include <memory>
1720
#include <string>
21+
#include <string_view>
1822
#include <utility>
1923

2024
#include <gmock/gmock.h>
@@ -36,6 +40,7 @@ using ::tensorstore::internal_os::DeleteFile;
3640
using ::tensorstore::internal_os::DeleteOpenFile;
3741
using ::tensorstore::internal_os::FileInfo;
3842
using ::tensorstore::internal_os::FsyncFile;
43+
using ::tensorstore::internal_os::GetDefaultPageSize;
3944
using ::tensorstore::internal_os::GetDeviceId;
4045
using ::tensorstore::internal_os::GetFileId;
4146
using ::tensorstore::internal_os::GetFileInfo;
@@ -171,28 +176,53 @@ TEST(FileUtilTest, MemmapFileReadOnly) {
171176
std::string foo_txt = absl::StrCat(tempdir.path(), "/baz.txt",
172177
tensorstore::internal_os::kLockSuffix);
173178

179+
// Allocate two pages and fill them with a-z.
180+
uint32_t size = GetDefaultPageSize() * 2;
181+
std::unique_ptr<char[]> buffer;
182+
buffer.reset(new char[size]);
183+
for (uint32_t i = 0; i < size; ++i) {
184+
buffer[i] = 'a' + (i % 26);
185+
}
186+
std::string_view expected(buffer.get(), size);
187+
174188
// Write a file:
175189
{
176190
auto f = OpenFileWrapper(foo_txt, OpenFlags::DefaultWrite);
177191
EXPECT_THAT(f, IsOk());
178192

179-
EXPECT_THAT(WriteToFile(f->get(), "abcdefghijklmnopqrstuvwxyz", 26),
180-
IsOkAndHolds(26));
193+
EXPECT_THAT(WriteToFile(f->get(), expected.data(), expected.size()),
194+
IsOkAndHolds(expected.size()));
181195
}
182196

183-
// Read
197+
// Read with bad offset => error.
184198
{
199+
TENSORSTORE_ASSERT_OK_AND_ASSIGN(
200+
auto fd, OpenFileWrapper(foo_txt, OpenFlags::OpenReadOnly));
201+
auto result = MemmapFileReadOnly(fd.get(), /*offset=*/4, 0);
202+
EXPECT_THAT(result.status(), StatusIs(absl::StatusCode::kInvalidArgument));
203+
}
204+
205+
// Read w/offset
206+
for (uint32_t offset : {uint32_t{0}, GetDefaultPageSize(), size}) {
185207
TENSORSTORE_ASSERT_OK_AND_ASSIGN(
186208
auto fd, OpenFileWrapper(foo_txt, OpenFlags::OpenReadOnly));
187209

188210
TENSORSTORE_ASSERT_OK_AND_ASSIGN(auto data,
189-
MemmapFileReadOnly(fd.get(), 0, 0));
190-
EXPECT_EQ(data.as_string_view().size(), 26);
191-
EXPECT_THAT(data.as_string_view(), "abcdefghijklmnopqrstuvwxyz");
211+
MemmapFileReadOnly(fd.get(), offset, 0));
212+
EXPECT_EQ(data.as_string_view().size(), expected.size() - offset);
213+
EXPECT_THAT(data.as_string_view(), expected.substr(offset));
192214

193215
auto cord_data = std::move(data).as_cord();
194-
EXPECT_EQ(cord_data.size(), 26);
195-
EXPECT_THAT(cord_data, "abcdefghijklmnopqrstuvwxyz");
216+
EXPECT_EQ(cord_data.size(), expected.size() - offset);
217+
EXPECT_THAT(cord_data, expected.substr(offset));
218+
219+
// Read a subset of the file.
220+
if (offset < size) {
221+
TENSORSTORE_ASSERT_OK_AND_ASSIGN(
222+
data, MemmapFileReadOnly(fd.get(), offset, 128));
223+
EXPECT_EQ(data.as_string_view().size(), 128);
224+
EXPECT_THAT(data.as_string_view(), expected.substr(offset, 128));
225+
}
196226
}
197227
}
198228

tensorstore/internal/os/file_util_win.cc

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -484,28 +484,30 @@ Result<MemoryRegion> MemmapFileReadOnly(FileDescriptor fd, size_t offset,
484484
LoggedTraceSpan tspan(__func__, detail_logging.Level(1),
485485
{{"handle", fd}, {"offset", offset}, {"size", size}});
486486
487-
if (size == 0) {
488-
::BY_HANDLE_FILE_INFORMATION info;
489-
if (!::GetFileInformationByHandle(fd, &info)) {
490-
return std::move(tspan).EndWithStatus(StatusFromOsError(
491-
::GetLastError(), "Failed in GetFileInformationByHandle"));
492-
}
487+
::BY_HANDLE_FILE_INFORMATION info;
488+
if (!::GetFileInformationByHandle(fd, &info)) {
489+
return std::move(tspan).EndWithStatus(StatusFromOsError(
490+
::GetLastError(), "Failed in GetFileInformationByHandle"));
491+
}
493492
494-
uint64_t file_size = GetSize(info);
495-
if (offset + size > file_size) {
496-
return std::move(tspan).EndWithStatus(absl::OutOfRangeError(
497-
absl::StrCat("Requested offset ", offset, " + size ", size,
498-
" exceeds file size ", file_size)));
499-
} else if (size == 0) {
500-
size = file_size - offset;
493+
uint64_t file_size = GetSize(info);
494+
if (offset + size > file_size) {
495+
return std::move(tspan).EndWithStatus(absl::OutOfRangeError(
496+
absl::StrCat("Requested offset ", offset, " + size ", size,
497+
" exceeds file size ", file_size)));
498+
}
499+
if (size == 0) {
500+
size = file_size - offset;
501+
if (size == 0) {
502+
return MemoryRegion(nullptr, 0, UnmapFileWin32);
501503
}
502504
}
503505
504506
UniqueFileDescriptor map_fd(
505-
::CreateFileMappingA(fd, NULL, PAGE_READONLY, 0, 0, nullptr));
507+
::CreateFileMappingW(fd, nullptr, PAGE_READONLY, 0, 0, nullptr));
506508
if (!map_fd.valid()) {
507509
return std::move(tspan).EndWithStatus(
508-
StatusFromOsError(::GetLastError(), "Failed in CreateFileMappingA"));
510+
StatusFromOsError(::GetLastError(), "Failed in CreateFileMappingW"));
509511
}
510512
511513
void* address = ::MapViewOfFile(

tensorstore/util/status.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ inline void MaybeAddSourceLocation(
8989
absl::Status& status,
9090
SourceLocation loc = tensorstore::SourceLocation::current()) {
9191
// Don't add locations to purely control flow status OBJECTS.
92-
if (status.message().empty()) return;
92+
if (status.ok() || status.message().empty()) return;
9393
internal::MaybeAddSourceLocationImpl(status, loc);
9494
}
9595

0 commit comments

Comments
 (0)