Skip to main content

Filesystem

Struct Filesystem 

Source
pub struct Filesystem<R> {
    pub superblock: Superblock,
    pub generation: u64,
    pub nodesize: u32,
    pub sectorsize: u32,
    /* private fields */
}
Expand description

In-memory filesystem state for a transaction session.

Holds everything needed to read and write tree blocks: the block reader (with chunk cache for logical-to-physical resolution), the superblock, all tree root pointers, the current transaction generation, and the set of dirty (modified) block addresses.

Fields§

§superblock: Superblock

Parsed superblock (updated in-memory during transactions).

§generation: u64

Current transaction generation (superblock.generation + 1 during a transaction, or superblock.generation when idle).

§nodesize: u32

Tree block size in bytes.

§sectorsize: u32

Minimum I/O unit in bytes.

Implementations§

Source§

impl<R: Read + Write + Seek> Filesystem<R>

Source

pub fn open(handle: R) -> Result<Self>

Open a btrfs filesystem from a readable+writable+seekable handle.

Performs the full bootstrap sequence (superblock, chunk cache, root tree), then wraps the result into an Filesystem ready for transactions.

§Errors

Returns an error if any I/O operation fails during bootstrap.

Source

pub fn open_mirror(handle: R, mirror: u32) -> Result<Self>

Open a btrfs filesystem using a specific superblock mirror.

§Errors

Returns an error if any I/O operation fails during bootstrap.

Source

pub fn open_multi(devices: BTreeMap<u64, R>) -> Result<Self>

Open a multi-device btrfs filesystem from a devid -> handle map.

Every device referenced by the filesystem’s chunk tree must be present in devices. Each device’s superblock is read and validated against the map key; all devices must share the same fsid. The bootstrap fails with a clear error if any of these invariants is violated.

§Errors

Returns an error if the device map is empty, any device’s superblock disagrees with its key or the primary’s fsid, the chunk tree references a devid not in the map, or any I/O fails.

Source

pub fn open_with_chunk_cache( handle: R, mirror: u32, chunk_cache: ChunkTreeCache, ) -> Result<Self>

Open a btrfs filesystem using a pre-built chunk cache.

Skips the chunk tree walk entirely, using the provided cache for logical-to-physical address resolution. This is the entry point for recovery tools like rescue chunk-recover --apply, where the on-disk chunk tree is damaged and the cache has been reconstructed from a raw device scan.

§Errors

Returns an error if any I/O operation fails during bootstrap.

Source

pub fn read_block(&mut self, logical: u64) -> Result<ExtentBuffer>

Read a tree block at the given logical address, returning an ExtentBuffer.

If the block is already in the in-memory cache (e.g. it was COW’d or previously read in this transaction), the cached version is returned without hitting disk.

§Errors

Returns an error if the block cannot be read from disk.

Source

pub fn write_block(&mut self, eb: &mut ExtentBuffer) -> Result<()>

Write an extent buffer to disk and mark it dirty.

The buffer’s checksum is updated before writing. The block is also stored in the in-memory cache so subsequent reads see the modification.

§Errors

Returns an error if the write fails.

Source

pub fn mark_dirty(&mut self, eb: &ExtentBuffer)

Store an extent buffer in the cache and mark it dirty, without writing to disk yet. The actual disk write happens at commit time.

Source

pub fn root_bytenr(&self, tree_id: u64) -> Option<u64>

Return the root block logical address for the given tree ID.

Source

pub fn set_root_bytenr(&mut self, tree_id: u64, bytenr: u64)

Update the root block logical address for a tree.

Source

pub fn root_node(&mut self, tree_id: u64) -> Result<ExtentBuffer>

Read the root block of the given tree as an ExtentBuffer.

§Errors

Returns an error if the tree ID is unknown or the block cannot be read.

Source

pub fn dirty_blocks(&self) -> impl Iterator<Item = u64> + '_

Return an iterator over all dirty block logical addresses.

Source

pub fn dirty_count(&self) -> usize

Return the number of dirty blocks.

Source

pub fn is_written(&self, logical: u64) -> bool

Check whether a block has been written to stable storage during this transaction. Such blocks must be COW’d before modification even if their generation matches the current transaction.

Source

pub fn clear_dirty(&mut self)

Clear the dirty and written sets (used after commit or abort).

Source

pub fn clear_cache(&mut self)

Clear the block cache (used after commit or abort to free memory).

Source

pub fn tree_roots(&self) -> impl Iterator<Item = (u64, u64)> + '_

Return all tree root entries as (tree_id, root_bytenr) pairs.

Source

pub fn flush_dirty(&mut self) -> Result<()>

Flush all dirty blocks to disk.

Iterates the dirty set, checksums each cached block, and writes it. Blocks that are dirty but not in the cache are skipped (they were already written by write_block).

§Errors

Returns an error if any write fails.

Source

pub fn reader_mut(&mut self) -> &mut BlockReader<R>

Return a mutable reference to the underlying block reader.

Source

pub fn reader(&self) -> &BlockReader<R>

Return a reference to the underlying block reader.

Source

pub fn remove_root(&mut self, tree_id: u64) -> Option<u64>

Remove a tree root entry.

Source

pub fn evict_block(&mut self, logical: u64)

Evict a block from the cache (e.g. after freeing it).

Source

pub fn snapshot_roots(&mut self)

Snapshot the current roots so we can detect changes at commit time.

Called at transaction start to record the baseline state.

Source

pub fn restore_roots_from_snapshot(&mut self)

Restore the roots map to the last snapshot. Used by Transaction::abort to roll back in-memory set_root_bytenr changes that pointed at COWed-but-never-written bytenrs.

Source

pub fn write_superblock_all_devices(&mut self) -> Result<()>

Write the in-memory superblock to all 3 mirrors of every open device, with each device’s per-device dev_item spliced in.

On a multi-device filesystem each device’s superblock has its own dev_item (devid, dev_uuid, per-device bytes_used, etc.). Writing the primary device’s superblock verbatim to a secondary would corrupt the secondary’s identity. This helper preserves that per-device state by splicing the matching dev_item from the snapshot taken at open time before serializing each device’s variant.

§Errors

Returns an error if any device referenced by the dev-item snapshot is not open, or if any underlying write fails.

Source

pub fn flush_writes(&mut self) -> Result<()>

Flush pending writes via Write::flush() on every device.

Flushes userspace write buffers on every open device. For file-backed storage, use Filesystem<File>::sync instead, which also calls fsync per device.

Source

pub fn changed_roots(&self) -> Vec<(u64, u64, u8)>

Return tree IDs whose root block changed since the last snapshot.

Compares current roots against the snapshot taken at transaction start. Excludes tree IDs 1 (root tree) and 3 (chunk tree) since their root pointers live in the superblock, not in root items.

Source

pub fn block_group_tree_id(&self) -> u64

Return the tree id that holds BLOCK_GROUP_ITEM records.

When bg_tree_override is set (typically by the convert-to-block-group-tree path), returns it verbatim. Otherwise auto-detects: returns 11 (BLOCK_GROUP_TREE) if a root for tree 11 is registered, else 2 (EXTENT_TREE).

All allocator and block-group-update code paths must consult this accessor instead of duplicating the routing logic, so that the override mechanism actually works for everything that touches block-group state.

Source

pub fn pin_block_group_tree(&mut self, id: u64) -> BgTreeOverrideGuard<'_, R>

Pin block_group_tree_id to the given tree id and return a guard that restores the previous override (typically None) when dropped.

Use this in conversion paths so that panics or ? early-returns cannot leave the override stuck on the wrong value.

Source§

impl Filesystem<File>

Source

pub fn sync(&mut self) -> Result<()>

Sync all data to stable storage on every device (fsync).

Calls File::sync_all() on every open device handle, ensuring all written data reaches stable storage. This should be called after commit to guarantee durability.

Auto Trait Implementations§

§

impl<R> Freeze for Filesystem<R>

§

impl<R> !RefUnwindSafe for Filesystem<R>

§

impl<R> Send for Filesystem<R>
where R: Send,

§

impl<R> Sync for Filesystem<R>
where R: Sync,

§

impl<R> Unpin for Filesystem<R>

§

impl<R> UnsafeUnpin for Filesystem<R>

§

impl<R> !UnwindSafe for Filesystem<R>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.