M enabled_unittests => enabled_unittests +1 -0
@@ 423,6 423,7 @@ TESTS_LIST["catch2-vfs-disk"]="
Null pointer passed to disk manager functions;
Boundary checks for partitions;
Disk sectors out of range for partition;
+ Alternative partitions in the disk manager;
"
#---------
TESTS_LIST["catch2-vfs-littlefs"]="
M module-vfs/board/linux/purefs/include/purefs/blkdev/disk_image.hpp => module-vfs/board/linux/purefs/include/purefs/blkdev/disk_image.hpp +15 -9
@@ 1,16 1,21 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// 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/blkdev/disk.hpp>
#include <mutex>
+#include <array>
namespace purefs::blkdev
{
class disk_image final : public disk
{
static constexpr auto sector_size = 512UL;
+ static constexpr auto invalid_fd = -1;
+ static constexpr auto syspart_count = 8U;
+ static constexpr auto syspart_size = 256UL * 1024UL * 1024UL;
+ static constexpr auto syspart_sectors = syspart_size / sector_size;
public:
disk_image(std::string_view image_filename);
@@ 20,18 25,19 @@ namespace purefs::blkdev
private:
auto probe(unsigned flags) -> int override;
auto cleanup() -> int override;
- auto write(const void *buf, sector_t lba, std::size_t count) -> int override;
- auto read(void *buf, sector_t lba, std::size_t count) -> int override;
+ auto write(const void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int override;
+ auto read(void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int override;
auto sync() -> int override;
auto status() const -> media_status override;
- auto get_info(info_type what) const -> scount_t override;
- auto erase(sector_t lba, std::size_t count) -> int override;
- auto range_valid(sector_t lba, std::size_t count) const -> bool;
+ auto get_info(info_type what, hwpart_t hwpart) const -> scount_t override;
+ auto erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int override;
+ auto range_valid(sector_t lba, std::size_t count, hwpart_t hwpart) const -> bool;
+ auto open_and_truncate(hwpart_t hwpart) -> int;
private:
- int m_filedes{-1};
- unsigned long m_sectors{0};
- std::string m_image_name;
+ std::array<int, syspart_count> m_filedes;
+ std::array<unsigned long, syspart_count> m_sectors;
+ const std::string m_image_name;
mutable std::recursive_mutex m_mtx;
};
} // namespace purefs::blkdev
M module-vfs/board/linux/purefs/src/blkdev/disk_image.cpp => module-vfs/board/linux/purefs/src/blkdev/disk_image.cpp +89 -36
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/blkdev/disk_image.hpp>
#include <fcntl.h>
@@ 11,49 11,60 @@ namespace purefs::blkdev
{
disk_image::disk_image(std::string_view image_filename) : m_image_name(image_filename)
- {}
+ {
+ m_filedes.fill(invalid_fd);
+ std::fill(m_sectors.begin() + 1, m_sectors.end(), syspart_sectors);
+ m_sectors[0] = 0;
+ }
auto disk_image::probe(unsigned int flags) -> int
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
- m_filedes = ::open(m_image_name.c_str(), O_RDWR, O_SYNC);
- if (!m_filedes)
- return m_filedes;
+ m_filedes[0] = ::open(m_image_name.c_str(), O_RDWR | O_SYNC);
+ if (!m_filedes[0])
+ return m_filedes[0];
struct stat fst;
- auto ret = ::fstat(m_filedes, &fst);
+ auto ret = ::fstat(m_filedes[0], &fst);
if (ret < 0) {
return -errno;
}
- m_sectors = fst.st_size / sector_size;
+ m_sectors[0] = fst.st_size / sector_size;
return fst.st_size % sector_size;
}
+
auto disk_image::cleanup() -> int
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
- int ret{-EBADFD};
- if (m_filedes) {
- if (m_filedes) {
- ret = ::close(m_filedes);
+ int ret{};
+ for (auto &fd : m_filedes)
+ if (fd > 0) {
+ ret = ::close(fd);
if (ret < 0)
- ret = -errno;
+ return -errno;
+ else
+ fd = invalid_fd;
}
- }
return ret;
}
- auto disk_image::write(const void *buf, sector_t lba, std::size_t count) -> int
+
+ auto disk_image::write(const void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
- if (!range_valid(lba, count)) {
+ if (!range_valid(lba, count, hwpart)) {
return -ERANGE;
}
- auto offs = ::lseek64(m_filedes, off64_t(lba) * off64_t(sector_size), SEEK_SET);
+ const int err = open_and_truncate(hwpart);
+ if (err) {
+ return err;
+ }
+ auto offs = ::lseek64(m_filedes[hwpart], off64_t(lba) * off64_t(sector_size), SEEK_SET);
if (offs < 0) {
return offs;
}
auto to_write = count * sector_size;
auto buf_b = reinterpret_cast<const uint8_t *>(buf);
do {
- auto ret = ::write(m_filedes, buf_b, to_write);
+ auto ret = ::write(m_filedes[hwpart], buf_b, to_write);
if (ret < 0) {
return -errno;
}
@@ 62,26 73,32 @@ namespace purefs::blkdev
} while (to_write > 0);
return 0;
}
- auto disk_image::erase(sector_t lba, std::size_t count) -> int
+
+ auto disk_image::erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
std::unique_ptr<char[]> buf(new char[count * sector_size]);
std::memset(buf.get(), 0xff, count * sector_size);
- return write(buf.get(), lba, count);
+ return write(buf.get(), lba, count, hwpart);
}
- auto disk_image::read(void *buf, sector_t lba, std::size_t count) -> int
+
+ auto disk_image::read(void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
- if (!range_valid(lba, count)) {
+ if (!range_valid(lba, count, hwpart)) {
return -ERANGE;
}
- auto offs = ::lseek64(m_filedes, off64_t(lba) * off64_t(sector_size), SEEK_SET);
+ const int err = open_and_truncate(hwpart);
+ if (err) {
+ return err;
+ }
+ auto offs = ::lseek64(m_filedes[hwpart], off64_t(lba) * off64_t(sector_size), SEEK_SET);
if (offs < 0) {
return offs;
}
auto to_read = count * sector_size;
auto buf_b = reinterpret_cast<uint8_t *>(buf);
do {
- auto ret = ::read(m_filedes, buf_b, to_read);
+ auto ret = ::read(m_filedes[hwpart], buf_b, to_read);
if (ret < 0) {
return -errno;
}
@@ 90,42 107,78 @@ namespace purefs::blkdev
} while (to_read > 0);
return 0;
}
+
auto disk_image::sync() -> int
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
- int ret{-EBADFD};
- if (m_filedes) {
- ret = fsync(m_filedes);
- if (ret < 0)
- ret = -errno;
- }
+ int ret{};
+ for (auto fd : m_filedes)
+ if (fd > 0) {
+ ret = fsync(fd);
+ if (ret < 0)
+ return -errno;
+ }
return ret;
}
+
auto disk_image::status() const -> media_status
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
struct stat st;
- auto ret = ::stat(m_image_name.c_str(), &st);
- if (!ret)
+ const auto ret = ::stat(m_image_name.c_str(), &st);
+ if (ret < 0)
return media_status::nomedia;
else
return media_status::healthly;
}
- auto disk_image::get_info(info_type what) const -> scount_t
+
+ auto disk_image::get_info(info_type what, hwpart_t hwpart) const -> scount_t
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
+ if (hwpart >= syspart_count) {
+ return -ERANGE;
+ }
switch (what) {
case info_type::sector_size:
return sector_size;
case info_type::sector_count:
- return m_sectors;
+ return m_sectors[hwpart];
case info_type::erase_block:
return 1;
}
- return -1;
+ return -ENOTSUP;
}
- auto disk_image::range_valid(sector_t lba, std::size_t count) const -> bool
+
+ auto disk_image::range_valid(sector_t lba, std::size_t count, hwpart_t hwpart) const -> bool
{
- return (lba < m_sectors) && ((lba + count) < m_sectors);
+ return (hwpart < syspart_count) && (lba < m_sectors[hwpart]) && ((lba + count) < m_sectors[hwpart]);
+ }
+
+ auto disk_image::disk_image::open_and_truncate(hwpart_t hwpart) -> int
+ {
+ if (hwpart >= syspart_count) {
+ return -ERANGE;
+ }
+ if (hwpart == 0 || m_filedes[hwpart] > 0) {
+ return 0;
+ }
+ using namespace std::string_literals;
+ const auto alt_filename = m_image_name + "."s + std::to_string(hwpart);
+ m_filedes[hwpart] = ::open(alt_filename.c_str(), O_RDWR | O_CREAT | O_SYNC, 0644);
+ if (m_filedes[hwpart] < 0) {
+ return -errno;
+ }
+ struct stat fst;
+ auto ret = ::fstat(m_filedes[hwpart], &fst);
+ if (ret < 0) {
+ return -errno;
+ }
+ if (static_cast<unsigned long>(fst.st_size) < m_sectors[hwpart] * sector_size) {
+ ret = ::ftruncate(m_filedes[hwpart], syspart_size);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+ return 0;
}
} // namespace purefs::blkdev
M module-vfs/board/rt1051/purefs/include/purefs/blkdev/disk_emmc.hpp => module-vfs/board/rt1051/purefs/include/purefs/blkdev/disk_emmc.hpp +9 -4
@@ 6,6 6,7 @@
#include <purefs/blkdev/disk.hpp>
#include <mutex.hpp>
#include <memory>
+#include <atomic>
#if !defined(TARGET_RT1051)
static_assert(false, "Unsupported target.");
@@ 26,16 27,20 @@ namespace purefs::blkdev
auto probe(unsigned flags) -> int override;
auto cleanup() -> int override;
- auto write(const void *buf, sector_t lba, std::size_t count) -> int override;
- auto read(void *buf, sector_t lba, std::size_t count) -> int override;
+ auto write(const void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int override;
+ auto read(void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int override;
auto sync() -> int override;
auto status() const -> media_status override;
- auto get_info(info_type what) const -> scount_t override;
- auto erase(sector_t lba, std::size_t count) -> int override;
+ auto get_info(info_type what, hwpart_t hwpart) const -> scount_t override;
+ auto erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int override;
+
+ private:
+ auto switch_partition(hwpart_t newpart) -> int;
private:
int initStatus;
std::unique_ptr<_mmc_card> mmcCard;
mutable cpp_freertos::MutexRecursive mutex;
+ std::atomic<hwpart_t> currHwPart{0};
};
} // namespace purefs::blkdev
M module-vfs/board/rt1051/purefs/src/blkdev/disk_emmc.cpp => module-vfs/board/rt1051/purefs/src/blkdev/disk_emmc.cpp +43 -8
@@ 47,32 47,40 @@ namespace purefs::blkdev
return statusBlkDevSuccess;
}
- auto disk_emmc::write(const void *buf, sector_t lba, std::size_t count) -> int
+ auto disk_emmc::write(const void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
cpp_freertos::LockGuard lock(mutex);
if (!mmcCard->isHostReady || buf == nullptr) {
return statusBlkDevFail;
}
- auto err = MMC_WriteBlocks(mmcCard.get(), static_cast<const uint8_t *>(buf), lba, count);
+ auto err = switch_partition(hwpart);
+ if (err != kStatus_Success) {
+ return err;
+ }
+ err = MMC_WriteBlocks(mmcCard.get(), static_cast<const uint8_t *>(buf), lba, count);
if (err != kStatus_Success) {
return err;
}
return statusBlkDevSuccess;
}
- auto disk_emmc::erase(sector_t lba, std::size_t count) -> int
+ auto disk_emmc::erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
// erase group size is 512kB so it has been deliberately disallowed
// group of this size would make the solution inefficient in this case
return statusBlkDevSuccess;
}
- auto disk_emmc::read(void *buf, sector_t lba, std::size_t count) -> int
+ auto disk_emmc::read(void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
cpp_freertos::LockGuard lock(mutex);
if (!mmcCard->isHostReady || buf == nullptr) {
return statusBlkDevFail;
}
- auto err = MMC_ReadBlocks(mmcCard.get(), static_cast<uint8_t *>(buf), lba, count);
+ auto err = switch_partition(hwpart);
+ if (err != kStatus_Success) {
+ return err;
+ }
+ err = MMC_ReadBlocks(mmcCard.get(), static_cast<uint8_t *>(buf), lba, count);
if (err != kStatus_Success) {
return err;
}
@@ 110,18 118,45 @@ namespace purefs::blkdev
return media_status::healthly;
}
- auto disk_emmc::get_info(info_type what) const -> scount_t
+ auto disk_emmc::get_info(info_type what, hwpart_t hwpart) const -> scount_t
{
cpp_freertos::LockGuard lock(mutex);
switch (what) {
case info_type::sector_size:
return mmcCard->blockSize;
case info_type::sector_count:
- return mmcCard->userPartitionBlocks;
+ switch (hwpart) {
+ case kMMC_AccessPartitionUserArea:
+ return mmcCard->userPartitionBlocks;
+ case kMMC_AccessPartitionBoot1:
+ case kMMC_AccessPartitionBoot2:
+ return mmcCard->bootPartitionBlocks;
+ default:
+ return mmcCard->systemPartitionBlocks;
+ }
case info_type::erase_block:
// not supported
return 0;
}
- return -1;
+ return -ENOTSUP;
}
+
+ auto disk_emmc::switch_partition(hwpart_t newpart) -> int
+ {
+ if (newpart > kMMC_AccessGeneralPurposePartition4) {
+ return -ERANGE;
+ }
+ int ret{};
+ if (newpart != currHwPart) {
+ ret = MMC_SelectPartition(mmcCard.get(), static_cast<mmc_access_partition_t>(newpart));
+ if (ret == kStatus_Success) {
+ currHwPart = newpart;
+ }
+ else {
+ LOG_ERROR("Unable to switch partition err %i", ret);
+ }
+ }
+ return ret;
+ }
+
} // namespace purefs::blkdev
M module-vfs/include/internal/purefs/blkdev/disk_handle.hpp => module-vfs/include/internal/purefs/blkdev/disk_handle.hpp +36 -5
@@ 5,6 5,7 @@
#include <memory>
#include <string>
+#include <limits>
#include <purefs/blkdev/defs.hpp>
namespace purefs::blkdev
@@ 17,11 18,41 @@ namespace purefs::blkdev::internal
class disk_handle
{
+ static constexpr part_t no_partition = -1;
+ static constexpr auto hw_partition_first = std::numeric_limits<part_t>::max() / 2;
+
public:
- static constexpr auto no_partition = -1;
- explicit disk_handle(std::weak_ptr<blkdev::disk> disk, std::string_view name, short partition = no_partition)
+ static constexpr auto to_syspart_num(part_t part) -> part_t
+ {
+ return part + hw_partition_first;
+ }
+ static auto is_any_partition(part_t part) noexcept -> bool
+ {
+ return part >= 0;
+ }
+ static auto is_system_partition(part_t part) noexcept -> bool
+ {
+ return part >= hw_partition_first;
+ }
+ static auto is_user_partition(part_t part) noexcept -> bool
+ {
+ return is_any_partition(part) && !is_system_partition(part);
+ }
+ explicit disk_handle(std::weak_ptr<blkdev::disk> disk, std::string_view name, part_t partition = no_partition)
: m_disk(disk), m_partition(partition), m_name(name)
{}
+ auto is_any_partition() const noexcept -> bool
+ {
+ return is_any_partition(m_partition);
+ }
+ auto is_system_partition() const noexcept -> bool
+ {
+ return is_system_partition(m_partition);
+ }
+ auto is_user_partition() const noexcept -> bool
+ {
+ return is_user_partition(m_partition);
+ }
auto disk() const noexcept
{
return m_disk.lock();
@@ 30,9 61,9 @@ namespace purefs::blkdev::internal
{
return m_partition;
}
- auto has_partition() const noexcept -> bool
+ auto system_partition() const noexcept -> int
{
- return m_partition != no_partition;
+ return (m_partition >= hw_partition_first) ? (m_partition - hw_partition_first + 1) : (0);
}
auto sectors() const noexcept -> sector_t;
auto name() const noexcept
@@ 42,7 73,7 @@ namespace purefs::blkdev::internal
private:
const std::weak_ptr<blkdev::disk> m_disk;
- const short m_partition{-1};
+ const part_t m_partition{no_partition};
mutable sector_t m_sectors{0};
const std::string m_name;
};
M module-vfs/include/user/purefs/blkdev/defs.hpp => module-vfs/include/user/purefs/blkdev/defs.hpp +9 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 7,8 7,16 @@
namespace purefs::blkdev
{
+ //! Unsigned sector type
using sector_t = uint64_t;
+ //! Signed sector type
using scount_t = int64_t;
+ //! Hardware partition type
+ using hwpart_t = uint8_t;
+ //! Common partition type
+ using part_t = int16_t;
+ //! Default hardware partition
+ constexpr hwpart_t default_hw_partition = 0;
namespace internal
{
class disk_handle;
M module-vfs/include/user/purefs/blkdev/disk.hpp => module-vfs/include/user/purefs/blkdev/disk.hpp +12 -9
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 11,9 11,9 @@ namespace purefs::blkdev
class disk
{
public:
+ disk() = default;
disk(const disk &) = delete;
auto operator=(const disk &) = delete;
- disk() = default;
virtual ~disk() = default;
/** Initialize the disk this method is called by the disc manager
@@ 30,25 30,28 @@ namespace purefs::blkdev
/** Write a data onto block device or partition
* @param[in] buf Data buffer to write
* @param[in] lba First sector
- * @param[in] Count sectors count
+ * @param[in] count sectors count
+ * @param[in] hwpart Hardware partition
* @return zero on success otherwise error
*/
- virtual auto write(const void *buf, sector_t lba, std::size_t count) -> int = 0;
+ virtual auto write(const void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int = 0;
/** Read a data from block device or partition
* @param[in] buf Data buffer for read
* @param[in] lba First sector
- * @param[in] Count sectors count
+ * @param[in] count sectors count
+ * @param[in] hwpart Hardware partition
* @return zero on success otherwise error
*/
- virtual auto read(void *buf, sector_t lba, std::size_t count) -> int = 0;
+ virtual auto read(void *buf, sector_t lba, std::size_t count, hwpart_t hwpart) -> int = 0;
/** Erase selected area on the block device or partition
* @param[in] lba First sector to erase
* @param[in] count Sectors count for erase
+ * @param[in] hwpart Hardware partition
* @return zero or success otherwise error
*/
- virtual auto erase(sector_t lba, std::size_t count) -> int;
+ virtual auto erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int;
/** Flush buffers and write all data into the physical device
* @return zero or success otherwise error
@@ 77,9 80,10 @@ namespace purefs::blkdev
/** List the partitions on the underlaying device
* @param[in] device_name Block device name
+ * @param[in] hwpart Hardware partition
* @return Partition list @see partition
*/
- [[nodiscard]] virtual auto get_info(info_type what) const -> scount_t = 0;
+ [[nodiscard]] virtual auto get_info(info_type what, hwpart_t hwpart) const -> scount_t = 0;
/** List the partitions on the underlaying device
* @param[in] device_name Block device name
@@ 90,7 94,6 @@ namespace purefs::blkdev
return m_partitions;
}
- protected:
/** Clear all partitions */
auto clear_partitions() -> void
{
M module-vfs/include/user/purefs/blkdev/disk_manager.hpp => module-vfs/include/user/purefs/blkdev/disk_manager.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 139,7 139,7 @@ namespace purefs::blkdev
static auto disk_handle_from_partition_handle(disk_fd disk) -> disk_fd;
private:
- static auto parse_device_name(std::string_view device) -> std::tuple<std::string_view, short>;
+ static auto parse_device_name(std::string_view device) -> std::tuple<std::string_view, part_t>;
static auto part_lba_to_disk_lba(disk_fd disk, sector_t part_lba, size_t count) -> scount_t;
private:
M module-vfs/src/purefs/blkdev/disk.cpp => module-vfs/src/purefs/blkdev/disk.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/blkdev/disk.hpp>
@@ 6,7 6,7 @@
namespace purefs::blkdev
{
- auto disk::erase(sector_t lba, std::size_t count) -> int
+ auto disk::erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
return -ENOTSUP;
}
M module-vfs/src/purefs/blkdev/disk_handle.cpp => module-vfs/src/purefs/blkdev/disk_handle.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/blkdev/disk_handle.hpp>
#include <purefs/blkdev/disk.hpp>
@@ 11,7 11,7 @@ namespace purefs::blkdev::internal
if (!m_sectors) {
auto pdisk = m_disk.lock();
if (pdisk) {
- const auto sector_count = pdisk->get_info(info_type::sector_count);
+ const auto sector_count = pdisk->get_info(info_type::sector_count, system_partition());
if (sector_count > 0) {
m_sectors = sector_count;
}
M module-vfs/src/purefs/blkdev/disk_manager.cpp => module-vfs/src/purefs/blkdev/disk_manager.cpp +36 -26
@@ 19,6 19,7 @@ namespace purefs::blkdev
{
using namespace std::literals;
static constexpr auto part_suffix = "part"sv;
+ static constexpr auto syspart_suffix = "sys"sv;
} // namespace
disk_manager::disk_manager() : m_lock(std::make_unique<cpp_freertos::MutexRecursive>())
@@ 80,7 81,7 @@ namespace purefs::blkdev
}
else {
ret = std::make_shared<internal::disk_handle>(it->second, device_name, part);
- if (part != internal::disk_handle::no_partition) {
+ if (internal::disk_handle::is_user_partition(part)) {
if (part >= int(partitions(ret).size())) {
LOG_ERROR("Partition %i doesn't exists", part);
ret = nullptr;
@@ 91,19 92,26 @@ namespace purefs::blkdev
return ret;
}
- auto disk_manager::parse_device_name(std::string_view device) -> std::tuple<std::string_view, short>
+ auto disk_manager::parse_device_name(std::string_view device) -> std::tuple<std::string_view, part_t>
{
- auto ret = device.rfind(part_suffix);
- if (ret != std::string::npos) {
- auto part_name = device.substr(0, ret);
- auto part_num = device.substr(ret + part_suffix.length());
- short part_inum{-1};
+ const auto parti = device.rfind(part_suffix);
+ const auto sysparti = device.rfind(syspart_suffix);
+ if ((parti != std::string::npos) != (sysparti != std::string::npos)) {
+ const auto si = (parti != std::string::npos) ? (parti) : (sysparti);
+ const auto sl = (parti != std::string::npos) ? (part_suffix.length()) : (syspart_suffix.length());
+ const auto part_name = device.substr(0, si);
+ const auto part_num = device.substr(si + sl);
+ part_t part_inum{-1};
if (!part_num.empty()) {
- auto ires = std::from_chars(std::begin(part_num), std::end(part_num), part_inum);
- if (ires.ec == std::errc())
+ const auto ires = std::from_chars(std::begin(part_num), std::end(part_num), part_inum);
+ if (ires.ec == std::errc()) {
+ if (sysparti != std::string::npos)
+ part_inum = internal::disk_handle::to_syspart_num(part_inum);
return std::make_tuple(part_name, part_inum);
- else
+ }
+ else {
return std::make_tuple(""sv, -1);
+ }
}
else {
return std::make_tuple(part_name, part_inum);
@@ 115,18 123,10 @@ namespace purefs::blkdev
}
auto disk_manager::part_lba_to_disk_lba(disk_fd disk, sector_t part_lba, size_t count) -> scount_t
{
- if (!disk->has_partition()) {
- if (part_lba + count > disk->sectors()) {
- LOG_ERROR("Disk sector req out of range");
- return -ERANGE;
- }
- else {
- return part_lba;
- }
- }
- else {
+ if (disk->is_user_partition()) {
auto pdisc = disk->disk();
if (!pdisc) {
+ LOG_ERROR("Unable to lock disk");
return -EIO;
}
const auto part = pdisc->partitions()[disk->partition()];
@@ 138,6 138,15 @@ namespace purefs::blkdev
return part_lba + part.start_sector;
}
}
+ else {
+ if (part_lba + count > disk->sectors()) {
+ LOG_ERROR("Disk sector req out of range");
+ return -ERANGE;
+ }
+ else {
+ return part_lba;
+ }
+ }
}
auto disk_manager::write(disk_fd dfd, const void *buf, sector_t lba, std::size_t count) -> int
{
@@ 155,7 164,7 @@ namespace purefs::blkdev
return calc_lba;
}
else {
- return disk->write(buf, calc_lba, count);
+ return disk->write(buf, calc_lba, count, dfd->system_partition());
}
}
auto disk_manager::read(disk_fd dfd, void *buf, sector_t lba, std::size_t count) -> int
@@ 174,7 183,7 @@ namespace purefs::blkdev
return calc_lba;
}
else {
- return disk->read(buf, calc_lba, count);
+ return disk->read(buf, calc_lba, count, dfd->system_partition());
}
}
auto disk_manager::erase(disk_fd dfd, sector_t lba, std::size_t count) -> int
@@ 193,7 202,7 @@ namespace purefs::blkdev
return calc_lba;
}
else {
- return disk->erase(calc_lba, count);
+ return disk->erase(calc_lba, count, dfd->system_partition());
}
}
auto disk_manager::sync(disk_fd dfd) -> int
@@ 272,7 281,7 @@ namespace purefs::blkdev
LOG_ERROR("Disk doesn't exists");
return std::nullopt;
}
- if (dfd->has_partition()) {
+ if (dfd->is_user_partition()) {
auto parts = disk->partitions();
if (size_t(dfd->partition()) >= parts.size()) {
LOG_ERROR("Partition num out of range");
@@ 299,7 308,7 @@ namespace purefs::blkdev
return {};
}
//! When it is partition as for partition sectors count
- if (what == info_type::sector_count && dfd->has_partition()) {
+ if (what == info_type::sector_count && dfd->is_user_partition()) {
if (unsigned(dfd->partition()) >= disk->partitions().size()) {
LOG_ERROR("Partition number out of range");
return -ERANGE;
@@ 308,7 317,7 @@ namespace purefs::blkdev
return part.num_sectors;
}
else {
- return disk->get_info(what);
+ return disk->get_info(what, dfd->system_partition());
}
}
auto disk_manager::reread_partitions(disk_fd dfd) -> int
@@ 322,6 331,7 @@ namespace purefs::blkdev
LOG_ERROR("Disk doesn't exists");
return {};
}
+ disk->clear_partitions();
internal::partition_parser pparser(disk, disk->partitions());
auto ret = pparser.partition_search();
// Fill the partition name
M module-vfs/src/purefs/blkdev/partition_parser.cpp => module-vfs/src/purefs/blkdev/partition_parser.cpp +7 -7
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/blkdev/partition_parser.hpp>
@@ 48,13 48,13 @@ namespace purefs::blkdev::internal
// Partition search
auto partition_parser::partition_search() -> int
{
- const auto sect_size = m_disk->get_info(info_type::sector_size);
+ const auto sect_size = m_disk->get_info(info_type::sector_size, 0);
if (sect_size < 0) {
LOG_ERROR("Unable to get sector size");
return sect_size;
}
std::vector<std::uint8_t> mbr_sect(sect_size);
- auto ret = m_disk->read(mbr_sect.data(), 0, 1);
+ auto ret = m_disk->read(mbr_sect.data(), 0, 1, 0);
if (ret < 0) {
return ret;
}
@@ 94,8 94,8 @@ namespace purefs::blkdev::internal
auto partition_parser::check_partition(const std::shared_ptr<disk> disk, const partition &part) -> bool
{
- auto sector_size = disk->get_info(info_type::sector_size);
- const auto this_size = uint64_t(disk->get_info(info_type::sector_count)) * uint64_t(sector_size);
+ auto sector_size = disk->get_info(info_type::sector_size, 0);
+ const auto this_size = uint64_t(disk->get_info(info_type::sector_count, 0)) * uint64_t(sector_size);
const auto poffset = uint64_t(part.start_sector) * uint64_t(sector_size);
const auto psize = uint64_t(part.num_sectors) * uint64_t(sector_size);
const auto pnext = uint64_t(part.start_sector) * uint64_t(sector_size) + poffset;
@@ 133,7 133,7 @@ namespace purefs::blkdev::internal
auto partition_parser::parse_extended(uint32_t lba, uint32_t count) -> int
{
static constexpr auto max_parts{100};
- auto sector_size = m_disk->get_info(info_type::sector_size);
+ auto sector_size = m_disk->get_info(info_type::sector_size, 0);
int extended_part_num;
std::array<partition, defs::num_parts> parts;
auto current_sector = lba;
@@ 149,7 149,7 @@ namespace purefs::blkdev::internal
while (try_count--) {
if (sector_in_buf != current_sector) {
LOG_INFO("extended parse: Read sector %u\n", unsigned(current_sector));
- error = m_disk->read(sect_buf.data(), current_sector, 1);
+ error = m_disk->read(sect_buf.data(), current_sector, 1, 0);
if (error < 0)
break;
sector_in_buf = current_sector;
M module-vfs/tests/unittest_disk_manager.cpp => module-vfs/tests/unittest_disk_manager.cpp +32 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// 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>
@@ 105,6 105,37 @@ TEST_CASE("RW boundary checking")
REQUIRE(buf1 == buf2);
}
+TEST_CASE("Alternative partitions in the disk manager")
+{
+ using namespace purefs;
+ blkdev::disk_manager dm;
+ auto disk = std::make_shared<blkdev::disk_image>(disk_image);
+ REQUIRE(disk);
+ REQUIRE(dm.register_device(disk, "emmc0") == 0);
+ const auto sect_size = dm.get_info("emmc0", blkdev::info_type::sector_size);
+ const auto sect_size1 = dm.get_info("emmc0sys1", blkdev::info_type::sector_size);
+ REQUIRE(sect_size > 0);
+ REQUIRE(sect_size == sect_size1);
+ const auto sect_count = dm.get_info("emmc0sys1", blkdev::info_type::sector_count);
+ REQUIRE(sect_count == (256L * 1024L * 1024L) / sect_size);
+ const auto sect_count1 = dm.get_info("emmc0", blkdev::info_type::sector_count);
+ REQUIRE(sect_count1 > sect_count);
+ std::vector<char> buf1(sect_size, 0);
+ REQUIRE(dm.read("emmc0", buf1.data(), 0, 1) == 0);
+ std::vector<char> buf2(sect_size, 0xAA);
+ REQUIRE(dm.write("emmc0sys1", buf2.data(), 0, 1) == 0);
+ std::fill(std::begin(buf2), std::end(buf2), 0xBB);
+ REQUIRE(dm.write("emmc0sys0", buf2.data(), 0, 1) == 0);
+ REQUIRE(dm.read("emmc0", buf2.data(), 0, 1) == 0);
+ REQUIRE(buf1 == buf2);
+ std::fill(std::begin(buf2), std::end(buf2), 0xAA);
+ REQUIRE(dm.read("emmc0sys1", buf1.data(), 0, 1) == 0);
+ REQUIRE(buf1 == buf2);
+ std::fill(std::begin(buf2), std::end(buf2), 0xBB);
+ REQUIRE(dm.read("emmc0sys0", buf1.data(), 0, 1) == 0);
+ REQUIRE(buf1 == buf2);
+}
+
TEST_CASE("Null pointer passed to disk manager functions")
{
using namespace purefs;