M module-vfs/board/linux/purefs/src/blkdev/disk_image.cpp => module-vfs/board/linux/purefs/src/blkdev/disk_image.cpp +8 -8
@@ 39,14 39,14 @@ namespace purefs::blkdev
}
auto disk_image::write(const void *buf, sector_t lba, std::size_t count) -> int
{
- int ret = ::lseek(m_filedes, lba * sector_size, SEEK_SET);
- if (ret < 0) {
- return ret;
+ auto offs = ::lseek(m_filedes, off_t(lba) * sector_size, SEEK_SET);
+ if (offs < 0) {
+ return offs;
}
auto to_write = count * sector_size;
auto buf_b = reinterpret_cast<const uint8_t *>(buf);
do {
- ret = ::write(m_filedes, buf_b, to_write);
+ auto ret = ::write(m_filedes, buf_b, to_write);
if (ret < 0) {
return -errno;
}
@@ 57,14 57,14 @@ namespace purefs::blkdev
}
auto disk_image::read(void *buf, sector_t lba, std::size_t count) -> int
{
- int ret = ::lseek(m_filedes, lba * sector_size, SEEK_SET);
- if (ret < 0) {
- return ret;
+ auto offs = ::lseek(m_filedes, off_t(lba) * sector_size, SEEK_SET);
+ if (offs < 0) {
+ return offs;
}
auto to_read = count * sector_size;
auto buf_b = reinterpret_cast<uint8_t *>(buf);
do {
- ret = ::read(m_filedes, buf_b, to_read);
+ auto ret = ::read(m_filedes, buf_b, to_read);
if (ret < 0) {
return -errno;
}
M module-vfs/board/linux/purefs/src/fs/thread_local_cwd.cpp => module-vfs/board/linux/purefs/src/fs/thread_local_cwd.cpp +9 -1
@@ 9,10 9,14 @@ namespace purefs::fs::internal
namespace
{
- thread_local std::string cwd_per_thread{"/"};
+ thread_local std::string cwd_per_thread;
+ std::string default_cwd{"/"};
}
auto get_thread_local_cwd_path() noexcept -> std::string_view
{
+ if (cwd_per_thread.empty()) {
+ cwd_per_thread = default_cwd;
+ }
return cwd_per_thread;
}
auto set_thread_cwd_path(std::string_view path) noexcept -> int
@@ 24,4 28,8 @@ namespace purefs::fs::internal
{
cwd_per_thread.erase();
}
+ auto set_default_thread_cwd(std::string_view str) noexcept -> void
+ {
+ default_cwd = str;
+ }
} // namespace purefs::fs::internal
M module-vfs/board/rt1051/purefs/src/fs/thread_local_cwd.cpp => module-vfs/board/rt1051/purefs/src/fs/thread_local_cwd.cpp +6 -1
@@ 14,13 14,14 @@ namespace purefs::fs::internal
namespace
{
constexpr auto CWD_THREAD_LOCAL_INDEX = 3;
+ std::string g_default_cwd{"/"};
auto get_tls() noexcept -> char *
{
auto pcwd = reinterpret_cast<char *>(pvTaskGetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX));
if (pcwd == nullptr) {
pcwd = new (std::nothrow) char[PATH_MAX + 1];
if (pcwd) {
- std::strncpy(pcwd, "/", PATH_MAX);
+ std::strncpy(pcwd, g_default_cwd.c_str(), PATH_MAX);
vTaskSetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX, pcwd);
}
}
@@ 54,4 55,8 @@ namespace purefs::fs::internal
vTaskSetThreadLocalStoragePointer(nullptr, CWD_THREAD_LOCAL_INDEX, nullptr);
}
}
+ auto set_default_thread_cwd(std::string_view str) noexcept -> void
+ {
+ g_default_cwd = str;
+ }
} // namespace purefs::fs::internal
M module-vfs/include/internal/purefs/blkdev/disk_handle.hpp => module-vfs/include/internal/purefs/blkdev/disk_handle.hpp +1 -1
@@ 44,6 44,6 @@ namespace purefs::blkdev::internal
const std::weak_ptr<blkdev::disk> m_disk;
const short m_partition{-1};
mutable sector_t m_sectors{0};
- const std::string_view m_name;
+ const std::string m_name;
};
} // namespace purefs::blkdev::internal
M module-vfs/include/internal/purefs/fs/mount_point.hpp => module-vfs/include/internal/purefs/fs/mount_point.hpp +2 -1
@@ 4,6 4,7 @@
#pragma once
#include <memory>
#include <string>
+#include <iostream>
namespace purefs::blkdev::internal
{
@@ 63,7 64,7 @@ namespace purefs::fs::internal
private:
const std::weak_ptr<blkdev::internal::disk_handle> m_diskh;
- const std::string_view m_path; //! Mounted path
+ const std::string m_path; //! Mounted path
const std::weak_ptr<filesystem_operations> m_fs; //! Filesystem operation
const unsigned m_flags;
};
M module-vfs/include/internal/purefs/fs/thread_local_cwd.hpp => module-vfs/include/internal/purefs/fs/thread_local_cwd.hpp +1 -0
@@ 9,4 9,5 @@ namespace purefs::fs::internal
auto get_thread_local_cwd_path() noexcept -> std::string_view;
auto set_thread_cwd_path(std::string_view path) noexcept -> int;
auto cleanup_thread_local_cwd_mem() -> void;
+ auto set_default_thread_cwd(std::string_view str) noexcept -> void;
} // namespace purefs::fs::internal
M module-vfs/include/user/purefs/vfs_subsystem.hpp => module-vfs/include/user/purefs/vfs_subsystem.hpp +1 -0
@@ 11,4 11,5 @@ namespace purefs::subsystem
auto initialize() -> std::tuple<std::shared_ptr<blkdev::disk_manager>, std::shared_ptr<fs::filesystem>>;
auto disk_mgr() -> std::shared_ptr<blkdev::disk_manager>;
auto vfs_core() -> std::shared_ptr<fs::filesystem>;
+ auto mount_defaults() -> int;
} // namespace purefs::subsystem
M module-vfs/src/purefs/vfs_subsystem.cpp => module-vfs/src/purefs/vfs_subsystem.cpp +136 -3
@@ 2,21 2,95 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/fs/filesystem.hpp>
+#include <purefs/fs/drivers/filesystem_vfat.hpp>
+#include <purefs/fs/drivers/filesystem_littlefs.hpp>
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/vfs_subsystem.hpp>
#include <purefs/vfs_subsystem_internal.hpp>
+#include <purefs/fs/thread_local_cwd.hpp>
#include <log/log.hpp>
+#include <purefs/filesystem_paths.hpp>
+#include <module-utils/json/json11.hpp>
+#include <sys/stat.h>
+#include <fcntl.h>
namespace purefs::subsystem
{
namespace
{
constexpr auto default_blkdev_name = "emmc0";
-
+ constexpr auto fat_part_code = 0x0b;
+ constexpr auto lfs_part_code = 0x9e;
+ constexpr auto old_layout_part_count = 2;
+ constexpr auto new_layout_part_count = 3;
+ constexpr auto boot_size_limit = 16384L;
+ namespace json
+ {
+ constexpr auto os_type = "ostype";
+ constexpr auto main = "main";
+ } // namespace json
std::weak_ptr<blkdev::disk_manager> g_disk_mgr;
std::weak_ptr<fs::filesystem> g_fs_core;
} // namespace
+ namespace
+ {
+ int read_file_to_cpp_string(std::shared_ptr<fs::filesystem> vfs, std::string_view file, std::string &str)
+ {
+ int fd = vfs->open(file, O_RDONLY, 0664);
+ if (fd < 0) {
+ return fd;
+ }
+ size_t rd_pos = 0;
+ size_t to_read = str.size();
+ do {
+ int err = vfs->read(fd, &str[rd_pos], to_read);
+ if (err < 0) {
+ vfs->close(fd);
+ return err;
+ }
+ else {
+ to_read -= err;
+ rd_pos += err;
+ }
+ } while (to_read > 0);
+ return vfs->close(fd);
+ }
+
+ std::string parse_boot_json_directory(std::string_view file)
+ {
+ using namespace std::literals;
+ auto vfsn = g_fs_core.lock();
+ if (!vfsn) {
+ LOG_ERROR("Unable to lock vfs. Fallback to current dir");
+ return "current"s;
+ }
+ struct stat stbuf;
+ int err = vfsn->stat(file, stbuf);
+ if (err) {
+ LOG_ERROR("Unable to lock vfs fallback to current dir");
+ return "current"s;
+ }
+ if (stbuf.st_size > boot_size_limit) {
+ LOG_ERROR("Boot file to long fallback to current dir");
+ return "current"s;
+ }
+ std::string json_str(stbuf.st_size, ' ');
+ std::string error;
+ err = read_file_to_cpp_string(vfsn, file, json_str);
+ if (err) {
+ LOG_ERROR("Unable to read boot file fallback to current dir err %i", err);
+ return "current"s;
+ }
+ auto json = json11::Json::parse(json_str, error);
+ if (!error.empty()) {
+ LOG_ERROR("Unable to parse json boot file fallback to current dir error %s", error.c_str());
+ return "current"s;
+ }
+ return json[json::main][json::os_type].string_value();
+ }
+ } // namespace
+
auto initialize() -> std::tuple<std::shared_ptr<blkdev::disk_manager>, std::shared_ptr<fs::filesystem>>
{
auto disk_mgr = std::make_shared<blkdev::disk_manager>();
@@ 24,9 98,20 @@ namespace purefs::subsystem
auto err = disk_mgr->register_device(bdev, default_blkdev_name);
if (err) {
LOG_FATAL("Unable to register block device with error %i", err);
- std::abort();
+ return {};
+ }
+ auto fs_core = std::make_shared<fs::filesystem>(disk_mgr);
+ err = fs_core->register_filesystem("vfat", std::make_shared<fs::drivers::filesystem_vfat>());
+ if (err) {
+ LOG_FATAL("Unable to register vfat filesystem with error %i", err);
+ return {};
}
- auto fs_core = std::make_shared<fs::filesystem>(g_disk_mgr.lock());
+ err = fs_core->register_filesystem("littlefs", std::make_shared<fs::drivers::filesystem_littlefs>());
+ if (err) {
+ LOG_FATAL("Unable to register vfat filesystem with error %i", err);
+ return {};
+ }
+
g_disk_mgr = disk_mgr;
g_fs_core = fs_core;
return {disk_mgr, fs_core};
@@ 41,4 126,52 @@ namespace purefs::subsystem
{
return g_fs_core.lock();
}
+
+ auto mount_defaults() -> int
+ {
+ auto disk = g_disk_mgr.lock();
+ if (!disk) {
+ LOG_FATAL("Unable to lock disk");
+ return -EIO;
+ }
+ auto parts = disk->partitions(default_blkdev_name);
+ if (parts.size() != old_layout_part_count && parts.size() != new_layout_part_count) {
+ LOG_FATAL("Unknown partition layout part size is %u", unsigned(parts.size()));
+ }
+ auto boot_it = std::end(parts);
+ auto lfs_it = std::end(parts);
+ for (auto it = std::begin(parts); it != std::end(parts); ++it) {
+ if (it->bootable && boot_it == std::end(parts)) {
+ boot_it = it;
+ }
+ else if (it->type == lfs_part_code && lfs_it == std::end(parts)) {
+ lfs_it = it;
+ }
+ }
+ if (lfs_it == std::end(parts) && parts.size() == old_layout_part_count) {
+ LOG_ERROR("!!!! Danger !!!! FAT partiton layout scheme. Data may be currupted when power loss.");
+ LOG_WARN("Please upgrade to new partition scheme with LITTLEFS partition.");
+ }
+ if (boot_it == std::end(parts)) {
+ LOG_FATAL("Unable to find boot partition");
+ return -ENOENT;
+ }
+ auto vfs = g_fs_core.lock();
+ if (!vfs) {
+ LOG_FATAL("Unable to lock vfs core");
+ return -EIO;
+ }
+ auto err = vfs->mount(boot_it->name, purefs::dir::getRootDiskPath().string(), "vfat");
+ if (err) {
+ return err;
+ }
+ if (lfs_it != std::end(parts)) {
+ err = vfs->mount(lfs_it->name, purefs::dir::getUserDiskPath().string(), "littlefs");
+ }
+ const std::string json_file = (dir::getRootDiskPath() / file::boot_json).string();
+ const auto boot_dir_name = parse_boot_json_directory(json_file);
+ const auto user_dir = (dir::getRootDiskPath() / boot_dir_name).string();
+ fs::internal::set_default_thread_cwd(user_dir);
+ return err;
+ }
} // namespace purefs::subsystem
M module-vfs/tests/unittest_filesystem_core.cpp => module-vfs/tests/unittest_filesystem_core.cpp +12 -0
@@ 7,6 7,8 @@
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/blkdev/disk_image.hpp>
#include <purefs/fs/drivers/filesystem_vfat.hpp>
+#include <purefs/vfs_subsystem.hpp>
+#include <purefs/fs/thread_local_cwd.hpp>
#include <sys/statvfs.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ 269,3 271,13 @@ TEST_CASE("Corefs: Directory operations")
REQUIRE(fscore.umount("/sys") == 0);
}
}
+
+TEST_CASE("Unititest integrated subsystem")
+{
+ auto [disk, vfs] = purefs::subsystem::initialize();
+ REQUIRE(purefs::subsystem::mount_defaults() == 0);
+ REQUIRE(purefs::fs::internal::get_thread_local_cwd_path() == "/sys/current");
+ const auto err = vfs->umount("/sys/user");
+ REQUIRE((err == 0 || err == -2));
+ REQUIRE(vfs->umount("/sys") == 0);
+}