Skip to content

Commit 13c2493

Browse files
committed
fix(vfs/posix): various vfs fixes for Linux
While trying to find what could possibly cause files on disk to become corrupted on Linux I started going through the VFS implementation for Linux and noticed a few issues. This fixes a few issues here: Read/ReadBulk/Write don't try to loop until all of their bytes are written RenameFile returns `0` on success, while we were checking if it was successful by checking if it was `!= 0` GetLength was still reading the buf even though there isn't valid data in it. See: https://man7.org/linux/man-pages/man2/write.2.html https://man7.org/linux/man-pages/man2/read.2.html https://man7.org/linux/man-pages/man2/pread.2.html https://man7.org/linux/man-pages/man3/fstat.3p.html https://man7.org/linux/man-pages/man2/rename.2.html
1 parent 2e87af4 commit 13c2493

1 file changed

Lines changed: 69 additions & 6 deletions

File tree

code/components/vfs-impl-server/src/PlatformDevice.Posix.cpp

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,90 @@ size_t LocalDevice::Read(THandle handle, void* outBuffer, size_t size)
6363
{
6464
assert(handle != Device::InvalidHandle);
6565

66-
ssize_t bytesRead = read(static_cast<int>(handle), outBuffer, size);
66+
size_t totalBytesRead = 0;
6767

68-
return (bytesRead < 0) ? -1 : static_cast<size_t>(bytesRead);
68+
while (totalBytesRead < size)
69+
{
70+
ssize_t bytesRead = read(static_cast<int>(handle), outBuffer + totalBytesRead, size - totalBytesRead);
71+
if (bytesRead < 0)
72+
{
73+
// we got interrupted, we should retry our read
74+
if (errno == EINTR)
75+
{
76+
continue;
77+
}
78+
79+
// TODO: Figure out if we want to return what we have or if we should return -1 here?
80+
return (totalBytesRead > 0) ? totalBytesRead : -1;
81+
}
82+
83+
if (bytesRead == 0)
84+
{
85+
break;
86+
}
87+
88+
totalBytesRead += static_cast<size_t>(bytesRead);
89+
}
90+
91+
return totalBytesRead;
6992
}
7093

7194
size_t LocalDevice::ReadBulk(THandle handle, uint64_t ptr, void* outBuffer, size_t size)
7295
{
7396
assert(handle != Device::InvalidHandle);
7497

75-
ssize_t bytesRead = pread(static_cast<int>(handle), outBuffer, size, static_cast<off_t>(ptr));
98+
size_t totalBytesRead = 0;
99+
100+
while (totalBytesRead < size)
101+
{
102+
ssize_t bytesRead = pread(static_cast<int>(handle), outBuffer + totalBytesRead, size - totalBytesRead);
103+
if (bytesRead < 0)
104+
{
105+
// we got interrupted, we should retry our pread
106+
if (errno == EINTR)
107+
{
108+
continue;
109+
}
110+
111+
// TODO: Figure out if we want to return what we have or if we should return -1 here?
112+
return (totalBytesRead > 0) ? totalBytesRead : -1;
113+
}
114+
115+
if (bytesRead == 0)
116+
{
117+
break;
118+
}
119+
120+
totalBytesRead += static_cast<size_t>(bytesRead);
121+
}
76122

77-
return (bytesRead < 0) ? -1 : static_cast<size_t>(bytesRead);
123+
return totalBytesRead;
78124
}
79125

80126
size_t LocalDevice::Write(THandle handle, const void* buffer, size_t size)
81127
{
82128
assert(handle != Device::InvalidHandle);
83129

84-
ssize_t bytesWritten = write(static_cast<int>(handle), buffer, size);
130+
size_t totalBytesWritten = 0;
131+
132+
while (totalBytesWritten < size)
133+
{
134+
ssize_t bytesWritten = write(static_cast<int>(handle), buffer + totalWritten, size - totalBytesWritten);
135+
if (bytesWritten < 0)
136+
{
137+
// if we got interrupted we should retry our write
138+
if (errno == EINTR)
139+
{
140+
continue;
141+
}
142+
143+
return -1;
144+
}
145+
146+
totalBytesWritten += static_cast<size_t>(bytesWritten);
147+
}
85148

86-
return (bytesWritten < 0) ? -1 : static_cast<size_t>(bytesWritten);
149+
return totalBytesWritten;
87150
}
88151

89152
size_t LocalDevice::WriteBulk(THandle handle, uint64_t ptr, const void* buffer, size_t size)

0 commit comments

Comments
 (0)