M module-vfs/include/user/purefs/blkdev/disk_manager.hpp => module-vfs/include/user/purefs/blkdev/disk_manager.hpp +9 -0
@@ 8,6 8,7 @@
#include <vector>
#include <unordered_map>
#include <tuple>
+#include <optional>
#include "defs.hpp"
#include "partition.hpp"
@@ 102,6 103,14 @@ namespace purefs::blkdev
*/
[[nodiscard]] auto partitions(disk_fd dfd) const -> std::vector<partition>;
[[nodiscard]] auto partitions(std::string_view device_name) const -> std::vector<partition>;
+
+ /** Get the selected partition info
+ * @Param[in] Disk manager fd
+ * @return Partition info data
+ */
+ [[nodiscard]] auto partition_info(disk_fd dfd) const -> std::optional<partition>;
+ [[nodiscard]] auto partition_info(std::string_view device_name) const -> std::optional<partition>;
+
/** Get media device info
* @param[in] dfd Disk manager handle
* @param[in] what Information type @see info_type
M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +1 -1
@@ 163,8 163,8 @@ namespace purefs::fs
auto add_filehandle(fsfile file) noexcept -> int;
auto remove_filehandle(int fds) noexcept -> fsfile;
auto find_filehandle(int fds) const noexcept -> fsfile;
+ auto autodetect_filesystem_type(std::string_view dev_or_part) const noexcept -> std::string;
- private:
enum class iaccess : bool
{
ro, //! Syscall is RO
M module-vfs/src/purefs/blkdev/disk_manager.cpp => module-vfs/src/purefs/blkdev/disk_manager.cpp +35 -0
@@ 261,6 261,32 @@ namespace purefs::blkdev
}
return disk->partitions();
}
+ auto disk_manager::partition_info(disk_fd dfd) const -> std::optional<partition>
+ {
+ if (!dfd) {
+ LOG_ERROR("Disk handle doesn't exists");
+ return std::nullopt;
+ }
+ auto disk = dfd->disk();
+ if (!disk) {
+ LOG_ERROR("Disk doesn't exists");
+ return std::nullopt;
+ }
+ if (dfd->has_partition()) {
+ auto parts = disk->partitions();
+ if (size_t(dfd->partition()) >= parts.size()) {
+ LOG_ERROR("Partition num out of range");
+ return std::nullopt;
+ }
+ else {
+ return {parts[dfd->partition()]};
+ }
+ }
+ else {
+ LOG_ERROR("No paritions on disc");
+ return std::nullopt;
+ }
+ }
auto disk_manager::get_info(disk_fd dfd, info_type what) const -> scount_t
{
if (!dfd) {
@@ 374,6 400,14 @@ namespace purefs::blkdev
else
return {};
}
+ auto disk_manager::partition_info(std::string_view device_name) const -> std::optional<partition>
+ {
+ auto dfd = device_handle(device_name);
+ if (dfd)
+ return partition_info(dfd);
+ else
+ return std::nullopt;
+ }
auto disk_manager::get_info(std::string_view device_name, info_type what) const -> scount_t
{
auto dfd = device_handle(device_name);
@@ 395,4 429,5 @@ namespace purefs::blkdev
const auto new_name = std::get<0>(parse_device_name(disk->name()));
return std::make_shared<internal::disk_handle>(disk->disk(), new_name);
}
+
} // namespace purefs::blkdev
M module-vfs/src/purefs/fs/filesystem.cpp => module-vfs/src/purefs/fs/filesystem.cpp +46 -2
@@ 13,6 13,13 @@
namespace purefs::fs
{
+ namespace
+ {
+ constexpr std::pair<short, std::string_view> part_types_to_vfs[] = {
+ {0x0b, "vfat"},
+ {0x9e, "littlefs"},
+ };
+ }
filesystem::filesystem(std::shared_ptr<blkdev::disk_manager> diskmm)
: m_diskmm(diskmm), m_lock(new cpp_freertos::MutexRecursive)
{}
@@ 91,9 98,20 @@ namespace purefs::fs
LOG_ERROR("VFS: partition already used %.*s", int(dev_or_part.length()), dev_or_part.data());
return -EBUSY;
}
- const auto vsi = m_fstypes.find(std::string(fs_type));
+ std::string filesystem_type;
+ if (fs_type.compare("auto") == 0) {
+ filesystem_type = autodetect_filesystem_type(std::string(dev_or_part));
+ if (filesystem_type.empty()) {
+ LOG_ERROR("Unable to auto detect filesystem");
+ return -ENODEV;
+ }
+ }
+ else {
+ filesystem_type = fs_type;
+ }
+ const auto vsi = m_fstypes.find(filesystem_type);
if (vsi == std::end(m_fstypes)) {
- LOG_ERROR("VFS: requested filesystem %.*s not registered", int(fs_type.length()), fs_type.data());
+ LOG_ERROR("VFS: requested filesystem %s not registered", filesystem_type.c_str());
return -ENODEV;
}
// Trying to open disk or part by manager
@@ 263,4 281,30 @@ namespace purefs::fs
return ret;
}
+ auto filesystem::autodetect_filesystem_type(std::string_view dev_or_part) const noexcept -> std::string
+ {
+ auto disk_mgr = m_diskmm.lock();
+ if (disk_mgr) {
+ auto part = disk_mgr->partition_info(dev_or_part);
+ if (part) {
+ for (auto &ptype : part_types_to_vfs) {
+ if (ptype.first == part.value().type) {
+ const auto ret = std::string(ptype.second);
+ LOG_INFO("Autodetected filesystem type %s", ret.c_str());
+ return ret;
+ }
+ }
+ LOG_ERROR("Unable to detect filesystem type");
+ return {};
+ }
+ else {
+ LOG_ERROR("No partition on device");
+ return {};
+ }
+ }
+ else {
+ LOG_ERROR("VFS: Unable to lock device manager");
+ return {};
+ }
+ }
} // namespace purefs::fs
M module-vfs/tests/unittest_filesystem_core.cpp => module-vfs/tests/unittest_filesystem_core.cpp +16 -0
@@ 345,6 345,22 @@ TEST_CASE("Remount filesystem from RO to RW and to RO")
REQUIRE(fscore->umount("/sys") == 0);
}
+TEST_CASE("Autodetect filesystems")
+{
+ using namespace purefs;
+ auto dm = std::make_shared<blkdev::disk_manager>();
+ auto disk = std::make_shared<blkdev::disk_image>(disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm->register_device(disk, "emmc0") == 0);
+ auto fscore = std::make_shared<purefs::fs::filesystem>(dm);
+ const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
+ REQUIRE(vfs_vfat->mount_count() == 0);
+ auto ret = fscore->register_filesystem("vfat", vfs_vfat);
+ REQUIRE(ret == 0);
+ REQUIRE(fscore->mount("emmc0part0", "/sys", "auto") == 0);
+ REQUIRE(fscore->umount("/sys") == 0);
+}
+
TEST_CASE("Unititest integrated subsystem")
{
auto [disk, vfs] = purefs::subsystem::initialize();