Line data Source code
1 : /* 2 : Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain 3 : Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany 4 : 5 : This software was partially supported by the 6 : EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). 7 : 8 : This software was partially supported by the 9 : ADA-FS project under the SPPEXA project funded by the DFG. 10 : 11 : This file is part of GekkoFS' POSIX interface. 12 : 13 : GekkoFS' POSIX interface is free software: you can redistribute it and/or 14 : modify it under the terms of the GNU Lesser General Public License as 15 : published by the Free Software Foundation, either version 3 of the License, 16 : or (at your option) any later version. 17 : 18 : GekkoFS' POSIX interface is distributed in the hope that it will be useful, 19 : but WITHOUT ANY WARRANTY; without even the implied warranty of 20 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 : GNU Lesser General Public License for more details. 22 : 23 : You should have received a copy of the GNU Lesser General Public License 24 : along with GekkoFS' POSIX interface. If not, see 25 : <https://www.gnu.org/licenses/>. 26 : 27 : SPDX-License-Identifier: LGPL-3.0-or-later 28 : */ 29 : 30 : #ifndef GEKKOFS_OPEN_FILE_MAP_HPP 31 : #define GEKKOFS_OPEN_FILE_MAP_HPP 32 : 33 : #include <map> 34 : #include <mutex> 35 : #include <memory> 36 : #include <atomic> 37 : #include <array> 38 : #include <string> 39 : 40 : namespace gkfs::filemap { 41 : 42 : /* Forward declaration */ 43 : class OpenDir; 44 : 45 : 46 : enum class OpenFile_flags { 47 : append = 0, 48 : creat, 49 : trunc, 50 : rdonly, 51 : wronly, 52 : rdwr, 53 : cloexec, 54 : flag_count // this is purely used as a size variable of this enum class 55 : }; 56 : 57 : enum class FileType { regular, directory }; 58 : 59 : class OpenFile { 60 : protected: 61 : FileType type_; 62 : std::string path_; 63 : std::array<bool, static_cast<int>(OpenFile_flags::flag_count)> flags_ = { 64 : {false}}; 65 : unsigned long pos_; 66 : std::mutex pos_mutex_; 67 : std::mutex flag_mutex_; 68 : 69 : public: 70 : // multiple threads may want to update the file position if fd has been 71 : // duplicated by dup() 72 : 73 : OpenFile(const std::string& path, int flags, 74 : FileType type = FileType::regular); 75 : 76 1164 : ~OpenFile() = default; 77 : 78 : // getter/setter 79 : std::string 80 : path() const; 81 : 82 : void 83 : path(const std::string& path_); 84 : 85 : unsigned long 86 : pos(); 87 : 88 : void 89 : pos(unsigned long pos_); 90 : 91 : bool 92 : get_flag(OpenFile_flags flag); 93 : 94 : void 95 : set_flag(OpenFile_flags flag, bool value); 96 : 97 : FileType 98 : type() const; 99 : }; 100 : 101 : 102 272 : class OpenFileMap { 103 : 104 : private: 105 : std::map<int, std::shared_ptr<OpenFile>> files_; 106 : std::recursive_mutex files_mutex_; 107 : 108 : int 109 : safe_generate_fd_idx_(); 110 : 111 : /* 112 : * TODO: Setting our file descriptor index to a specific value is dangerous 113 : * because we might clash with the kernel. E.g., if we would passthrough and 114 : * not intercept and the kernel assigns a file descriptor but we will later 115 : * use the same fd value, we will intercept calls that were supposed to be 116 : * going to the kernel. This works the other way around too. To mitigate 117 : * this issue, we set the initial fd number to a high value. We "hope" that 118 : * we do not clash but this is no permanent solution. Note: This solution 119 : * will probably work well already for many cases because kernel fd values 120 : * are reused, unlike to ours. The only case where we will clash with the 121 : * kernel is, if one process has more than 100000 files open at the same 122 : * time. 123 : */ 124 : int fd_idx; 125 : std::mutex fd_idx_mutex; 126 : std::atomic<bool> fd_validation_needed; 127 : 128 : public: 129 : OpenFileMap(); 130 : 131 : std::shared_ptr<OpenFile> 132 : get(int fd); 133 : 134 : std::shared_ptr<OpenDir> 135 : get_dir(int dirfd); 136 : 137 : bool 138 : exist(int fd); 139 : 140 : int add(std::shared_ptr<OpenFile>); 141 : 142 : bool 143 : remove(int fd); 144 : 145 : int 146 : dup(int oldfd); 147 : 148 : int 149 : dup2(int oldfd, int newfd); 150 : 151 : int 152 : generate_fd_idx(); 153 : 154 : int 155 : get_fd_idx(); 156 : }; 157 : 158 : } // namespace gkfs::filemap 159 : 160 : #endif // GEKKOFS_OPEN_FILE_MAP_HPP