lseek on devices

fixed dirents not updating when RefreshDirents is called too fast after lseek
This commit is contained in:
Marek Ledworowski 2025-11-21 00:06:56 +01:00
parent 0ae2275e2d
commit 008b61d28d
14 changed files with 17 additions and 17 deletions

View File

@ -30,7 +30,6 @@ public:
s64 read(void* buf, u64 count) override { DEVICE_STUB(); };
s64 write(const void* buf, u64 count) override { DEVICE_STUB(); };
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); };
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); };
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); };
s32 fsync() override { DEVICE_STUB(); };
s32 ftruncate(s64 length) override { DEVICE_STUB(); };

View File

@ -30,7 +30,6 @@ public:
s64 read(void* buf, u64 count) override { DEVICE_STUB(); };
s64 write(const void* buf, u64 count) override { DEVICE_STUB(); };
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); };
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); };
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); };
s32 fsync() override { DEVICE_STUB(); };
s32 ftruncate(s64 length) override { DEVICE_STUB(); };

View File

@ -40,7 +40,6 @@ public:
// clang-format off
s64 read(void* buf, u64 count) override { DEVICE_STUB(); };
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }

View File

@ -23,7 +23,6 @@ public:
s64 read(void* buf, u64 count) override { return 0; };
s64 write(const void* buf, u64 count) override { return 0; };
s32 ioctl(u64 cmd, Common::VaCtx* args) override { return 0; };
s64 lseek(s64 current, s64 offset, s32 whence) override { return 0; };
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { return 0; };
s32 fsync() override { return 0; };
s32 ftruncate(s64 length) override { return 0; };

View File

@ -30,7 +30,6 @@ public:
// clang-format off
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }

View File

@ -29,7 +29,6 @@ public:
// clang-format off
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }

View File

@ -30,7 +30,6 @@ public:
// clang-format off
s64 read(void* buf, u64 count) override { DEVICE_STUB(); }
s64 write(const void* buf, u64 count) override { DEVICE_STUB(); }
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }

View File

@ -30,7 +30,6 @@ public:
// clang-format off
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }

View File

@ -30,7 +30,6 @@ public:
// clang-format off
s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }
s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }

View File

@ -24,6 +24,7 @@ public:
s64 pread(void* buf, u64 count, s64 offset) final override;
s64 pwrite(const void* buf, u64 count, s64 offset) final override;
s64 lseek(s64 current, s64 offset, s32 whence) final override;
};
} // namespace QuasiFS

View File

@ -30,7 +30,7 @@ protected:
std::map<std::string, inode_ptr> entries{};
void RebuildDirents(void);
time_t last_dirent_rebuild_time{0};
bool dirents_changed{false};
std::vector<u8> dirent_cache_bin{};
public:

View File

@ -31,4 +31,11 @@ s64 Device::pwrite(const void* buf, u64 count, s64 offset) {
return write(buf, count);
}
s64 Device::lseek(s64 current, s64 offset, s32 whence) {
return ((QuasiFS::SeekOrigin::ORIGIN == whence) * offset) +
((QuasiFS::SeekOrigin::CURRENT == whence) * (current + offset)) +
((QuasiFS::SeekOrigin::END == whence) * ((offset > 0) * offset));
// ::END is pro-forma
}
} // namespace QuasiFS

View File

@ -26,6 +26,7 @@ s64 QuasiDirectory::pread(void* buf, u64 count, s64 offset) {
s64 QuasiDirectory::lseek(s64 current, s64 offset, s32 whence) {
RebuildDirents();
this->dirents_changed = false;
return Inode::lseek(current, offset, whence);
}
@ -41,6 +42,7 @@ s32 QuasiDirectory::ftruncate(s64 length) {
s64 QuasiDirectory::getdents(void* buf, u32 count, s64 offset, s64* basep) {
RebuildDirents();
st.st_atim.tv_sec = time(0);
// at this point count is ALWAYS >512 (checked in VIO Driver)
// always returns up to 512 bytes
@ -122,10 +124,9 @@ std::vector<std::string> QuasiDirectory::list() {
}
void QuasiDirectory::RebuildDirents(void) {
// adding/removing entries changes mtime
if (this->st.st_mtim.tv_sec == this->last_dirent_rebuild_time)
if (this->dirents_changed)
return;
this->last_dirent_rebuild_time = this->st.st_mtim.tv_sec;
this->dirents_changed = false;
constexpr u32 dirent_meta_size = sizeof(dirent_t::d_fileno) + sizeof(dirent_t::d_type) +
sizeof(dirent_t::d_namlen) + sizeof(dirent_t::d_reclen);

View File

@ -22,6 +22,7 @@ DirectoryPFS::~DirectoryPFS() = default;
s64 DirectoryPFS::pread(void* buf, u64 count, s64 offset) {
RebuildDirents();
st.st_atim.tv_sec = time(0);
// data is contiguous. i think that's how it's said
// anyway, everything goes raw
@ -67,6 +68,7 @@ s64 DirectoryPFS::lseek(s64 current, s64 offset, s32 whence) {
// future
s64 DirectoryPFS::getdents(void* buf, u32 count, s64 offset, s64* basep) {
RebuildDirents();
st.st_atim.tv_sec = time(0);
if (count != 65536)
LOG_CRITICAL(Kernel_Fs, "PFS dirents read with count={} (which is not 65536) (report this)",
@ -123,11 +125,9 @@ s64 DirectoryPFS::getdents(void* buf, u32 count, s64 offset, s64* basep) {
}
void DirectoryPFS::RebuildDirents(void) {
// adding/removing entries changes mtime
if (this->st.st_mtim.tv_sec == this->last_dirent_rebuild_time)
if (this->dirents_changed)
return;
this->last_dirent_rebuild_time = this->st.st_mtim.tv_sec;
this->dirents_changed = false;
constexpr u32 dirent_meta_size = sizeof(dirent_pfs_t::d_fileno) + sizeof(dirent_pfs_t::d_type) +
sizeof(dirent_pfs_t::d_namlen) +