From 8545fa3bb32d0b1f364702dd604a1d840212f34e Mon Sep 17 00:00:00 2001 From: Lucjan Bryndza Date: Wed, 13 Jan 2021 11:36:40 +0100 Subject: [PATCH] [EGD-4498] Add unit test for remount RO Add unit test for remount filesystem in ro mode Some minor fixes --- .../src/purefs/fs/filesystem_littlefs.cpp | 6 +- .../drivers/src/purefs/fs/filesystem_vfat.cpp | 6 +- .../internal/purefs/fs/file_handle.hpp | 1 + .../internal/purefs/fs/mount_point.hpp | 11 ++- .../include/user/purefs/fs/filesystem.hpp | 4 +- module-vfs/src/purefs/fs/filesystem.cpp | 2 +- module-vfs/tests/unittest_filesystem_core.cpp | 73 +++++++++++++++++++ 7 files changed, 92 insertions(+), 11 deletions(-) diff --git a/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp b/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp index e3c7bb3f15f0dfe04a4549d8ba0277c60b0b2c83..b79b24f1c2605011d0bb825862c8b2b397421464 100644 --- a/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +++ b/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp @@ -341,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(vfile->mntpoint()); - translate_lfsinfo_to_stat(linfo, *vmnt->lfs_config(), vmnt->flags() & mount_flags::read_only, st); + translate_lfsinfo_to_stat(linfo, *vmnt->lfs_config(), vmnt->is_ro(), st); } return err; } @@ -352,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(mnt); - translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), mntp->flags() & mount_flags::read_only, st); + translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), mntp->is_ro(), st); } return err; } @@ -421,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(dirstate->mntpoint()); - translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), mntp->flags() & mount_flags::read_only, filestat); + translate_lfsinfo_to_stat(linfo, *mntp->lfs_config(), mntp->is_ro(), filestat); filename = linfo.name; err = 0; } diff --git a/module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp b/module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp index be1301ba67458b56bb398228778483d09083d37c..f42ef9606c65180f6f96c43f86db82413e7c0a3a 100644 --- a/module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp +++ b/module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp @@ -342,7 +342,7 @@ namespace purefs::fs::drivers if (fres == FR_OK) { const auto vmnt = vfile->mntpoint(); if (vmnt) { - translate_filinfo_to_stat(finfo, vfile->ff_filp(), vmnt->flags() & mount_flags::read_only, st); + translate_filinfo_to_stat(finfo, vfile->ff_filp(), vmnt->is_ro(), st); } else { return -EIO; @@ -362,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, vmnt->flags() & mount_flags::read_only, st); + translate_filinfo_to_stat(finfo, nullptr, vmnt->is_ro(), st); } return translate_error(fres); } @@ -445,7 +445,7 @@ namespace purefs::fs::drivers else { const auto vmnt = dirp->mntpoint(); if (vmnt) { - translate_filinfo_to_stat(ffinfo, nullptr, vmnt->flags() & mount_flags::read_only, filestat); + translate_filinfo_to_stat(ffinfo, nullptr, vmnt->is_ro(), filestat); filename = ffinfo.fname; } else { diff --git a/module-vfs/include/internal/purefs/fs/file_handle.hpp b/module-vfs/include/internal/purefs/fs/file_handle.hpp index 854095a2f113012922dd7a2b578cc27e3798b3f3..ad0d9706013d4c8b2e23002ecf73a7de54bb55e4 100644 --- a/module-vfs/include/internal/purefs/fs/file_handle.hpp +++ b/module-vfs/include/internal/purefs/fs/file_handle.hpp @@ -13,6 +13,7 @@ namespace purefs::fs::internal { public: file_handle(const file_handle &) = delete; + auto operator=(const file_handle &) = delete; virtual ~file_handle() = default; file_handle(std::shared_ptr mp, unsigned flags) : m_mount_point(mp), m_flags(flags) {} diff --git a/module-vfs/include/internal/purefs/fs/mount_point.hpp b/module-vfs/include/internal/purefs/fs/mount_point.hpp index 212b46e79dc457655e2e002385ac6c7545191027..7c197ffbd4f32fd3a55dcc36e5a89852c8f5f4f6 100644 --- a/module-vfs/include/internal/purefs/fs/mount_point.hpp +++ b/module-vfs/include/internal/purefs/fs/mount_point.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace purefs::blkdev::internal { @@ -28,6 +29,8 @@ namespace purefs::fs::internal std::shared_ptr fs) : m_diskh(diskh), m_path(path), m_fs(fs), m_flags(flags) {} + mount_point(const mount_point &) = delete; + auto operator=(const mount_point &) = delete; virtual ~mount_point() = default; auto disk() const noexcept { @@ -41,10 +44,14 @@ namespace purefs::fs::internal { return m_fs.lock(); } - auto flags() const noexcept + auto flags() const noexcept -> unsigned { return m_flags; } + auto is_ro() const noexcept -> bool + { + return (m_flags & mount_flags::read_only) == mount_flags::read_only; + } void modify_flags(unsigned flags) noexcept { m_flags = flags; @@ -70,6 +77,6 @@ namespace purefs::fs::internal const std::weak_ptr m_diskh; const std::string m_path; //! Mounted path const std::weak_ptr m_fs; //! Filesystem operation - unsigned m_flags; + volatile unsigned m_flags; }; } // namespace purefs::fs::internal diff --git a/module-vfs/include/user/purefs/fs/filesystem.hpp b/module-vfs/include/user/purefs/fs/filesystem.hpp index 6fe377077f01964e40ee1d1302b9985edbd1e48d..19e2d8a3ce84217b10a59681737362126e6758cf 100644 --- a/module-vfs/include/user/purefs/fs/filesystem.hpp +++ b/module-vfs/include/user/purefs/fs/filesystem.hpp @@ -202,7 +202,7 @@ namespace purefs::fs if (!mountp) { return -ENOENT; } - if (acc == iaccess::rw && (mountp->flags() & mount_flags::read_only)) { + if (acc == iaccess::rw && mountp->is_ro()) { return -EACCES; } auto fsops = mountp->fs_ops(); @@ -225,7 +225,7 @@ namespace purefs::fs if (!mountp) { return -ENOENT; } - if (mountp->flags() & mount_flags::read_only) { + if (mountp->is_ro()) { return -EACCES; } if (path.compare(0, pathpos, path2, 0, pathpos) != 0) { diff --git a/module-vfs/src/purefs/fs/filesystem.cpp b/module-vfs/src/purefs/fs/filesystem.cpp index 61de493356e374965544910230ff49384f2822cf..5b777fde2d3f896c7817f24eec5aac3a06aef640 100644 --- a/module-vfs/src/purefs/fs/filesystem.cpp +++ b/module-vfs/src/purefs/fs/filesystem.cpp @@ -75,7 +75,7 @@ namespace purefs::fs if (mpi != std::end(m_mounts)) { if (flags & mount_flags::remount) { // NOTE: Currently only RO is supported - mpi->second->modify_flags(flags); + mpi->second->modify_flags(flags & ~mount_flags::remount); return {}; } else { diff --git a/module-vfs/tests/unittest_filesystem_core.cpp b/module-vfs/tests/unittest_filesystem_core.cpp index dbaf3164853ea3ef999d4ff6719a3ba6f7e3a994..3b04a39d2904049f74da85972f30d1d528d04779 100644 --- a/module-vfs/tests/unittest_filesystem_core.cpp +++ b/module-vfs/tests/unittest_filesystem_core.cpp @@ -272,6 +272,79 @@ TEST_CASE("Corefs: Directory operations") } } +TEST_CASE("Read only filesystem") +{ + using namespace purefs; + auto dm = std::make_shared(); + auto disk = std::make_shared(disk_image); + REQUIRE(disk); + REQUIRE(dm->register_device(disk, "emmc0") == 0); + purefs::fs::filesystem fscore(dm); + const auto vfs_vfat = std::make_shared(); + REQUIRE(vfs_vfat->mount_count() == 0); + auto ret = fscore.register_filesystem("vfat", vfs_vfat); + REQUIRE(ret == 0); + REQUIRE(fscore.mount("emmc0part0", "/sys", "vfat", fs::mount_flags::read_only) == 0); + SECTION("Open file in O_RDWR") + { + int hwnd = fscore.open("/sys/rotest.txt", O_RDWR | O_CREAT, 0660); + REQUIRE(hwnd == -EACCES); + const std::string text = "test"; + fscore.write(hwnd, text.c_str(), text.size()); + } + SECTION("Check function which not modify fs") + { + struct statvfs ssv; + ret = fscore.stat_vfs("/sys/", ssv); + REQUIRE(ret == 0); + } + SECTION("Check stat to not set S_IW...") + { + struct stat st; + ret = fscore.stat("/sys/current", st); + REQUIRE(ret == 0); + REQUIRE(st.st_mode & S_IFDIR); + REQUIRE((st.st_mode & (S_IWGRP | S_IWUSR | S_IWOTH)) == 0); + } + REQUIRE(fscore.umount("/sys") == 0); +} + +TEST_CASE("Remount filesystem from RO to RW and to RO") +{ + using namespace purefs; + auto dm = std::make_shared(); + auto disk = std::make_shared(disk_image); + REQUIRE(disk); + REQUIRE(dm->register_device(disk, "emmc0") == 0); + auto fscore = std::make_shared(dm); + const auto vfs_vfat = std::make_shared(); + REQUIRE(vfs_vfat->mount_count() == 0); + auto ret = fscore->register_filesystem("vfat", vfs_vfat); + REQUIRE(ret == 0); + REQUIRE(fscore->mount("emmc0part0", "/sys", "vfat", fs::mount_flags::read_only) == 0); + + { + const int hwnd = fscore->open("/sys/remount_test.txt", O_RDWR | O_CREAT, 0660); + REQUIRE(hwnd == -EACCES); + } + REQUIRE(fscore->mount("", "/sys", "", fs::mount_flags::remount) == 0); + { + int hwnd = fscore->open("/sys/remount_test4.txt", O_RDWR | O_CREAT, 0660); + REQUIRE(hwnd > 2); + const std::string text = "test"; + fscore->write(hwnd, text.c_str(), text.size()); + REQUIRE(fscore->close(hwnd) == 0); + } + { + struct stat st; + ret = fscore->stat("/sys/current", st); + REQUIRE(ret == 0); + REQUIRE(st.st_mode & S_IFDIR); + REQUIRE(st.st_mode & (S_IWGRP | S_IWUSR | S_IWOTH)); + } + REQUIRE(fscore->umount("/sys") == 0); +} + TEST_CASE("Unititest integrated subsystem") { auto [disk, vfs] = purefs::subsystem::initialize();