From a074b8ee3bcdf070157b56d809e838b2804b3344 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Mon, 17 Nov 2025 18:31:22 +0000 Subject: [PATCH 1/6] rocfile: Wrap statx --- rocfile/src/sys.cpp | 8 ++++++++ rocfile/src/sys.h | 5 +++-- rocfile/test/msys.h | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/rocfile/src/sys.cpp b/rocfile/src/sys.cpp index 7cb46c7b..c9f8cfda 100644 --- a/rocfile/src/sys.cpp +++ b/rocfile/src/sys.cpp @@ -69,4 +69,12 @@ Sys::fcntl(int fd, int op, uintptr_t arg) const return throwOn(-1, ::fcntl(fd, op, arg)); } +struct statx +Sys::statx(int dirfd, const char *pathname, int flags, unsigned int mask) const +{ + struct statx statxbuf; + throwOn(-1, ::statx(dirfd, pathname, flags, mask, &statxbuf)); + return statxbuf; +} + } diff --git a/rocfile/src/sys.h b/rocfile/src/sys.h index d21aa9a9..60bfe360 100644 --- a/rocfile/src/sys.h +++ b/rocfile/src/sys.h @@ -8,8 +8,8 @@ #include #include #include +#include #include - #include #include @@ -33,7 +33,8 @@ struct Sys { virtual void syslog(int priority, const char *msg) const; - virtual struct stat fstat(int fd) const; + virtual struct stat fstat(int fd) const; + virtual struct statx statx(int dirfd, const char *pathname, int flags, unsigned int mask) const; virtual int fcntl(int fd, int op, uintptr_t arg) const; diff --git a/rocfile/test/msys.h b/rocfile/test/msys.h index 20a4ad35..26d40ae9 100644 --- a/rocfile/test/msys.h +++ b/rocfile/test/msys.h @@ -28,6 +28,8 @@ struct MSys : Sys { MOCK_METHOD(void, syslog, (int priority, const char *msg), (const override)); MOCK_METHOD(struct stat, fstat, (int fd), (const override)); + MOCK_METHOD(struct statx, statx, (int dirfd, const char *pathname, int flags, unsigned int mask), + (const override)); MOCK_METHOD(int, fcntl, (int fd, int op, uintptr_t arg), (const override)); }; From 2d9c5002925487235d2df7b074523dca4eab4858 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Mon, 17 Nov 2025 21:40:10 +0000 Subject: [PATCH 2/6] rocfile: Use statx (2) to get file status statx includes direct io alignment requirements and the device IDs for raw devices. --- rocfile/src/file.cpp | 21 ++++++++++++++++++--- rocfile/src/file.h | 21 ++++++++++++++++----- rocfile/test/handle.cpp | 27 ++++++++++++++++++--------- rocfile/test/mfile.h | 1 + rocfile/test/rocfile-test.h | 3 ++- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/rocfile/src/file.cpp b/rocfile/src/file.cpp index eec07bd6..d5cf4852 100644 --- a/rocfile/src/file.cpp +++ b/rocfile/src/file.cpp @@ -23,7 +23,10 @@ using std::vector; namespace rocFile { UnregisteredFile::UnregisteredFile(int fd) - : m_fd(fd), m_stat{Context::get()->fstat(fd)}, m_flags{Context::get()->fcntl(fd, F_GETFL, 0)}, + : m_fd(fd), m_stat{Context::get()->fstat(fd)}, + m_stx{Context::get()->statx(fd, "", AT_EMPTY_PATH, + STATX_BASIC_STATS | STATX_MNT_ID | STATX_DIOALIGN)}, + m_flags{Context::get()->fcntl(fd, F_GETFL, 0)}, m_mountinfo{Context::get()->getMountInfo(m_stat.st_dev)} { } @@ -40,6 +43,12 @@ UnregisteredFile::getStat() const noexcept return m_stat; } +struct statx +UnregisteredFile::getStatx() const noexcept +{ + return m_stx; +} + int UnregisteredFile::getFlags() const noexcept { @@ -59,8 +68,8 @@ IFile::getHandle() const } File::File(const UnregisteredFile &uf) - : fd{uf.getFd()}, device{uf.getStat().st_dev}, mode{uf.getStat().st_mode}, status_flags{uf.getFlags()}, - mountinfo{uf.getMountInfo()} + : fd{uf.getFd()}, device{uf.getStat().st_dev}, mode{uf.getStat().st_mode}, stx{uf.getStatx()}, + status_flags{uf.getFlags()}, mountinfo{uf.getMountInfo()} { } @@ -82,6 +91,12 @@ File::getMode() const return mode; } +const struct statx & +File::getStatx() const noexcept +{ + return stx; +} + int File::getStatusFlags() const { diff --git a/rocfile/src/file.h b/rocfile/src/file.h index 996157a3..20117cf3 100644 --- a/rocfile/src/file.h +++ b/rocfile/src/file.h @@ -54,6 +54,9 @@ class UnregisteredFile { /// @return Returns the information provided by fstat (2) struct stat getStat() const noexcept; + /// @return Returns the information provided by statx (2) + struct statx getStatx() const noexcept; + /// @return Returns the flags provided by fcntl (2) int getFlags() const noexcept; @@ -67,6 +70,9 @@ class UnregisteredFile { /// @brief Information provided by fstat (2) struct stat m_stat; + /// @brief Information provided by statx (2) + struct statx m_stx; + /// @brief Flags provided by fcntl(2) int m_flags; @@ -82,11 +88,12 @@ class IFile { /// @return The handle for this file virtual rocFileHandle_t getHandle() const; - virtual int getFd() const = 0; - virtual dev_t getDevice() const = 0; - virtual mode_t getMode() const = 0; - virtual int getStatusFlags() const = 0; - virtual std::optional getMountInfo() const = 0; + virtual int getFd() const = 0; + virtual dev_t getDevice() const = 0; + virtual mode_t getMode() const = 0; + virtual const struct statx &getStatx() const noexcept = 0; + virtual int getStatusFlags() const = 0; + virtual std::optional getMountInfo() const = 0; }; class File : public IFile { @@ -105,6 +112,7 @@ class File : public IFile { virtual int getFd() const override; virtual dev_t getDevice() const override; virtual mode_t getMode() const override; + virtual const struct statx &getStatx() const noexcept override; virtual int getStatusFlags() const override; virtual std::optional getMountInfo() const override; @@ -126,6 +134,9 @@ class File : public IFile { /// Specifies the file type (regular file, block device, ...) and mode. See fstat(2) and inode(7) mode_t mode; + /// @brief File status information obtained from statx (2) + struct statx stx; + /// @brief The file's status flags. See fcntl(2) /// /// Used to determine if the O_DIRECT flag is set diff --git a/rocfile/test/handle.cpp b/rocfile/test/handle.cpp index 650ade84..6ab7e970 100644 --- a/rocfile/test/handle.cpp +++ b/rocfile/test/handle.cpp @@ -35,15 +35,17 @@ void expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper) { EXPECT_CALL(msys, fstat); + EXPECT_CALL(msys, statx); EXPECT_CALL(msys, fcntl(_, F_GETFL, 0)); EXPECT_CALL(mlibmounthelper, getMountInfo); } void -expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper, struct stat statbuf, int fcntl_flags, - MountInfo mountinfo) +expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper, struct stat statbuf, + struct statx stxbuf, int fcntl_flags, MountInfo mountinfo) { EXPECT_CALL(msys, fstat).WillOnce(Return(statbuf)); + EXPECT_CALL(msys, statx).WillOnce(Return(stxbuf)); EXPECT_CALL(msys, fcntl(_, F_GETFL, 0)).WillOnce(Return(fcntl_flags)); EXPECT_CALL(mlibmounthelper, getMountInfo).WillOnce(Return(mountinfo)); } @@ -63,23 +65,28 @@ TEST_F(RocFileHandle, register_handle_internal_linux_fd) TEST_F(RocFileHandle, file_initialization) { - int fd{0x12345678}; - int status_flags{0x789ABCDE}; + int fd{0x12345678}; + int status_flags{0x789ABCDE}; + struct statx stxbuf; + stxbuf.stx_dev_major = 0x12345678; + stxbuf.stx_dev_minor = 0x87654321; + stxbuf.stx_mode = 0xFEDC; struct stat fstat; - fstat.st_dev = makedev(0x12345678, 0x87654321); - fstat.st_mode = 0xFEDCBA98; + fstat.st_dev = makedev(stxbuf.stx_dev_major, stxbuf.stx_dev_minor); + fstat.st_mode = stxbuf.stx_mode; + MountInfo mountinfo; mountinfo.type = FilesystemType::ext4; mountinfo.options.ext4.journaling_mode = ExtJournalingMode::ordered; - expect_file_registration(msys, mlibmounthelper, fstat, status_flags, mountinfo); + expect_file_registration(msys, mlibmounthelper, fstat, stxbuf, status_flags, mountinfo); auto fh{Context::get()->registerFile(fd)}; auto file{Context::get()->getFile(fh)}; EXPECT_EQ(fh, file->getHandle()); EXPECT_EQ(fd, file->getFd()); - EXPECT_EQ(fstat.st_dev, file->getDevice()); - EXPECT_EQ(fstat.st_mode, file->getMode()); + EXPECT_EQ(makedev(stxbuf.stx_dev_major, stxbuf.stx_dev_minor), file->getDevice()); + EXPECT_EQ(stxbuf.stx_mode, file->getMode()); EXPECT_EQ(status_flags, file->getStatusFlags()); EXPECT_EQ(mountinfo.type, file->getMountInfo().value().type); EXPECT_EQ(mountinfo.options.ext4.journaling_mode, @@ -130,6 +137,7 @@ TEST_F(RocFileHandle, RocfileHandleRegisterFcntlError) rfd.handle.fd = 0xBADF00D; EXPECT_CALL(msys, fstat); + EXPECT_CALL(msys, statx); EXPECT_CALL(msys, fcntl).WillOnce(Throw(Sys::RuntimeError(EBADF))); ASSERT_EQ(rocFileHandleRegister(&fh, &rfd), RocFileOpError(rocFileInternalError)); @@ -144,6 +152,7 @@ TEST_F(RocFileHandle, RocfileHandleRegisterLibMountError) rfd.handle.fd = 0xBADF00D; EXPECT_CALL(msys, fstat); + EXPECT_CALL(msys, statx); EXPECT_CALL(msys, fcntl); EXPECT_CALL(mlibmounthelper, getMountInfo).WillOnce(Throw(std::runtime_error("error from test"))); diff --git a/rocfile/test/mfile.h b/rocfile/test/mfile.h index e1d54bc0..066ae6d3 100644 --- a/rocfile/test/mfile.h +++ b/rocfile/test/mfile.h @@ -22,6 +22,7 @@ class MFile : public IFile { MOCK_METHOD(int, getFd, (), (const override)); MOCK_METHOD(dev_t, getDevice, (), (const override)); MOCK_METHOD(mode_t, getMode, (), (const override)); + MOCK_METHOD(const struct statx &, getStatx, (), (const, noexcept, override)); MOCK_METHOD(int, getStatusFlags, (), (const override)); MOCK_METHOD(std::optional, getMountInfo, (), (const override)); }; diff --git a/rocfile/test/rocfile-test.h b/rocfile/test/rocfile-test.h index a433dc97..cbd30db7 100644 --- a/rocfile/test/rocfile-test.h +++ b/rocfile/test/rocfile-test.h @@ -129,7 +129,8 @@ void expect_file_registration(rocFile::MSys &msys, rocFile::MLibMountHelper &mli /// /// Mock methods will return the specified values void expect_file_registration(rocFile::MSys &msys, rocFile::MLibMountHelper &mlibmounthelper, - struct stat statbuf, int fcntl_flags, rocFile::MountInfo mountinfo); + struct stat statbuf, struct statx stxbuf, int fcntl_flags, + rocFile::MountInfo mountinfo); // *********************************************************************** // ENUM VALUE HELPERS From 0666a0c2733153b2ee98de116a74d6cc9fcb0064 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Mon, 17 Nov 2025 22:25:19 +0000 Subject: [PATCH 3/6] rocfile: Remove stat data from file Adding statx data to file has made stat data redundant. --- rocfile/src/file.cpp | 30 ++++++------------------------ rocfile/src/file.h | 20 -------------------- rocfile/test/driver.cpp | 2 +- rocfile/test/handle.cpp | 28 ++++++++++------------------ rocfile/test/mfile.h | 2 -- rocfile/test/rocfile-test.h | 3 +-- 6 files changed, 18 insertions(+), 67 deletions(-) diff --git a/rocfile/src/file.cpp b/rocfile/src/file.cpp index d5cf4852..c242a0f6 100644 --- a/rocfile/src/file.cpp +++ b/rocfile/src/file.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include using std::optional; @@ -23,11 +24,11 @@ using std::vector; namespace rocFile { UnregisteredFile::UnregisteredFile(int fd) - : m_fd(fd), m_stat{Context::get()->fstat(fd)}, - m_stx{Context::get()->statx(fd, "", AT_EMPTY_PATH, - STATX_BASIC_STATS | STATX_MNT_ID | STATX_DIOALIGN)}, + : m_fd(fd), + m_stx{Context::get()->statx(fd, "", AT_EMPTY_PATH, STATX_TYPE | STATX_MODE | STATX_DIOALIGN)}, m_flags{Context::get()->fcntl(fd, F_GETFL, 0)}, - m_mountinfo{Context::get()->getMountInfo(m_stat.st_dev)} + m_mountinfo{ + Context::get()->getMountInfo(makedev(m_stx.stx_dev_major, m_stx.stx_dev_minor))} { } @@ -37,12 +38,6 @@ UnregisteredFile::getFd() const noexcept return m_fd; } -struct stat -UnregisteredFile::getStat() const noexcept -{ - return m_stat; -} - struct statx UnregisteredFile::getStatx() const noexcept { @@ -68,8 +63,7 @@ IFile::getHandle() const } File::File(const UnregisteredFile &uf) - : fd{uf.getFd()}, device{uf.getStat().st_dev}, mode{uf.getStat().st_mode}, stx{uf.getStatx()}, - status_flags{uf.getFlags()}, mountinfo{uf.getMountInfo()} + : fd{uf.getFd()}, stx{uf.getStatx()}, status_flags{uf.getFlags()}, mountinfo{uf.getMountInfo()} { } @@ -79,18 +73,6 @@ File::getFd() const return fd; } -dev_t -File::getDevice() const -{ - return device; -} - -mode_t -File::getMode() const -{ - return mode; -} - const struct statx & File::getStatx() const noexcept { diff --git a/rocfile/src/file.h b/rocfile/src/file.h index 20117cf3..f4a446f1 100644 --- a/rocfile/src/file.h +++ b/rocfile/src/file.h @@ -51,9 +51,6 @@ class UnregisteredFile { /// @return Returns the file descriptor int getFd() const noexcept; - /// @return Returns the information provided by fstat (2) - struct stat getStat() const noexcept; - /// @return Returns the information provided by statx (2) struct statx getStatx() const noexcept; @@ -67,9 +64,6 @@ class UnregisteredFile { /// @brief The file descriptor int m_fd; - /// @brief Information provided by fstat (2) - struct stat m_stat; - /// @brief Information provided by statx (2) struct statx m_stx; @@ -89,8 +83,6 @@ class IFile { virtual rocFileHandle_t getHandle() const; virtual int getFd() const = 0; - virtual dev_t getDevice() const = 0; - virtual mode_t getMode() const = 0; virtual const struct statx &getStatx() const noexcept = 0; virtual int getStatusFlags() const = 0; virtual std::optional getMountInfo() const = 0; @@ -110,8 +102,6 @@ class File : public IFile { File &operator=(File &&) = delete; virtual int getFd() const override; - virtual dev_t getDevice() const override; - virtual mode_t getMode() const override; virtual const struct statx &getStatx() const noexcept override; virtual int getStatusFlags() const override; virtual std::optional getMountInfo() const override; @@ -124,16 +114,6 @@ class File : public IFile { /// @brief The file descriptor int fd; - /// @brief The ID of the device containing file - /// - /// Used to lookup mount information. See fstat(2), inode(7), and proc_pid_mountinfo(5) - dev_t device; - - /// @brief The file type and mode - /// - /// Specifies the file type (regular file, block device, ...) and mode. See fstat(2) and inode(7) - mode_t mode; - /// @brief File status information obtained from statx (2) struct statx stx; diff --git a/rocfile/test/driver.cpp b/rocfile/test/driver.cpp index 4d9ffcfa..e35c5f74 100644 --- a/rocfile/test/driver.cpp +++ b/rocfile/test/driver.cpp @@ -105,7 +105,7 @@ TEST_F(RocFileDriverAdmin, HandleRegisterBadFD) descr.handle.fd = -1; descr.type = rocFileHandleTypeOpaqueFD; - EXPECT_CALL(msys, fstat).WillOnce(Throw(Sys::RuntimeError(EBADF))); + EXPECT_CALL(msys, statx).WillOnce(Throw(Sys::RuntimeError(EBADF))); ASSERT_EQ(rocFileUseCount(), 0); ASSERT_NE(rocFileHandleRegister(&handle, &descr), ROCFILE_SUCCESS); diff --git a/rocfile/test/handle.cpp b/rocfile/test/handle.cpp index 6ab7e970..edc64dad 100644 --- a/rocfile/test/handle.cpp +++ b/rocfile/test/handle.cpp @@ -15,6 +15,7 @@ #include "sys.h" #include +#include #include #include #include @@ -34,17 +35,15 @@ HIPFILE_WARN_NO_GLOBAL_CTOR_OFF void expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper) { - EXPECT_CALL(msys, fstat); EXPECT_CALL(msys, statx); EXPECT_CALL(msys, fcntl(_, F_GETFL, 0)); EXPECT_CALL(mlibmounthelper, getMountInfo); } void -expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper, struct stat statbuf, - struct statx stxbuf, int fcntl_flags, MountInfo mountinfo) +expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper, struct statx stxbuf, int fcntl_flags, + MountInfo mountinfo) { - EXPECT_CALL(msys, fstat).WillOnce(Return(statbuf)); EXPECT_CALL(msys, statx).WillOnce(Return(stxbuf)); EXPECT_CALL(msys, fcntl(_, F_GETFL, 0)).WillOnce(Return(fcntl_flags)); EXPECT_CALL(mlibmounthelper, getMountInfo).WillOnce(Return(mountinfo)); @@ -68,25 +67,20 @@ TEST_F(RocFileHandle, file_initialization) int fd{0x12345678}; int status_flags{0x789ABCDE}; struct statx stxbuf; - stxbuf.stx_dev_major = 0x12345678; - stxbuf.stx_dev_minor = 0x87654321; - stxbuf.stx_mode = 0xFEDC; - struct stat fstat; - fstat.st_dev = makedev(stxbuf.stx_dev_major, stxbuf.stx_dev_minor); - fstat.st_mode = stxbuf.stx_mode; + memset(&stxbuf, 0xA5, sizeof(stxbuf)); MountInfo mountinfo; mountinfo.type = FilesystemType::ext4; mountinfo.options.ext4.journaling_mode = ExtJournalingMode::ordered; - expect_file_registration(msys, mlibmounthelper, fstat, stxbuf, status_flags, mountinfo); + expect_file_registration(msys, mlibmounthelper, stxbuf, status_flags, mountinfo); auto fh{Context::get()->registerFile(fd)}; auto file{Context::get()->getFile(fh)}; EXPECT_EQ(fh, file->getHandle()); EXPECT_EQ(fd, file->getFd()); - EXPECT_EQ(makedev(stxbuf.stx_dev_major, stxbuf.stx_dev_minor), file->getDevice()); - EXPECT_EQ(stxbuf.stx_mode, file->getMode()); + auto file_stx{file->getStatx()}; + EXPECT_EQ(0, memcmp(&file_stx, &stxbuf, sizeof(stxbuf))); EXPECT_EQ(status_flags, file->getStatusFlags()); EXPECT_EQ(mountinfo.type, file->getMountInfo().value().type); EXPECT_EQ(mountinfo.options.ext4.journaling_mode, @@ -115,15 +109,15 @@ TEST_F(RocFileHandle, register_handle_linux_fd) ASSERT_NE(fh, nullptr); } -// If the fstat() fails during file registration return rocfileInternalError -TEST_F(RocFileHandle, RocfileHandleRegisterFstatError) +// If statx() fails during file registration return rocfileInternalError +TEST_F(RocFileHandle, RocfileHandleRegisterStatxError) { rocFileHandle_t fh{}; rocFileDescr_t rfd{}; rfd.type = rocFileHandleTypeOpaqueFD; rfd.handle.fd = 0xBADF00D; - EXPECT_CALL(msys, fstat).WillOnce(Throw(Sys::RuntimeError(EBADF))); + EXPECT_CALL(msys, statx).WillOnce(Throw(Sys::RuntimeError(EBADF))); ASSERT_EQ(rocFileHandleRegister(&fh, &rfd), RocFileOpError(rocFileInternalError)); } @@ -136,7 +130,6 @@ TEST_F(RocFileHandle, RocfileHandleRegisterFcntlError) rfd.type = rocFileHandleTypeOpaqueFD; rfd.handle.fd = 0xBADF00D; - EXPECT_CALL(msys, fstat); EXPECT_CALL(msys, statx); EXPECT_CALL(msys, fcntl).WillOnce(Throw(Sys::RuntimeError(EBADF))); @@ -151,7 +144,6 @@ TEST_F(RocFileHandle, RocfileHandleRegisterLibMountError) rfd.type = rocFileHandleTypeOpaqueFD; rfd.handle.fd = 0xBADF00D; - EXPECT_CALL(msys, fstat); EXPECT_CALL(msys, statx); EXPECT_CALL(msys, fcntl); EXPECT_CALL(mlibmounthelper, getMountInfo).WillOnce(Throw(std::runtime_error("error from test"))); diff --git a/rocfile/test/mfile.h b/rocfile/test/mfile.h index 066ae6d3..37828379 100644 --- a/rocfile/test/mfile.h +++ b/rocfile/test/mfile.h @@ -20,8 +20,6 @@ class MFile : public IFile { public: MOCK_METHOD(rocFileHandle_t, getHandle, (), (const override)); MOCK_METHOD(int, getFd, (), (const override)); - MOCK_METHOD(dev_t, getDevice, (), (const override)); - MOCK_METHOD(mode_t, getMode, (), (const override)); MOCK_METHOD(const struct statx &, getStatx, (), (const, noexcept, override)); MOCK_METHOD(int, getStatusFlags, (), (const override)); MOCK_METHOD(std::optional, getMountInfo, (), (const override)); diff --git a/rocfile/test/rocfile-test.h b/rocfile/test/rocfile-test.h index cbd30db7..9d8253b6 100644 --- a/rocfile/test/rocfile-test.h +++ b/rocfile/test/rocfile-test.h @@ -129,8 +129,7 @@ void expect_file_registration(rocFile::MSys &msys, rocFile::MLibMountHelper &mli /// /// Mock methods will return the specified values void expect_file_registration(rocFile::MSys &msys, rocFile::MLibMountHelper &mlibmounthelper, - struct stat statbuf, struct statx stxbuf, int fcntl_flags, - rocFile::MountInfo mountinfo); + struct statx stxbuf, int fcntl_flags, rocFile::MountInfo mountinfo); // *********************************************************************** // ENUM VALUE HELPERS From d1d7603cae2687e299f36931228aaacbf3178f77 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Tue, 18 Nov 2025 22:37:23 +0000 Subject: [PATCH 4/6] rocfile: Use statx direct IO alignment & size data in Fastpath::score() See statx (2) for more information. --- rocfile/src/backend/fastpath.cpp | 16 +++-- rocfile/test/fastpath.cpp | 105 ++++++++++++++++++++++++------- 2 files changed, 93 insertions(+), 28 deletions(-) diff --git a/rocfile/src/backend/fastpath.cpp b/rocfile/src/backend/fastpath.cpp index 74c5dd80..b92bc5de 100644 --- a/rocfile/src/backend/fastpath.cpp +++ b/rocfile/src/backend/fastpath.cpp @@ -20,9 +20,10 @@ using namespace std; /* The fastpath backend is used when: * - The file has been opened with the O_DIRECT flag - * - file_offset is 4KiB aligned - * - buffer_offset is 4KiB aligned - * - size is a multiple of 4KiB + * - statx indicates the file descriptor supports direct IO (see statx (2)) + * - file_offset is a multiple of stx_dio_offset_align (see statx (2)) + * - buffer_offset is a multiple of stx_dio_mem_align (see statx (2)) + * - size is a multiple of stx_dio_offset_align (see statx (2)) * - The buffer type is hipMemoryTypeDevice * * When using the fastpath the IO flows through the following @@ -126,9 +127,12 @@ Fastpath::score(shared_ptr file, shared_ptr buffer, size_t size, accept_io &= 0 <= file_offset; accept_io &= 0 <= buffer_offset; - accept_io &= !(size & 0xFFF); - accept_io &= !(file_offset & 0xFFF); - accept_io &= !(buffer_offset & 0xFFF); + const struct statx &stx{file->getStatx()}; + accept_io &= !!(stx.stx_mask & STATX_DIOALIGN); + accept_io &= stx.stx_dio_offset_align && stx.stx_dio_mem_align; + accept_io &= !(size & (stx.stx_dio_offset_align - 1)); + accept_io &= !(file_offset & (stx.stx_dio_offset_align - 1)); + accept_io &= !(buffer_offset & (stx.stx_dio_mem_align - 1)); return accept_io ? 100 : -1; } diff --git a/rocfile/test/fastpath.cpp b/rocfile/test/fastpath.cpp index e74f7b6e..135c199f 100644 --- a/rocfile/test/fastpath.cpp +++ b/rocfile/test/fastpath.cpp @@ -41,25 +41,35 @@ operator==(const hipAmdFileHandle_t &lhs, const hipAmdFileHandle_t &rhs) // Provide default values for variables used in fastpath tests struct FastpathTestBase { - const size_t DEFAULT_IO_SIZE{1024 * 1024}; - void *const DEFAULT_BUFFER_ADDR{reinterpret_cast(0xCAFE000)}; - const off_t DEFAULT_BUFFER_OFFSET{4096}; - const hipMemoryType DEFAULT_BUFFER_TYPE{hipMemoryTypeDevice}; - const int DEFAULT_FILE_DESCRIPTOR{7}; - const int DEFAULT_FILE_FLAGS{O_DIRECT}; - const off_t DEFAULT_FILE_OFFSET{8192}; + const size_t DEFAULT_IO_SIZE{1024 * 1024}; + void *const DEFAULT_BUFFER_ADDR{reinterpret_cast(0x600DB10C)}; + const off_t DEFAULT_BUFFER_OFFSET{512}; + const hipMemoryType DEFAULT_BUFFER_TYPE{hipMemoryTypeDevice}; + const int DEFAULT_FILE_DESCRIPTOR{7}; + const int DEFAULT_FILE_FLAGS{O_DIRECT}; + const off_t DEFAULT_FILE_OFFSET{8192}; + static const struct statx DEFAULT_STATX; // Buffer and file mocks used to setup expectations shared_ptr> mfile{make_shared>()}; shared_ptr> mbuffer{make_shared>()}; }; +const struct statx FastpathTestBase::DEFAULT_STATX = []() { + struct statx stx; + stx.stx_mask = STATX_DIOALIGN; + stx.stx_dio_mem_align = 4; + stx.stx_dio_offset_align = 512; + return stx; +}(); + struct FastpathTest : public FastpathTestBase, public Test {}; TEST_F(FastpathTest, DefaultExpecations) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), SCORE_ACCEPT); @@ -69,17 +79,42 @@ TEST_F(FastpathTest, BufferedFile) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS & ~O_DIRECT)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), SCORE_REJECT); } +TEST_F(FastpathTest, ScoreRejectsNegativeAlignedFileOffset) +{ + EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS & ~O_DIRECT)); + EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); + + ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, + -static_cast(DEFAULT_STATX.stx_dio_offset_align), + DEFAULT_BUFFER_OFFSET), + SCORE_REJECT); +} + +TEST_F(FastpathTest, ScoreRejectsNegativeAlignedBufferOffset) +{ + EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS & ~O_DIRECT)); + EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); + + ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_BUFFER_OFFSET, + -static_cast(DEFAULT_STATX.stx_dio_offset_align)), + SCORE_REJECT); +} + struct FastpathSupportedHipMemoryParam : public FastpathTestBase, public TestWithParam {}; TEST_P(FastpathSupportedHipMemoryParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(GetParam())); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), SCORE_ACCEPT); @@ -93,6 +128,7 @@ TEST_P(FastpathUnsupportedHipMemoryParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(GetParam())); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), SCORE_REJECT); @@ -107,13 +143,17 @@ TEST_P(FastpathAlignedIoSizesParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, GetParam(), DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), SCORE_ACCEPT); } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedIoSizesParam, - Values(0, 4096, 1024 * 1024, 1024 * 1024 * 1024)); + Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3)); struct FastpathUnalignedIoSizesParam : public FastpathTestBase, public TestWithParam {}; @@ -121,70 +161,91 @@ TEST_P(FastpathUnalignedIoSizesParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, GetParam(), DEFAULT_FILE_OFFSET, DEFAULT_BUFFER_OFFSET), SCORE_REJECT); } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathUnalignedIoSizesParam, - Values(1, 4096 - 1, 1024 * 1024 + 1, 1024 * 1024 * 1024 - 1)); + Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0 + 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1 - 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2 + 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3 - 1)); -struct FastpathAlignedFileOffsetsParam : public FastpathTestBase, public TestWithParam {}; +struct FastpathAlignedFileOffsetsParam : public FastpathTestBase, public TestWithParam {}; TEST_P(FastpathAlignedFileOffsetsParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, GetParam(), DEFAULT_BUFFER_OFFSET), SCORE_ACCEPT); } -static array aligned_offsets{0, 4096, 1024 * 1024, 1024 * 1024 * 1024}; -INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedFileOffsetsParam, ValuesIn(aligned_offsets)); +INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedFileOffsetsParam, + Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3)); /// @brief Tests negative and unaligned file offsets -struct FastpathInvalidFileOffsetsParam : public FastpathTestBase, public TestWithParam {}; +struct FastpathUnalignedFileOffsetsParam : public FastpathTestBase, public TestWithParam {}; -TEST_P(FastpathInvalidFileOffsetsParam, Score) +TEST_P(FastpathUnalignedFileOffsetsParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, GetParam(), DEFAULT_BUFFER_OFFSET), SCORE_REJECT); } -static array invalid_offsets{-1024 * 1024 * 1024, -1024 * 1024, -4096, 1, 4096 - 1, - 1024 * 1024 + 1, 1024 * 1024 * 1024 - 1}; -INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathInvalidFileOffsetsParam, ValuesIn(invalid_offsets)); +INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathUnalignedFileOffsetsParam, + Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0 + 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1 - 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2 + 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3 - 1)); -struct FastpathAlignedBufferOffsetsParam : public FastpathTestBase, public TestWithParam {}; +struct FastpathAlignedBufferOffsetsParam : public FastpathTestBase, public TestWithParam {}; TEST_P(FastpathAlignedBufferOffsetsParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_BUFFER_OFFSET, GetParam()), SCORE_ACCEPT); } -INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedBufferOffsetsParam, ValuesIn(aligned_offsets)); +INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedBufferOffsetsParam, + Values(FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 0, + FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 2, + FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 3)); /// @brief Tests negative and unaligned buffer offsets -struct FastpathInvalidBufferOffsetsParam : public FastpathTestBase, public TestWithParam {}; +struct FastpathUnalignedBufferOffsetsParam : public FastpathTestBase, public TestWithParam {}; -TEST_P(FastpathInvalidBufferOffsetsParam, Score) +TEST_P(FastpathUnalignedBufferOffsetsParam, Score) { EXPECT_CALL(*mfile, getStatusFlags).WillOnce(Return(DEFAULT_FILE_FLAGS)); EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); + EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_FILE_OFFSET, GetParam()), SCORE_REJECT); } -INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathInvalidBufferOffsetsParam, ValuesIn(invalid_offsets)); +INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathUnalignedBufferOffsetsParam, + Values(FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 0 + 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 1 - 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 2 + 1, + FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 3 - 1)); struct FastpathIoParam : public FastpathTestBase, public TestWithParam {}; From 14b4e1f94b52b7577ff03b8ad4ec41096fe91860 Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Tue, 18 Nov 2025 22:53:39 +0000 Subject: [PATCH 5/6] rocfile: IWYU changes --- rocfile/src/backend/fastpath.cpp | 1 + rocfile/src/file.h | 3 +-- rocfile/src/sys.cpp | 1 + rocfile/src/sys.h | 2 +- rocfile/test/fastpath.cpp | 1 + rocfile/test/handle.cpp | 3 +-- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/rocfile/src/backend/fastpath.cpp b/rocfile/src/backend/fastpath.cpp index b92bc5de..2cce93d8 100644 --- a/rocfile/src/backend/fastpath.cpp +++ b/rocfile/src/backend/fastpath.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include using namespace rocFile; diff --git a/rocfile/src/file.h b/rocfile/src/file.h index f4a446f1..f1ff06b6 100644 --- a/rocfile/src/file.h +++ b/rocfile/src/file.h @@ -8,11 +8,10 @@ #include "rocfile.h" #include "mountinfo.h" +#include #include #include #include -#include -#include #include namespace rocFile { diff --git a/rocfile/src/sys.cpp b/rocfile/src/sys.cpp index c9f8cfda..d7f9768a 100644 --- a/rocfile/src/sys.cpp +++ b/rocfile/src/sys.cpp @@ -5,6 +5,7 @@ #include "sys.h" +#include #include #include #include diff --git a/rocfile/src/sys.h b/rocfile/src/sys.h index 60bfe360..40caf886 100644 --- a/rocfile/src/sys.h +++ b/rocfile/src/sys.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/rocfile/test/fastpath.cpp b/rocfile/test/fastpath.cpp index 135c199f..835dec24 100644 --- a/rocfile/test/fastpath.cpp +++ b/rocfile/test/fastpath.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/rocfile/test/handle.cpp b/rocfile/test/handle.cpp index edc64dad..f9a31bcd 100644 --- a/rocfile/test/handle.cpp +++ b/rocfile/test/handle.cpp @@ -19,11 +19,10 @@ #include #include #include +#include #include #include #include -#include -#include using namespace rocFile; using namespace testing; From 0c8aa390f7fdc834309ead40b7c59dba3e6047dd Mon Sep 17 00:00:00 2001 From: Kurt McMillan Date: Tue, 18 Nov 2025 23:47:07 +0000 Subject: [PATCH 6/6] rocfile/fastpath: Handle STATX_DIOALIGN not being available on pre 6.1 Kernels If STATX_DIOALIGN is not available fallback to requiring IO size, file offset, and buffer offset to be multiples of 4KiB. --- rocfile/src/backend/fastpath.cpp | 19 ++++++-- rocfile/src/file.cpp | 9 +++- rocfile/test/fastpath.cpp | 84 ++++++++++++++++---------------- 3 files changed, 63 insertions(+), 49 deletions(-) diff --git a/rocfile/src/backend/fastpath.cpp b/rocfile/src/backend/fastpath.cpp index 2cce93d8..087a5866 100644 --- a/rocfile/src/backend/fastpath.cpp +++ b/rocfile/src/backend/fastpath.cpp @@ -21,10 +21,15 @@ using namespace std; /* The fastpath backend is used when: * - The file has been opened with the O_DIRECT flag - * - statx indicates the file descriptor supports direct IO (see statx (2)) - * - file_offset is a multiple of stx_dio_offset_align (see statx (2)) - * - buffer_offset is a multiple of stx_dio_mem_align (see statx (2)) - * - size is a multiple of stx_dio_offset_align (see statx (2)) + * - if statx contains direct io information + * - statx indicates the file descriptor supports direct IO (see statx (2)) + * - file_offset is a multiple of stx_dio_offset_align (see statx (2)) + * - buffer_offset is a multiple of stx_dio_mem_align (see statx (2)) + * - size is a multiple of stx_dio_offset_align (see statx (2)) + * - if statx does not contain direct io information + * - file_offset is a multiple of 4096 + * - buffer_offset is a multiple of 4096 + * - size is a multiple of 4096 * - The buffer type is hipMemoryTypeDevice * * When using the fastpath the IO flows through the following @@ -128,12 +133,18 @@ Fastpath::score(shared_ptr file, shared_ptr buffer, size_t size, accept_io &= 0 <= file_offset; accept_io &= 0 <= buffer_offset; +#if defined(STATX_DIOALIGN) const struct statx &stx{file->getStatx()}; accept_io &= !!(stx.stx_mask & STATX_DIOALIGN); accept_io &= stx.stx_dio_offset_align && stx.stx_dio_mem_align; accept_io &= !(size & (stx.stx_dio_offset_align - 1)); accept_io &= !(file_offset & (stx.stx_dio_offset_align - 1)); accept_io &= !(buffer_offset & (stx.stx_dio_mem_align - 1)); +#else + accept_io &= !(size & 0xFFF); + accept_io &= !(file_offset & 0xFFF); + accept_io &= !(buffer_offset & 0xFFF); +#endif return accept_io ? 100 : -1; } diff --git a/rocfile/src/file.cpp b/rocfile/src/file.cpp index c242a0f6..dbcbb382 100644 --- a/rocfile/src/file.cpp +++ b/rocfile/src/file.cpp @@ -24,8 +24,13 @@ using std::vector; namespace rocFile { UnregisteredFile::UnregisteredFile(int fd) - : m_fd(fd), - m_stx{Context::get()->statx(fd, "", AT_EMPTY_PATH, STATX_TYPE | STATX_MODE | STATX_DIOALIGN)}, + : m_fd(fd), m_stx{Context::get()->statx(fd, "", AT_EMPTY_PATH, +#if defined(STATX_DIOALIGN) + STATX_TYPE | STATX_MODE | STATX_DIOALIGN +#else + STATX_TYPE | STATX_MODE +#endif + )}, m_flags{Context::get()->fcntl(fd, F_GETFL, 0)}, m_mountinfo{ Context::get()->getMountInfo(makedev(m_stx.stx_dev_major, m_stx.stx_dev_minor))} diff --git a/rocfile/test/fastpath.cpp b/rocfile/test/fastpath.cpp index 835dec24..c561131a 100644 --- a/rocfile/test/fastpath.cpp +++ b/rocfile/test/fastpath.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,14 @@ HIPFILE_WARN_NO_GLOBAL_CTOR_OFF static int SCORE_ACCEPT{100}; static const int SCORE_REJECT{-1}; +#if defined(STATX_DIOALIGN) +static uint32_t DEFAULT_MEM_ALIGN{4}; +static uint32_t DEFAULT_OFFSET_ALIGN{512}; +#else +static uint32_t DEFAULT_MEM_ALIGN{4096}; +static uint32_t DEFAULT_OFFSET_ALIGN{4096}; +#endif + namespace rocFile { inline bool operator==(const hipAmdFileHandle_t &lhs, const hipAmdFileHandle_t &rhs) @@ -42,28 +51,30 @@ operator==(const hipAmdFileHandle_t &lhs, const hipAmdFileHandle_t &rhs) // Provide default values for variables used in fastpath tests struct FastpathTestBase { - const size_t DEFAULT_IO_SIZE{1024 * 1024}; - void *const DEFAULT_BUFFER_ADDR{reinterpret_cast(0x600DB10C)}; - const off_t DEFAULT_BUFFER_OFFSET{512}; - const hipMemoryType DEFAULT_BUFFER_TYPE{hipMemoryTypeDevice}; - const int DEFAULT_FILE_DESCRIPTOR{7}; - const int DEFAULT_FILE_FLAGS{O_DIRECT}; - const off_t DEFAULT_FILE_OFFSET{8192}; - static const struct statx DEFAULT_STATX; + const size_t DEFAULT_IO_SIZE{1024 * 1024}; + void *const DEFAULT_BUFFER_ADDR{reinterpret_cast(0x600DB10C)}; + const off_t DEFAULT_BUFFER_OFFSET{512}; + const hipMemoryType DEFAULT_BUFFER_TYPE{hipMemoryTypeDevice}; + const int DEFAULT_FILE_DESCRIPTOR{7}; + const int DEFAULT_FILE_FLAGS{O_DIRECT}; + const off_t DEFAULT_FILE_OFFSET{8192}; + const struct statx DEFAULT_STATX { + []() { + struct statx stx {}; +#if defined(STATX_DIOALIGN) + stx.stx_mask = STATX_DIOALIGN; + stx.stx_dio_mem_align = DEFAULT_MEM_ALIGN; + stx.stx_dio_offset_align = DEFAULT_OFFSET_ALIGN; +#endif + return stx; + }() + }; // Buffer and file mocks used to setup expectations shared_ptr> mfile{make_shared>()}; shared_ptr> mbuffer{make_shared>()}; }; -const struct statx FastpathTestBase::DEFAULT_STATX = []() { - struct statx stx; - stx.stx_mask = STATX_DIOALIGN; - stx.stx_dio_mem_align = 4; - stx.stx_dio_offset_align = 512; - return stx; -}(); - struct FastpathTest : public FastpathTestBase, public Test {}; TEST_F(FastpathTest, DefaultExpecations) @@ -92,8 +103,7 @@ TEST_F(FastpathTest, ScoreRejectsNegativeAlignedFileOffset) EXPECT_CALL(*mbuffer, getType).WillOnce(Return(DEFAULT_BUFFER_TYPE)); EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); - ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, - -static_cast(DEFAULT_STATX.stx_dio_offset_align), + ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, -static_cast(DEFAULT_OFFSET_ALIGN), DEFAULT_BUFFER_OFFSET), SCORE_REJECT); } @@ -105,7 +115,7 @@ TEST_F(FastpathTest, ScoreRejectsNegativeAlignedBufferOffset) EXPECT_CALL(*mfile, getStatx).WillOnce(ReturnRef(DEFAULT_STATX)); ASSERT_EQ(Fastpath().score(mfile, mbuffer, DEFAULT_IO_SIZE, DEFAULT_BUFFER_OFFSET, - -static_cast(DEFAULT_STATX.stx_dio_offset_align)), + -static_cast(DEFAULT_MEM_ALIGN)), SCORE_REJECT); } @@ -151,10 +161,8 @@ TEST_P(FastpathAlignedIoSizesParam, Score) } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedIoSizesParam, - Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3)); + Values(DEFAULT_OFFSET_ALIGN * 0, DEFAULT_OFFSET_ALIGN * 1, DEFAULT_OFFSET_ALIGN * 2, + DEFAULT_OFFSET_ALIGN * 3)); struct FastpathUnalignedIoSizesParam : public FastpathTestBase, public TestWithParam {}; @@ -169,10 +177,8 @@ TEST_P(FastpathUnalignedIoSizesParam, Score) } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathUnalignedIoSizesParam, - Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0 + 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1 - 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2 + 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3 - 1)); + Values(DEFAULT_OFFSET_ALIGN * 0 + 1, DEFAULT_OFFSET_ALIGN * 1 - 1, + DEFAULT_OFFSET_ALIGN * 2 + 1, DEFAULT_OFFSET_ALIGN * 3 - 1)); struct FastpathAlignedFileOffsetsParam : public FastpathTestBase, public TestWithParam {}; @@ -187,10 +193,8 @@ TEST_P(FastpathAlignedFileOffsetsParam, Score) } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedFileOffsetsParam, - Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3)); + Values(DEFAULT_OFFSET_ALIGN * 0, DEFAULT_OFFSET_ALIGN * 1, DEFAULT_OFFSET_ALIGN * 2, + DEFAULT_OFFSET_ALIGN * 3)); /// @brief Tests negative and unaligned file offsets struct FastpathUnalignedFileOffsetsParam : public FastpathTestBase, public TestWithParam {}; @@ -206,10 +210,8 @@ TEST_P(FastpathUnalignedFileOffsetsParam, Score) } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathUnalignedFileOffsetsParam, - Values(FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 0 + 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 1 - 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 2 + 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_offset_align * 3 - 1)); + Values(DEFAULT_OFFSET_ALIGN * 0 + 1, DEFAULT_OFFSET_ALIGN * 1 - 1, + DEFAULT_OFFSET_ALIGN * 2 + 1, DEFAULT_OFFSET_ALIGN * 3 - 1)); struct FastpathAlignedBufferOffsetsParam : public FastpathTestBase, public TestWithParam {}; @@ -224,10 +226,8 @@ TEST_P(FastpathAlignedBufferOffsetsParam, Score) } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathAlignedBufferOffsetsParam, - Values(FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 0, - FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 2, - FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 3)); + Values(DEFAULT_MEM_ALIGN * 0, DEFAULT_MEM_ALIGN * 1, DEFAULT_MEM_ALIGN * 2, + DEFAULT_MEM_ALIGN * 3)); /// @brief Tests negative and unaligned buffer offsets struct FastpathUnalignedBufferOffsetsParam : public FastpathTestBase, public TestWithParam {}; @@ -243,10 +243,8 @@ TEST_P(FastpathUnalignedBufferOffsetsParam, Score) } INSTANTIATE_TEST_SUITE_P(FastpathTest, FastpathUnalignedBufferOffsetsParam, - Values(FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 0 + 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 1 - 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 2 + 1, - FastpathTestBase::DEFAULT_STATX.stx_dio_mem_align * 3 - 1)); + Values(DEFAULT_MEM_ALIGN * 0 + 1, DEFAULT_MEM_ALIGN * 1 - 1, + DEFAULT_MEM_ALIGN * 2 + 1, DEFAULT_MEM_ALIGN * 3 - 1)); struct FastpathIoParam : public FastpathTestBase, public TestWithParam {};