Skip to content

Commit 6dd7079

Browse files
committed
Fix sanity_check to handle first boot and distinguish header corruption
On first boot (format_devices path), all devices have invalid headers on disk when PhysicalDev is constructed — before write_super_block is called. The original code blindly memcmp'd header vs footer on garbage data, causing a crash on HDD devices where mirror_super_block=1. In load_devices, a device with an invalid header goes to pdevs_to_format and then format_single_device. At that point m_first_blk_hdr (and thus m_pdev_info.system_uuid) is already populated from other valid devices in the cluster. So if the footer on disk is valid and its system_uuid matches, it means the footer survived but the header was corrupted — not a fresh device. If the footer uuid does not match (or footer is invalid), it is leftover/garbage data and safe to treat as first boot. New logic: - Header valid: compare header and footer as before - Header invalid, footer valid + uuid matches cluster: header corruption, assert - Otherwise: first boot / leftover data, skip validation
1 parent be59185 commit 6dd7079

2 files changed

Lines changed: 22 additions & 16 deletions

File tree

conanfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class HomestoreConan(ConanFile):
1111
name = "homestore"
12-
version = "7.5.10"
12+
version = "7.5.11"
1313

1414
homepage = "https://github.com/eBay/Homestore"
1515
description = "HomeStore Storage Engine"

src/lib/device/physical_dev.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,40 +145,46 @@ std::error_code PhysicalDev::read_super_block(uint8_t* buf, uint32_t sb_size, ui
145145
void PhysicalDev::close_device() { close_and_uncache_dev(m_devname, m_iodev); }
146146

147147
void PhysicalDev::sanity_check() {
148-
// Only validate footer if mirroring is enabled (HDD devices)
149148
if (!m_super_blk_in_footer) { return; }
150149

151150
HS_LOG(INFO, device, "Validating footer superblock consistency on device={}", m_devname);
152151

153-
// Read header first block
154152
auto header_buf = hs_utils::iobuf_alloc(first_block::s_io_fb_size, sisl::buftag::superblk,
155153
m_pdev_info.dev_attr.align_size);
156154
auto header_err = read_super_block(header_buf, first_block::s_io_fb_size, hs_super_blk::first_block_offset());
157155
HS_REL_ASSERT(!header_err,
158-
"IO error reading header first block during sanity check on device={}, error={}, homestore will go down",
159-
m_devname, header_err.message());
156+
"IO error reading header first block on device={}, error={}, homestore will go down", m_devname,
157+
header_err.message());
160158

161-
// Read footer first block using the same offset calculation as write_super_block()
162159
auto footer_offset = data_end_offset() + hs_super_blk::first_block_offset();
163160
auto footer_buf = hs_utils::iobuf_alloc(first_block::s_io_fb_size, sisl::buftag::superblk,
164161
m_pdev_info.dev_attr.align_size);
165162
auto footer_err = read_super_block(footer_buf, first_block::s_io_fb_size, footer_offset);
166-
HS_REL_ASSERT(
167-
!footer_err,
168-
"IO error reading footer first block during sanity check on device={}, offset={}, error={}, homestore will go down",
169-
m_devname, footer_offset, footer_err.message());
163+
HS_REL_ASSERT(!footer_err,
164+
"IO error reading footer first block on device={}, offset={}, error={}, homestore will go down",
165+
m_devname, footer_offset, footer_err.message());
170166

171-
// Compare header and footer
172167
auto header_blk = r_cast< first_block* >(header_buf);
173168
auto footer_blk = r_cast< first_block* >(footer_buf);
174-
HS_REL_ASSERT(std::memcmp(header_blk, footer_blk, first_block::s_atomic_fb_size) == 0,
175-
"Footer first block mismatch with header on device={}, header=[{}], footer=[{}], this indicates "
176-
"corruption, homestore will go down",
177-
m_devname, header_blk->to_string(), footer_blk->to_string());
169+
170+
if (header_blk->is_valid()) {
171+
HS_REL_ASSERT(std::memcmp(header_blk, footer_blk, first_block::s_atomic_fb_size) == 0,
172+
"Footer mismatch with header on device={}, header=[{}], footer=[{}], corruption detected, "
173+
"homestore will go down",
174+
m_devname, header_blk->to_string(), footer_blk->to_string());
175+
HS_LOG(INFO, device, "Footer superblock validated successfully on device={}", m_devname);
176+
} else if (footer_blk->is_valid() && footer_blk->this_pdev_hdr.system_uuid == m_pdev_info.system_uuid) {
177+
HS_REL_ASSERT(false,
178+
"Header invalid but footer has matching system_uuid on device={}, indicates header superblock "
179+
"corruption, homestore will go down",
180+
m_devname);
181+
} else {
182+
HS_LOG(INFO, device,
183+
"Header invalid and footer has no matching system_uuid on device={}, treating as first boot", m_devname);
184+
}
178185

179186
hs_utils::iobuf_free(header_buf, sisl::buftag::superblk);
180187
hs_utils::iobuf_free(footer_buf, sisl::buftag::superblk);
181-
HS_LOG(INFO, device, "Footer superblock validated successfully on device={}", m_devname);
182188
}
183189

184190
folly::Future< std::error_code > PhysicalDev::async_write(const char* data, uint32_t size, uint64_t offset,

0 commit comments

Comments
 (0)