diff --git a/rocfile/src/backend/fastpath.cpp b/rocfile/src/backend/fastpath.cpp index 74c5dd80..087a5866 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; @@ -20,9 +21,15 @@ 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 + * - 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 @@ -126,9 +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 eec07bd6..dbcbb382 100644 --- a/rocfile/src/file.cpp +++ b/rocfile/src/file.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include using std::optional; @@ -23,8 +24,16 @@ 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_mountinfo{Context::get()->getMountInfo(m_stat.st_dev)} + : 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))} { } @@ -34,10 +43,10 @@ UnregisteredFile::getFd() const noexcept return m_fd; } -struct stat -UnregisteredFile::getStat() const noexcept +struct statx +UnregisteredFile::getStatx() const noexcept { - return m_stat; + return m_stx; } int @@ -59,8 +68,7 @@ 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()}, stx{uf.getStatx()}, status_flags{uf.getFlags()}, mountinfo{uf.getMountInfo()} { } @@ -70,16 +78,10 @@ File::getFd() const return fd; } -dev_t -File::getDevice() const -{ - return device; -} - -mode_t -File::getMode() const +const struct statx & +File::getStatx() const noexcept { - return mode; + return stx; } int diff --git a/rocfile/src/file.h b/rocfile/src/file.h index 996157a3..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 { @@ -51,8 +50,8 @@ 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; /// @return Returns the flags provided by fcntl (2) int getFlags() const noexcept; @@ -64,8 +63,8 @@ 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; /// @brief Flags provided by fcntl(2) int m_flags; @@ -82,11 +81,10 @@ 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 const struct statx &getStatx() const noexcept = 0; + virtual int getStatusFlags() const = 0; + virtual std::optional getMountInfo() const = 0; }; class File : public IFile { @@ -103,8 +101,7 @@ 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; @@ -116,15 +113,8 @@ 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; /// @brief The file's status flags. See fcntl(2) /// diff --git a/rocfile/src/sys.cpp b/rocfile/src/sys.cpp index 7cb46c7b..d7f9768a 100644 --- a/rocfile/src/sys.cpp +++ b/rocfile/src/sys.cpp @@ -5,6 +5,7 @@ #include "sys.h" +#include #include #include #include @@ -69,4 +70,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..40caf886 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/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/fastpath.cpp b/rocfile/test/fastpath.cpp index e74f7b6e..c561131a 100644 --- a/rocfile/test/fastpath.cpp +++ b/rocfile/test/fastpath.cpp @@ -14,10 +14,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -31,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,12 +52,23 @@ 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}; + 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>()}; @@ -60,6 +81,7 @@ 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 +91,41 @@ 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_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_MEM_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 +139,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 +154,15 @@ 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(DEFAULT_OFFSET_ALIGN * 0, DEFAULT_OFFSET_ALIGN * 1, DEFAULT_OFFSET_ALIGN * 2, + DEFAULT_OFFSET_ALIGN * 3)); struct FastpathUnalignedIoSizesParam : public FastpathTestBase, public TestWithParam {}; @@ -121,70 +170,81 @@ 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(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 {}; +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(DEFAULT_OFFSET_ALIGN * 0, DEFAULT_OFFSET_ALIGN * 1, DEFAULT_OFFSET_ALIGN * 2, + DEFAULT_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(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 {}; +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(DEFAULT_MEM_ALIGN * 0, DEFAULT_MEM_ALIGN * 1, DEFAULT_MEM_ALIGN * 2, + DEFAULT_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(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 {}; diff --git a/rocfile/test/handle.cpp b/rocfile/test/handle.cpp index 650ade84..f9a31bcd 100644 --- a/rocfile/test/handle.cpp +++ b/rocfile/test/handle.cpp @@ -15,14 +15,14 @@ #include "sys.h" #include +#include #include #include #include +#include #include #include #include -#include -#include using namespace rocFile; using namespace testing; @@ -34,16 +34,16 @@ 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, int fcntl_flags, +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)); } @@ -63,23 +63,23 @@ TEST_F(RocFileHandle, register_handle_internal_linux_fd) TEST_F(RocFileHandle, file_initialization) { - int fd{0x12345678}; - int status_flags{0x789ABCDE}; - struct stat fstat; - fstat.st_dev = makedev(0x12345678, 0x87654321); - fstat.st_mode = 0xFEDCBA98; + int fd{0x12345678}; + int status_flags{0x789ABCDE}; + struct statx stxbuf; + memset(&stxbuf, 0xA5, sizeof(stxbuf)); + 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, 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()); + 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, @@ -108,15 +108,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)); } @@ -129,7 +129,7 @@ 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))); ASSERT_EQ(rocFileHandleRegister(&fh, &rfd), RocFileOpError(rocFileInternalError)); @@ -143,7 +143,7 @@ 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 e1d54bc0..37828379 100644 --- a/rocfile/test/mfile.h +++ b/rocfile/test/mfile.h @@ -20,8 +20,7 @@ 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/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)); }; diff --git a/rocfile/test/rocfile-test.h b/rocfile/test/rocfile-test.h index a433dc97..9d8253b6 100644 --- a/rocfile/test/rocfile-test.h +++ b/rocfile/test/rocfile-test.h @@ -129,7 +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, int fcntl_flags, rocFile::MountInfo mountinfo); + struct statx stxbuf, int fcntl_flags, rocFile::MountInfo mountinfo); // *********************************************************************** // ENUM VALUE HELPERS