Block Storage & File Organization

1. Lecture 12: Block Storage

1.1. Administrative notes

  • The course slides should be available.
  • The midterm was announced for Monday in two weeks from this lecture.
  • A sample exam was planned.
  • The midterm scope was announced as covering material up to the following Wednesday lecture.

1.2. Clarification from the previous lecture: DMA, memory protection, and IOMMU

1.2.1. DMA recap

  • DMA stands for Direct Memory Access.
  • With DMA, a device copies data directly between the device and main memory without the CPU copying every byte.
  • The driver gives the device a memory address and a length.
  • The device then performs the transfer itself.
  • This improves performance, but it also bypasses the CPU’s normal memory-management path.

1.2.2. Why DMA bypasses normal CPU memory protection

  • Normal CPU memory accesses go through the MMU.
  • The MMU translates virtual addresses to physical addresses and checks permissions.
  • A DMA-capable device does not automatically go through the CPU MMU.
  • If the device is simply given a physical address, it may access memory directly.
  • Therefore, ordinary CPU-side mechanisms such as:

    • page tables,
    • user/kernel privilege rings,
    • SMEP/SMAP-like CPU protections,

    cannot by themselves stop a malicious or buggy DMA device.

1.2.3. Correctness issues caused by DMA

  1. Page pinning
    • If the OS gives a physical page to a device for DMA, the OS must ensure that page remains valid for the duration of the transfer.
    • The page must not be:
      • swapped out,
      • remapped for another purpose,
      • freed and reused for something else.
    • This is called pinning the page.
    • Without pinning, the device may write into memory that no longer belongs to the intended buffer.
  2. Addressability and bounce buffers
    • Some devices can only address a limited physical address range.
    • For example, a 32-bit device may only address the first \(2^{32}\) bytes, i.e. 4 GiB, of physical address space.
    • On a 64-bit machine, the OS may allocate a buffer above the range the device can address.
    • A bounce buffer solves this by allocating an intermediate buffer in an address range the device can access.
    • The flow is then:
      1. Device performs DMA to or from the bounce buffer.
      2. The OS copies data between the bounce buffer and the real high-memory buffer.
    • This is correct but slower because it adds an extra memory copy.
  3. Cache coherence
    • CPUs normally see memory through caches.
    • A DMA device may modify main memory directly.
    • If the CPU has stale cached data for the same memory region, the CPU may see old data.
    • Therefore, the OS or hardware must ensure cache coherence, for example by:
      • invalidating cache lines before reading DMA-written data,
      • flushing dirty cache lines before device reads,
      • using cache-coherent interconnect support when available.

1.2.4. Security issues caused by DMA

  • A DMA-capable device may be able to read or write arbitrary physical memory if unrestricted.
  • This means a malicious device could:
    • read secrets from RAM,
    • overwrite kernel data structures,
    • modify code or credentials,
    • bypass CPU privilege checks.
  • This is especially dangerous for hot-plug devices.
  • A hot-plug device can be attached while the system is already running.
  • Historical attacks showed that plugging a malicious device into a running laptop could dump memory quickly.

1.2.5. IOMMU

  1. Basic idea
    • An IOMMU is an I/O memory-management unit.
    • It is analogous to the CPU MMU, but it sits on the I/O side.
    • Instead of allowing devices to directly use physical addresses, the IOMMU gives devices an I/O virtual address space.
    • The address spaces are conceptually:
      • CPU virtual address \(\rightarrow\) physical address, managed by the CPU MMU;
      • device I/O virtual address, often called IOVA \(\rightarrow\) physical address, managed by the IOMMU.
  2. What the IOMMU provides
    • It adds a layer of indirection for device memory access.
    • The OS configures which physical pages a device may access.
    • A device can only access pages mapped in its IOMMU page tables.
    • Unauthorized device accesses can be blocked, similarly to a page fault.
    • This helps with:
      • device isolation,
      • DMA safety,
      • virtualization,
      • protection against malicious or buggy devices.
  3. Limitations of IOMMU protection
    • It is not automatically perfect.
    • Problems include:
      • identity/pass-through mode may effectively disable protection;
      • early boot may contain a vulnerable window before the OS configures the IOMMU;
      • the OS must correctly remove or flush stale mappings;
      • mappings are often page-granular, so a device may still access the whole page even if the intended buffer is smaller.
    • The IOMMU is therefore a strong mitigation, but not magic.

1.3. Storage and persistence

1.3.1. What storage is

  • Storage is the part of the system responsible for long-term retention of data.
  • The key property is persistence: data should survive after power loss, program termination, logout, and machine restart.

1.3.2. Degrees of permanence

Persistence is not just a binary property. The lecture described a spectrum:

  • Survive across program invocations.
  • Survive across user logins.
  • Survive across machine restarts.
  • Survive across machine failures.
  • Survive across disk failures.
  • Survive across multiple disk failures.

1.3.3. Permanent storage media

  • Main memory is not suitable for permanent storage because it loses data on power loss.
  • Battery-backed memory can preserve data but is expensive, and the battery itself becomes a failure mode.
  • Non-volatile memory provides memory-like persistence, but is a more specialized technology.
  • Disks and flash storage are the main block storage technologies discussed.
  • Tape is older but still relevant for large-scale archival storage.

1.3.4. The storage stack

The lecture placed storage in a stack:

  • User level:
    • applications,
    • file interface.
  • OS level:
    • file system,
    • block cache,
    • device drivers.
  • Hardware level:
    • HDDs,
    • SSDs,
    • other persistent devices.

This lecture focused mostly on the hardware/block-device level. Later lectures move upward into caching, file systems, naming, reliability, and the POSIX/VFS interface.

1.4. Block storage devices

1.4.1. Core abstraction

  • A block storage device exposes an array of blocks.
  • Blocks can be read and written.
  • A block is the minimum unit of access.
  • You cannot read half a block or write only three bytes directly to the raw block device.
  • Fine-grained byte operations are implemented by higher layers, usually by reading a whole block into memory, modifying bytes in memory, and writing the block back.

1.4.2. Properties expected from block storage

  • Persistent across power loss.
  • Large capacity.
  • Low cost per byte compared to main memory.
  • Random access support.
  • Reliability: once data is written, later reads should return the same data unless a failure or corruption occurs.

1.4.3. Main technologies

  1. Magnetic disk / HDD
    • Mechanical hard disk drive.
    • Stores data magnetically on spinning platters.
    • Has moving parts.
    • Cheaper per GB.
    • Larger capacity.
    • Higher access latency.
    • Lower throughput.
    • Higher energy consumption.
    • Does not suffer from flash-style write-wear.
  2. Flash storage / SSD
    • Solid-state drive built from NAND flash.
    • Purely electronic; no moving parts.
    • More expensive per GB.
    • Usually lower capacity for the same price.
    • Lower latency.
    • Higher throughput.
    • Lower energy consumption.
    • Suffers from write-wear.

1.5. Magnetic disks / HDDs

1.5.1. Physical structure

An HDD contains:

  • platters: spinning disks coated with magnetic material;
  • spindle: motor-driven axis that rotates platters;
  • surfaces: each platter side can store data;
  • arm assembly: moves read/write heads over the platters;
  • read/write head: reads and writes magnetic patterns.

1.5.2. Information layout terminology

  1. Sector
    • A sector is the smallest addressable unit on the disk surface.
    • Modern sector sizes are typically 4 KiB.
    • Older disks often used 512-byte sectors.
  2. Track
    • A track is a circular path on one platter surface.
    • If the head stays at one radius and the platter spins once, it passes over one track.
  3. Cylinder
    • A cylinder is the set of tracks at the same radius across all platter surfaces.
    • Moving the arm to a cylinder positions all heads at the same radial location.
    • Cylinder terminology matters because moving the arm is slow, while switching heads is fast.

1.5.3. Typical HDD parameters

Typical values discussed:

  • physical size: about 1.8 to 3.5 inches;
  • rotation speed: about 4,200 to 15,000 RPM;
  • platters: often 1 to 8, giving 2 to 16 surfaces;
  • tracks per surface: on the order of \(100K\);
  • track width: tens to hundreds of nanometers;
  • sectors per track: hundreds to thousands;
  • sector size: today commonly 4 KiB;
  • capacity: roughly 1 to 20+ TB;
  • cost: relatively low per TB.

1.5.4. Disk interface

From the OS point of view, the disk exposes functions conceptually like:

ReadSector(logical_sector_number, buffer);
WriteSector(logical_sector_number, buffer);
  • The OS uses a logical sector number.
  • Historically, the logical sector number mapped more directly to physical geometry:
    • platter/head,
    • cylinder/track,
    • sector.
  • Modern disks hide much of the physical layout behind logical block addressing and internal controllers.

1.5.5. Disk access steps

To read a sector, the disk roughly performs:

  1. Head selection: choose the correct surface/head.
  2. Seek: move the arm to the correct cylinder.
  3. Rotational latency: wait until the desired sector rotates under the head.
  4. Transfer: read the sector into the disk buffer and then transfer it to main memory.

The access time is: \[ T_{\text{access}} = T_{\text{head selection}} + T_{\text{seek}} + T_{\text{rotation}} + T_{\text{transfer}}. \]

1.5.6. Component costs

  1. Head selection
    • Electronic switch.
    • Very fast, roughly nanoseconds.
    • Usually not worth optimizing heavily.
  2. Seek time
    • Mechanical movement of the arm.
    • Usually milliseconds.
    • Approximately related to how far the arm must move across cylinders.
    • Often dominates HDD access time.
  3. Rotational latency
    • Waiting for the desired sector to rotate under the head.
    • Also usually milliseconds.
    • Example:
      • \(7200\) RPM = \(7200 / 60 = 120\) rotations per second.
      • one full rotation takes \(1/120 \approx 8.3\) ms.
      • average wait is half a rotation, about \(4.15\) ms.
  4. Transfer time
    • Once the head is positioned and the sector is under the head, transferring a sector is much faster.
    • Usually microseconds for one block.
    • Example:
      • 4 KiB sector,
      • 100 MB/s transfer rate,
      • transfer time \(\approx 4\text{ KiB} / 100\text{ MB/s} \approx 40\mu s\).
    • For large buffers, transfer time can still matter.
    • Example:
      • 256 MB at 100 MB/s takes more than 2 seconds.

1.5.7. Key observation: disk access is much slower than memory

  • Memory access is typically nanoseconds.
  • HDD access is often milliseconds.
  • That is a difference of many orders of magnitude.
  • Seek time and rotational latency dominate.
  • Therefore, operating systems and file systems must be designed to avoid unnecessary disk access.

1.6. Optimizing disk access

1.6.1. Rule 1: do not access the disk unless necessary

  • Disk access is slow.
  • The OS should use a cache whenever possible.
  • This motivates the buffer/page cache discussed in Lecture 13.

1.6.2. Rule 2: do not wait for the disk unnecessarily

  • Once the disk has paid seek and rotational cost for one sector, nearby sectors are cheap to read.
  • Sequential access is therefore much faster than random access.
  • The OS or device can use:
    • read-ahead,
    • prefetching,
    • sequential write aggregation.
  • This only works when future accesses are predictable and sequential.

1.6.3. Rule 3: minimize seeks

  • Seeking is expensive.
  • Disk scheduling reorders requests to reduce arm movement.
  • Instead of serving requests strictly in arrival order, the OS or disk controller may choose an order with lower total seek distance.

1.6.4. Rule 4: avoid rotational latency by careful allocation

  • Related data should be placed near each other.
  • For a file, blocks should ideally be on nearby sectors/tracks/cylinders.
  • This allows sequential access and reduces both seeking and waiting.

1.7. Evolution of disk control

1.7.1. 1990s model

  • The OS had more explicit control over sectors.
  • The OS performed more scheduling and placement decisions itself.
  • The OS needed more knowledge of disk geometry.

1.7.2. 2000s model: LBA

  • Logical Block Addressing made the disk look like a linear array of blocks.
  • The disk controlled the physical layout.
  • The OS still performed some request scheduling.

1.7.3. Modern model

  • Disk controllers accept multiple commands in parallel.
  • Controllers internally reorder and schedule operations.
  • Native Command Queuing (NCQ) is one example.
  • The OS has gradually lost detailed control over physical placement and scheduling.

1.7.4. Reality is more complicated than simple geometry

  • Different disks have different internal layouts.
  • Manufacturers implement hidden optimizations.
  • Track buffering:
    • if the head is already passing over nearby sectors, the disk may read and cache them speculatively.
  • Shingled Magnetic Recording (SMR):
    • tracks overlap like roof shingles to increase density;
    • writing one track may disturb adjacent tracks;
    • therefore, regions must often be written in order;
    • overwriting individual sectors becomes complicated.

1.8. Flash storage / SSDs

1.8.1. Basic SSD idea

  • SSDs are not actually disks.
  • They are built from NAND flash chips.
  • They have no platters, heads, arms, or other moving parts.
  • Nevertheless, SSDs are designed to look like disks:
    • physically, they may fit into disk-like form factors;
    • logically, they expose a sector/block interface to the OS.

1.8.2. NAND flash organization

  • The basic read/write unit is a page, often 4 KiB.
  • Pages are grouped into erase blocks.
  • Example: one erase block may contain 64 pages.
  • Each NAND chip contains many erase blocks.
  • An SSD contains multiple NAND chips plus a controller and internal memory.

1.8.3. NAND flash operations

  1. Read
    • Reads one page.
    • Typical latency: about \(10\mu s\).
  2. Program / write
    • Writes one page.
    • Typical latency: about \(100\mu s\).
    • Slower than reading.
  3. Erase
    • Erases an entire erase block.
    • Typical latency: a few milliseconds.
    • A page cannot simply be overwritten in-place; the containing block must be erased before reuse.
    • Erasing sets bits to the erased state.
    • Each erase block supports only a limited number of erase cycles, for example around \(100{,}000\), depending on technology.

1.8.4. SSD interface

  • The OS still sees functions like:
ReadSector(logical_sector_no, buffer);
WriteSector(logical_sector_no, buffer);
  • The SSD internally maintains a logical sector map.
  • The OS does not need to know which physical NAND page contains a logical sector.

1.8.5. SSD characteristics

  • Higher bandwidth than HDDs.
  • Much lower latency:
    • reads around \(10\mu s\),
    • writes around \(100\mu s\).
  • Supports multiple outstanding commands.
  • Random access is much less painful than on HDDs because there is no mechanical seek or rotation.

1.8.6. SSD uses

  • Mobile consumer electronics.
  • Laptops.
  • High-end servers.
  • Often combined with HDDs:
    • SSDs for hot data or caching,
    • HDDs for cheaper high-capacity storage.
  • SSDs are also physically robust compared to HDDs because there are no moving parts.

1.8.7. SSD limitations

  1. No in-place overwrite
    • Flash pages cannot simply be overwritten.
    • To reuse a page, the entire erase block must be erased first.
    • If handled naively, every write would have to wait for erase latency.
  2. Write-wear
    • Erase blocks wear out after enough erase cycles.
    • If the same physical block is rewritten repeatedly, it may die quickly.
    • The SSD must spread writes across the device.

1.9. Flash Translation Layer (FTL)

1.9.1. Motivation

The lecture used the classic idea:

  • Many computer-science problems can be solved by adding another layer of indirection.
  • For SSDs, the extra indirection layer is the Flash Translation Layer.

1.9.2. FTL mapping

  • The FTL maps logical page numbers to physical page numbers.
  • It keeps a mapping table in SSD controller memory for fast lookup.
  • It also stores mapping metadata persistently in flash, because the mapping must survive power loss.

1.9.3. Read path

  1. Receive logical sector/page number.
  2. Look up the physical page in the FTL table.
  3. Read the physical page.

1.9.4. Write path

  1. Receive logical sector/page number.
  2. Allocate a new unused, already-erased physical page.
  3. Write/program the new page.
  4. Update the logical-to-physical mapping.
  5. Mark the old physical page invalid/stale.
  6. Erase invalid blocks later in the background.

1.9.5. How FTL hides erase latency

  • Writes can use pre-erased free pages.
  • Expensive erases are moved off the critical write path.
  • Garbage collection erases blocks in the background.

1.9.6. Wear leveling

  • The FTL tracks how much physical blocks have been erased.
  • It tries to distribute writes and erases across blocks.
  • This prevents a small set of hot logical pages from destroying the same physical blocks repeatedly.
  • Wear leveling is the main mechanism that makes SSD lifetime acceptable.

1.10. NVM and NVMe

1.10.1. NVM: non-volatile memory

  • NVM means non-volatile memory.
  • It allows byte-level access to persistent storage.
  • Conceptually, it is closer to memory than to a block device.
  • It is slower than DRAM but faster than conventional SSDs.
  • It can blur the line between memory and storage.

1.10.2. NVMe is not NVM

  • NVMe means Non-Volatile Memory Express.
  • It is an interface/protocol for high-speed SSDs over PCIe.
  • Despite the name, an NVMe SSD is still a block device.
  • It is not byte-addressable memory.
  • NVMe improves parallelism, bandwidth, and latency for SSD I/O.

1.11. Combining multiple drives: RAID

1.11.1. Motivation

  • Disks improved much more slowly than CPUs.
  • HDD latency and bandwidth improved by perhaps around one order of magnitude over decades.
  • CPU performance improved by several orders of magnitude.
  • This widened the storage/CPU gap.
  • One way to improve storage bandwidth cheaply is to combine multiple disks.

1.11.2. RAID definition

  • RAID originally means Redundant Array of Independent Disks.
  • The key idea is parallel I/O across multiple drives.
  • Benefits:
    • higher bandwidth,
    • larger logical capacity,
    • possible redundancy and reliability.

1.11.3. Striping

  • Instead of placing all sectors on one disk, data is spread across disks.
  • Example:
    • stripe 0 on disk 0,
    • stripe 1 on disk 1,
    • stripe 2 on disk 2,
    • and so on.
  • Large reads and writes can access multiple disks in parallel.
  • Idealized bandwidth with \(n\) disks:

\[ \text{bandwidth}_{RAID} \approx n \times \text{bandwidth}_{one\ disk}. \]

  • In practice, the controller, I/O bus, workload, and implementation limit scaling.

1.11.4. RAID organization

  • RAID can be implemented:
    • in a dedicated RAID box/controller with disks, memory, and processor;
    • in software by the OS kernel;
    • in hybrid forms with partial hardware support.
  • A hardware RAID box may appear to the OS as one large disk.

1.11.5. Problem with naïve striping

  • If data is striped across many disks and there is no redundancy, one disk failure can make the whole array unusable.
  • With \(n\) disks, the array fails if any one disk fails.
  • Approximate mean time between failures:

\[ MTBF_{array} \approx \frac{MTBF_{disk}}{n}. \]

  • Example:
    • one disk MTBF \(\approx 50{,}000\) hours, about 5 years;
    • RAID with 10 disks has MTBF around 0.5 years.
  • Therefore, plain striping improves performance but hurts reliability.

1.12. RAID levels

1.12.1. RAID-0: striping without redundancy

  • Non-redundant disk array.
  • Best read and write bandwidth among the covered schemes.
  • Uses all disk capacity for data.
  • Any disk failure causes data loss or unavailability.
  • Good for performance when data loss is acceptable or data is replicated elsewhere.

1.12.2. RAID-1: mirroring

  • Every data disk has a mirror copy.
  • Capacity is roughly half of raw disk capacity.
  • Writes must go to both data and mirror disks.
  • Reads can be served from either copy.
  • After one disk fails, the surviving mirror can be used.
  • Replacing a failed disk is conceptually simple: copy data from the surviving disk to the replacement.
  • Tradeoff:
    • strong reliability and simple recovery;
    • expensive in capacity because every byte is stored twice.

1.12.3. RAID-4: dedicated parity disk

  • Uses \(N\) data disks plus one parity disk.
  • For a stripe group, parity is computed by XOR:

\[ P = D_0 \oplus D_1 \oplus \cdots \oplus D_{N-1}. \]

  • If one data disk fails, its data can be reconstructed:

\[ D_i = P \oplus D_0 \oplus \cdots \oplus D_{i-1} \oplus D_{i+1} \oplus \cdots \oplus D_{N-1}. \]

  • If the parity disk fails, data disks still contain the data and parity can be rebuilt.
  • Can tolerate one disk failure.
  • More capacity-efficient than RAID-1.
  1. RAID-4 write bottleneck
    • Every write must update the parity disk.
    • Therefore, the parity disk becomes a bottleneck for write-heavy workloads.
    • Reads can still be parallel, but parallel writes are limited by the single parity disk.

1.12.4. RAID-5: distributed parity

  • Similar to RAID-4, but parity is distributed across all disks.
  • Different stripe groups place parity on different disks.
  • This balances parity write load.
  • Avoids the single dedicated parity-disk bottleneck.
  • Can tolerate one disk failure.
  • More complex than RAID-0 or RAID-1.

1.12.5. Other RAID levels

  1. RAID-2 and RAID-3
    • Mentioned as no longer commonly used in this context.
  2. RAID-6
    • Like RAID-5 but with double parity.
    • Can tolerate two disk failures.
    • Useful because rebuild periods are vulnerable, especially with large disks.
  3. RAID-10 / RAID-1+0
    • A RAID-0 stripe over RAID-1 mirrored pairs.
    • Combines good performance with strong reliability.
    • Expensive because mirroring reduces usable capacity.

1.13. Lecture 12 key takeaways

  • Block storage provides persistent block-level read/write operations.
  • HDDs and SSDs expose similar block interfaces but have very different internal behavior.
  • HDD performance is dominated by mechanical seek and rotation.
  • Sequential access and careful scheduling/allocation are crucial for HDDs.
  • SSDs avoid mechanical latency but introduce erase-before-write and wear-out constraints.
  • The FTL uses indirection to hide erase latency and perform wear leveling.
  • RAID combines disks for bandwidth, capacity, and reliability.
  • RAID-0 gives speed but no redundancy.
  • RAID-1 mirrors data.
  • RAID-4 uses a dedicated parity disk but creates a write bottleneck.
  • RAID-5 distributes parity.
  • RAID-6 and RAID-10 are common extensions with different reliability/performance/cost tradeoffs.

2. Lecture 13: Block Cache and File Organization

2.1. Administrative notes

  • The midterm was announced for the following Monday.
  • Students were asked to register so the teaching team could print the right number of copies.
  • The midterm scope was announced as everything up to and including this lecture.
  • The lecture itself focused on:
    • caching block storage for performance;
    • mapping files to blocks;
    • file layout;
    • metadata;
    • free-space management.

2.2. Review from Lecture 12

  • Block storage devices expose read/write access to fixed-size blocks.
  • HDDs and SSDs are much slower than main memory.
  • RAID combines disks for performance and reliability.
  • A major rule for high performance is: avoid disk access unless necessary.
  • This motivates block caching.

2.3. Why cache storage blocks?

2.3.1. Disks and SSDs are much slower than memory

  • HDDs are especially slow because of seek and rotational latency.
  • SSDs are faster than HDDs but still much slower than DRAM.
  • Therefore, repeatedly going to storage for the same data is wasteful.

2.3.2. Data must be in memory anyway

  • The CPU operates on memory addresses.
  • To process file data, the OS must eventually bring it into memory.
  • Once the data is already in memory, keeping it around can make future accesses much faster.

2.3.3. Locality

Applications and file systems often show locality:

  • temporal locality:
    • recently used data is likely to be used again soon;
  • spatial locality:
    • data near recently used data is likely to be used soon.

Caching exploits both.

2.3.4. Repeated reads become cheap

  • First read:
    • miss in cache;
    • fetch block from storage;
    • store it in memory.
  • Later reads:
    • hit in cache;
    • avoid storage access;
    • return data from memory.

2.3.5. Fine-grained writes

  • Block devices operate at block granularity.
  • Applications often write only a few bytes.
  • Without a cache, a small write may require:
    1. read whole block,
    2. modify a few bytes in memory,
    3. write whole block back.
  • With a cache, the OS can modify the cached block in memory and delay or combine writes.

2.3.6. Combining writes

  • Multiple writes to the same block can be merged before writing back to disk.
  • Sequential writes can be grouped into larger I/O requests.
  • This improves performance and can reduce SSD wear.

2.4. Buffer cache / page cache

2.4.1. Basic idea

  • The buffer cache, also called the page cache, stores recently used storage blocks in memory.
  • Persistent data remains on disk.
  • Recently used data is also held in memory.
  • The important design question is how to allocate and manage this memory.

2.4.2. Early Unix-style fixed buffer cache

  • Simple approach:
    • allocate a fixed pool of buffers at boot;
    • use that pool only for disk block caching.
  1. Advantages
    • Simple design.
    • Predictable amount of memory reserved for the buffer cache.
  2. Disadvantages
    • Fixed size:
      • too small if workload needs more cache;
      • too large if workload needs memory for other purposes.
    • Memory is reserved and cannot easily be used elsewhere.
    • Double caching:
      • one copy in the buffer cache;
      • another copy in a process’s virtual memory.
    • Double caching wastes memory and requires extra copying.

2.4.3. Integrated buffer cache

  1. Core idea
    • Modern systems integrate the buffer cache with the virtual memory system.
    • The same physical page pool is used both for:
      • ordinary virtual memory pages;
      • cached file/block data.
    • Unused physical pages can cache file data.
    • If the kernel later needs memory, it can reclaim clean cached pages or write back dirty pages.
  2. Buffer cache and paging are the same idea from opposite directions
    • Buffer cache view:
      • primary copy is on disk;
      • recently used data is cached in memory.
    • Paging view:
      • primary working data is in memory;
      • not recently used pages may be stored on disk.
    • Both manage memory pages and disk-backed contents.
  3. Advantages
    • Highly flexible memory use.
    • One memory pool instead of two fixed pools.
    • Less duplicated logic.
    • Avoids double caching.
    • Enables mapping file-backed pages directly into process address spaces.
    • Works well with mechanisms such as copy-on-write.

2.4.4. Clarifying the unification

  • In the fixed-cache design, the kernel may read a disk block into a separate buffer cache region, then copy it into a process buffer.
  • In an integrated design, a physical page can simultaneously be:
    • the cached copy of a file block;
    • mapped into a process address space.
  • Therefore, if a file block is already cached, the OS may only need to map the page rather than copy it.
  • If a process writes to a shared page, the OS must handle correctness, for example through synchronization or copy-on-write depending on the mapping semantics.

2.5. Example: BSD buffer cache interface

2.5.1. Basic functions

Conceptual BSD-style functions:

// Fill buffer from underlying device/file.
int bread(struct vnode *vp, daddr_t blkno, int size, struct buf **bpp);

// Release a clean buffer.
void brelse(struct buf *bp);

// Synchronously write buffer contents to device/file.
int bwrite(struct buf *bp);

// Asynchronously write buffer contents.
void bawrite(struct buf *bp);
  1. Important parameters
    • vnode *vp identifies the file/device object.
    • blkno is the logical block number.
    • buf **bpp returns a buffer handle.

2.5.2. Read-ahead

int bread_cluster(struct vnode *vp, daddr_t blkno, int size, struct buf **bpp);
  • Reads the requested block.
  • Also starts loading subsequent blocks.
  • Useful when sequential access is likely.
  • Hides future disk latency.

2.5.3. Delayed write / write-back

void bdwrite(struct buf *bp);
  • Marks a buffer dirty.
  • Queues it for later write-back.
  • Allows the OS to:
    • combine writes;
    • schedule writes efficiently;
    • avoid immediate disk access.
  • But delayed writes affect persistence semantics:
    • if the system crashes before write-back, dirty data may be lost;
    • applications that need durability must use explicit sync/fsync-like operations.

2.5.4. Synchronous vs asynchronous writes

  • Synchronous write:
    • caller waits until data is written.
    • stronger durability point.
    • slower.
  • Asynchronous write:
    • write is queued or started in the background.
    • caller can continue sooner.
    • the OS must preserve correctness despite possible reordering or overlapping writes.

2.6. BSD buffer lifecycle

2.6.1. Four main states

A buffer can be in one of the following conceptual states:

  • Unused / Empty
  • Clean
  • Busy / Locked
  • Dirty

2.6.2. Unused / Empty

  • The buffer is free.
  • It does not currently correspond to a useful disk block.
  • It is available for new data.
  • A read can allocate it and fill it from disk.

2.6.3. Clean

  • The buffer contains data from disk.
  • The memory copy is in sync with the disk copy.
  • If the OS needs memory, a clean buffer can be reclaimed without writing it back.
  • A clean buffer can be requested for I/O and become busy/locked.

2.6.4. Busy / Locked

  • Some operation is currently using the buffer.
  • The buffer may be read or modified.
  • The kernel records this state so that other operations do not concurrently corrupt or reclaim the buffer.
  • When the user/kernel operation releases the buffer:
    • if contents did not change, it returns to clean;
    • if contents changed, it becomes dirty.

2.6.5. Dirty

  • The buffer contains data that differs from the disk.
  • It must eventually be written back to disk.
  • After write-back completes, it becomes clean again.

2.6.6. State transitions

  1. Unused \(\rightarrow\) Clean
    • The OS reads data from disk into an empty buffer.
    • The buffer now contains an up-to-date disk block.
  2. Clean \(\rightarrow\) Busy / Locked
    • Some process or kernel code requests the buffer for I/O or access.
    • The buffer is locked while in use.
  3. Busy / Locked \(\rightarrow\) Clean
    • The operation finishes without modifying the data.
    • The memory copy still matches the disk.
  4. Busy / Locked \(\rightarrow\) Dirty
    • The operation modifies the buffer.
    • The memory copy no longer matches disk.
  5. Dirty \(\rightarrow\) Clean
    • The OS writes the dirty contents back to disk.
    • After successful write-back, memory and disk match again.
  6. Clean \(\rightarrow\) Unused
    • If the buffer is clean and no longer needed, the OS can reclaim it.
    • The disk still has the data, so the memory copy can be discarded.

2.6.7. Why certain transitions do not exist

  1. No Dirty \(\rightarrow\) Unused
    • Dirty data cannot simply be discarded.
    • It must first be written back.
    • Otherwise, updates would be lost.
  2. No Unused \(\rightarrow\) Dirty
    • A buffer cannot become dirty before it contains meaningful data.
    • Usually the OS must first read the block or allocate/initialize it.
    • Then modifications can make it dirty.
  3. Dirty \(\rightarrow\) Clean does not go through Busy
    • Busy means the buffer contents are actively being used or potentially modified.
    • Writing dirty data back to disk does not modify the buffer contents themselves.
    • It only synchronizes the disk copy with the existing memory contents.

2.6.8. Implementation idea: multiple views of the same buffers

  • A real buffer cache implementation needs several data structures.
  • It may organize buffers by:
    • state lists: locked, dirty, clean, empty;
    • hash table: key such as \((vnode, file offset)\) to quickly find cached blocks.
  • The same buffer can be linked into multiple structures so the kernel can efficiently answer different questions:
    • Is block \(X\) of file \(Y\) cached?
    • Which dirty buffers need write-back?
    • Which clean buffers can be reclaimed?
    • Are there empty buffers available?

2.7. File systems

2.7.1. What a file system is

  • A file system is a storage abstraction layer.
  • It maps human/application-level file operations to block-device operations.
  • It hides details such as:
    • block allocation,
    • placement,
    • free-space tracking,
    • metadata layout.

2.7.2. Why applications should not use raw blocks directly

Without a file system, every application would need to manage:

  • which disk blocks belong to it;
  • how to grow or shrink data;
  • how to avoid collisions with other applications;
  • how to name and find stored data;
  • how to enforce permissions;
  • how to recover after crashes.

A file system centralizes these responsibilities.

2.7.3. What a file system provides

  • Naming:
    • human-readable names,
    • paths,
    • directories.
  • Access permissions.
  • Sharing:
    • between users,
    • between processes.
  • Reliability.
  • High performance.
  • Persistence across runs, reboots, power outages, and failures.
  • Concurrency support for simultaneous access.

2.7.4. File system challenges

  • Disk management:
    • efficient use of disk space;
    • fast access to files and directories;
    • sharing space between users.
  • Naming:
    • how users select and find files.
  • Protection:
    • enforcing access permissions.
  • Persistence:
    • surviving program runs, reboots, power outages, and hardware failures.
  • Concurrency:
    • multiple processes/users may read and write simultaneously.

This lecture focused mainly on disk management: file structure and free-space management.

2.8. File structure

2.8.1. What is a file?

  1. Application view
    • A file is a named collection of bytes.
    • It has sequential byte offsets.
  2. OS view
    • A file is an ordered set of blocks stored on a block device.
    • The OS must translate byte offsets to block numbers.
  3. File-system view
    • On write:
      • pack bytes into disk blocks.
    • On read:
      • unpack bytes from disk blocks into the user buffer.
    • The file system must make block-granularity devices look like byte-granularity files.

2.8.2. Common file access patterns

  1. Sequential read
    • Example: parsing an input file.
    • Data is read in order.
    • Very friendly to read-ahead and HDD layout.
  2. Append
    • Example: log files.
    • New data is written at the end.
    • Often sequential.
  3. Sequential overwrite
    • Example: updating intermediate results or checkpoints.
    • Existing regions may be overwritten in order.
  4. Random read / overwrite
    • Examples:
      • browser cache,
      • database row update,
      • backing storage for demand paging.
    • Harder to optimize with sequential layout assumptions.
  5. File-size distribution
    • Many systems have:
      • a few very large files;
      • many very small files.
    • Many accesses are to small files.
    • A good file system must handle both cases efficiently.

2.8.3. File-system implementation problem

The file system must translate:

Read(uid, buffer, bytes);

into block-device operations such as:

ReadSector(logical_sector_number, buffer);

The central question:

  • How do we use disk blocks to represent files?
  • Storing bytes in blocks is easy.
  • The hard part is knowing which block corresponds to which file and offset.

2.9. File-system metadata

2.9.1. Metadata needed for files

A file system must store information such as:

  • file size;
  • owner;
  • access rights;
  • access time;
  • modification time;
  • location of file blocks;
  • free-space information.

2.9.2. inode

  • In Unix terminology, file metadata is stored in an inode.
  • inode = index node.
  • An inode contains:
    • file size,
    • permissions,
    • ownership,
    • timestamps,
    • pointers or indexes to the file’s data blocks.
  • The important mapping is:

\[ (file,\ offset) \rightarrow block. \]

2.9.3. Free-space map

  • The file system also needs to know which disk blocks are unused.
  • This is needed when creating or growing files.
  • Free-space metadata must also be persistent.
  • If the system reboots and the free-space map was only in memory, the file system would not know which blocks are available.

2.10. Data allocation: goals and schemes

2.10.1. Goals

A good file allocation scheme should:

  • use disk space effectively;
  • support fast sequential access;
  • support random access when needed;
  • avoid excessive fragmentation;
  • allow files to grow;
  • keep metadata compact;
  • work well for both small and large files.

2.10.2. Schemes covered

  • Contiguous allocation / extents.
  • Segmentation / multiple extents per file.
  • Linked list of blocks.
  • File Allocation Table (FAT).
  • Indexed file.
  • Multi-level indexed file.
  • Dynamic extent trees.

2.11. Contiguous allocation: single extent

2.11.1. Basic idea

  • Allocate each file as one contiguous extent.
  • An extent is:

\[ Extent(start, len) \] where start is the first block and len is the number of contiguous blocks.

  • The inode only needs to record the start and length.
  • The free-space map tracks unused extents.

2.11.2. Advantages

  • Very fast sequential access.
  • Easy read-ahead.
  • Compact metadata.
  • Simple design.
  • Good performance on HDDs because blocks are physically/logically close.

2.11.3. Disadvantages

  1. External fragmentation
    • Free space may exist but be split into holes too small for a new file.
    • Example:
      • file 1 and file 2 occupy blocks with a gap between them;
      • file 3 needs more contiguous space than the gap;
      • file 3 cannot use that gap even though total free space may be enough.
  2. Hard to grow files
    • If a file needs to grow but the following blocks are already occupied, the file cannot extend in place.
    • The file system may need to move the file or allocate a new region.
  3. Internal fragmentation
    • Even a tiny file may need at least one whole block.
    • If an extent is allocated larger than the file actually uses, the unused part is wasted inside the allocation.

2.12. Segmentation: multiple extents per file

2.12.1. Basic idea

  • A file may consist of multiple extents.
  • The inode stores a table of \((base, size)\) pairs.
  • Each pair describes a contiguous run of blocks.

2.12.2. Advantages

  • Still supports fast sequential access within each extent.
  • More flexible than a single extent.
  • A growing file can be extended by allocating another extent elsewhere.
  • Reduces some external fragmentation compared with strict contiguous allocation.

2.12.3. Disadvantages

  • Still has some fragmentation.
  • Metadata grows as the file becomes more fragmented.
  • Sequential access across extent boundaries may require jumps.
  • Too many small extents can degrade performance.
  • Still has block-level internal fragmentation for tiny files.

2.13. Linked list of blocks

2.13.1. Basic idea

  • Organize the blocks of a file as a linked list.
  • Each block stores a pointer to the next block.
  • The file’s metadata stores at least the first block.
  • Free space can be managed with a global free list.

2.13.2. Advantages

  • Constant-size per-file metadata, excluding the pointers stored in blocks.
  • No external fragmentation:
    • any free block can be used.
  • Easy to grow:
    • allocate a new block and link it at the end.

2.13.3. Disadvantages

  1. Random access is poor
    • To access block \(k\), the file system must follow \(k\) pointers from the start.
    • This is linear-time pointer chasing.
  2. Sequential access is also slower
    • Blocks may be scattered across the disk.
    • Even sequential file reading can become random disk I/O.
    • Pointer chasing may require reading metadata from each block.
  3. Internal fragmentation and metadata overhead
    • Each block must store a pointer.
    • This reduces usable data space in each block.
    • Pointer metadata grows linearly with the number of blocks.

2.14. File Allocation Table (FAT)

2.14.1. Basic idea

  • FAT keeps the linked-list pointers in a separate table instead of inside each data block.
  • Data blocks contain only file data.
  • The FAT entry for a block tells which block comes next.
  • File metadata or directory entries identify the first block of the file.

2.14.2. Example intuition

For a file whose first data block is 9:

  • FAT[9] may point to 10.
  • FAT[10] may point to 11.
  • FAT[11] may point to 3.
  • FAT[3] may point to the next block, and so on.
  • An end marker indicates the end of the file.

2.14.3. Why FAT improves over in-block linked lists

  • The pointer table is separate and can be cached in memory.
  • Pointer chasing can happen in memory instead of on disk.
  • This is much better than reading every data block just to find the next pointer.

2.14.4. Requirements and costs

  • The FAT must be stored on disk for persistence.
  • It is usually loaded/cached in memory.
  • It needs entries for possible blocks.
  • Therefore, metadata can be large.
  • For FAT32-style entries, each entry is 32 bits.
  • Maximum addressable size depends on entry size and block/cluster size.

2.14.5. Advantages

  • Conceptually simple.
  • Data blocks are not polluted with next-block pointers.
  • Better than raw linked lists if the FAT is cached.
  • Supports finding the next block without reading the current data block.

2.14.6. Disadvantages

  • Large metadata table.
  • Must cache the FAT for performance.
  • Random access is still slow in the sense that the file system may need to walk the chain in the FAT.
  • Fragmented files still cause non-sequential data I/O.
  • Historically often required defragmentation for performance on HDDs.

2.15. Indexed file

2.15.1. Basic idea

  • Keep an array of block pointers in the inode.
  • Each pointer refers directly to a data block.
  • Blocks are allocated dynamically as the file grows.

2.15.2. Advantages

  • Direct indexing is better for random access than linked lists.
  • The file system can compute which pointer corresponds to a file offset.
  • Data blocks do not need to store next pointers.

2.15.3. Problems

  • The inode may need many pointers for large files.
  • Lots of metadata may be stored in the inode.
  • A maximum file size may need to be fixed at creation time.
  • It is hard to predict how large a file will become.
  • Wastes inode space for small files if too many pointer slots are reserved.

2.16. Multi-level indexed file

2.16.1. Basic idea

  • Use an asymmetric tree of blocks rooted in the inode.
  • The inode contains:
    • direct pointers to data blocks;
    • indirect pointer(s) to blocks that contain more pointers;
    • double-indirect pointer(s);
    • triple-indirect pointer(s).
  • Indirect blocks are allocated only when needed.

2.16.2. Direct pointers

  • Point directly from inode to data blocks.
  • Efficient for small files.
  • Many small files can be represented without extra metadata blocks.

2.16.3. Single indirect pointer

  • Points to a block containing many data-block pointers.
  • Allows larger files without putting all pointers directly in the inode.

2.16.4. Double indirect pointer

  • Points to a block of pointers to indirect blocks.
  • Each indirect block then points to data blocks.
  • Supports much larger files.

2.16.5. Triple indirect pointer

  • Adds one more level.
  • Supports very large files at the cost of more metadata lookups.

2.16.6. Why the tree is asymmetric

  • The inode has a small number of direct pointers for small files.
  • It also has indirect pointers for larger files.
  • Small files stay cheap.
  • Large files can still grow.

2.16.7. Sparse files

  • Multi-level indexing allows holes.
  • A file can have a large logical size without allocating blocks for all offsets.
  • Example:
    • a 1 GiB file with data only at offset 0 and offset 1 GiB;
    • blocks in the middle need not be allocated.
  • Reading a hole can return zeros without storing physical blocks.

2.16.8. Examples

  • Unix Fast File System (FFS).
  • ext2.
  • ext3.

2.16.9. Advantages

  • Simple to manage compared with more complex dynamic extent trees.
  • Metadata grows incrementally.
  • Efficient for small files because direct pointers are enough.
  • Supports sparse files.
  • Allows files to grow after creation.

2.16.10. Disadvantages

  • Inefficient for very large files compared with extent-based schemes.
  • Large files require many metadata blocks.
  • Accessing blocks through double/triple indirection may require extra metadata reads.
  • Metadata overhead can become large.

2.17. Dynamic extent trees

2.17.1. Motivation

  • Block-by-block pointer schemes are not ideal for large files.
  • Large files often benefit from contiguous ranges.
  • Extents are compact:
    • one extent can represent many contiguous blocks.
  • Extents are fast:
    • sequential access works well if fragmentation is low.

2.17.2. Basic idea

  • Organize extents in a dynamic tree.
  • Inner nodes point to other tree nodes or extent descriptors.
  • Leaves describe data extents.
  • The tree height and shape can change as the file changes.
  • This combines:
    • extent efficiency for large contiguous ranges;
    • dynamic growth like an index/tree structure.

2.17.3. Examples

  • NTFS.
  • ZFS.
  • ext4.

2.17.4. Advantages

  • Low fragmentation when allocation succeeds well.
  • Fast sequential access.
  • Compact metadata for large contiguous files.
  • Better for large files than block-by-block indexing.

2.17.5. Disadvantages

  • More complex implementation.
  • Metadata overhead grows with fragmentation.
  • Long-lived large files that are repeatedly modified can become fragmented.
  • The file system needs more sophisticated allocation and tree maintenance.

2.18. Fragmentation

2.18.1. External fragmentation

  • Free space exists, but not in large enough contiguous chunks.
  • Affects contiguous and extent-based allocation.
  • Makes it harder to allocate large contiguous files.

2.18.2. Internal fragmentation

  • Allocated space is not fully used.
  • Example:
    • a 1-byte file still consumes at least one block.
  • Also occurs if a file reserves an extent larger than its actual data.

2.18.3. Fragmentation and performance

  • HDDs are very sensitive to fragmentation because fragmented files cause seeks.
  • SSDs are less sensitive to physical seek costs, but fragmentation still affects:
    • metadata size,
    • I/O request count,
    • cache behavior,
    • write amplification in some cases.

2.19. Free-space management

2.19.1. Problem

  • The file system must quickly find free blocks when creating or extending files.
  • It must also free blocks when files shrink or are deleted.
  • The method depends on the file organization scheme.

2.19.2. Goals

  • Allocating a block should be fast.
  • Allocating contiguous ranges should be possible when beneficial.
  • Fragmentation should be minimized.
  • Metadata overhead should remain acceptable.
  • Free-space data must be persistent.

2.20. Bitmap free-space management

2.20.1. Basic idea

  • Use one bit per disk block.
  • Convention from the lecture:
    • bit = 1 means block is free;
    • bit = 0 means block is used.
  • Allocation:
    1. find a bit set to 1;
    2. set it to 0;
    3. return the corresponding block number.
  • Freeing:
    1. set the bit for that block back to 1.

2.20.2. Space overhead example

For a 4 TB drive with 4 KiB blocks: \[ \frac{4\text{ TB}}{4\text{ KiB}} = \frac{2^{42}}{2^{12}} = 2^{30} \] blocks.

One bit per block means: \[ 2^{30}\text{ bits} = 2^{27}\text{ bytes} = 128\text{ MiB}. \]

So the bitmap overhead is about 128 MiB.

2.20.3. Advantages

  • Compact relative to disk size.
  • Easy to test whether a block is free.
  • Can be scanned for contiguous free ranges.
  • Works well with bit-level and word-level operations.

2.20.4. Disadvantages

  • Large disks still require large bitmaps.
  • Naive scanning can be slow.
  • Finding large contiguous regions may require extra structure.
  • The bitmap itself must be cached and updated consistently.

2.20.5. Optimizations

  1. Chunking
    • Break the bitmap into chunks.
    • Store per-chunk statistics:
      • number of free blocks;
      • largest contiguous free region;
      • maybe first/last free positions.
    • This helps quickly choose promising chunks.
  2. Hints
    • Store hints about where the next allocation might succeed.
    • Avoid scanning from the beginning every time.
  3. Word-level operations
    • Access bitmap as machine words.
    • If a word is 0, then it contains no free blocks under the lecture’s convention.
    • This skips many bits at once.
  4. Batch allocation / preallocation
    • Allocate multiple blocks at once.
    • Prefer contiguous ranges.
    • Helps sequential writes.
    • Reduces metadata update frequency.

2.21. Other free-space management schemes

2.21.1. Linked list of free blocks

  • Link all free blocks together.
  • Each free block points to the next free block.
  • Easy to implement.
  • Easy to allocate one block at a time.
  • Slow when trying to find multiple contiguous blocks.
  • Poor for extent-based allocation.

2.21.2. Grouped linked list

  • Similar to linked free list, but groups contiguous blocks together.
  • Stores ranges rather than individual blocks.
  • More efficient for allocating large runs.
  • Better for large files and sequential layout.
  • More complicated than a simple linked list.

2.21.3. Relation to allocation scheme

  • Contiguous allocation needs free extents.
  • Linked-list file allocation can work with a simple free list.
  • Extent trees benefit from free-space structures that find large contiguous regions.
  • Multi-level indexed files can tolerate scattered blocks better, but still benefit from locality.

2.22. Lecture 13 key takeaways

  • Block caching is necessary because storage is much slower than memory.
  • The buffer/page cache stores recently used disk blocks in memory.
  • Modern systems integrate the buffer cache with virtual memory.
  • Clean, dirty, busy/locked, and unused states help maintain correctness.
  • Delayed write and read-ahead improve performance but require careful durability semantics.
  • A file system maps named byte streams to block devices.
  • File metadata is stored in inodes or inode-like structures.
  • File allocation schemes trade off metadata size, sequential performance, random access, fragmentation, and growth.
  • Contiguous extents are fast but hard to grow and fragment externally.
  • Segmentation uses multiple extents to improve flexibility.
  • Linked lists avoid external fragmentation but make random access bad.
  • FAT moves linked-list pointers into a separate table, improving pointer access if cached.
  • Indexed and multi-level indexed files improve random access and support sparse files.
  • Dynamic extent trees combine extent efficiency with dynamic growth.
  • Free-space management must quickly find blocks and preferably contiguous ranges.
  • Bitmaps are compact and common, but require optimization for large disks.

3. Cross-lecture synthesis

3.1. The main design tension

Storage systems constantly trade off:

  • performance,
  • reliability,
  • capacity,
  • metadata overhead,
  • implementation complexity,
  • persistence guarantees.

3.2. Why the lower-level device details matter to file systems

  • HDDs reward sequential layout and punish random seeks.
  • SSDs reduce random-access penalties but introduce erase-before-write and wear-leveling issues.
  • RAID can improve bandwidth and reliability, but changes failure modes and write behavior.
  • Block caches hide latency and combine writes, but create correctness and durability questions.
  • File organization determines whether access patterns become sequential or random at the block-device level.

3.3. A useful mental model

A file read goes through several translations:

  1. Application asks for bytes from a file.
  2. File system maps file offset to logical block(s).
  3. Buffer/page cache checks whether the block is already in memory.
  4. If not cached, the block device is asked to read logical sector(s).
  5. HDD/SSD/controller maps logical sectors to physical media operations.
  6. Data is returned to memory.
  7. The OS copies or maps the data to the application.

A file write similarly flows downward, but may stop temporarily in the cache as dirty data before reaching persistent storage.

3.4. Important exam-style comparisons

3.4.1. HDD vs SSD

Aspect HDD SSD
Technology Magnetic platters NAND flash
Moving parts Yes No
Random access Slow Fast
Sequential access Much faster than random Still beneficial
Dominant latency Seek + rotation Flash read/write/erase
Write wear No flash-style wear Erase blocks wear out
In-place overwrite Yes, conceptually No
Internal indirection Controller/LBA FTL

3.4.2. RAID levels

Level Main idea Capacity Failure tolerance Main issue
RAID-0 Striping Full None Any disk failure loses data
RAID-1 Mirroring Half One mirror copy can fail Expensive capacity cost
RAID-4 Dedicated parity disk \(N/(N+1)\) data fraction One disk Parity disk write bottleneck
RAID-5 Distributed parity Similar to RAID-4 One disk More complex; rebuild risk
RAID-6 Double parity Lower than RAID-5 Two disks More parity overhead
RAID-10 Stripe over mirrors Half Depends on which disks fail Expensive

3.4.3. File allocation schemes

Scheme Sequential access Random access Metadata Growth Fragmentation
Single extent Excellent Good if offset known Tiny Hard High external
Multiple extents Good if few extents Good with extent table Grows with extents Easier Some external
Linked blocks Poor if scattered Poor Pointer per block Easy No external, internal overhead
FAT Better pointer access if cached Still chain traversal Large table Easy Data can fragment
Indexed Good random access Good Many inode pointers Fixed max problem Depends on allocation
Multi-level indexed Good for small files; scalable Good but may need metadata reads Incremental Good Supports sparse files
Dynamic extent tree Excellent if low fragmentation Good Compact for large extents Good Low if allocator succeeds

4. Glossary

4.1. Block

The minimum unit of read/write access exposed by a block storage device.

4.2. Sector

HDD terminology for a physical/logical unit of disk access, often used similarly to block.

4.3. Track

A circular path on one disk surface.

4.4. Cylinder

The set of tracks at the same radius across all disk surfaces.

4.5. Seek

Mechanical movement of the HDD arm to the desired cylinder.

4.6. Rotational latency

Waiting for the desired sector to rotate under the head.

4.7. Read-ahead / prefetching

Loading blocks before they are explicitly requested, based on expected sequential access.

4.8. Buffer cache / page cache

In-memory cache of recently used storage blocks or file pages.

4.9. Clean buffer

Cached data that matches the disk copy.

4.10. Dirty buffer

Cached data that has been modified in memory but not yet written back to disk.

4.11. Busy / locked buffer

A buffer currently being used, so it should not be reclaimed or concurrently modified unsafely.

4.12. inode

Unix-style metadata structure for a file.

4.13. Extent

A contiguous run of disk blocks.

4.14. Fragmentation

A situation where free or used space is split into pieces, reducing allocation efficiency or access performance.

4.15. FAT

File Allocation Table; a file organization scheme that stores linked-list block pointers in a separate table.

4.16. Sparse file

A file with holes: large logical regions without allocated physical blocks.

4.17. Bitmap

A compact data structure using one bit per block to track free/used status.

4.18. FTL

Flash Translation Layer; SSD controller layer mapping logical pages to physical flash pages.

4.19. Wear leveling

SSD technique that spreads erases/writes across physical blocks to avoid wearing out a few hot blocks.

4.20. RAID

Combining multiple disks for performance, capacity, and/or reliability.

4.21. Parity

Redundant information, often XOR of data blocks, used to reconstruct missing data after a disk failure.

Author: Lowtroo

Created on: 2026-05-31 Sun 10:00

Powered by Emacs 29.3 (Org mode 9.6.15)