1use crate::superblock::{BLOCKS_PER_SEGMENT, BLOCK_SIZE, SEGMENT_SIZE};
5use anyhow::{ensure, Error};
6use std::collections::HashMap;
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
8
9#[repr(C, packed)]
11#[derive(Copy, Clone, Default, Debug, Immutable, Unaligned, KnownLayout, FromBytes, IntoBytes)]
12pub struct RawNatEntry {
13 pub version: u8,
14 pub ino: u32,
15 pub block_addr: u32,
16}
17
18pub const NAT_ENTRY_PER_BLOCK: usize = BLOCK_SIZE / std::mem::size_of::<RawNatEntry>(); pub struct Nat {
25 device_offset: usize,
27 nat_bitmap: Vec<u8>,
31 pub nat_journal: HashMap<u32, RawNatEntry>,
34}
35
36impl Nat {
37 pub fn new(
38 nat_blkaddr: u32,
39 nat_bitmap: Vec<u8>,
40 nat_journal: HashMap<u32, RawNatEntry>,
41 ) -> Self {
42 let device_offset = nat_blkaddr as usize * BLOCK_SIZE;
43 Self { device_offset, nat_bitmap, nat_journal }
44 }
45
46 pub fn get_nat_block_for_entry(&self, nid: u32) -> Result<u32, Error> {
48 let nat_block_ix = nid as usize / NAT_ENTRY_PER_BLOCK;
50 let segment_offset = nat_block_ix / BLOCKS_PER_SEGMENT * SEGMENT_SIZE * 2;
52 ensure!(
54 nat_block_ix / 8 < self.nat_bitmap.len(),
55 "Got request for nid {nid} which is beyond the bitmap size of {}",
56 self.nat_bitmap.len()
57 );
58 let bitmap_offset =
59 if (self.nat_bitmap[nat_block_ix / 8] << (nat_block_ix % 8)) & 0x80 == 0x80 {
60 SEGMENT_SIZE
61 } else {
62 0
63 };
64 let byte_offset = self.device_offset
65 + segment_offset
66 + (nat_block_ix % BLOCKS_PER_SEGMENT) * BLOCK_SIZE
67 + bitmap_offset;
68 Ok((byte_offset / BLOCK_SIZE) as u32)
69 }
70
71 pub fn get_nat_block_offset_for_entry(&self, nid: u32) -> usize {
73 (nid as usize % NAT_ENTRY_PER_BLOCK) * std::mem::size_of::<RawNatEntry>()
74 }
75}
76
77#[repr(C, packed)]
78#[derive(Copy, Clone, Debug, Immutable, KnownLayout, FromBytes, IntoBytes, Unaligned)]
79pub struct Summary {
80 pub nid: u32,
81 pub version: u8,
82 pub ofs_in_node: u16,
83}
84
85#[repr(C, packed)]
86#[derive(Copy, Clone, Debug, Immutable, KnownLayout, FromBytes, IntoBytes, Unaligned)]
87pub struct SummaryFooter {
88 pub entry_type: u8,
89 pub check_sum: u32,
90}
91
92#[repr(C, packed)]
93#[derive(Copy, Clone, Debug, Immutable, KnownLayout, FromBytes, IntoBytes, Unaligned)]
94pub struct NatJournalEntry {
95 pub ino: u32,
96 pub entry: RawNatEntry,
97}
98
99const SUM_ENTRY_SIZE: usize = std::mem::size_of::<Summary>() * 512;
100const N_NATS_SIZE: usize = 2;
101const NAT_JOURNAL_SIZE: usize =
102 BLOCK_SIZE - SUM_ENTRY_SIZE - N_NATS_SIZE - std::mem::size_of::<SummaryFooter>();
103#[repr(C, packed)]
104#[derive(Copy, Clone, Debug, Immutable, KnownLayout, FromBytes, IntoBytes, Unaligned)]
105pub struct NatJournal {
106 pub entries: [NatJournalEntry; NAT_JOURNAL_SIZE / std::mem::size_of::<NatJournalEntry>()],
107 _reserved: [u8; NAT_JOURNAL_SIZE % std::mem::size_of::<NatJournalEntry>()],
108}
109
110#[repr(C, packed)]
112#[derive(Copy, Clone, Debug, Immutable, KnownLayout, FromBytes, IntoBytes, Unaligned)]
113pub struct SummaryBlock {
114 pub entries: [Summary; 512],
115 pub n_nats: u16,
116 pub nat_journal: NatJournal,
117 pub footer: SummaryFooter,
118}