Kernel/Ext2: Write superblock backups
We don't ever read them out, but this should make fsck a lot less mad.
This commit is contained in:
parent
cc1cb72fb5
commit
a0705202ea
Notes:
sideshowbarker
2024-07-17 05:05:51 +09:00
Author: https://github.com/kleinesfilmroellchen Commit: https://github.com/SerenityOS/serenity/commit/a0705202ea Pull-request: https://github.com/SerenityOS/serenity/pull/20086 Reviewed-by: https://github.com/gmta ✅
4 changed files with 54 additions and 2 deletions
|
@ -54,4 +54,18 @@ constexpr I pow(I base, I exponent)
|
|||
return res;
|
||||
}
|
||||
|
||||
template<auto base, Unsigned U = decltype(base)>
|
||||
constexpr bool is_power_of(U x)
|
||||
{
|
||||
if constexpr (base == 2)
|
||||
return is_power_of_two(x);
|
||||
|
||||
// FIXME: I am naive! A log2-based approach (pow<U>(base, (log2(x) / log2(base))) == x) does not work due to rounding errors.
|
||||
for (U exponent = 0; exponent <= log2(x) / log2(base) + 1; ++exponent) {
|
||||
if (pow<U>(base, exponent) == x)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/IntegralMath.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/FileSystem/Ext2FS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/Ext2FS/Inode.h>
|
||||
|
@ -30,7 +31,23 @@ ErrorOr<void> Ext2FS::flush_super_block()
|
|||
MutexLocker locker(m_lock);
|
||||
VERIFY((sizeof(ext2_super_block) % logical_block_size()) == 0);
|
||||
auto super_block_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&m_super_block);
|
||||
return raw_write_blocks(2, (sizeof(ext2_super_block) / logical_block_size()), super_block_buffer);
|
||||
auto const superblock_physical_block_count = (sizeof(ext2_super_block) / logical_block_size());
|
||||
|
||||
// First superblock is always at offset 1024 (physical block index 2).
|
||||
TRY(raw_write_blocks(2, superblock_physical_block_count, super_block_buffer));
|
||||
|
||||
auto is_sparse = has_flag(get_features_readonly(), FeaturesReadOnly::SparseSuperblock);
|
||||
|
||||
for (auto group = 1u; group < m_block_group_count; ++group) {
|
||||
auto first_block_in_group = first_block_of_group(group);
|
||||
// Superblock copies with sparse layout are in group number 2 and powers of 3, 5, and 7.
|
||||
if (!is_sparse || group == 2 || AK::is_power_of<3>(group - 1) || AK::is_power_of<5>(group - 1) || AK::is_power_of<7>(group - 1)) {
|
||||
dbgln_if(EXT2_DEBUG, "Writing superblock backup to block group {} (block {})", group, first_block_in_group);
|
||||
TRY(write_blocks(first_block_in_group, 1, super_block_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
ext2_group_desc const& Ext2FS::group_descriptor(GroupIndex group_index) const
|
||||
|
|
|
@ -22,10 +22,13 @@ class Ext2FS final : public BlockBasedFileSystem {
|
|||
friend class Ext2FSInode;
|
||||
|
||||
public:
|
||||
// s_feature_ro_compat
|
||||
enum class FeaturesReadOnly : u32 {
|
||||
None = 0,
|
||||
FileSize64bits = 1 << 1,
|
||||
SparseSuperblock = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
|
||||
FileSize64bits = EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
|
||||
};
|
||||
AK_ENUM_BITWISE_FRIEND_OPERATORS(FeaturesReadOnly);
|
||||
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> try_create(OpenFileDescription&, ReadonlyBytes);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <LibTest/TestCase.h>
|
||||
|
||||
#include <AK/IntegralMath.h>
|
||||
#include <initializer_list>
|
||||
|
||||
TEST_CASE(pow)
|
||||
{
|
||||
|
@ -18,3 +19,20 @@ TEST_CASE(pow)
|
|||
EXPECT_EQ(AK::pow<u64>(10, 5), 100'000ull);
|
||||
EXPECT_EQ(AK::pow<u64>(10, 6), 1'000'000ull);
|
||||
}
|
||||
|
||||
TEST_CASE(is_power_of)
|
||||
{
|
||||
constexpr auto check_prime = []<u64 prime>(u64 limit) {
|
||||
for (u64 power = 0; power < limit; ++power)
|
||||
EXPECT(AK::is_power_of<prime>(AK::pow(prime, power)));
|
||||
};
|
||||
|
||||
// Limits calculated as floor( log_{prime}(2^64) ) to prevent overflows.
|
||||
check_prime.operator()<2>(64);
|
||||
check_prime.operator()<3>(40);
|
||||
check_prime.operator()<5>(27);
|
||||
check_prime.operator()<7>(20);
|
||||
check_prime.operator()<11>(18);
|
||||
check_prime.operator()<97>(9);
|
||||
check_prime.operator()<257>(7);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue