~aleteoryx/muditaos

537629013b5168c2714ac055af4159d7e9818b29 — Lucjan Bryndza 5 years ago 1c0c20e
[EGD-4498] Add support RO filesystem in the vfscore

Add support readonly filesystem mount flag
Add support for mount / remount
A board/rt1051/newlib/include/sys/mount.h => board/rt1051/newlib/include/sys/mount.h +41 -0
@@ 0,0 1,41 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once



/* These are the fs-independent mount-flags: up to 16 flags are
   supported  */
enum
{
  MS_RDONLY = 1,		/* Mount read-only.  */
  MS_NOEXEC = 8,		/* Disallow program execution.  */
  MS_SYNCHRONOUS = 16,		/* Writes are synced at once.  */
  MS_REMOUNT = 32,		/* Alter flags of a mounted FS.  */
  MS_MANDLOCK = 64,		/* Allow mandatory locks on an FS.  */
  MS_DIRSYNC = 128,		/* Directory modifications are synchronous.  */
  MS_NOATIME = 1024,		/* Do not update access times.  */
  MS_NODIRATIME = 2048,		/* Do not update directory access times.  */
  MS_BIND = 4096,		/* Bind directory at different place.  */
};




#ifdef __cplusplus
extern "C" {
#endif

/* Mount a filesystem.  */
int mount (const char *special_file, const char *dir,
		  const char *fstype, unsigned long int rwflag,
		  const void *data);

/* Unmount a filesystem.  */
int umount (const char *special_file);


#ifdef __cplusplus
}
#endif


M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +13 -10
@@ 8,6 8,7 @@
#include <purefs/fs/drivers/directory_handle_littlefs.hpp>
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/blkdev/disk_handle.hpp>
#include <purefs/fs/mount_flags.hpp>
#include <littlefs/lfs.h>
#include <log/log.hpp>



@@ 86,27 87,29 @@ namespace
        return lfs_mode;
    }

    auto translate_attrib_to_st_mode(uint8_t type)
    auto translate_attrib_to_st_mode(uint8_t type, bool ro)
    {
        decltype(static_cast<struct stat *>(nullptr)->st_mode) mode =
            S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH;
        decltype(static_cast<struct stat *>(nullptr)->st_mode) mode = S_IRUSR | S_IRGRP | S_IROTH;
        if (!ro) {
            mode |= S_IWUSR | S_IWGRP | S_IWOTH;
        }
        if (type == LFS_TYPE_REG) {
            mode |= (S_IFREG | S_IXUSR | S_IXGRP | S_IXOTH);
            mode |= S_IFREG;
        }
        else if (type == LFS_TYPE_DIR) {
            mode |= S_IFDIR;
            mode |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH);
        }
        return mode;
    }

    void translate_lfsinfo_to_stat(const ::lfs_info &fs, const lfs_config &cfg, struct stat &st)
    void translate_lfsinfo_to_stat(const ::lfs_info &fs, const lfs_config &cfg, bool ro, struct stat &st)
    {
        std::memset(&st, 0, sizeof st);
        st.st_nlink   = 1;
        st.st_size    = fs.size;
        st.st_blksize = cfg.block_size;
        st.st_blocks  = fs.size / cfg.block_count;
        st.st_mode    = translate_attrib_to_st_mode(fs.type);
        st.st_mode    = translate_attrib_to_st_mode(fs.type, ro);
    }

    [[gnu::nonnull(1)]] int setup_lfs_config(lfs_config *cfg, size_t sector_size, size_t part_sectors_count)


@@ 338,7 341,7 @@ namespace purefs::fs::drivers
        const auto err  = invoke_lfs(zfile->mntpoint(), ::lfs_stat, path.c_str(), &linfo);
        if (!err) {
            auto vmnt = std::static_pointer_cast<mount_point_littlefs>(vfile->mntpoint());
            translate_lfsinfo_to_stat(linfo, *vmnt->lfs_config(), st);
            translate_lfsinfo_to_stat(linfo, *vmnt->lfs_config(), vmnt->flags() & mount_flags::read_only, st);
        }
        return err;
    }


@@ 349,7 352,7 @@ namespace purefs::fs::drivers
        const auto err = invoke_lfs(mnt, file, ::lfs_stat, &linfo);
        if (!err) {
            auto mntp = std::static_pointer_cast<mount_point_littlefs>(mnt);
            translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), st);
            translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), mntp->flags() & mount_flags::read_only, st);
        }
        return err;
    }


@@ 418,7 421,7 @@ namespace purefs::fs::drivers
        int err = invoke_lfs(dirstate, ::lfs_dir_read, &linfo);
        if (err == 1) {
            auto mntp = std::static_pointer_cast<mount_point_littlefs>(dirstate->mntpoint());
            translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), filestat);
            translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), mntp->flags() & mount_flags::read_only, filestat);
            filename = linfo.name;
            err      = 0;
        }

M module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp => module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp +21 -8
@@ 7,6 7,7 @@
#include <purefs/blkdev/disk_handle.hpp>
#include <purefs/fs/drivers/file_handle_vfat.hpp>
#include <purefs/fs/drivers/directory_handle_vfat.hpp>
#include <purefs/fs/mount_flags.hpp>
#include <log/log.hpp>
#include <fatfs/volume_mapper.hpp>
#include <ff.h>


@@ 82,7 83,7 @@ namespace purefs::fs::drivers
            return fat_mode;
        }

        auto translate_fat_attrib_to_mode(BYTE fattrib)
        auto translate_fat_attrib_to_mode(BYTE fattrib, bool ro)
        {
            decltype(static_cast<struct stat *>(nullptr)->st_mode) mode = S_IRUSR | S_IRGRP | S_IROTH;



@@ 92,7 93,7 @@ namespace purefs::fs::drivers
            else {
                mode |= S_IFREG;
            }
            if ((fattrib & AM_RDO) == 0) {
            if ((fattrib & AM_RDO) == 0 && !ro) {
                mode |= (S_IWUSR | S_IWGRP | S_IWOTH);
            }
            if (fattrib & AM_HID) {}


@@ 109,7 110,7 @@ namespace purefs::fs::drivers
            return attr;
        }

        void translate_filinfo_to_stat(const FILINFO &fs, const FIL *fil, struct stat &st)
        void translate_filinfo_to_stat(const FILINFO &fs, const FIL *fil, bool ro, struct stat &st)
        {
            if (fil) {
                st.st_dev = fil->obj.id;


@@ 119,7 120,7 @@ namespace purefs::fs::drivers
                st.st_dev = 0;
                st.st_ino = 0;
            }
            st.st_mode  = translate_fat_attrib_to_mode(fs.fattrib);
            st.st_mode  = translate_fat_attrib_to_mode(fs.fattrib, ro);
            st.st_nlink = 1;
            st.st_uid   = 0;
            st.st_gid   = 0;


@@ 339,7 340,13 @@ namespace purefs::fs::drivers
        FILINFO finfo;
        const auto fres = f_stat(vfile->open_path().c_str(), &finfo);
        if (fres == FR_OK) {
            translate_filinfo_to_stat(finfo, vfile->ff_filp(), st);
            const auto vmnt = vfile->mntpoint();
            if (vmnt) {
                translate_filinfo_to_stat(finfo, vfile->ff_filp(), vmnt->flags() & mount_flags::read_only, st);
            }
            else {
                return -EIO;
            }
        }
        return translate_error(fres);
    }


@@ 355,7 362,7 @@ namespace purefs::fs::drivers
        const auto fspath = vmnt->native_path(file);
        const int fres    = f_stat(fspath.c_str(), &finfo);
        if (fres == FR_OK) {
            translate_filinfo_to_stat(finfo, nullptr, st);
            translate_filinfo_to_stat(finfo, nullptr, vmnt->flags() & mount_flags::read_only, st);
        }
        return translate_error(fres);
    }


@@ 436,8 443,14 @@ namespace purefs::fs::drivers
                return -ENODATA;
            }
            else {
                translate_filinfo_to_stat(ffinfo, nullptr, filestat);
                filename = ffinfo.fname;
                const auto vmnt = dirp->mntpoint();
                if (vmnt) {
                    translate_filinfo_to_stat(ffinfo, nullptr, vmnt->flags() & mount_flags::read_only, filestat);
                    filename = ffinfo.fname;
                }
                else {
                    return -EIO;
                }
            }
        }
        return translate_error(ferr);

A module-vfs/include/internal/purefs/fs/mount_flags.hpp => module-vfs/include/internal/purefs/fs/mount_flags.hpp +17 -0
@@ 0,0 1,17 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace purefs::fs
{
    //! Mount flags struct
    struct mount_flags
    {
        enum _mount_flags
        {
            read_only = 1,
            remount   = 32,
        };
    };
} // namespace purefs::fs

M module-vfs/include/internal/purefs/fs/mount_point.hpp => module-vfs/include/internal/purefs/fs/mount_point.hpp +5 -1
@@ 45,6 45,10 @@ namespace purefs::fs::internal
        {
            return m_flags;
        }
        void modify_flags(unsigned flags) noexcept
        {
            m_flags = flags;
        }
        auto native_path(std::string_view full_path) const noexcept -> std::string
        {
            const auto n1 = full_path.find(m_path);


@@ 66,6 70,6 @@ namespace purefs::fs::internal
        const std::weak_ptr<blkdev::internal::disk_handle> m_diskh;
        const std::string m_path;                        //! Mounted path
        const std::weak_ptr<filesystem_operations> m_fs; //! Filesystem operation
        const unsigned m_flags;
        unsigned m_flags;
    };
} // namespace purefs::fs::internal

M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +13 -10
@@ 14,6 14,7 @@
#include <purefs/fs/file_handle.hpp>
#include <purefs/fs/directory_handle.hpp>
#include <purefs/fs/mount_point.hpp>
#include <purefs/fs/mount_flags.hpp>
#include <type_traits>

struct statvfs;


@@ 41,15 42,6 @@ namespace purefs::fs
    {
        class directory_handle;
    }
    //! Mount flags struct
    struct mount_flags
    {
        enum _mount_flags
        {
            read_only = 1U < 0U, // !Read only filesystem
        };
    };

    class filesystem
    {
        static constexpr auto path_separator = '/';


@@ 173,6 165,11 @@ namespace purefs::fs
        auto find_filehandle(int fds) const noexcept -> fsfile;

      private:
        enum class iaccess : bool
        {
            ro, //! Syscall is RO
            rw  //! Syscall is RW
        };
        template <class Base, class T, typename... Args>
        inline auto invoke_fops(T Base::*method, int fds, Args &&... args)
            -> decltype((static_cast<Base *>(nullptr)->*method)(0, std::forward<Args>(args)...))


@@ 197,7 194,7 @@ namespace purefs::fs
        }

        template <class Base, class T, typename... Args>
        inline auto invoke_fops(T Base::*method, std::string_view path, Args &&... args) const
        inline auto invoke_fops(iaccess acc, T Base::*method, std::string_view path, Args &&... args) const
            -> decltype((static_cast<Base *>(nullptr)->*method)(nullptr, {}, std::forward<Args>(args)...))
        {
            const auto abspath     = absolute_path(path);


@@ 205,6 202,9 @@ namespace purefs::fs
            if (!mountp) {
                return -ENOENT;
            }
            if (acc == iaccess::rw && (mountp->flags() & mount_flags::read_only)) {
                return -EACCES;
            }
            auto fsops = mountp->fs_ops();
            if (fsops)
                return (fsops.get()->*method)(mountp, abspath, std::forward<Args>(args)...);


@@ 225,6 225,9 @@ namespace purefs::fs
            if (!mountp) {
                return -ENOENT;
            }
            if (mountp->flags() & mount_flags::read_only) {
                return -EACCES;
            }
            if (path.compare(0, pathpos, path2, 0, pathpos) != 0) {
                // Mount points are not the same
                return -EXDEV;

M module-vfs/src/purefs/fs/filesystem.cpp => module-vfs/src/purefs/fs/filesystem.cpp +9 -2
@@ 73,8 73,15 @@ namespace purefs::fs
            cpp_freertos::LockGuard _lock(*m_lock);
            const auto mpi = m_mounts.find(std::string(target));
            if (mpi != std::end(m_mounts)) {
                LOG_ERROR("VFS: mount point already exists %.*s", int(target.length()), target.data());
                return -EBUSY;
                if (flags & mount_flags::remount) {
                    // NOTE: Currently only RO is supported
                    mpi->second->modify_flags(flags);
                    return {};
                }
                else {
                    LOG_ERROR("VFS: mount point already exists %.*s", int(target.length()), target.data());
                    return -EBUSY;
                }
            }
            const auto mpp = m_partitions.find(std::string(dev_or_part));
            if (mpp != std::end(m_partitions)) {

M module-vfs/src/purefs/fs/filesystem_syscalls.cpp => module-vfs/src/purefs/fs/filesystem_syscalls.cpp +12 -7
@@ 7,37 7,38 @@
#include <purefs/fs/file_handle.hpp>
#include <purefs/fs/directory_handle.hpp>
#include <purefs/fs/thread_local_cwd.hpp>
#include <fcntl.h>

namespace purefs::fs
{
    auto filesystem::stat_vfs(std::string_view path, struct ::statvfs &stat) const noexcept -> int
    {
        return invoke_fops(&filesystem_operations::stat_vfs, path, stat);
        return invoke_fops(iaccess::ro, &filesystem_operations::stat_vfs, path, stat);
    }

    auto filesystem::stat(std::string_view file, struct stat &st) noexcept -> int
    {
        return invoke_fops(&filesystem_operations::stat, file, st);
        return invoke_fops(iaccess::ro, &filesystem_operations::stat, file, st);
    }

    auto filesystem::unlink(std::string_view name) noexcept -> int
    {
        return invoke_fops(&filesystem_operations::unlink, name);
        return invoke_fops(iaccess::rw, &filesystem_operations::unlink, name);
    }

    auto filesystem::mkdir(std::string_view path, int mode) noexcept -> int
    {
        return invoke_fops(&filesystem_operations::mkdir, path, mode);
        return invoke_fops(iaccess::rw, &filesystem_operations::mkdir, path, mode);
    }

    auto filesystem::ioctl(std::string_view path, int cmd, void *arg) noexcept -> int
    {
        return invoke_fops(&filesystem_operations::ioctl, path, cmd, arg);
        return invoke_fops(iaccess::ro, &filesystem_operations::ioctl, path, cmd, arg);
    }

    auto filesystem::utimens(std::string_view path, std::array<timespec, 2> &tv) noexcept -> int
    {
        return invoke_fops(&filesystem_operations::utimens, path, tv);
        return invoke_fops(iaccess::ro, &filesystem_operations::utimens, path, tv);
    }

    auto filesystem::flock(int fd, int cmd) noexcept -> int


@@ 52,7 53,7 @@ namespace purefs::fs

    auto filesystem::chmod(std::string_view path, mode_t mode) noexcept -> int
    {
        return invoke_fops(&filesystem_operations::chmod, path, mode);
        return invoke_fops(iaccess::rw, &filesystem_operations::chmod, path, mode);
    }

    auto filesystem::write(int fd, const char *ptr, size_t len) noexcept -> ssize_t


@@ 115,6 116,10 @@ namespace purefs::fs
        }
        auto fsops = mountp->fs_ops();
        if (fsops) {
            if ((flags & O_ACCMODE) != O_RDONLY && (mountp->flags() & mount_flags::read_only)) {
                LOG_ERROR("Trying to open file %.*s with WR... flag on RO filesystem", int(path.size()), path.data());
                return -EACCES;
            }
            auto fh = fsops->open(mountp, abspath, flags, mode);
            if (!fh) {
                LOG_ERROR("VFS: Unable to get fops");