M .gitmodules => .gitmodules +4 -0
@@ 102,3 102,7 @@
[submodule "third-party/dr_libs/src"]
path = third-party/dr_libs/src
url = https://github.com/mudita/dr_libs.git
+[submodule "reliance-edge"]
+ path = third-party/reedgefs/src
+ url = ../reliance-edge.git
+ branch = mudita
M module-platform/linux/src/DiskImage.cpp => module-platform/linux/src/DiskImage.cpp +2 -0
@@ 151,6 151,8 @@ namespace purefs::blkdev
return m_sectors[hwpart];
case info_type::erase_block:
return 1;
+ case info_type::start_sector:
+ return -ENOTSUP;
}
return -ENOTSUP;
}
M module-platform/linux/tests/CMakeLists.txt => module-platform/linux/tests/CMakeLists.txt +15 -5
@@ 11,7 11,7 @@ add_custom_command(
add_catch2_executable(
NAME vfs-disk
SRCS
- ${CMAKE_CURRENT_LIST_DIR}/unittest_disk_manager.cpp
+ unittest_disk_manager.cpp
LIBS
platform
purefs-paths
@@ 23,7 23,7 @@ add_catch2_executable(
add_catch2_executable(
NAME vfs-core-fs
SRCS
- ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_core.cpp
+ unittest_filesystem_core.cpp
LIBS
platform
module-vfs
@@ 48,7 48,7 @@ add_custom_target(
add_catch2_executable(
NAME vfs-littlefs
SRCS
- ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_littlefs.cpp
+ unittest_filesystem_littlefs.cpp
LIBS
platform
module-vfs
@@ 60,7 60,7 @@ add_catch2_executable(
add_catch2_executable(
NAME vfs-ext4
SRCS
- ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_ext4.cpp
+ unittest_filesystem_ext4.cpp
LIBS
platform
module-vfs
@@ 72,7 72,7 @@ add_catch2_executable(
add_catch2_executable(
NAME vfs-dualmount
SRCS
- ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_dualmount.cpp
+ unittest_filesystem_dualmount.cpp
LIBS
platform
module-vfs
@@ 94,6 94,16 @@ add_catch2_executable(
USE_FS
)
+add_catch2_executable(
+ NAME vfs-reedgefs
+ SRCS
+ unittest_filesystem_reedgefs.cpp
+ LIBS
+ platform
+ module-vfs
+ USE_FS
+)
+
# prepare test assets
set(ASSETS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test_dir")
set(ASSETS_TARGET_DIR "${CMAKE_BINARY_DIR}/module-platform/test_dir")
A module-platform/linux/tests/unittest_filesystem_reedgefs.cpp => module-platform/linux/tests/unittest_filesystem_reedgefs.cpp +379 -0
@@ 0,0 1,379 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+#include <platform/linux/DiskImage.hpp>
+
+#include <purefs/fs/filesystem.hpp>
+#include <purefs/blkdev/disk_manager.hpp>
+#include <purefs/fs/drivers/filesystem_reedgefs.hpp>
+#include <purefs/vfs_subsystem.hpp>
+
+#include <purefs/fs/thread_local_cwd.hpp>
+
+#include "test-setup.hpp"
+
+#include <tuple>
+
+#include <sys/statvfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+TEST_CASE("reedgefs: Registering and unregistering block device")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ /* Requested filesystem is not registered */
+ REQUIRE(fscore.mount("emmc0", "/sys", "reedgefs") == -ENODEV);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ ret = fscore.mount("emmc0part0", "/sys", "reedgefs");
+ REQUIRE(ret == 0);
+ REQUIRE(vfs_reedgefs->mount_count() == 1);
+ REQUIRE(fscore.umount("/ala") == -ENOENT);
+ ret = fscore.mount("emmc0part0", "/sys", "reedgefs");
+ REQUIRE(ret == -EBUSY);
+ ret = fscore.mount("emmc0part0", "/path", "reedgefs");
+ REQUIRE(ret == -EBUSY);
+ ret = fscore.mount("emmc0part2", "/path", "nonexisting_fs");
+ REQUIRE(ret == -ENODEV);
+ ret = fscore.umount("/sys");
+ REQUIRE(ret == 0);
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ ret = fscore.mount("emmc0part0", "/path", "reedgefs");
+ REQUIRE(ret == 0);
+ REQUIRE(vfs_reedgefs->mount_count() == 1);
+ ret = fscore.umount("/path");
+ REQUIRE(ret == 0);
+}
+
+TEST_CASE("reedgefs: Basic API test")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ // List partitions
+ for (const auto &part : dm->partitions("emmc0")) {
+ std::cout << part.name << " " << part.bootable << std::endl;
+ }
+ ret = fscore.mount("emmc0part0", "/sys", "reedgefs");
+ REQUIRE(ret == 0);
+ {
+ struct statvfs ssv;
+ ret = fscore.stat_vfs("/sys/", ssv);
+ REQUIRE(ret == 0);
+ }
+
+ // TODO: switch to image once image is ready
+ {
+ ret = fscore.open("/sys/ala/ma/kota/", 0, 0);
+ REQUIRE(ret == -ENOENT);
+ // Simple file test
+ // TODO: to remove when image ready
+ {
+ int hwnd = fscore.open("/sys/.boot.json", O_RDWR | O_CREAT, 0);
+ REQUIRE(hwnd >= 3);
+ const std::string text = "test";
+ REQUIRE(fscore.write(hwnd, text.c_str(), text.size()) == ssize_t(text.length()));
+ REQUIRE(fscore.close(hwnd) == 0);
+ }
+ int hwnd = fscore.open("/sys/.boot.json", 0, 0);
+ REQUIRE(hwnd >= 3);
+ std::cout << "File open handle " << hwnd << std::endl;
+ struct stat st;
+ ret = fscore.fstat(hwnd, st);
+ REQUIRE(ret == 0);
+ std::cout << "File size " << st.st_size << std::endl;
+ ret = fscore.stat("/sys/.boot.json", st);
+ REQUIRE(ret == 0);
+ std::cout << "File size " << st.st_size << std::endl;
+ char buf[4096]{};
+ ret = fscore.read(hwnd, buf, sizeof buf);
+ REQUIRE(ret > 0);
+ ret = fscore.close(hwnd);
+ REQUIRE(ret == 0);
+ {
+ // TODO: to remove when image ready
+ {
+ int hwnd = fscore.open("/sys/.boot2.json", O_RDWR | O_CREAT, 0);
+ REQUIRE(hwnd >= 3);
+ const std::string text = "test";
+ REQUIRE(fscore.write(hwnd, text.c_str(), text.size()) == ssize_t(text.length()));
+ REQUIRE(fscore.close(hwnd) == 0);
+ }
+ // Simple directory test
+ auto dirhandle = fscore.diropen("/sys");
+ REQUIRE(dirhandle);
+ REQUIRE(dirhandle->error() == 0);
+ for (std::string fnm;;) {
+ if (fscore.dirnext(dirhandle, fnm, st) != 0) {
+ break;
+ }
+ else {
+ std::cout << "name " << fnm << " size " << st.st_size << std::endl;
+ }
+ }
+ fscore.dirclose(dirhandle);
+ dirhandle = nullptr;
+ }
+ }
+ REQUIRE(fscore.umount("/sys") == 0);
+}
+
+TEST_CASE("reedgefs: Create new file, write, read from it")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore.mount("emmc0part0", "/sys", "reedgefs") == 0);
+
+ int hwnd = fscore.open("/sys/test.txt", O_RDWR | O_CREAT, 0660);
+ REQUIRE(hwnd >= 3);
+
+ const std::string text = "test";
+ fscore.write(hwnd, text.c_str(), text.size());
+
+ REQUIRE(fscore.close(hwnd) == 0);
+ SECTION("Read from file")
+ {
+ int hwnd = fscore.open("/sys/test.txt", O_RDONLY, 0);
+ REQUIRE(hwnd >= 3);
+ char buf[sizeof(text.c_str())] = {0};
+ REQUIRE(fscore.read(hwnd, buf, sizeof(buf)) == 4);
+ REQUIRE(strcmp(buf, text.c_str()) == 0);
+ fscore.close(hwnd);
+ REQUIRE(fscore.umount("/sys") == 0);
+ }
+
+ SECTION("Test seek file")
+ {
+ int hwnd = fscore.open("/sys/test.txt", O_RDONLY, 0);
+ REQUIRE(hwnd >= 3);
+ char buf[4096]{};
+ REQUIRE(fscore.read(hwnd, buf, sizeof(buf)) == 4);
+ REQUIRE(fscore.seek(hwnd, 0, SEEK_END) == 4);
+ REQUIRE(fscore.read(hwnd, buf, sizeof(buf)) == 0);
+ REQUIRE(fscore.seek(hwnd, 0, SEEK_SET) == 0);
+ fscore.close(hwnd);
+ REQUIRE(fscore.umount("/sys") == 0);
+ }
+}
+
+TEST_CASE("reedgefs: Mount empty strings")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore.mount("", "", "") == -EINVAL);
+ REQUIRE(fscore.umount("") == -ENOENT);
+}
+
+TEST_CASE("reedgefs: Write to not valid file descriptor")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore.mount("emmc0part0", "/sys", "reedgefs") == 0);
+
+ int fd = fscore.open("/sys/.boot.json", O_RDWR | O_CREAT, 0);
+ REQUIRE(fd >= 3);
+ const auto text = "test";
+ REQUIRE(fscore.write(0, text, sizeof(text)) == -EBADF);
+ REQUIRE(fscore.write(fd + 1, text, sizeof(text)) == -EBADF);
+ REQUIRE(fscore.close(fd) == 0);
+ REQUIRE(fscore.umount("/sys") == 0);
+}
+
+TEST_CASE("reedgefs: Directory operations")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore.mount("emmc0part0", "/sys", "reedgefs") == 0);
+
+ REQUIRE(fscore.mkdir("/sys/current", 0) == 0);
+
+ const auto dirhandle = fscore.diropen("/sys/current");
+ REQUIRE(dirhandle);
+ REQUIRE(dirhandle->error() == 0);
+
+ SECTION("Null pointer handle dirnext")
+ {
+ struct stat st;
+ std::string fnm;
+ REQUIRE(fscore.dirnext(nullptr, fnm, st) == -ENXIO);
+ REQUIRE(fscore.dirclose(dirhandle) == 0);
+ REQUIRE(fscore.umount("/sys") == 0);
+ }
+
+ SECTION("Null pointer handle dirclose")
+ {
+ REQUIRE(fscore.dirclose(nullptr) == -ENXIO);
+ REQUIRE(fscore.dirclose(dirhandle) == 0);
+ REQUIRE(fscore.umount("/sys") == 0);
+ }
+
+ SECTION("Directory reset")
+ {
+ struct stat st;
+ std::vector<std::tuple<std::string, struct stat>> vec;
+ for (std::string fnm;;) {
+ if (fscore.dirnext(dirhandle, fnm, st) != 0) {
+ break;
+ }
+ else {
+ vec.push_back(std::make_tuple(fnm, st));
+ std::cout << "name " << fnm << " size " << st.st_size << std::endl;
+ }
+ }
+
+ fscore.dirreset(dirhandle);
+ int i = 0;
+ for (std::string fnm;; i++) {
+ if (fscore.dirnext(dirhandle, fnm, st) != 0) {
+ break;
+ }
+ else {
+ const auto [fnm_vec, st_vec] = vec[i];
+ REQUIRE(fnm == fnm_vec);
+ REQUIRE(st_vec.st_size == st.st_size);
+ std::cout << "name " << fnm << " size " << st.st_size << std::endl;
+ }
+ }
+ REQUIRE(fscore.dirclose(dirhandle) == 0);
+ REQUIRE(fscore.umount("/sys") == 0);
+ }
+}
+
+TEST_CASE("reedgefs: Read only filesystem")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ purefs::fs::filesystem fscore(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore.register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore.mount("emmc0part0", "/sys", "reedgefs", 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", 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("reedgefs: Remount filesystem from RO to RW and to RO")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ auto fscore = std::make_shared<purefs::fs::filesystem>(dm);
+ const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+ REQUIRE(vfs_reedgefs->mount_count() == 0);
+ auto ret = fscore->register_filesystem("reedgefs", vfs_reedgefs);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore->mount("emmc0part0", "/sys", "reedgefs", 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);
+ }
+ {
+ REQUIRE(fscore->mkdir("/sys/current", 0660) == 0);
+ struct stat st;
+ ret = fscore->stat("/sys", 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("reedgefs: Autodetect filesystems")
+// {
+// using namespace purefs;
+// auto dm = std::make_shared<blkdev::disk_manager>();
+// auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
+// REQUIRE(disk);
+// REQUIRE(dm->register_device(disk, "emmc0") == 0);
+// auto fscore = std::make_shared<purefs::fs::filesystem>(dm);
+// const auto vfs_reedgefs = std::make_shared<fs::drivers::filesystem_reedgefs>();
+// REQUIRE(vfs_reedgefs->mount_count() == 0);
+// auto ret = fscore->register_filesystem("reedgefs", vfs_reedgefs);
+// REQUIRE(ret == 0);
+// REQUIRE(fscore->mount("emmc0part0", "/sys", "auto") == 0);
+// REQUIRE(fscore->umount("/sys") == 0);
+// }
M module-platform/rt1051/src/disk_emmc.cpp => module-platform/rt1051/src/disk_emmc.cpp +3 -0
@@ 155,6 155,9 @@ namespace purefs::blkdev
case info_type::erase_block:
// not supported
return 0;
+ case info_type::start_sector:
+ // not supported
+ return 0;
}
return -ENOTSUP;
}
M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +18 -0
@@ 16,26 16,42 @@ target_sources(module-vfs
drivers/include/purefs/fs/drivers/directory_handle_littlefs.hpp
drivers/include/purefs/fs/drivers/directory_handle_vfat.hpp
+ drivers/include/purefs/fs/drivers/directory_handle_reedgefs.hpp
drivers/include/purefs/fs/drivers/file_handle_littlefs.hpp
drivers/include/purefs/fs/drivers/file_handle_vfat.hpp
+ drivers/include/purefs/fs/drivers/file_handle_reedgefs.hpp
drivers/include/purefs/fs/drivers/filesystem_littlefs.hpp
drivers/include/purefs/fs/drivers/filesystem_ext4.hpp
drivers/include/purefs/fs/drivers/filesystem_vfat.hpp
+ drivers/include/purefs/fs/drivers/filesystem_reedgefs.hpp
drivers/include/purefs/fs/drivers/mount_point_littlefs.hpp
drivers/include/purefs/fs/drivers/mount_point_vfat.hpp
drivers/include/purefs/fs/drivers/mount_point_ext4.hpp
+ drivers/include/purefs/fs/drivers/mount_point_reedgefs.hpp
drivers/include/thirdparty/fatfs/ffconf.h
+ drivers/include/thirdparty/reedgefs/redconf.h
drivers/include/thirdparty/fatfs/volume_mapper.hpp
drivers/include/thirdparty/littlefs/volume_mapper.hpp
drivers/include/thirdparty/lwext4/ext4_bdev.hpp
drivers/src/purefs/fs/filesystem_littlefs.cpp
drivers/src/purefs/fs/filesystem_ext4.cpp
drivers/src/purefs/fs/filesystem_vfat.cpp
+ drivers/src/purefs/fs/filesystem_reedgefs.cpp
drivers/src/thirdparty/fatfs/ff_glue.cpp
drivers/src/thirdparty/fatfs/ffsystem.cpp
drivers/src/thirdparty/littlefs/lfs_glue.cpp
drivers/src/thirdparty/lwext4/ext4_bdev.cpp
drivers/src/purefs/fs/mount_point_ext4.cpp
+ drivers/src/thirdparty/reedgefs/redconf.c
+ drivers/src/thirdparty/reedgefs/glue.cpp
+ drivers/src/thirdparty/reedgefs/services/osassert.c
+ drivers/src/thirdparty/reedgefs/services/osbdev_custom.h
+ drivers/src/thirdparty/reedgefs/services/osbdev.c
+ drivers/src/thirdparty/reedgefs/services/osclock.c
+ drivers/src/thirdparty/reedgefs/services/osmutex.c
+ drivers/src/thirdparty/reedgefs/services/osoutput.c
+ drivers/src/thirdparty/reedgefs/services/ostask.c
+ drivers/src/thirdparty/reedgefs/services/ostimestamp.c
include/internal/purefs/blkdev/disk_handle.hpp
include/internal/purefs/blkdev/partition_parser.hpp
@@ 87,6 103,7 @@ target_include_directories(module-vfs
$<$<STREQUAL:${PROJECT_TARGET},TARGET_Linux>:${CMAKE_CURRENT_SOURCE_DIR}/board/linux/purefs/include>
${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty
${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty/fatfs
+ ${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty/reedgefs
${CMAKE_CURRENT_SOURCE_DIR}/include/internal
>
PUBLIC
@@ 98,6 115,7 @@ target_include_directories(module-vfs
target_link_libraries(module-vfs
PRIVATE
+ reliance-edge::fs
fatfs::fatfs
lwext4::lwext4
json::json
M module-vfs/README.md => module-vfs/README.md +10 -0
@@ 42,3 42,13 @@ For LittleFS you will have to use fuse to mount partition. Tool is already build
2. Mount: `./lfsfuse --block_size=32768 /dev/sdX mymount` where sdbx is device where you expect LFS partition
3. Enter here and play with data
4. Umount and eject the device i.e. with: `udisksctl power-off -b /dev/sdb`
+
+## Reliance edge - redgefs
+
+Reliance edge support is considered as WIP. Below are the proposed steps to finish implementation
+* prepare tool to create image
+* do NOT format partion on the fly during mounting
+* run UT on image with redgefs partion
+* run rt1051 with redgefs partiion and do functional and performance tests e.g. check if statvfs is not too slow
+* prepare fuse tool
+* port redgefs to Updater
A module-vfs/drivers/include/purefs/fs/drivers/directory_handle_reedgefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/directory_handle_reedgefs.hpp +31 -0
@@ 0,0 1,31 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <purefs/fs/directory_handle.hpp>
+#include <redfs.h>
+#include <redposix.h>
+
+namespace purefs::fs::drivers
+{
+ class directory_handle_reedgefs final : public internal::directory_handle
+ {
+ public:
+ directory_handle_reedgefs(std::shared_ptr<internal::mount_point> mp, int error)
+ : internal::directory_handle(mp, error)
+ {}
+ virtual ~directory_handle_reedgefs() = default;
+ auto reedgefs_dirp() const noexcept
+ {
+ return m_dir;
+ }
+ auto reedgefs_dirp(::REDDIR *dir) noexcept
+ {
+ m_dir = dir;
+ }
+
+ private:
+ ::REDDIR *m_dir{};
+ };
+} // namespace purefs::fs::drivers
A module-vfs/drivers/include/purefs/fs/drivers/file_handle_reedgefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/file_handle_reedgefs.hpp +35 -0
@@ 0,0 1,35 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <purefs/fs/file_handle.hpp>
+
+namespace purefs::fs::drivers
+{
+ class file_handle_reedgefs final : public internal::file_handle
+ {
+ public:
+ file_handle_reedgefs(std::shared_ptr<internal::mount_point> mp, std::string_view path, unsigned flags)
+ : file_handle(mp, flags), m_path(path)
+ {}
+ virtual ~file_handle_reedgefs() = default;
+ auto fd() const noexcept
+ {
+ return m_fd;
+ }
+ auto fd(int32_t fd) noexcept -> void
+ {
+ m_fd = fd;
+ }
+ auto open_path() const noexcept -> std::string override
+ {
+ return m_path;
+ }
+
+ private:
+ int32_t m_fd{};
+ //! Store full path because some handle based fncs are not in ff_Fat
+ const std::string m_path;
+ };
+} // namespace purefs::fs::drivers
A module-vfs/drivers/include/purefs/fs/drivers/filesystem_reedgefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/filesystem_reedgefs.hpp +49 -0
@@ 0,0 1,49 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+#include <purefs/fs/filesystem_operations.hpp>
+
+namespace purefs::fs::drivers
+{
+ /** Filesystem specific driver base class */
+ class filesystem_reedgefs final : public filesystem_operations
+ {
+ public:
+ filesystem_reedgefs();
+ virtual ~filesystem_reedgefs();
+
+ private:
+ auto mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh, std::string_view path, unsigned flags)
+ -> fsmount override;
+ auto mount(fsmount mnt, const void *data) noexcept -> int override;
+ auto umount(fsmount mnt) noexcept -> int override;
+
+ auto stat_vfs(fsmount mnt, std::string_view path, statvfs &stat) const noexcept -> int override;
+
+ /** Standard file access API */
+ auto open(fsmount mnt, std::string_view path, int flags, int mode) noexcept -> fsfile override;
+ auto close(fsfile zfile) noexcept -> int override;
+ auto write(fsfile zfile, const char *ptr, size_t len) noexcept -> ssize_t override;
+ auto read(fsfile zfile, char *ptr, size_t len) noexcept -> ssize_t override;
+ auto seek(fsfile zfile, off_t pos, int dir) noexcept -> off_t override;
+ auto fstat(fsfile zfile, struct stat &st) noexcept -> int override;
+ auto stat(fsmount mnt, std::string_view file, struct stat &st) noexcept -> int override;
+ auto unlink(fsmount mnt, std::string_view name) noexcept -> int override;
+ auto rename(fsmount mnt, std::string_view oldname, std::string_view newname) noexcept -> int override;
+ auto mkdir(fsmount mnt, std::string_view path, int mode) noexcept -> int override;
+
+ /** Directory support API */
+ auto diropen(fsmount mnt, std::string_view path) noexcept -> fsdir override;
+ auto dirreset(fsdir dirstate) noexcept -> int override;
+ auto dirnext(fsdir dirstate, std::string &filename, struct stat &filestat) -> int override;
+ auto dirclose(fsdir dirstate) noexcept -> int override;
+
+ /** Other fops API */
+ auto ftruncate(fsfile zfile, off_t len) noexcept -> int override;
+ auto fsync(fsfile zfile) noexcept -> int override;
+ auto isatty(fsfile zfile) noexcept -> int override;
+
+ auto filesystem_register_completed() const noexcept -> int override;
+ };
+} // namespace purefs::fs::drivers
M module-vfs/drivers/include/purefs/fs/drivers/mount_point_ext4.hpp => module-vfs/drivers/include/purefs/fs/drivers/mount_point_ext4.hpp +1 -1
@@ 33,7 33,7 @@ namespace purefs::fs::drivers
auto unlock() noexcept -> void;
private:
- auto native_root() const noexcept -> std::string_view override
+ auto native_root() const noexcept -> std::string override
{
return m_root;
}
M module-vfs/drivers/include/purefs/fs/drivers/mount_point_littlefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/mount_point_littlefs.hpp +1 -1
@@ 28,7 28,7 @@ namespace purefs::fs::drivers
}
private:
- auto native_root() const noexcept -> std::string_view override
+ auto native_root() const noexcept -> std::string override
{
return "";
}
A module-vfs/drivers/include/purefs/fs/drivers/mount_point_reedgefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/mount_point_reedgefs.hpp +38 -0
@@ 0,0 1,38 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <purefs/fs/mount_point.hpp>
+
+namespace purefs::fs::drivers
+{
+ class mount_point_reedgefs final : public purefs::fs::internal::mount_point
+ {
+ public:
+ mount_point_reedgefs(std::shared_ptr<blkdev::internal::disk_handle> diskh,
+ std::string_view path,
+ unsigned flags,
+ std::shared_ptr<filesystem_operations> fs)
+ : mount_point(diskh, path, flags, fs)
+ {}
+ virtual ~mount_point_reedgefs() = default;
+
+ auto volume_name(std::string volume_name) -> void
+ {
+ m_volume_name = volume_name;
+ }
+
+ auto volume_name() const noexcept -> std::string
+ {
+ return m_volume_name;
+ }
+
+ private:
+ auto native_root() const noexcept -> std::string override
+ {
+ return volume_name();
+ }
+ std::string m_volume_name;
+ };
+} // namespace purefs::fs::drivers
M module-vfs/drivers/include/purefs/fs/drivers/mount_point_vfat.hpp => module-vfs/drivers/include/purefs/fs/drivers/mount_point_vfat.hpp +1 -1
@@ 43,7 43,7 @@ namespace purefs::fs::drivers
}
private:
- auto native_root() const noexcept -> std::string_view override
+ auto native_root() const noexcept -> std::string override
{
return ff_drive();
}
A module-vfs/drivers/include/thirdparty/reedgefs/redconf.h => module-vfs/drivers/include/thirdparty/reedgefs/redconf.h +125 -0
@@ 0,0 1,125 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* THIS FILE WAS GENERATED BY THE TUXERA RELIANCE EDGE CONFIGURATION UTILITY.
+ DO NOT MODIFY.
+
+ Generated by configuration utility version 2.5
+*/
+/** @file
+ */
+#ifndef REDCONF_H
+#define REDCONF_H
+
+#include <string.h>
+
+#define REDCONF_READ_ONLY 0
+
+#define REDCONF_API_POSIX 1
+
+#define REDCONF_API_FSE 0
+
+#define REDCONF_API_POSIX_FORMAT 1
+
+#define REDCONF_API_POSIX_LINK 1
+
+#define REDCONF_API_POSIX_UNLINK 1
+
+#define REDCONF_API_POSIX_MKDIR 1
+
+#define REDCONF_API_POSIX_RMDIR 1
+
+#define REDCONF_API_POSIX_RENAME 1
+
+#define REDCONF_RENAME_ATOMIC 1
+
+#define REDCONF_API_POSIX_FTRUNCATE 1
+
+#define REDCONF_API_POSIX_READDIR 1
+
+#define REDCONF_API_POSIX_CWD 0
+
+#define REDCONF_API_POSIX_FSTRIM 0
+
+#define REDCONF_NAME_MAX 256U
+
+#define REDCONF_PATH_SEPARATOR '/'
+
+#define REDCONF_TASK_COUNT 20U
+
+#define REDCONF_HANDLE_COUNT 512U
+
+#define REDCONF_API_FSE_FORMAT 0
+
+#define REDCONF_API_FSE_TRUNCATE 0
+
+#define REDCONF_API_FSE_TRANSMASKGET 0
+
+#define REDCONF_API_FSE_TRANSMASKSET 0
+
+#define REDCONF_OUTPUT 1
+
+#define REDCONF_ASSERTS 1
+
+#define REDCONF_BLOCK_SIZE 1024U
+
+#define REDCONF_VOLUME_COUNT 4U
+
+#define REDCONF_ENDIAN_BIG 0
+
+#define REDCONF_ALIGNMENT_SIZE 4U
+
+#define REDCONF_CRC_ALGORITHM CRC_SLICEBY8
+
+#define REDCONF_INODE_BLOCKS 1
+
+#define REDCONF_INODE_TIMESTAMPS 1
+
+#define REDCONF_ATIME 0
+
+#define REDCONF_DIRECT_POINTERS 20U
+
+#define REDCONF_INDIRECT_POINTERS 40U
+
+#define REDCONF_BUFFER_COUNT 20U
+
+#define REDCONF_BUFFER_ALIGNMENT 8U
+
+#define REDCONF_BUFFER_WRITE_GATHER_SIZE_KB 0U
+
+#define RedMemCpyUnchecked memcpy
+
+#define RedMemMoveUnchecked memmove
+
+#define RedMemSetUnchecked memset
+
+#define RedMemCmpUnchecked memcmp
+
+#define RedStrLenUnchecked strlen
+
+#define RedStrCmpUnchecked strcmp
+
+#define RedStrNCmpUnchecked strncmp
+
+#define RedStrNCpyUnchecked strncpy
+
+#define REDCONF_TRANSACT_DEFAULT \
+ ((RED_TRANSACT_CREAT | RED_TRANSACT_MKDIR | RED_TRANSACT_RENAME | RED_TRANSACT_LINK | RED_TRANSACT_UNLINK | \
+ RED_TRANSACT_FSYNC | RED_TRANSACT_CLOSE | RED_TRANSACT_VOLFULL | RED_TRANSACT_UMOUNT | RED_TRANSACT_SYNC) & \
+ RED_TRANSACT_MASK)
+
+#define REDCONF_IMAP_INLINE 1
+
+#define REDCONF_IMAP_EXTERNAL 1
+
+#define REDCONF_DISCARDS 0
+
+#define REDCONF_IMAGE_BUILDER 0
+
+#define REDCONF_CHECKER 0
+
+#define RED_CONFIG_UTILITY_VERSION 0x2050000U
+
+#define RED_CONFIG_MINCOMPAT_VER 0x2030000U
+
+#endif
A module-vfs/drivers/include/thirdparty/reedgefs/redconf/redconf.h => module-vfs/drivers/include/thirdparty/reedgefs/redconf/redconf.h +111 -0
@@ 0,0 1,111 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/** @file
+ */
+
+/* Inherit most settings from the target configuration.
+ */
+#include "../redconf.h"
+
+#ifndef HOST_REDCONF_H
+#define HOST_REDCONF_H
+
+/* Assuming the host machine is little endian. If the host machine is actually
+ big endian, this can be worked around by changing the below "== 1" to "== 0"
+ and setting REDCONF_ENDIAN_BIG to 1 below.
+*/
+#if REDCONF_ENDIAN_BIG == 1
+#define REDCONF_ENDIAN_SWAP
+#endif
+
+#undef REDCONF_ENDIAN_BIG
+#define REDCONF_ENDIAN_BIG 0
+
+/* Ignore the target system memory alignment. For Linux, 4 bytes works well.
+ */
+#undef REDCONF_ALIGNMENT_SIZE
+#define REDCONF_ALIGNMENT_SIZE 4U
+
+/* Host tools always have output.
+ */
+#undef REDCONF_OUTPUT
+#define REDCONF_OUTPUT 1
+
+/* Read-only must be disabled for the image builder.
+ */
+#undef REDCONF_READ_ONLY
+#define REDCONF_READ_ONLY 0
+
+/* Enable the checker host tool.
+ */
+#undef REDCONF_CHECKER
+#define REDCONF_CHECKER 1
+
+/* Enable the formatter code in POSIX-like API configurations for the image
+ builder and formatter host tools.
+*/
+#undef REDCONF_API_POSIX_FORMAT
+#define REDCONF_API_POSIX_FORMAT 1
+
+/* Enable the image builder host tool.
+ */
+#undef REDCONF_IMAGE_BUILDER
+#define REDCONF_IMAGE_BUILDER 1
+
+/* The image builder needs red_mkdir().
+ */
+#undef REDCONF_API_POSIX_MKDIR
+#define REDCONF_API_POSIX_MKDIR 1
+
+/* The image copier utility needs red_readdir().
+ */
+#undef REDCONF_API_POSIX_READDIR
+#define REDCONF_API_POSIX_READDIR 1
+
+/* The image copier utility needs a handle for every level of directory depth.
+ While Reliance Edge has no maximum directory depth or path depth, Windows
+ limits paths to 260 bytes, and each level of depth eats up at least two
+ characters, 130 handles will be sufficient for all images that can be
+ copied.
+*/
+#undef REDCONF_HANDLE_COUNT
+#define REDCONF_HANDLE_COUNT 130U
+
+/* Use the fastest CRC algorithm for the tools. Slice-by-8 will work well on
+ a host machine and the extra code space is a nonissue.
+*/
+#undef REDCONF_CRC_ALGORITHM
+#define REDCONF_CRC_ALGORITHM CRC_SLICEBY8
+
+/* The target redconf.h may have configured the memory and string functions to
+ use custom implementations that are only available on the target system. So
+ for the host, we just use the C library versions.
+*/
+#include <string.h>
+
+#undef RedMemCpyUnchecked
+#define RedMemCpyUnchecked memcpy
+#undef RedMemMoveUnchecked
+#define RedMemMoveUnchecked memmove
+#undef RedMemSetUnchecked
+#define RedMemSetUnchecked memset
+#undef RedMemCmpUnchecked
+#define RedMemCmpUnchecked memcmp
+
+#undef RedStrLenUnchecked
+#define RedStrLenUnchecked strlen
+#undef RedStrCmpUnchecked
+#define RedStrCmpUnchecked strcmp
+#undef RedStrNCmpUnchecked
+#define RedStrNCmpUnchecked strncmp
+#undef RedStrNCpyUnchecked
+#define RedStrNCpyUnchecked strncpy
+
+/* Avoid extra transactions to improve image builder performance.
+ */
+#undef REDCONF_TRANSACT_DEFAULT
+#define REDCONF_TRANSACT_DEFAULT \
+ ((RED_TRANSACT_FSYNC | RED_TRANSACT_VOLFULL | RED_TRANSACT_UMOUNT | RED_TRANSACT_SYNC) & RED_TRANSACT_MASK)
+
+#endif
A module-vfs/drivers/include/thirdparty/reedgefs/redostypes.h => module-vfs/drivers/include/thirdparty/reedgefs/redostypes.h +42 -0
@@ 0,0 1,42 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Defines OS-specific types for use in common code.
+*/
+#ifndef REDOSTYPES_H
+#define REDOSTYPES_H
+
+/** @brief Implementation-defined timestamp type.
+
+ This can be an integer, a structure, or a pointer: anything that is
+ convenient for the implementation. Since the underlying type is not fixed,
+ common code should treat this as an opaque type.
+*/
+typedef uint32_t REDTIMESTAMP;
+
+#endif
A module-vfs/drivers/include/thirdparty/reedgefs/redtypes.h => module-vfs/drivers/include/thirdparty/reedgefs/redtypes.h +97 -0
@@ 0,0 1,97 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Defines basic types used by Reliance Edge.
+
+ The following types *must* be defined by this header, either directly (using
+ typedef) or indirectly (by including other headers, such as the C99 headers
+ stdint.h and stdbool.h):
+
+ - bool: Boolean type, capable of storing true (1) or false (0)
+ - uint8_t: Unsigned 8-bit integer
+ - int8_t: Signed 8-bit integer
+ - uint16_t: Unsigned 16-bit integer
+ - int16_t: Signed 16-bit integer
+ - uint32_t: Unsigned 32-bit integer
+ - int32_t: Signed 32-bit integer
+ - uint64_t: Unsigned 64-bit integer
+ - int64_t: Signed 64-bit integer
+ - uintptr_t: Unsigned integer capable of storing a pointer, preferably the
+ same size as pointers themselves.
+
+ These types deliberately use the same names as the standard C99 types, so
+ that if the C99 headers stdint.h and stdbool.h are available, they may be
+ included here.
+
+ If the user application defines similar types, those may be reused. For
+ example, suppose there is an application header apptypes.h which defines
+ types with a similar purpose but different names. That header could be
+ reused to define the types Reliance Edge needs:
+
+ ~~~{.c}
+ #include <apptypes.h>
+
+ typedef BOOL bool;
+ typedef BYTE uint8_t;
+ typedef INT8 int8_t;
+ // And so on...
+ ~~~
+
+ If there are neither C99 headers nor suitable types in application headers,
+ this header should be populated with typedefs that define the required types
+ in terms of the standard C types. This requires knowledge of the size of
+ the C types on the target hardware (e.g., how big is an "int" or a pointer).
+ Below is an example which assumes the target has 8-bit chars, 16-bit shorts,
+ 32-bit ints, 32-bit pointers, and 64-bit long longs:
+
+ ~~~{.c}
+ typedef int bool;
+ typedef unsigned char uint8_t;
+ typedef signed char int8_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned long long uint64_t;
+ typedef long long int64_t;
+ typedef uint32_t uintptr_t;
+ ~~~
+*/
+#ifndef REDTYPES_H
+#define REDTYPES_H
+
+/* Defines bool.
+ */
+#include <stdbool.h>
+
+/* Defines uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t,
+ int64_t, and uintptr_t.
+*/
+#include <stdint.h>
+
+#endif
A module-vfs/drivers/include/thirdparty/reedgefs/volume_mapper.hpp => module-vfs/drivers/include/thirdparty/reedgefs/volume_mapper.hpp +34 -0
@@ 0,0 1,34 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <string>
+#include <memory>
+#include <purefs/blkdev/defs.hpp>
+
+namespace purefs::blkdev
+{
+ class disk_manager;
+}
+namespace purefs::fs::drivers::reedgefs::internal
+{
+
+ /** Map volume to partion of logical drive
+ * @param[in] disk Disk manager handle to attach partition
+ * @return Volume identifier or error if negative
+ */
+ std::pair<std::string, int> append_volume(blkdev::disk_fd diskh, const std::string &path);
+
+ /** Clear mapping table of logical drives
+ * @param[in] diskmm Initialized disk manager object
+ */
+ void reset_volumes(std::shared_ptr<blkdev::disk_manager> diskmm);
+
+ /** Remove volume from map
+ * @param [in] diskh Disk manager handle object
+ * @return 0 on success otherwise error
+ */
+ int remove_volume(blkdev::disk_fd diskh);
+
+} // namespace purefs::fs::drivers::reedgefs::internal
A module-vfs/drivers/src/purefs/fs/filesystem_reedgefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_reedgefs.cpp +519 -0
@@ 0,0 1,519 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <purefs/fs/drivers/filesystem_reedgefs.hpp>
+#include <purefs/fs/drivers/mount_point_reedgefs.hpp>
+#include <purefs/blkdev/disk_manager.hpp>
+#include <purefs/blkdev/disk_handle.hpp>
+#include <purefs/fs/drivers/file_handle_reedgefs.hpp>
+#include <purefs/fs/drivers/directory_handle_reedgefs.hpp>
+#include <purefs/fs/mount_flags.hpp>
+#include <log/log.hpp>
+#include <reedgefs/volume_mapper.hpp>
+#include <sys/statvfs.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <redfs.h>
+#include <redposix.h>
+
+#include <cstring>
+
+namespace purefs::fs::drivers
+{
+ namespace
+ {
+ int translate_error(int error)
+ {
+ switch (error) {
+ case -RED_ENOTSUPP:
+ return -ENOTSUP;
+ default:
+ return error;
+ }
+ }
+
+ uint8_t translate_flags(unsigned flags)
+ {
+ uint8_t mode = 0;
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ mode |= RED_O_RDONLY;
+ break;
+ case O_WRONLY:
+ mode |= RED_O_WRONLY;
+ break;
+ case O_RDWR:
+ mode |= RED_O_RDWR;
+ break;
+ }
+
+ if (flags & O_APPEND) {
+ mode |= RED_O_APPEND;
+ }
+ if (flags & O_CREAT) {
+ mode |= RED_O_CREAT;
+ }
+ if (flags & O_TRUNC) {
+ mode |= RED_O_TRUNC;
+ }
+ if (flags & O_EXCL) {
+ mode |= RED_O_EXCL;
+ }
+ return mode;
+ }
+
+ auto translate_mode_to_st_mode(uint16_t _mode, bool readOnly)
+ {
+ decltype(std::declval<struct stat *>()->st_mode) mode = _mode | S_IRUSR | S_IRGRP | S_IROTH;
+ if (!readOnly) {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ }
+ return mode;
+ }
+
+ void translate_redstat_to_stat(const REDSTAT &fs, uint32_t blksize, struct stat &st, bool ro)
+ {
+ std::memset(&st, 0, sizeof st);
+ st.st_dev = fs.st_dev;
+ st.st_ino = fs.st_ino;
+ st.st_mode = translate_mode_to_st_mode(fs.st_mode, ro);
+ st.st_nlink = fs.st_nlink;
+ st.st_uid = 0;
+ st.st_gid = 0;
+ st.st_rdev = 0;
+ st.st_size = fs.st_size;
+
+ st.st_blksize = blksize;
+ st.st_blocks = fs.st_blocks;
+ // For some reason compiler returns error here even if REDCONF_INODE_TIMESTAMPS is set to 1
+ // #if REDCONF_INODE_TIMESTAMPS == 1
+ // st.st_atime = fs.st_atime;
+ // st.st_mtime = fs.st_mtime;
+ // st.st_ctime = fs.st_ctime;
+ // #endif
+ }
+ } // namespace
+
+ filesystem_reedgefs::filesystem_reedgefs()
+ {
+ red_init();
+ }
+
+ filesystem_reedgefs::~filesystem_reedgefs()
+ {
+ red_uninit();
+ }
+
+ auto filesystem_reedgefs::mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh,
+ std::string_view path,
+ unsigned flags) -> fsmount
+ {
+ return std::make_shared<mount_point_reedgefs>(diskh, path, flags, shared_from_this());
+ }
+
+ auto filesystem_reedgefs::mount(fsmount mnt, const void *data) noexcept -> int
+ {
+ auto disk = mnt->disk();
+ if (!disk) {
+ return -EIO;
+ }
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -EIO;
+ }
+ const auto mountPath = vmnt->mount_path();
+ auto [volumeName, ret] = reedgefs::internal::append_volume(disk, mountPath);
+ if (ret < 0) {
+ LOG_ERROR("Unable to attach volume to ff layer with errno %i", ret);
+ return ret;
+ }
+ // TODO: This is temporary fix, need to be removed when image creation is ready
+ red_format(volumeName.c_str());
+ // TODO: ////////////////////////////////
+
+ if (red_mount(volumeName.c_str()) < 0) {
+ return translate_error(-red_errno);
+ }
+ vmnt->volume_name(volumeName);
+ filesystem_operations::mount(mnt, data);
+ return ret;
+ }
+
+ auto filesystem_reedgefs::filesystem_register_completed() const noexcept -> int
+ {
+ const auto dmgr = disk_mngr();
+ if (dmgr) {
+ reedgefs::internal::reset_volumes(dmgr);
+ return 0;
+ }
+ else {
+ return -EIO;
+ }
+ }
+
+ auto filesystem_reedgefs::umount(fsmount mnt) noexcept -> int
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -EIO;
+ }
+
+ auto disk = mnt->disk();
+ if (!disk) {
+ return -EIO;
+ }
+
+ int ret = red_umount(vmnt->volume_name().c_str());
+ if (ret < 0) {
+ ret = translate_error(-red_errno);
+ }
+ if (!ret) {
+ ret = reedgefs::internal::remove_volume(disk);
+ filesystem_operations::umount(mnt);
+ }
+ return ret;
+ }
+
+ auto filesystem_reedgefs::stat_vfs(fsmount mnt, std::string_view, struct statvfs &stat) const noexcept -> int
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -EIO;
+ }
+ REDSTATFS statvfs;
+ auto ret = red_statvfs(vmnt->volume_name().c_str(), &statvfs);
+ if (ret != 0) {
+ return translate_error(-red_errno);
+ }
+
+ stat.f_bsize = statvfs.f_bsize;
+ stat.f_frsize = statvfs.f_frsize;
+ stat.f_blocks = statvfs.f_blocks;
+ stat.f_bfree = statvfs.f_bfree;
+ stat.f_bavail = statvfs.f_bavail;
+ stat.f_flag = statvfs.f_flag;
+ stat.f_files = statvfs.f_files;
+ stat.f_ffree = statvfs.f_ffree;
+ stat.f_favail = statvfs.f_favail;
+ stat.f_fsid = statvfs.f_fsid;
+ stat.f_namemax = statvfs.f_namemax;
+ return 0;
+ }
+
+ auto filesystem_reedgefs::open(fsmount mnt, std::string_view path, int flags, int mode) noexcept -> fsfile
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return nullptr;
+ }
+ const auto fspath = vmnt->native_path(path);
+ const auto fsflags = translate_flags(flags);
+ auto fileo = std::make_shared<file_handle_reedgefs>(mnt, fspath, flags);
+ auto ret = red_open(fspath.c_str(), fsflags);
+ if (ret < 0) {
+ fileo->error(translate_error(-red_errno));
+ }
+ else {
+ fileo->fd(ret);
+ }
+
+ return fileo;
+ }
+
+ auto filesystem_reedgefs::close(fsfile zfile) noexcept -> int
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+ const auto ret = red_close(vfile->fd());
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+ return 0;
+ }
+
+ auto filesystem_reedgefs::write(fsfile zfile, const char *ptr, size_t len) noexcept -> ssize_t
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+
+ const auto ret = red_write(vfile->fd(), ptr, len);
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+
+ return ret;
+ }
+
+ auto filesystem_reedgefs::read(fsfile zfile, char *ptr, size_t len) noexcept -> ssize_t
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+ const auto ret = red_read(vfile->fd(), ptr, len);
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+
+ return ret;
+ }
+
+ auto filesystem_reedgefs::seek(fsfile zfile, off_t pos, int dir) noexcept -> off_t
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+
+ auto ret = red_lseek(vfile->fd(), pos, static_cast<REDWHENCE>(dir));
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+
+ return ret;
+ }
+
+ auto filesystem_reedgefs::fstat(fsfile zfile, struct stat &st) noexcept -> int
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+ REDSTAT redstat;
+ const auto ret = red_fstat(vfile->fd(), &redstat);
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+
+ const auto mnt = vfile->mntpoint();
+ if (mnt) {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -EIO;
+ }
+ REDSTATFS redstatfs;
+ auto ret = red_statvfs(vmnt->volume_name().c_str(), &redstatfs);
+ if (ret != 0) {
+ return translate_error(-red_errno);
+ }
+ translate_redstat_to_stat(redstat, redstatfs.f_bsize, st, vmnt->is_ro());
+ }
+ else {
+ return -EIO;
+ }
+
+ return 0;
+ }
+
+ auto filesystem_reedgefs::stat(fsmount mnt, std::string_view file, struct stat &st) noexcept -> int
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -EBADF;
+ }
+
+ const auto fspath = vmnt->native_path(file);
+ auto fh = red_open(fspath.c_str(), RED_O_RDONLY);
+ if (fh < 0) {
+ return translate_error(-red_errno);
+ }
+ REDSTAT redstat;
+ auto ret = red_fstat(fh, &redstat);
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+ REDSTATFS redstatfs;
+ ret = red_statvfs(vmnt->volume_name().c_str(), &redstatfs);
+ if (ret != 0) {
+ return translate_error(-red_errno);
+ }
+ translate_redstat_to_stat(redstat, redstatfs.f_bsize, st, vmnt->is_ro());
+ ret = red_close(fh);
+ if (ret < 0) {
+ return translate_error(-red_errno);
+ }
+ return 0;
+ }
+
+ auto filesystem_reedgefs::unlink(fsmount mnt, std::string_view name) noexcept -> int
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -ENXIO;
+ }
+ const auto fspath = vmnt->native_path(name);
+ const auto fret = red_unlink(fspath.c_str());
+ if (fret != 0) {
+ return translate_error(-red_errno);
+ }
+ return fret;
+ }
+
+ auto filesystem_reedgefs::rename(fsmount mnt, std::string_view oldname, std::string_view newname) noexcept -> int
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -ENXIO;
+ }
+ const auto fsold = vmnt->native_path(oldname);
+ const auto fsnew = vmnt->native_path(newname);
+ const auto fret = red_rename(fsold.c_str(), fsnew.c_str());
+ if (fret != 0) {
+ return translate_error(-red_errno);
+ }
+ return fret;
+ }
+
+ auto filesystem_reedgefs::mkdir(fsmount mnt, std::string_view path, int mode) noexcept -> int
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -ENXIO;
+ }
+ const auto fspath = vmnt->native_path(path);
+ const auto fret = red_mkdir(fspath.c_str());
+ if (fret != 0) {
+ return translate_error(-red_errno);
+ }
+ return fret;
+ }
+
+ auto filesystem_reedgefs::diropen(fsmount mnt, std::string_view path) noexcept -> fsdir
+ {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return nullptr;
+ }
+ const auto fspath = vmnt->native_path(path);
+ const auto dirp = std::make_shared<directory_handle_reedgefs>(mnt, 0);
+ const auto fret = red_opendir(fspath.c_str());
+ if (fret == nullptr) {
+ dirp->error(translate_error(-red_errno));
+ }
+ else {
+ dirp->reedgefs_dirp(fret);
+ }
+
+ return dirp;
+ }
+
+ auto filesystem_reedgefs::dirreset(fsdir dirstate) noexcept -> int
+ {
+ auto dirp = std::dynamic_pointer_cast<directory_handle_reedgefs>(dirstate);
+ if (!dirp) {
+ LOG_ERROR("Non reedgefs directory handle");
+ return -ENXIO;
+ }
+ red_rewinddir(dirp->reedgefs_dirp());
+ return 0;
+ }
+
+ auto filesystem_reedgefs::dirnext(fsdir dirstate, std::string &filename, struct stat &filestat) -> int
+ {
+ auto dirp = std::dynamic_pointer_cast<directory_handle_reedgefs>(dirstate);
+ if (!dirp) {
+ LOG_ERROR("Non reedgefs directory handle");
+ return -ENXIO;
+ }
+ red_errno = 0;
+ auto reddirent = red_readdir(dirp->reedgefs_dirp());
+ if (reddirent != nullptr) {
+ if (reddirent->d_name[0] == '\0') {
+ return -ENODATA;
+ }
+ else {
+ const auto mnt = dirp->mntpoint();
+ if (mnt) {
+ auto vmnt = std::dynamic_pointer_cast<mount_point_reedgefs>(mnt);
+ if (!vmnt) {
+ LOG_ERROR("Non reedgefs mount point");
+ return -EIO;
+ }
+
+ REDSTATFS redstatfs;
+ auto ret = red_statvfs(vmnt->volume_name().c_str(), &redstatfs);
+ if (ret != 0) {
+ return translate_error(-red_errno);
+ }
+ translate_redstat_to_stat(reddirent->d_stat, redstatfs.f_bsize, filestat, vmnt->is_ro());
+ filename = reddirent->d_name;
+ return 0;
+ }
+ else {
+ return -EIO;
+ }
+ }
+ }
+ return red_errno != 0 ? translate_error(-red_errno) : -ENODATA;
+ }
+
+ auto filesystem_reedgefs::dirclose(fsdir dirstate) noexcept -> int
+ {
+ auto dirp = std::dynamic_pointer_cast<directory_handle_reedgefs>(dirstate);
+ if (!dirp) {
+ LOG_ERROR("Not a reedgefs directory handle");
+ return -ENXIO;
+ }
+ const auto fret = red_closedir(dirp->reedgefs_dirp());
+ if (fret != 0) {
+ return translate_error(-red_errno);
+ }
+ return fret;
+ }
+
+ auto filesystem_reedgefs::ftruncate(fsfile zfile, off_t len) noexcept -> int
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+ const int fret = red_ftruncate(vfile->fd(), len);
+ if (fret != 0) {
+ return translate_error(-red_errno);
+ }
+ return fret;
+ }
+
+ auto filesystem_reedgefs::fsync(fsfile zfile) noexcept -> int
+ {
+ auto vfile = std::dynamic_pointer_cast<file_handle_reedgefs>(zfile);
+ if (!vfile) {
+ LOG_ERROR("Non reedgefs filesystem pointer");
+ return -EBADF;
+ }
+ const int fret = red_fsync(vfile->fd());
+ if (fret != 0) {
+ return translate_error(-red_errno);
+ }
+ return fret;
+ }
+
+ auto filesystem_reedgefs::isatty(fsfile zfile) noexcept -> int
+ {
+ // NOTE: Handle is always not a tty
+ return 0;
+ }
+
+} // namespace purefs::fs::drivers
A module-vfs/drivers/src/thirdparty/reedgefs/glue.cpp => module-vfs/drivers/src/thirdparty/reedgefs/glue.cpp +204 -0
@@ 0,0 1,204 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+// ffFAT glue layer code
+
+#include <errno.h>
+#include <cstring>
+#include <string>
+#include <unordered_map>
+#include "services/osbdev_custom.h"
+#include <reedgefs/volume_mapper.hpp>
+#include <mutex.hpp>
+#include <purefs/blkdev/defs.hpp>
+#include <purefs/blkdev/disk_handle.hpp>
+#include <purefs/blkdev/disk_manager.hpp>
+#include <purefs/fs/handle_mapper.hpp>
+#include <redvolume.h>
+
+namespace purefs::fs::drivers::reedgefs::internal
+{
+ extern "C"
+ {
+ extern VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT];
+ extern BDEVINFO gaRedBdevInfo[REDCONF_VOLUME_COUNT];
+ }
+ namespace
+ {
+ cpp_freertos::MutexRecursive g_lock;
+ // Device manager part / LUN map
+ std::unordered_map<std::string, int> g_registered_vol;
+ fs::internal::handle_mapper<std::shared_ptr<blkdev::internal::disk_handle>> g_disk_handles;
+ std::weak_ptr<blkdev::disk_manager> g_disk_mm;
+ } // namespace
+ namespace
+ {
+ inline auto disk_handle_from_pdrive(size_t pdrive)
+ {
+ cpp_freertos::LockGuard _lck(g_lock);
+ return (g_disk_handles.exists(pdrive)) ? g_disk_handles[pdrive] : nullptr;
+ }
+ } // namespace
+
+ std::pair<std::string, int> append_volume(blkdev::disk_fd diskh, const std::string &path)
+ {
+ cpp_freertos::LockGuard _lck(g_lock);
+ const auto vol = g_registered_vol.find(std::string(diskh->name()));
+ if (vol != std::end(g_registered_vol)) {
+ return {"", vol->second};
+ }
+ if (g_disk_handles.size() >= REDCONF_VOLUME_COUNT) {
+ return {"", -EOVERFLOW};
+ }
+ auto diskmm = g_disk_mm.lock();
+ if (!diskmm) {
+ return {"", -EIO};
+ }
+
+ if (path.length() > sizeof(VOLCONF::pszPathPrefix)) {
+ return {"", -EIO};
+ }
+
+ const auto hwnd = g_disk_handles.insert(diskh);
+ g_registered_vol.emplace(std::make_pair(diskh->name(), hwnd));
+ gaRedVolConf[hwnd].ullSectorOffset = diskmm->get_info(diskh, blkdev::info_type::start_sector);
+ return {std::string(gaRedVolConf[hwnd].pszPathPrefix), hwnd};
+ }
+
+ int remove_volume(blkdev::disk_fd diskh)
+ {
+ cpp_freertos::LockGuard _lck(g_lock);
+ const auto vol_it = g_registered_vol.find(std::string(diskh->name()));
+ if (vol_it == std::end(g_registered_vol)) {
+ return -EBADF;
+ }
+ g_disk_handles.remove(vol_it->second);
+ g_registered_vol.erase(vol_it);
+ return 0;
+ }
+
+ void reset_volumes(std::shared_ptr<blkdev::disk_manager> diskmm)
+ {
+ cpp_freertos::LockGuard _lck(g_lock);
+ g_disk_mm = diskmm;
+ g_registered_vol.clear();
+ g_disk_handles.clear();
+ }
+
+ extern "C"
+ {
+
+ REDSTATUS DiskOpen(uint8_t bVolNum, BDEVOPENMODE mode)
+ {
+ return disk_handle_from_pdrive(bVolNum) ? (0) : (-RED_EIO);
+ }
+
+ REDSTATUS DiskClose(uint8_t bVolNum)
+ {
+ (void)bVolNum;
+ return 0;
+ }
+
+ REDSTATUS DiskGetGeometry(uint8_t bVolNum, BDEVINFO *pInfo)
+ {
+ const auto diskh = disk_handle_from_pdrive(bVolNum);
+ if (!diskh) {
+ return -RED_EIO;
+ }
+ const auto diskmm = g_disk_mm.lock();
+ if (!diskmm) {
+ return -RED_EIO;
+ }
+ auto sectorSize = diskmm->get_info(diskh, blkdev::info_type::sector_size);
+ auto sectorCount = diskmm->get_info(diskh, blkdev::info_type::sector_count);
+
+ if (sectorSize > 0 && sectorCount > 0) {
+ pInfo->ulSectorSize = sectorSize;
+ pInfo->ullSectorCount = sectorCount;
+ return 0;
+ }
+
+ return -RED_EIO;
+ }
+
+ REDSTATUS DiskRead(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer)
+ {
+ uint32_t ulSectorIdx = 0U;
+ uint32_t ulSectorSize = gaRedBdevInfo[bVolNum].ulSectorSize;
+ auto pbBuffer = static_cast<uint8_t *>(pBuffer);
+ const auto diskh = disk_handle_from_pdrive(bVolNum);
+ if (!diskh) {
+ return -RED_EIO;
+ }
+ const auto diskmm = g_disk_mm.lock();
+ if (!diskmm) {
+ return -RED_EIO;
+ }
+
+ while (ulSectorIdx < ulSectorCount) {
+ uint32_t ulTransfer = REDMIN(ulSectorCount - ulSectorIdx, MAX_SECTOR_TRANSFER);
+
+ auto result = diskmm->read(
+ diskh, &pbBuffer[ulSectorIdx * ulSectorSize], (ullSectorStart + ulSectorIdx), ulTransfer);
+ if (result < 0) {
+ LOG_ERROR("write error %i", result);
+ return (result == -ERANGE) ? (-RED_ERANGE) : (-RED_EIO);
+ }
+
+ ulSectorIdx += ulTransfer;
+ }
+
+ return 0;
+ }
+
+ REDSTATUS DiskWrite(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, const void *pBuffer)
+ {
+ uint32_t ulSectorIdx = 0U;
+ uint32_t ulSectorSize = gaRedBdevInfo[bVolNum].ulSectorSize;
+ auto pbBuffer = static_cast<const uint8_t *>(pBuffer);
+ const auto diskh = disk_handle_from_pdrive(bVolNum);
+ if (!diskh) {
+ return -RED_EIO;
+ }
+ const auto diskmm = g_disk_mm.lock();
+ if (!diskmm) {
+ return -RED_EIO;
+ }
+
+ while (ulSectorIdx < ulSectorCount) {
+ uint32_t ulTransfer = REDMIN(ulSectorCount - ulSectorIdx, MAX_SECTOR_TRANSFER);
+
+ auto result = diskmm->write(
+ diskh, &pbBuffer[ulSectorIdx * ulSectorSize], (ullSectorStart + ulSectorIdx), ulTransfer);
+ if (result < 0) {
+ LOG_ERROR("write error %i", result);
+ return (result == -ERANGE) ? (-RED_ERANGE) : (-RED_EIO);
+ }
+
+ ulSectorIdx += ulTransfer;
+ }
+
+ return 0;
+ }
+
+ REDSTATUS DiskFlush(uint8_t bVolNum)
+ {
+ const auto diskh = disk_handle_from_pdrive(bVolNum);
+ if (!diskh) {
+ return -RED_EIO;
+ }
+ const auto diskmm = g_disk_mm.lock();
+ if (!diskmm) {
+ return -RED_EIO;
+ }
+
+ auto result = diskmm->sync(diskh);
+ if (result < 0) {
+ LOG_ERROR("sync error %i", result);
+ return -RED_EIO;
+ }
+
+ return 0;
+ }
+ }
+
+} // namespace purefs::fs::drivers::reedgefs::internal
A module-vfs/drivers/src/thirdparty/reedgefs/include/redostypes.h => module-vfs/drivers/src/thirdparty/reedgefs/include/redostypes.h +42 -0
@@ 0,0 1,42 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Defines OS-specific types for use in common code.
+*/
+#ifndef REDOSTYPES_H
+#define REDOSTYPES_H
+
+/** @brief Implementation-defined timestamp type.
+
+ This can be an integer, a structure, or a pointer: anything that is
+ convenient for the implementation. Since the underlying type is not fixed,
+ common code should treat this as an opaque type.
+*/
+typedef uint32_t REDTIMESTAMP;
+
+#endif
A module-vfs/drivers/src/thirdparty/reedgefs/redconf.c => module-vfs/drivers/src/thirdparty/reedgefs/redconf.c +19 -0
@@ 0,0 1,19 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* THIS FILE WAS GENERATED BY THE TUXERA RELIANCE EDGE CONFIGURATION UTILITY.
+ DO NOT MODIFY.
+
+ Generated by configuration utility version 2.5
+*/
+/** @file
+ */
+#include <redconf.h>
+#include <redtypes.h>
+#include <redmacs.h>
+#include <redvolume.h>
+
+VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT] = {{SECTOR_SIZE_AUTO, SECTOR_COUNT_AUTO, 0U, false, 10000U, 2U, "VOL0:"},
+ {SECTOR_SIZE_AUTO, SECTOR_COUNT_AUTO, 0U, false, 10000U, 2U, "VOL1:"},
+ {SECTOR_SIZE_AUTO, SECTOR_COUNT_AUTO, 0U, false, 10000U, 2U, "VOL2:"},
+ {SECTOR_SIZE_AUTO, SECTOR_COUNT_AUTO, 0U, false, 10000U, 2U, "VOL3:"}};
A module-vfs/drivers/src/thirdparty/reedgefs/services/osassert.c => module-vfs/drivers/src/thirdparty/reedgefs/services/osassert.c +59 -0
@@ 0,0 1,59 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements assertion handling.
+*/
+#include <redfs.h>
+#include <log/log.hpp>
+
+#include <stdlib.h>
+
+#if REDCONF_ASSERTS == 1
+
+#if REDCONF_OUTPUT == 1
+#include <stdio.h>
+#endif
+
+/** @brief Invoke the native assertion handler.
+
+ @param pszFileName Null-terminated string containing the name of the file
+ where the assertion fired.
+ @param ulLineNum Line number in @p pszFileName where the assertion
+ fired.
+*/
+void RedOsAssertFail(const char *pszFileName, uint32_t ulLineNum)
+{
+#if REDCONF_OUTPUT == 1
+ LOG_FATAL(
+ "Assertion failed in \"%s\" at line %u\n\r", (pszFileName == NULL) ? "" : pszFileName, (unsigned)ulLineNum);
+#endif
+
+ abort();
+}
+
+#endif
A module-vfs/drivers/src/thirdparty/reedgefs/services/osbdev.c => module-vfs/drivers/src/thirdparty/reedgefs/services/osbdev.c +353 -0
@@ 0,0 1,353 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements block device I/O.
+*/
+#include <FreeRTOS.h>
+
+#include <redfs.h>
+#include <redvolume.h>
+#include <redbdev.h>
+
+/*------------------------------------------------------------------------------
+ Porting Note:
+
+ Several example implementations of this module for FreeRTOS are available.
+ If you are lucky, you can use one of these implementations; otherwise, these
+ can serve as examples of how to implement this service.
+------------------------------------------------------------------------------*/
+
+/** @brief A custom implementation, initially stubbed out.
+
+ This the default setting: it is initially stubbed out (does nothing) and
+ produces an error when compiled so that it is obvious that this file needs
+ to be modified. You can edit this code to provide your own implementation
+ of the block device. Alternatively, you can delete all of the Disk*()
+ functions and put the custom code directly into the RedOsBDev*() functions.
+*/
+#define BDEV_CUSTOM (0U)
+
+/** @brief Tuxera FlashFX Tera driver implementation.
+
+ This implementation uses Tuxera's FlashFX Tera driver to use raw flash
+ storage with Reliance Edge.
+
+ This option is only available in commercial releases of Reliance Edge.
+*/
+#define BDEV_FLASHFX (1U)
+
+/** @brief The FatFs example implementation.
+
+ This implementation is designed to reuse an existing block device driver
+ that was written for FatFs. If you have such a driver, it can be linked
+ in and used immediately. The FatFs `diskio.h` header must be in the include
+ directory path.
+*/
+#define BDEV_FATFS (3U)
+
+/** @brief The Atmel Studio Framework SD/MMC driver example implementation.
+
+ This implementation uses a modified version of the open source SD/MMC driver
+ included in the Atmel Studio Framework (ASF) and will work as-is for many
+ varieties of Atmel hardware. This example assumes relatively minor
+ modifications to the ASF SD/MMC driver to make it support multi-sector read
+ and write requests, which greatly improves performance. The modified driver
+ is distributed with the Reliance Edge commercial kit and is included in
+ FreeRTOS Atmel projects that come with the commercial kit (such as in
+ projects/freertos/atmel/sam4e-ek/src/ASF).
+
+ This example can easily be modified to work with an unmodified version of
+ the ASF SD/MMC driver. Simply replace sd_mmc_mem_2_ram_multi() and
+ sd_mmc_ram_2_mem_multi() with sd_mmc_mem_2_ram() and sd_mmc_ram_2_mem()
+ respectively, and add a for loop to loop over each sector in the request.
+ However, as described in the manual, there are considerable performance
+ advantages to issuing real multi-sector requests, so using the modified
+ driver is recommended.
+*/
+#define BDEV_ATMEL_SDMMC (4U)
+
+/** @brief The ST Microelectronics STM32 SDIO driver example implementation.
+
+ This implementation accesses the microSD card through the BSP utilities
+ provided as part of the STM32Cube package, used with the STM32 HAL drivers.
+ The STM3240G-EVAL and STM32F746NG-Discovery boards are currently supported.
+*/
+#define BDEV_STM32_SDIO (5U)
+
+/** @brief The RAM disk example implementation.
+
+ This implementation uses a RAM disk. It will allow you to compile and test
+ Reliance Edge even if your storage driver is not yet ready. On typical
+ target hardware, the amount of spare RAM will be limited so generally only
+ very small disks will be available.
+*/
+#define BDEV_RAM_DISK (6U)
+
+/** @brief Pick which example implementation is compiled.
+
+ Must be one of:
+ - #BDEV_CUSTOM
+ - #BDEV_FLASHFX
+ - #BDEV_FATFS
+ - #BDEV_ATMEL_SDMMC
+ - #BDEV_STM32_SDIO
+ - #BDEV_RAM_DISK
+*/
+#ifndef BDEV_EXAMPLE_IMPLEMENTATION
+#define BDEV_EXAMPLE_IMPLEMENTATION BDEV_CUSTOM
+#endif
+
+/* The DiskOpen(), DiskClose(), DiskRead(), DiskWrite(), DiskFlush(), and
+ DiskDiscard() functions used below are defined in these header files:
+*/
+#if BDEV_EXAMPLE_IMPLEMENTATION == BDEV_CUSTOM
+#include "osbdev_custom.h"
+#elif BDEV_EXAMPLE_IMPLEMENTATION == BDEV_FLASHFX
+#if RED_KIT == RED_KIT_GPL
+#error "FlashFX block device only supported in commercial versions of Reliance Edge."
+#endif
+#include "osbdev_flashfx.h"
+#elif BDEV_EXAMPLE_IMPLEMENTATION == BDEV_FATFS
+#include "osbdev_fatfs.h"
+#elif BDEV_EXAMPLE_IMPLEMENTATION == BDEV_ATMEL_SDMMC
+#include "osbdev_asfsdmmc.h"
+#elif BDEV_EXAMPLE_IMPLEMENTATION == BDEV_STM32_SDIO
+#include "osbdev_stm32sdio.h"
+#elif BDEV_EXAMPLE_IMPLEMENTATION == BDEV_RAM_DISK
+#include "osbdev_ramdisk.h"
+#else
+#error "Invalid BDEV_EXAMPLE_IMPLEMENTATION value"
+#endif /* BDEV_EXAMPLE_IMPLEMENTATION == ... */
+
+/** @brief Initialize a block device.
+
+ This function is called when the file system needs access to a block
+ device.
+
+ Upon successful return, the block device should be fully initialized and
+ ready to service read/write/flush/close requests.
+
+ The behavior of calling this function on a block device which is already
+ open is undefined.
+
+ @param bVolNum The volume number of the volume whose block device is being
+ initialized.
+ @param mode The open mode, indicating the type of access required.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EINVAL @p bVolNum is an invalid volume number.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS RedOsBDevOpen(uint8_t bVolNum, BDEVOPENMODE mode)
+{
+ REDSTATUS ret;
+
+ if (bVolNum >= REDCONF_VOLUME_COUNT) {
+ ret = -RED_EINVAL;
+ }
+ else {
+ ret = DiskOpen(bVolNum, mode);
+ }
+
+ return ret;
+}
+
+/** @brief Uninitialize a block device.
+
+ This function is called when the file system no longer needs access to a
+ block device. If any resource were allocated by RedOsBDevOpen() to service
+ block device requests, they should be freed at this time.
+
+ Upon successful return, the block device must be in such a state that it
+ can be opened again.
+
+ The behavior of calling this function on a block device which is already
+ closed is undefined.
+
+ @param bVolNum The volume number of the volume whose block device is being
+ uninitialized.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EINVAL @p bVolNum is an invalid volume number.
+*/
+REDSTATUS RedOsBDevClose(uint8_t bVolNum)
+{
+ REDSTATUS ret;
+
+ if (bVolNum >= REDCONF_VOLUME_COUNT) {
+ ret = -RED_EINVAL;
+ }
+ else {
+ ret = DiskClose(bVolNum);
+ }
+
+ return ret;
+}
+
+/** @brief Return the block device geometry.
+
+ The behavior of calling this function is undefined if the block device is
+ closed.
+
+ @param bVolNum The volume number of the volume whose block device geometry
+ is being queried.
+ @param pInfo On successful return, populated with the geometry of the
+ block device.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EINVAL @p bVolNum is an invalid volume number, or @p pInfo
+ is `NULL`.
+ @retval -RED_EIO A disk I/O error occurred.
+ @retval -RED_ENOTSUPP The geometry cannot be queried on this block device.
+*/
+REDSTATUS RedOsBDevGetGeometry(uint8_t bVolNum, BDEVINFO *pInfo)
+{
+ REDSTATUS ret;
+
+ if ((bVolNum >= REDCONF_VOLUME_COUNT) || (pInfo == NULL)) {
+ ret = -RED_EINVAL;
+ }
+ else {
+ ret = DiskGetGeometry(bVolNum, pInfo);
+ }
+
+ return ret;
+}
+
+/** @brief Read sectors from a physical block device.
+
+ The behavior of calling this function is undefined if the block device is
+ closed or if it was opened with ::BDEV_O_WRONLY.
+
+ @param bVolNum The volume number of the volume whose block device
+ is being read from.
+ @param ullSectorStart The starting sector number.
+ @param ulSectorCount The number of sectors to read.
+ @param pBuffer The buffer into which to read the sector data.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EINVAL @p bVolNum is an invalid volume number, @p pBuffer is
+ `NULL`, or @p ullStartSector and/or @p ulSectorCount
+ refer to an invalid range of sectors.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS RedOsBDevRead(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer)
+{
+ REDSTATUS ret;
+
+ if ((bVolNum >= REDCONF_VOLUME_COUNT) || !VOLUME_SECTOR_RANGE_IS_VALID(bVolNum, ullSectorStart, ulSectorCount) ||
+ (pBuffer == NULL)) {
+ ret = -RED_EINVAL;
+ }
+ else {
+ ret = DiskRead(bVolNum, ullSectorStart, ulSectorCount, pBuffer);
+ }
+
+ return ret;
+}
+
+#if REDCONF_READ_ONLY == 0
+
+/** @brief Write sectors to a physical block device.
+
+ The behavior of calling this function is undefined if the block device is
+ closed or if it was opened with ::BDEV_O_RDONLY.
+
+ @param bVolNum The volume number of the volume whose block device
+ is being written to.
+ @param ullSectorStart The starting sector number.
+ @param ulSectorCount The number of sectors to write.
+ @param pBuffer The buffer from which to write the sector data.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EINVAL @p bVolNum is an invalid volume number, @p pBuffer is
+ `NULL`, or @p ullStartSector and/or @p ulSectorCount
+ refer to an invalid range of sectors.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS RedOsBDevWrite(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, const void *pBuffer)
+{
+ REDSTATUS ret;
+
+ if ((bVolNum >= REDCONF_VOLUME_COUNT) || !VOLUME_SECTOR_RANGE_IS_VALID(bVolNum, ullSectorStart, ulSectorCount) ||
+ (pBuffer == NULL)) {
+ ret = -RED_EINVAL;
+ }
+ else {
+ ret = DiskWrite(bVolNum, ullSectorStart, ulSectorCount, pBuffer);
+ }
+
+ return ret;
+}
+
+/** @brief Flush any caches beneath the file system.
+
+ This function must synchronously flush all software and hardware caches
+ beneath the file system, ensuring that all sectors written previously are
+ committed to permanent storage.
+
+ If the environment has no caching beneath the file system, the
+ implementation of this function can do nothing and return success.
+
+ The behavior of calling this function is undefined if the block device is
+ closed or if it was opened with ::BDEV_O_RDONLY.
+
+ @param bVolNum The volume number of the volume whose block device is being
+ flushed.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EINVAL @p bVolNum is an invalid volume number.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS RedOsBDevFlush(uint8_t bVolNum)
+{
+ REDSTATUS ret;
+
+ if (bVolNum >= REDCONF_VOLUME_COUNT) {
+ ret = -RED_EINVAL;
+ }
+ else {
+ ret = DiskFlush(bVolNum);
+ }
+
+ return ret;
+}
+
+#endif /* REDCONF_READ_ONLY == 0 */
A module-vfs/drivers/src/thirdparty/reedgefs/services/osbdev_custom.h => module-vfs/drivers/src/thirdparty/reedgefs/services/osbdev_custom.h +129 -0
@@ 0,0 1,129 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @brief
+ @file FreeRTOS block device implementation; see osbdev.c for details.
+*/
+#ifndef OSBDEV_CUSTOM_H
+#define OSBDEV_CUSTOM_H
+
+#include <redfs.h>
+
+#define MAX_SECTOR_TRANSFER UINT8_MAX
+
+/* If you need to include headers to access your block device, do so here. For
+ example, if you are using an SD card driver whose interfaces are defined in
+ sd.h, that would be included here.
+#include <foobar.h>
+*/
+
+/** @brief Initialize a disk.
+
+ @param bVolNum The volume number of the volume whose block device is being
+ initialized.
+ @param mode The open mode, indicating the type of access required.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS DiskOpen(uint8_t bVolNum, BDEVOPENMODE mode);
+
+/** @brief Uninitialize a disk.
+
+ @param bVolNum The volume number of the volume whose block device is being
+ uninitialized.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+*/
+REDSTATUS DiskClose(uint8_t bVolNum);
+
+/** @brief Return the disk geometry.
+
+ @param bVolNum The volume number of the volume whose block device geometry
+ is being queried.
+ @param pInfo On successful return, populated with the geometry of the
+ block device.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EIO A disk I/O or driver error occurred.
+ @retval -RED_ENOTSUPP The geometry cannot be queried on this block device.
+*/
+REDSTATUS DiskGetGeometry(uint8_t bVolNum, BDEVINFO *pInfo);
+
+/** @brief Read sectors from a disk.
+
+ @param bVolNum The volume number of the volume whose block device
+ is being read from.
+ @param ullSectorStart The starting sector number.
+ @param ulSectorCount The number of sectors to read.
+ @param pBuffer The buffer into which to read the sector data.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS DiskRead(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer);
+
+#if REDCONF_READ_ONLY == 0
+
+/** @brief Write sectors to a disk.
+
+ @param bVolNum The volume number of the volume whose block device
+ is being written to.
+ @param ullSectorStart The starting sector number.
+ @param ulSectorCount The number of sectors to write.
+ @param pBuffer The buffer from which to write the sector data.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS DiskWrite(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, const void *pBuffer);
+
+/** @brief Flush any caches beneath the file system.
+
+ @param bVolNum The volume number of the volume whose block device is being
+ flushed.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_EIO A disk I/O error occurred.
+*/
+REDSTATUS DiskFlush(uint8_t bVolNum);
+
+#endif /* REDCONF_READ_ONLY == 0 */
+
+#endif /* OSBDEV_CUSTOM_H */
A module-vfs/drivers/src/thirdparty/reedgefs/services/osclock.c => module-vfs/drivers/src/thirdparty/reedgefs/services/osclock.c +78 -0
@@ 0,0 1,78 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements real-time clock functions.
+*/
+#include <redfs.h>
+
+/** @brief Initialize the real time clock.
+
+ The behavior of calling this function when the RTC is already initialized
+ is undefined.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+*/
+REDSTATUS RedOsClockInit(void)
+{
+ return 0;
+}
+
+/** @brief Uninitialize the real time clock.
+
+ The behavior of calling this function when the RTC is not initialized is
+ undefined.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+*/
+REDSTATUS RedOsClockUninit(void)
+{
+ return 0;
+}
+
+/** @brief Get the date/time.
+
+ The behavior of calling this function when the RTC is not initialized is
+ undefined.
+
+ @return The number of seconds since January 1, 1970 excluding leap seconds
+ (in other words, standard Unix time). If the resolution or epoch
+ of the RTC is different than this, the implementation must convert
+ it to the expected representation.
+*/
+uint32_t RedOsClockGetTime(void)
+{
+ /* FreeRTOS does not provide an RTC abstraction since most of the systems
+ it targets have no RTC hardware. If your hardware includes an RTC that
+ you would like to use, this function must be customized.
+ */
+ return 0;
+}
A module-vfs/drivers/src/thirdparty/reedgefs/services/osmutex.c => module-vfs/drivers/src/thirdparty/reedgefs/services/osmutex.c +126 -0
@@ 0,0 1,126 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements a synchronization object to provide mutual exclusion.
+*/
+#include <FreeRTOS.h>
+#include <semphr.h>
+
+#include <redfs.h>
+
+#if REDCONF_TASK_COUNT > 1U
+
+static SemaphoreHandle_t xMutex;
+#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
+static StaticSemaphore_t xMutexBuffer;
+#endif
+
+/** @brief Initialize the mutex.
+
+ After initialization, the mutex is in the released state.
+
+ The behavior of calling this function when the mutex is still initialized
+ is undefined.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+*/
+REDSTATUS RedOsMutexInit(void)
+{
+ REDSTATUS ret = 0;
+
+#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
+ xMutex = xSemaphoreCreateMutexStatic(&xMutexBuffer);
+
+ if (xMutex == NULL) {
+ /* The only error case for xSemaphoreCreateMutexStatic is that the mutex
+ buffer parameter is NULL, which is not the case.
+ */
+ REDERROR();
+ ret = -RED_EINVAL;
+ }
+
+#else
+ xMutex = xSemaphoreCreateMutex();
+ if (xMutex == NULL) {
+ ret = -RED_ENOMEM;
+ }
+#endif
+
+ return ret;
+}
+
+/** @brief Uninitialize the mutex.
+
+ The behavior of calling this function when the mutex is not initialized is
+ undefined; likewise, the behavior of uninitializing the mutex when it is
+ in the acquired state is undefined.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+*/
+REDSTATUS RedOsMutexUninit(void)
+{
+ vSemaphoreDelete(xMutex);
+ xMutex = NULL;
+
+ return 0;
+}
+
+/** @brief Acquire the mutex.
+
+ The behavior of calling this function when the mutex is not initialized is
+ undefined; likewise, the behavior of recursively acquiring the mutex is
+ undefined.
+*/
+void RedOsMutexAcquire(void)
+{
+ while (xSemaphoreTake(xMutex, portMAX_DELAY) != pdTRUE) {}
+}
+
+/** @brief Release the mutex.
+
+ The behavior is undefined in the following cases:
+
+ - Releasing the mutex when the mutex is not initialized.
+ - Releasing the mutex when it is not in the acquired state.
+ - Releasing the mutex from a task or thread other than the one which
+ acquired the mutex.
+*/
+void RedOsMutexRelease(void)
+{
+ BaseType_t xSuccess;
+
+ xSuccess = xSemaphoreGive(xMutex);
+ REDASSERT(xSuccess == pdTRUE);
+ (void)xSuccess;
+}
+
+#endif
A module-vfs/drivers/src/thirdparty/reedgefs/services/osoutput.c => module-vfs/drivers/src/thirdparty/reedgefs/services/osoutput.c +55 -0
@@ 0,0 1,55 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements outputting a character string.
+*/
+#include <redfs.h>
+#include <log/log.hpp>
+
+#if REDCONF_OUTPUT == 1
+
+#include <stdio.h>
+
+/** @brief Write a string to a user-visible output location.
+
+ Write a null-terminated string to the serial port, console, terminal, or
+ other display device, such that the text is visible to the user.
+
+ @param pszString A null-terminated string.
+*/
+void RedOsOutputString(const char *pszString)
+{
+ if (pszString == NULL) {
+ REDERROR();
+ }
+ else {
+ LOG_INFO("%s", pszString);
+ }
+}
+
+#endif
A module-vfs/drivers/src/thirdparty/reedgefs/services/ostask.c => module-vfs/drivers/src/thirdparty/reedgefs/services/ostask.c +67 -0
@@ 0,0 1,67 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements task functions.
+*/
+#include <FreeRTOS.h>
+#include <task.h>
+
+#include <redfs.h>
+
+#if (REDCONF_TASK_COUNT > 1U) && (REDCONF_API_POSIX == 1)
+
+#if INCLUDE_xTaskGetCurrentTaskHandle != 1
+#error "INCLUDE_xTaskGetCurrentTaskHandle must be 1 when REDCONF_TASK_COUNT > 1 and REDCONF_API_POSIX == 1"
+#endif
+
+/** @brief Get the current task ID.
+
+ This task ID must be unique for all tasks using the file system.
+
+ @return The task ID. Must not be 0.
+*/
+uint32_t RedOsTaskId(void)
+{
+ /* Simply casting the xTaskGetCurrentTaskHandle() return value results in
+ warnings from some compilers, so use variables.
+ */
+ TaskHandle_t xTask = xTaskGetCurrentTaskHandle();
+ uintptr_t taskptr = (uintptr_t)xTask;
+ uint32_t ulTaskPtr = (uint32_t)taskptr;
+
+ /* Assert no information was lost casting from uintptr_t to uint32_t.
+ */
+ REDASSERT(ulTaskPtr == taskptr);
+
+ /* NULL is a valid task handle in FreeRTOS, so add one to all task IDs.
+ */
+ REDASSERT((ulTaskPtr + 1U) != 0U);
+ return ulTaskPtr + 1U;
+}
+
+#endif
A module-vfs/drivers/src/thirdparty/reedgefs/services/ostimestamp.c => module-vfs/drivers/src/thirdparty/reedgefs/services/ostimestamp.c +105 -0
@@ 0,0 1,105 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+ Copyright (c) 2014-2021 Tuxera US Inc.
+ All Rights Reserved Worldwide.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; use version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/* Businesses and individuals that for commercial or other reasons cannot
+ comply with the terms of the GPLv2 license must obtain a commercial license
+ before incorporating Reliance Edge into proprietary software for
+ distribution in any form. Visit http://www.datalight.com/reliance-edge for
+ more information.
+*/
+/** @file
+ @brief Implements timestamp functions.
+
+ The functionality implemented herein is not needed for the file system
+ driver, only to provide accurate results with performance tests.
+*/
+#include <FreeRTOS.h>
+#include <task.h>
+
+#include <redfs.h>
+
+/* configTICK_RATE_HZ is almost always 100, 250, 500, or 1000. If
+ 1000000U % configTICK_RATE_HZ != 0, then RedOsTimePassed() will be a
+ little inaccurate.
+*/
+#define MICROSECS_PER_TICK (1000000U / configTICK_RATE_HZ)
+
+/** @brief Initialize the timestamp service.
+
+ The behavior of invoking this function when timestamps are already
+ initialized is undefined.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+ @retval -RED_ENOSYS The timestamp service has not been implemented.
+*/
+REDSTATUS RedOsTimestampInit(void)
+{
+ return 0;
+}
+
+/** @brief Uninitialize the timestamp service.
+
+ The behavior of invoking this function when timestamps are not initialized
+ is undefined.
+
+ @return A negated ::REDSTATUS code indicating the operation result.
+
+ @retval 0 Operation was successful.
+*/
+REDSTATUS RedOsTimestampUninit(void)
+{
+ return 0;
+}
+
+/** @brief Retrieve a timestamp.
+
+ The behavior of invoking this function when timestamps are not initialized
+ is undefined
+
+ @return A timestamp which can later be passed to RedOsTimePassed() to
+ determine the amount of time which passed between the two calls.
+*/
+REDTIMESTAMP RedOsTimestamp(void)
+{
+ return xTaskGetTickCount();
+}
+
+/** @brief Determine how much time has passed since a timestamp was retrieved.
+
+ The behavior of invoking this function when timestamps are not initialized
+ is undefined.
+
+ @param tsSince A timestamp acquired earlier via RedOsTimestamp().
+
+ @return The number of microseconds which have passed since @p tsSince.
+*/
+uint64_t RedOsTimePassed(REDTIMESTAMP tsSince)
+{
+ /* This works even if the tick count has wrapped around, provided it has
+ only wrapped around once.
+ */
+ uint32_t ulTicksPassed = (uint32_t)xTaskGetTickCount() - tsSince;
+ uint64_t ullMicrosecs = (uint64_t)ulTicksPassed * MICROSECS_PER_TICK;
+
+ return ullMicrosecs;
+}
M module-vfs/include/user/purefs/blkdev/defs.hpp => module-vfs/include/user/purefs/blkdev/defs.hpp +2 -1
@@ 36,7 36,8 @@ namespace purefs::blkdev
{
sector_count, //! Number of sectors on disk or part
sector_size, //! Single sector size
- erase_block //! Number of sectors in erase block
+ erase_block, //! Number of sectors in erase block
+ start_sector //! First sector
};
//! Power control states
M module-vfs/include/user/purefs/fs/mount_point.hpp => module-vfs/include/user/purefs/fs/mount_point.hpp +1 -1
@@ 71,7 71,7 @@ namespace purefs::fs::internal
}
private:
- virtual auto native_root() const noexcept -> std::string_view = 0;
+ virtual auto native_root() const noexcept -> std::string = 0;
private:
const std::weak_ptr<blkdev::internal::disk_handle> m_diskh;
M module-vfs/src/purefs/blkdev/disk_manager.cpp => module-vfs/src/purefs/blkdev/disk_manager.cpp +9 -3
@@ 327,14 327,20 @@ namespace purefs::blkdev
LOG_ERROR("Disk doesn't exists");
return {};
}
- //! When it is partition as for partition sectors count
- if (what == info_type::sector_count && dfd->is_user_partition()) {
+ //! When it is partition ask for partition info
+ if ((what == info_type::sector_count || what == info_type::start_sector) && dfd->is_user_partition()) {
if (unsigned(dfd->partition()) >= disk->partitions().size()) {
LOG_ERROR("Partition number out of range");
return -ERANGE;
}
const auto part = disk->partitions()[dfd->partition()];
- return part.num_sectors;
+ if (what == info_type::sector_count) {
+ return part.num_sectors;
+ }
+ if (what == info_type::start_sector) {
+ return part.start_sector;
+ }
+ return {};
}
else {
return disk->get_info(what, dfd->system_partition());
M third-party/CMakeLists.txt => third-party/CMakeLists.txt +1 -0
@@ 3,6 3,7 @@
add_subdirectory(base64)
add_subdirectory(date)
+add_subdirectory(reedgefs)
add_subdirectory(fatfs)
add_subdirectory(gsl)
add_subdirectory(hash-library)
A third-party/reedgefs/CMakeLists.txt => third-party/reedgefs/CMakeLists.txt +61 -0
@@ 0,0 1,61 @@
+
+add_library(reedgefs INTERFACE)
+add_library(reliance-edge::fs ALIAS reedgefs)
+
+target_include_directories(reedgefs
+ INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/include>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/core/include>
+)
+
+target_sources( reedgefs
+ INTERFACE
+ src/bdev/bdev.c
+ src/core/driver/blockio.c
+ src/core/driver/buffer.c
+ src/core/driver/buffercmn.c
+ src/core/driver/core.c
+ src/core/driver/dir.c
+ src/core/driver/format.c
+ src/core/driver/imap.c
+ src/core/driver/imapextern.c
+ src/core/driver/imapinline.c
+ src/core/driver/inode.c
+ src/core/driver/inodedata.c
+ src/core/driver/volume.c
+ src/fse/fse.c
+ src/posix/path.c
+ src/posix/posix.c
+ src/util/bitmap.c
+ src/util/crc.c
+ src/util/endian.c
+ src/util/memory.c
+ src/util/namelen.c
+ src/util/sign.c
+ src/util/string.c
+
+ src/include/redapimacs.h
+ src/include/redbdev.h
+ src/include/redconfigchk.h
+ src/include/redcoreapi.h
+ src/include/rederrno.h
+ src/include/redexclude.h
+ src/include/redformat.h
+ src/include/redfs.h
+ src/include/redfse.h
+ src/include/redgetopt.h
+ src/include/redmacs.h
+ src/include/redmditer.h
+ src/include/redmisc.h
+ src/include/redosserv.h
+ src/include/redpath.h
+ src/include/redposix.h
+ src/include/redstat.h
+ src/include/redtests.h
+ src/include/redtestutils.h
+ src/include/redtoolcmn.h
+ src/include/redtools.h
+ src/include/redutils.h
+ src/include/redver.h
+ src/include/redvolume.h
+)
A third-party/reedgefs/src => third-party/reedgefs/src +1 -0
@@ 0,0 1,1 @@
+Subproject commit 2b939184534184dafb28575026ca76c92b37f185