Session 6.1 – Secondary Storage Structure

Understanding magnetic disks, SSD architecture, and storage performance optimization in modern operating systems

2 Hours Module 6 Storage Management & Security

Learning Objectives

By the end of this session, you will be able to:

  • Understand the physical structure and operation of magnetic disk drives
  • Analyze SSD architecture and compare with traditional hard drives
  • Calculate disk scheduling algorithms and their performance implications
  • Evaluate storage performance metrics and optimization techniques
  • Design efficient storage hierarchies for different application requirements

Magnetic Disk Structure

Physical Components

Magnetic disk drives consist of several key physical components that work together to provide persistent storage. Understanding these components is essential for optimizing storage performance and predicting system behavior.

Disk Components:
  • Platter: Circular magnetic disk surface
  • Track: Concentric circles on platter surface
  • Sector: Fixed-size storage units on tracks
  • Cylinder: Set of tracks at same arm position
  • Head: Read/write mechanism
  • Arm: Mechanical actuator for head movement

Disk Geometry and Addressing

Modern disk drives use Cylinder-Head-Sector (CHS) addressing or Logical Block Addressing (LBA) to locate specific data blocks. Understanding addressing schemes is crucial for disk scheduling optimization.

Example: CHS to LBA Conversion

Given a disk with:

  • Cylinders: 1024
  • Heads: 16
  • Sectors per track: 63
CHS to LBA Conversion Formula:

LBA = (C × Heads + H) × Sectors_per_track + (S - 1)

Where:
    C = Cylinder number
    H = Head number  
    S = Sector number

Example Calculation:
Given: CHS (100, 5, 30)
    Cylinders = 1024, Heads = 16, Sectors_per_track = 63

Step 1: Calculate cylinder and head component
    (C × Heads + H) = (100 × 16 + 5) = 1605

Step 2: Multiply by sectors per track
    1605 × 63 = 101,115

Step 3: Add sector offset
    101,115 + (30 - 1) = 101,115 + 29 = 101,144

Result: LBA = 101,144

Disk Performance Metrics

Several timing components contribute to overall disk access time. Understanding these metrics enables effective performance analysis and optimization.

Disk Access Time Components
Total Access Time Formula:

Access_Time = Seek_Time + Rotational_Delay + Transfer_Time

Component Breakdown:

┌───────────────────┬────────────────────────────────────────┐
│    Component     │                Description                     │
├───────────────────┼────────────────────────────────────────┤
│                 │ Time to position read/write head over      │
│   Seek Time     │ the correct track. Depends on:             │
│                 │ • Current head position                   │
│                 │ • Target track location                   │
├───────────────────┼────────────────────────────────────────┤
│                 │ Time for desired sector to rotate under    │
│ Rotational      │ the head. Average = Revolution_time / 2    │
│   Delay         │ • Depends on rotational speed (RPM)       │
│                 │ • Worst case = Full revolution            │
├───────────────────┼────────────────────────────────────────┤
│                 │ Time to read/write data from/to disk.      │
│ Transfer Time   │ = Data_size / Transfer_rate                 │
│                 │ • Usually smallest component               │
│                 │ • Sequential access is faster             │
└───────────────────┴────────────────────────────────────────┘

Performance Optimization Focus:
    • Seek Time: Use scheduling algorithms (SSTF, SCAN)
    • Rotational Delay: NCQ, read-ahead, write coalescing
    • Transfer Time: Larger block sizes, parallel I/O
Example: Access Time Calculation

For a disk with the following specifications:

  • Average seek time: 8ms
  • Rotational speed: 7200 RPM
  • Transfer rate: 100 MB/s
  • Block size: 4KB
Disk Access Time Calculation:

Given Specifications:
    • Average seek time: 8ms
    • Rotational speed: 7200 RPM
    • Transfer rate: 100 MB/s
    • Block size: 4KB

Step 1: Calculate Rotational Delay
    Revolution_time = 60 seconds ÷ 7200 RPM = 8.33ms
    Average_rotational_delay = 8.33ms ÷ 2 = 4.17ms

Step 2: Calculate Transfer Time
    Transfer_time = 4KB ÷ 100MB/s 
                  = 4,096 bytes ÷ (100 × 10⁶ bytes/s)
                  = 0.04ms

Step 3: Calculate Total Access Time
    Total_time = Seek_time + Rotational_delay + Transfer_time
               = 8ms + 4.17ms + 0.04ms
               = 12.21ms

Time Breakdown:
    ┌─────────────────┬─────────┬──────────┐
    │   Component     │  Time   │ Percent  │
    ├─────────────────┼─────────┼──────────┤
    │ Seek Time       │  8.00ms │   65.5%  │
    │ Rotational Delay│  4.17ms │   34.2%  │
    │ Transfer Time   │  0.04ms │    0.3%  │
    │ TOTAL          │ 12.21ms │  100.0%  │
    └─────────────────┴─────────┴──────────┘

Disk Scheduling Algorithms

Disk scheduling algorithms minimize seek time by optimizing the order in which disk I/O requests are serviced. Different algorithms offer varying performance characteristics depending on workload patterns.

First-Come, First-Served (FCFS)

FCFS Algorithm
Algorithm FCFS_Disk_Scheduling:

Input: request_queue[], initial_head_position
Output: service_sequence[], total_seek_time

BEGIN
    total_seek_time = 0
    current_position = initial_head_position
    service_sequence = []
    
    FOR EACH request in request_queue DO
        seek_distance = |current_position - request|
        total_seek_time = total_seek_time + seek_distance
        service_sequence.append(request)
        current_position = request
    END FOR
    
    RETURN service_sequence, total_seek_time
END
Time Complexity: O(n)

Simple but may result in high seek times for scattered requests.

Shortest Seek Time First (SSTF)

SSTF Algorithm
Algorithm SSTF_Disk_Scheduling:

Input: request_queue[], initial_head_position
Output: service_sequence[], total_seek_time

BEGIN
    remaining_requests = copy(request_queue)
    total_seek_time = 0
    current_position = initial_head_position
    service_sequence = []
    
    WHILE remaining_requests is not empty DO
        closest_request = NULL
        min_distance = INFINITY
        
        FOR EACH request in remaining_requests DO
            distance = |current_position - request|
            IF distance < min_distance THEN
                min_distance = distance
                closest_request = request
            END IF
        END FOR
        
        total_seek_time = total_seek_time + min_distance
        service_sequence.append(closest_request)
        remaining_requests.remove(closest_request)
        current_position = closest_request
    END WHILE
    
    RETURN service_sequence, total_seek_time
END
Time Complexity: O(n²)

Better average performance but can cause starvation of distant requests.

SCAN (Elevator) Algorithm

SCAN (Elevator) Algorithm
Algorithm SCAN_Disk_Scheduling:

Input: request_queue[], initial_head_position, disk_size, direction
Output: service_sequence[], total_seek_time

BEGIN
    left_requests = []
    right_requests = []
    
    // Partition requests based on initial head position
    FOR EACH request in request_queue DO
        IF request < initial_head_position THEN
            left_requests.append(request)
        ELSE
            right_requests.append(request)
        END IF
    END FOR
    
    // Sort requests for optimal scanning
    sort(left_requests, DESCENDING)   // From head toward 0
    sort(right_requests, ASCENDING)   // From head toward end
    
    total_seek_time = 0
    current_position = initial_head_position
    service_sequence = []
    
    IF direction == "RIGHT" THEN
        // Service right side first
        FOR EACH request in right_requests DO
            total_seek_time += |current_position - request|
            service_sequence.append(request)
            current_position = request
        END FOR
        
        // Move to disk end if needed
        IF current_position != disk_size-1 THEN
            total_seek_time += (disk_size-1) - current_position
            current_position = disk_size-1
        END IF
        
        // Service left side
        FOR EACH request in left_requests DO
            total_seek_time += |current_position - request|
            service_sequence.append(request)
            current_position = request
        END FOR
    END IF
    
    RETURN service_sequence, total_seek_time
END
Time Complexity: O(n log n)

Provides uniform wait times and prevents starvation.

C-SCAN (Circular SCAN) Algorithm

C-SCAN (Circular SCAN) Algorithm
Algorithm C_SCAN_Disk_Scheduling:

Input: request_queue[], initial_head_position, disk_size
Output: service_sequence[], total_seek_time

BEGIN
    left_requests = []
    right_requests = []
    
    // Partition requests based on initial head position
    FOR EACH request in request_queue DO
        IF request < initial_head_position THEN
            left_requests.append(request)
        ELSE
            right_requests.append(request)
        END IF
    END FOR
    
    // Sort for circular scanning (both ascending)
    sort(left_requests, ASCENDING)    // From 0 upward
    sort(right_requests, ASCENDING)   // From head upward
    
    total_seek_time = 0
    current_position = initial_head_position
    service_sequence = []
    
    // Service right side first (toward end)
    FOR EACH request in right_requests DO
        total_seek_time += |current_position - request|
        service_sequence.append(request)
        current_position = request
    END FOR
    
    // Circular jump: go to end, then to beginning
    IF right_requests is not empty THEN
        total_seek_time += (disk_size-1) - current_position  // To end
        total_seek_time += disk_size - 1                     // To beginning
        current_position = 0
    END IF
    
    // Service left side from beginning
    FOR EACH request in left_requests DO
        total_seek_time += |current_position - request|
        service_sequence.append(request)
        current_position = request
    END FOR
    
    RETURN service_sequence, total_seek_time
END
Time Complexity: O(n log n)

More uniform wait times than SCAN, treats all requests more fairly.

Interactive Disk Scheduling Demo

Test Scenario: Requests [98, 183, 37, 122, 14, 124, 65, 67] with head at position 53

Request Queue Visualization:

0    25   50   75   100  125  150  175  200
|----|----|----|----|----|----|----|----|----|
          ↑                          
        HEAD                         
       (53)                         
             
Pending Requests:
   14   37   65   67   98   122  124  183
   ↓    ↓    ↓    ↓    ↓    ↓    ↓    ↓
  [39] [16] [12] [14] [45] [69] [71] [130] ← Distance from head

Solid State Drive Architecture

Solid State Drives (SSDs) use NAND flash memory instead of magnetic storage, providing significantly different performance characteristics and operational considerations compared to traditional hard disk drives.

NAND Flash Memory Structure

NAND Flash Memory Hierarchy
SSD Organization Structure:

Channel Level (Highest)
┌────────────────────────────────────────────────────────────────┐
│  CHANNEL (Parallel data pathways - typically 4-16 channels)    │
│  • Independent data buses for parallel operation              │
│  • Each channel can operate simultaneously                   │
│  • Bandwidth scales with number of channels                 │
└────────────────────────────────────────────────────────────────┘
                                  │
                                  ↓
┌────────────────────────────────────────────────────────────────┐
│  DIE (Independent flash memory units - 1-8 per channel)       │
│  • Each die has its own control logic                       │
│  • Can execute commands independently                       │
│  • Typical capacity: 32GB - 256GB per die                  │
└────────────────────────────────────────────────────────────────┘
                                  │
                                  ↓
┌────────────────────────────────────────────────────────────────┐
│  PLANE (Collection of blocks sharing resources - 1-4 per die) │
│  • Shares page buffers and bit lines                        │
│  │  • Can perform some operations in parallel                │
│  • Typical size: 8GB - 64GB per plane                      │
└────────────────────────────────────────────────────────────────┘
                                  │
                                  ↓
┌────────────────────────────────────────────────────────────────┐
│  BLOCK (Smallest erase unit - 128-512 pages per block)       │
│  • Erasing must be done at block level                     │
│  • Typical size: 512KB - 4MB per block                     │
│  • Limited erase cycles: 1K-10K (depends on NAND type)     │
└────────────────────────────────────────────────────────────────┘
                                  │
                                  ↓
┌────────────────────────────────────────────────────────────────┐
│  PAGE (Smallest read/write unit - 4KB to 16KB per page)      │
│  • Can only write to empty (erased) pages                  │
│  • Contains user data + spare area (ECC, metadata)         │
│  • Read/Program operations at page granularity              │
└────────────────────────────────────────────────────────────────┘
                                  │
                                  ↓
┌────────────────────────────────────────────────────────────────┐
│  CELL (Basic storage unit - stores 1-4 bits per cell)        │
│  • SLC: 1 bit/cell (fastest, most durable)                │
│  • MLC: 2 bits/cell (balanced performance/cost)            │
│  • TLC: 3 bits/cell (higher density, slower)              │
│  • QLC: 4 bits/cell (highest density, lowest endurance)   │
└────────────────────────────────────────────────────────────────┘
(Lowest Level)

SSD Operations and Limitations

Operation Characteristics Performance Impact Limitations
Read Page-level operation Fast (25-100μs) Read disturb after many reads
Write Page-level, requires empty page Medium (200-1500μs) Write amplification
Erase Block-level operation Slow (1.5-3ms) Limited P/E cycles (1K-10K)

Flash Translation Layer (FTL)

The Flash Translation Layer manages the mapping between logical block addresses (LBA) and physical flash memory addresses, handling wear leveling, garbage collection, and bad block management.

Flash Translation Layer (FTL)
Algorithm FTL_Write_Operation:

Input: logical_block_address (LBA), data
Output: success/failure status

Data Structures:
    mapping_table[LBA] → Physical_Block_Address (PBA)
    reverse_mapping[PBA] → LBA
    free_block_list[]
    erase_count[block_id]

BEGIN
    // Check if LBA already has a mapping
    IF LBA exists in mapping_table THEN
        old_PBA = mapping_table[LBA]
        mark_page_invalid(old_PBA)
        update_valid_page_count(get_block(old_PBA))
    END IF
    
    // Allocate new physical page
    new_PBA = allocate_free_page()
    IF new_PBA == NULL THEN
        // No free pages, trigger garbage collection
        victim_block = select_victim_block()
        new_PBA = garbage_collect(victim_block)
        IF new_PBA == NULL THEN
            RETURN FAILURE  // Disk full
        END IF
    END IF
    
    // Update mapping tables
    mapping_table[LBA] = new_PBA
    reverse_mapping[new_PBA] = LBA
    
    // Write data to flash memory
    status = flash_program(new_PBA, data)
    RETURN status
END

Wear Leveling Strategies

Wear Leveling Algorithms
Algorithm Dynamic_Wear_Leveling:

Input: write_request
Output: selected_physical_block

BEGIN
    available_blocks = get_free_blocks()
    IF available_blocks is empty THEN
        RETURN NULL
    END IF
    
    min_erase_count = INFINITY
    selected_block = NULL
    
    FOR EACH block in available_blocks DO
        IF erase_count[block] < min_erase_count THEN
            min_erase_count = erase_count[block]
            selected_block = block
        END IF
    END FOR
    
    RETURN selected_block
END

Algorithm Static_Wear_Leveling:

BEGIN
    hot_block = find_max_erase_count_block()
    cold_block = find_min_erase_count_block_with_static_data()
    
    erase_diff = erase_count[hot_block] - erase_count[cold_block]
    
    IF erase_diff > WEAR_LEVELING_THRESHOLD THEN
        // Swap data between blocks
        temp_data = read_block(cold_block)
        erase_block(cold_block)
        write_block(cold_block, read_block(hot_block))
        erase_block(hot_block)
        write_block(hot_block, temp_data)
        
        // Update erase counts
        erase_count[cold_block]++
        erase_count[hot_block]++
    END IF
END

Storage Performance Optimization

I/O Queue Management

Modern storage systems implement sophisticated queue management techniques to maximize throughput and minimize latency. Understanding queue depths and parallelism is crucial for performance optimization.

Native Command Queuing (NCQ) Benefits
NCQ Performance Analysis:

Without NCQ (Sequential Processing):
┌─────────────┬────────────┬───────────┬─────────────┐
│   Request   │ Seek Time  │Transfer   │ Total Time  │
├─────────────┼────────────┼───────────┼─────────────┤
│ Request_1   │    8ms     │  0.04ms   │   8.04ms    │
│ (Track 100) │            │           │             │
├─────────────┼────────────┼───────────┼─────────────┤
│ Request_2   │    6ms     │  0.04ms   │   6.04ms    │
│ (Track 200) │            │           │             │
├─────────────┼────────────┼───────────┼─────────────┤
│ Request_3   │   10ms     │  0.04ms   │  10.04ms    │
│ (Track 50)  │            │           │             │
├─────────────┼────────────┼───────────┼─────────────┤
│    TOTAL    │   24ms     │  0.12ms   │  24.12ms    │
└─────────────┴────────────┴───────────┴─────────────┘

With NCQ (Optimized Ordering):
Reordered Sequence: 50 → 100 → 200
┌─────────────┬────────────┬───────────┬─────────────┐
│   Request   │ Seek Time  │Transfer   │ Total Time  │
├─────────────┼────────────┼───────────┼─────────────┤
│ Request_3   │   10ms     │  0.04ms   │  10.04ms    │
│ (Track 50)  │ (from 53)  │           │             │
├─────────────┼────────────┼───────────┼─────────────┤
│ Request_1   │    3ms     │  0.04ms   │   3.04ms    │
│ (Track 100) │ (from 50)  │           │             │
├─────────────┼────────────┼───────────┼─────────────┤
│ Request_2   │    6ms     │  0.04ms   │   6.04ms    │
│ (Track 200) │ (from 100) │           │             │
├─────────────┼────────────┼───────────┼─────────────┤
│    TOTAL    │   19ms     │  0.12ms   │  19.12ms    │
└─────────────┴────────────┴───────────┴─────────────┘

Performance Improvement: 21% reduction in seek time

Storage Hierarchy Optimization

Storage Tier Capacity Latency Bandwidth Cost/GB Use Case
L1 Cache 32-128KB 1-3 cycles 1TB/s $1000+ CPU operations
RAM 8-128GB 50-100ns 25-100GB/s $3-8 Active data
NVMe SSD 256GB-8TB 10-100μs 3-7GB/s $0.10-0.30 OS, applications
SATA SSD 128GB-4TB 50-200μs 500MB/s $0.08-0.20 Frequent access
HDD 500GB-20TB 5-15ms 100-250MB/s $0.02-0.05 Bulk storage

Advanced Optimization Techniques

Advanced Storage Optimization Techniques
1. Read-ahead/Prefetching Algorithm:

Algorithm Adaptive_Readahead:
BEGIN
    window_size = INITIAL_WINDOW
    hit_rate = 0.0
    access_pattern = []
    
    FOR EACH read_request DO
        // Detect sequential pattern
        IF is_sequential(access_pattern) THEN
            window_size = min(MAX_WINDOW, window_size * 2)
            prefetch_blocks(current_block + 1, window_size)
        ELSE
            window_size = max(MIN_WINDOW, window_size / 2)
        END IF
        
        update_access_pattern(current_block)
    END FOR
END

2. Write Coalescing:
    • Combine small writes into larger sequential writes
    • Reduce number of I/O operations
    • Improve bandwidth utilization
    • Buffer writes temporarily in memory

3. I/O Scheduling Optimization:
    • NCQ (Native Command Queuing): 32 outstanding commands
    • TCQ (Tagged Command Queuing): Legacy alternative
    • Elevator algorithms: SCAN, C-SCAN for fairness
    • Deadline scheduling: Prevent I/O starvation

4. Multi-level Buffer Management:
    • L1: CPU Cache (1-3 cycles)
    • L2: Main Memory (50-100ns) 
    • L3: SSD Cache (10-100μs)
    • L4: HDD Storage (5-15ms)

5. Parallel I/O Techniques:
    • RAID striping across multiple disks
    • Multiple I/O channels utilization  
    • Asynchronous I/O operations
    • Multi-threading for concurrent access

Summary

This session covered the fundamental concepts of secondary storage structure including:

  • Magnetic Disk Structure: Physical components, geometry, addressing schemes, and performance metrics
  • Disk Scheduling Algorithms: FCFS, SSTF, SCAN, and C-SCAN with their trade-offs and use cases
  • SSD Architecture: NAND flash memory structure, Flash Translation Layer, and wear leveling techniques
  • Performance Optimization: I/O queue management, storage hierarchies, and advanced optimization strategies
Key Takeaways

Understanding storage hardware characteristics is crucial for system performance optimization. Different storage technologies require different optimization approaches, and modern systems use hierarchical storage to balance performance, capacity, and cost.