Skip to content

Commit

Permalink
Fix sector scrubbing
Browse files Browse the repository at this point in the history
  • Loading branch information
nazar-pc committed Mar 22, 2024
1 parent 788dec1 commit 07b6028
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 49 deletions.
1 change: 1 addition & 0 deletions crates/subspace-farmer-components/src/plotting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ where
// * sector contents map
// * record chunks as s-buckets
// * record metadata
// * checksum
{
let (sector_contents_map_region, remaining_bytes) =
sector_output.split_at_mut(SectorContentsMap::encoded_size(pieces_in_sector));
Expand Down
107 changes: 58 additions & 49 deletions crates/subspace-farmer/src/single_disk_farm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,15 @@ use std::{fs, io, mem};
use subspace_core_primitives::crypto::kzg::Kzg;
use subspace_core_primitives::crypto::{blake3_hash, Scalar};
use subspace_core_primitives::{
Blake3Hash, HistorySize, Piece, PieceOffset, PublicKey, Record, SectorId, SectorIndex,
SegmentIndex,
Blake3Hash, HistorySize, PieceOffset, PublicKey, Record, SectorId, SectorIndex, SegmentIndex,
};
use subspace_erasure_coding::ErasureCoding;
use subspace_farmer_components::file_ext::FileExt;
#[cfg(not(windows))]
use subspace_farmer_components::file_ext::OpenOptionsExt;
use subspace_farmer_components::plotting::PlottedSector;
use subspace_farmer_components::reading::ReadSectorRecordChunksMode;
use subspace_farmer_components::sector::{
sector_size, SectorContentsMap, SectorMetadata, SectorMetadataChecksummed,
};
use subspace_farmer_components::sector::{sector_size, SectorMetadata, SectorMetadataChecksummed};
use subspace_farmer_components::{FarmerProtocolInfo, PieceGetter, ReadAtSync};
use subspace_networking::KnownPeersManager;
use subspace_proof_of_space::Table;
Expand Down Expand Up @@ -1871,27 +1868,27 @@ impl SingleDiskFarm {
plot_file
};

let sector_bytes_range = 0..(sector_size as usize - mem::size_of::<Blake3Hash>());

info!("Checking sectors and corresponding metadata");
(0..metadata_header.plotted_sector_count)
.into_par_iter()
.map_init(
|| {
let sector_metadata_bytes = vec![0; sector_metadata_size];
let piece = Piece::default();

(sector_metadata_bytes, piece)
},
|(sector_metadata_bytes, piece), sector_index| {
|| vec![0u8; Record::SIZE],
|scratch_buffer, sector_index| {
let _span_guard = span.enter();

let offset = RESERVED_PLOT_METADATA
+ u64::from(sector_index) * sector_metadata_size as u64;
if let Err(error) = metadata_file.read_exact_at(sector_metadata_bytes, offset) {
if let Err(error) = metadata_file
.read_exact_at(&mut scratch_buffer[..sector_metadata_size], offset)
{
warn!(
path = %metadata_file_path.display(),
%error,
%sector_index,
%offset,
size = %sector_metadata_size,
%sector_index,
"Failed to read sector metadata, replacing with dummy expired sector \
metadata"
);
Expand All @@ -1908,7 +1905,7 @@ impl SingleDiskFarm {
}

let sector_metadata = match SectorMetadataChecksummed::decode(
&mut sector_metadata_bytes.as_slice(),
&mut &scratch_buffer[..sector_metadata_size],
) {
Ok(sector_metadata) => sector_metadata,
Err(error) => {
Expand Down Expand Up @@ -1973,40 +1970,47 @@ impl SingleDiskFarm {
}

let mut hasher = blake3::Hasher::new();
for piece_offset in 0..pieces_in_sector {
let offset = u64::from(sector_index) * sector_size
+ u64::from(piece_offset) * Piece::SIZE as u64;
// Read sector bytes and compute checksum
for offset_in_sector in sector_bytes_range.clone().step_by(scratch_buffer.len())
{
let offset =
u64::from(sector_index) * sector_size + offset_in_sector as u64;
let bytes_to_read = (offset_in_sector + scratch_buffer.len())
.min(sector_bytes_range.end)
- offset_in_sector;

let bytes = &mut scratch_buffer[..bytes_to_read];

if let Err(error) = plot_file.read_exact_at(piece.as_mut(), offset) {
if let Err(error) = plot_file.read_exact_at(bytes, offset) {
warn!(
path = %plot_file_path.display(),
%error,
%sector_index,
%piece_offset,
size = %piece.len() as u64,
%offset,
"Failed to read piece bytes"
size = %bytes.len() as u64,
"Failed to read sector bytes"
);

continue;
}

hasher.update(piece.as_ref());
hasher.update(bytes);
}

let actual_checksum = *hasher.finalize().as_bytes();
let mut expected_checksum = [0; mem::size_of::<Blake3Hash>()];
{
let offset = u64::from(sector_index) * sector_size
+ u64::from(pieces_in_sector) * Piece::SIZE as u64;
let offset =
u64::from(sector_index) * sector_size + sector_bytes_range.end as u64;
if let Err(error) = plot_file.read_exact_at(&mut expected_checksum, offset)
{
warn!(
path = %plot_file_path.display(),
%error,
%sector_index,
%offset,
"Failed to read checksum bytes"
size = %expected_checksum.len() as u64,
"Failed to read sector checksum bytes"
);
}
}
Expand All @@ -2030,42 +2034,47 @@ impl SingleDiskFarm {
)?;
}

*piece = Piece::default();
scratch_buffer.fill(0);

// Write dummy pieces
let mut hasher = blake3::Hasher::new();
for piece_offset in 0..pieces_in_sector {
let offset = u64::from(sector_index) * sector_size
+ u64::from(piece_offset) * Piece::SIZE as u64;
hasher.reset();
// Fill sector with zeroes and compute checksum
for offset_in_sector in
sector_bytes_range.clone().step_by(scratch_buffer.len())
{
let offset =
u64::from(sector_index) * sector_size + offset_in_sector as u64;
let bytes_to_write = (offset_in_sector + scratch_buffer.len())
.min(sector_bytes_range.end)
- offset_in_sector;
let bytes = &mut scratch_buffer[..bytes_to_write];

if !dry_run {
if let Err(error) = plot_file.write_all_at(piece.as_ref(), offset) {
if let Err(error) = plot_file.write_all_at(bytes, offset) {
return Err(SingleDiskFarmScrubError::FailedToWriteBytes {
file: plot_file_path.clone(),
size: piece.len() as u64,
size: scratch_buffer.len() as u64,
offset,
error,
});
}
}

hasher.update(piece.as_ref());
hasher.update(bytes);
}

let offset = u64::from(sector_index) * sector_size
+ u64::from(pieces_in_sector) * Piece::SIZE as u64;

// Write checksum
if !dry_run {
if let Err(error) =
plot_file.write_all_at(hasher.finalize().as_bytes(), offset)
{
return Err(SingleDiskFarmScrubError::FailedToWriteBytes {
file: plot_file_path.clone(),
size: hasher.finalize().as_bytes().len() as u64,
offset,
error,
});
{
let checksum = *hasher.finalize().as_bytes();
let offset = u64::from(sector_index) * sector_size
+ sector_bytes_range.end as u64;
if !dry_run {
if let Err(error) = plot_file.write_all_at(&checksum, offset) {
return Err(SingleDiskFarmScrubError::FailedToWriteBytes {
file: plot_file_path.clone(),
size: checksum.len() as u64,
offset,
error,
});
}
}
}

Expand Down

0 comments on commit 07b6028

Please sign in to comment.