From 6e6876c0ed4c286a70179830928e584e8e7e68a1 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Sun, 28 Jun 2026 00:13:39 +0200 Subject: [PATCH] Reject unsupported append mode --- cpp/include/cucim/filesystem/cufile_driver.h | 4 +++- cpp/src/filesystem/cufile_driver.cpp | 14 +++++++++++--- cpp/tests/test_cufile.cpp | 14 ++++++++++++++ python/pybind11/filesystem/cufile_pydoc.h | 1 + python/pybind11/filesystem/filesystem_pydoc.h | 4 ++-- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cpp/include/cucim/filesystem/cufile_driver.h b/cpp/include/cucim/filesystem/cufile_driver.h index 55e5c6cc2..f93521c6d 100644 --- a/cpp/include/cucim/filesystem/cufile_driver.h +++ b/cpp/include/cucim/filesystem/cufile_driver.h @@ -35,9 +35,10 @@ bool EXPORT_VISIBLE is_gds_available(); * - "r": O_RDONLY * - "r+": O_RDWR * - "w": O_RDWR | O_CREAT | O_TRUNC - * - "a": O_RDWR | O_CREAT * In addition to above flags, the method append O_CLOEXEC and O_DIRECT by default. * + * Append mode ("a") is not supported because CuFileDriver exposes explicit-offset pread()/pwrite() APIs. + * * The following is optional flags that can be added to above string: * - 'p': Use POSIX APIs only (first try to open with O_DIRECT). It does not use GDS. * - 'n': Do not add O_DIRECT flag. @@ -56,6 +57,7 @@ std::shared_ptr EXPORT_VISIBLE open(const char* file_path, const c * Open file with existing file descriptor. * * @param fd A file descriptor. To use GDS, fd needs to be opened with O_DIRECT flag. + * File descriptors opened with O_APPEND are not supported. * @param no_gds true if you do not want to use GDS. Default value is `false`. * @param use_mmap true if you want to use memory-mapped IO. This flag is supported only for the read-only file descriptor. Default value is `false`. * @return A std::shared_ptr object of CuFileDriver. diff --git a/cpp/src/filesystem/cufile_driver.cpp b/cpp/src/filesystem/cufile_driver.cpp index db12b0d40..0d8dc9a26 100644 --- a/cpp/src/filesystem/cufile_driver.cpp +++ b/cpp/src/filesystem/cufile_driver.cpp @@ -30,6 +30,8 @@ namespace cucim::filesystem { static constexpr unsigned int PAGE_SIZE = 4096; static constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 128 << 20; // 128MiB +static constexpr char kAppendModeUnsupportedMessage[] = + "Append mode is not supported because CuFileDriver uses explicit-offset pread()/pwrite() semantics."; static CuFileStub s_cufile_stub; static CuFileDriverInitializer s_cufile_initializer; thread_local static CuFileDriverCache s_cufile_cache; @@ -76,9 +78,6 @@ static int get_file_flags(const char* flags) case 'w': file_flags = O_RDWR | O_CREAT | O_TRUNC; break; - case 'a': - file_flags = O_RDWR | O_CREAT; - break; default: return -1; } @@ -96,6 +95,11 @@ bool is_gds_available() std::shared_ptr open(const char* file_path, const char* flags, mode_t mode) { + if (flags != nullptr && flags[0] == 'a') + { + throw std::invalid_argument(kAppendModeUnsupportedMessage); + } + bool use_o_direct = true; bool no_gds = false; bool use_mmap = false; @@ -189,6 +193,10 @@ CuFileDriver::CuFileDriver(int fd, bool no_gds, bool use_mmap, const char* file_ { throw std::runtime_error(fmt::format("[Error] fcntl failed for fd {} ({})", fd, std::strerror(errno))); } + if (flags & O_APPEND) + { + throw std::invalid_argument(kAppendModeUnsupportedMessage); + } file_flags_ = flags; FileHandleType file_type = (flags & O_DIRECT) ? FileHandleType::kPosixODirect : FileHandleType::kPosix; diff --git a/cpp/tests/test_cufile.cpp b/cpp/tests/test_cufile.cpp index 3b1610800..0e0ac8ccd 100644 --- a/cpp/tests/test_cufile.cpp +++ b/cpp/tests/test_cufile.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include // Test @@ -58,6 +59,19 @@ static void create_test_file(const char* file_name, int size) close(fd); } +TEST_CASE("Append mode should be rejected", "[test_cufile.cpp]") +{ + std::string output_file = fmt::format("{}/test_cufile_append.raw", g_config.temp_folder); + create_test_file(output_file.c_str(), 32); + + REQUIRE_THROWS_AS(cucim::filesystem::open(output_file.c_str(), "a"), std::invalid_argument); + + int append_fd = ::open(output_file.c_str(), O_RDWR | O_APPEND); + REQUIRE(append_fd >= 0); + REQUIRE_THROWS_AS(cucim::filesystem::open(append_fd, true, false), std::invalid_argument); + ::close(append_fd); +} + TEST_CASE("Verify libcufile usage", "[test_cufile.cpp]") { cudaError_t cuda_status; diff --git a/python/pybind11/filesystem/cufile_pydoc.h b/python/pybind11/filesystem/cufile_pydoc.h index bb8e98d68..d5b9b2133 100644 --- a/python/pybind11/filesystem/cufile_pydoc.h +++ b/python/pybind11/filesystem/cufile_pydoc.h @@ -16,6 +16,7 @@ Constructor of CuFileDriver. Args: fd: A file descriptor (in `int` type) which is available through `os.open()` method. + File descriptors opened with `os.O_APPEND` are not supported. no_gds: If True, use POSIX APIs only even when GDS can be supported for the file. use_mmap: If True, use memory-mapped IO. This flag is supported only for the read-only file descriptor. Default value is `False`. file_path: A file path for the file descriptor. It would retrieve the absolute file path of the file descriptor if not specified. diff --git a/python/pybind11/filesystem/filesystem_pydoc.h b/python/pybind11/filesystem/filesystem_pydoc.h index aa55d8dbc..30c977ff0 100644 --- a/python/pybind11/filesystem/filesystem_pydoc.h +++ b/python/pybind11/filesystem/filesystem_pydoc.h @@ -31,10 +31,10 @@ Open file with specific flags and mode. - "w": os.O_RDWR | os.O_CREAT | os.O_TRUNC -- "a": os.O_RDWR | os.O_CREAT - In addition to above flags, the method append os.O_CLOEXEC and os.O_DIRECT by default. +Append mode ("a") is not supported because CuFileDriver exposes explicit-offset pread()/pwrite() APIs. + The following is optional flags that can be added to above string: - 'p': Use POSIX APIs only (first try to open with O_DIRECT). It does not use GDS.