open_file_map.hpp 3.83 KiB
Newer Older
  Copyright 2018-2022, Barcelona Supercomputing Center (BSC), Spain
  Copyright 2015-2022, Johannes Gutenberg Universitaet Mainz, Germany

  This software was partially supported by the
  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).

  This software was partially supported by the
  ADA-FS project under the SPPEXA project funded by the DFG.

  This file is part of GekkoFS' POSIX interface.

  GekkoFS' POSIX interface is free software: you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public License as
  published by the Free Software Foundation, either version 3 of the License,
  or (at your option) any later version.

  GekkoFS' POSIX interface is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with GekkoFS' POSIX interface.  If not, see
  <https://www.gnu.org/licenses/>.

  SPDX-License-Identifier: LGPL-3.0-or-later
*/

#ifndef GEKKOFS_OPEN_FILE_MAP_HPP
#define GEKKOFS_OPEN_FILE_MAP_HPP
Marc Vef's avatar
Marc Vef committed

#include <map>
#include <mutex>
#include <memory>
#include <atomic>
Ramon Nou's avatar
Ramon Nou committed
#include <array>
Marc Vef's avatar
Marc Vef committed

Marc Vef's avatar
Marc Vef committed
namespace gkfs::filemap {
/* Forward declaration */
class OpenDir;


enum class OpenFile_flags {
    append = 0,
    creat,
    trunc,
    rdonly,
    wronly,
    rdwr,
Tommaso Tocci's avatar
Tommaso Tocci committed
    cloexec,
    flag_count // this is purely used as a size variable of this enum class
};

enum class FileType { regular, directory };
Tommaso Tocci's avatar
Tommaso Tocci committed

Marc Vef's avatar
Marc Vef committed
class OpenFile {
Tommaso Tocci's avatar
Tommaso Tocci committed
protected:
    FileType type_;
    std::array<bool, static_cast<int>(OpenFile_flags::flag_count)> flags_ = {
            {false}};
Tommaso Tocci's avatar
Tommaso Tocci committed
    unsigned long pos_;
    std::mutex pos_mutex_;
    std::mutex flag_mutex_;
Marc Vef's avatar
Marc Vef committed

public:
    // multiple threads may want to update the file position if fd has been
    // duplicated by dup()
    OpenFile(const std::string& path, int flags,
             FileType type = FileType::regular);
Marc Vef's avatar
Marc Vef committed

    // getter/setter
    std::string
    path() const;
Marc Vef's avatar
Marc Vef committed

    void
    path(const std::string& path_);
Marc Vef's avatar
Marc Vef committed

    unsigned long
    pos();
Nafi3's avatar
Nafi3 committed

    void
    pos(unsigned long pos_);
Nafi3's avatar
Nafi3 committed

    bool
    get_flag(OpenFile_flags flag);
    void
    set_flag(OpenFile_flags flag, bool value);
    FileType
    type() const;
Marc Vef's avatar
Marc Vef committed
};


class OpenFileMap {

private:
    std::map<int, std::shared_ptr<OpenFile>> files_;
    std::recursive_mutex files_mutex_;
    int
    safe_generate_fd_idx_();
     * TODO: Setting our file descriptor index to a specific value is dangerous
     * because we might clash with the kernel. E.g., if we would passthrough and
     * not intercept and the kernel assigns a file descriptor but we will later
     * use the same fd value, we will intercept calls that were supposed to be
     * going to the kernel. This works the other way around too. To mitigate
     * this issue, we set the initial fd number to a high value. We "hope" that
     * we do not clash but this is no permanent solution. Note: This solution
     * will probably work well already for many cases because kernel fd values
     * are reused, unlike to ours. The only case where we will clash with the
     * kernel is, if one process has more than 100000 files open at the same
     * time.
     */
    int fd_idx;
    std::mutex fd_idx_mutex;
    std::atomic<bool> fd_validation_needed;

Marc Vef's avatar
Marc Vef committed
public:
    OpenFileMap();

    std::shared_ptr<OpenFile>
    get(int fd);
    std::shared_ptr<OpenDir>
    get_dir(int dirfd);
    int add(std::shared_ptr<OpenFile>);
Tommaso Tocci's avatar
Tommaso Tocci committed

    int
    dup2(int oldfd, int newfd);
    int
    generate_fd_idx();
Marc Vef's avatar
Marc Vef committed
} // namespace gkfs::filemap
#endif // GEKKOFS_OPEN_FILE_MAP_HPP