Super Block State Management
Super block state management tracks the states of Super Blocks in use by the FTL. It mirrors the state of the blocks inside the SEF Unit so decisions can be driven by information in DRAM rather than a constant stream of device requests. The Super Block state machine is driven by a combination of notifications from the SEF Unit, the results of I/O operations, and operations performed by garbage collection (GC).
The state of each Super Block is tracked in an array indexed by Super Block ID. As a result,
memory consumption is affected by the size of the Virtual Device, 16 bytes per Super Block. A
bitmap is allocated to track which ADUs are valid, requiring 8+super_block_capacity_adus/8
bytes for each Super Block assigned to the QoS Domain. The bits are set and cleared using
SSBSetAduValid()
and SSBClearAduValid()
, respectively. A snapshot of the bits is read
using SSBCopyValidBits()
. As an example, for a 1TiB Virtual Device with 64Kibi ADUs per
Super Block and a maximally sized QoS Domain, the memory required is 64KiB for an empty QoS
Domain and just over 32MiB when it is full.
Super blocks can be in 1 of 7 states. The Super Block states are described in Super Block States, and transitions are shown in Figure 4.
Super Block States
State | Description |
---|---|
Deleted | Not in use by the QoS Domain. |
Allocated | Owned by the QoS Domain but is not yet available for read or write. A Super Block that is the destination for nameless copy is in this state until it is filled. |
Open | Mirrors the open state in the device. The Super Block is available for read and write. |
Closed | Mirrors the closed state in the device. The Super Block is available only for read. |
Busy | Valid ADU count is zero, but there are still reads in-flight. No new reads are allowed. |
Empty | Valid ADU count is zero and the Super Block is being released back to the Virtual Device Super Block pool. |
Meta | Holds FTL data, not user data. These are allocated/released when the block layer shuts down and persists the LUT. |
Figure 4: Super Block State Transitions
The state value also contains a reader count. When a read is issued against a Super
Block, that count is incremented by SSBMarkBusy()
to prevent it from being deleted.
SSBMarkNotBusy()
decrements the count once the read completes. There is also a reference
count that is incremented by SSBSetAduValid()
for each valid ADU and decremented by
SSBClearAduValid()
for each invalid ADU. Two extra counts are held for the allocated and
open states. The extra counts are removed by calls to SSBRemoveRef()
and by SSBClosed()
.
Super Block Transitions provides additional detail on when a Super
Block will transition to a new state.
Super Block Transitions
Transition | Triggers |
---|---|
Deleted to Allocated | There are two events that cause this transition: when a flash address is returned from a write for a Super Block in the deleted state and when garbage collection allocates a destination Super Block. |
Allocated to Open | When a flash address is returned from a write transitioning the Super Block to the allocated state, it moves immediately to the open state. |
Allocated/Open to Closed | A close notification from the device is processed. |
Closed to Busy | The reference count for the Super Block has become zero, and the active reader count is non-zero. The reference count is decremented when an LBA is rewritten, GC moves an LBA, or the Super Block transitions out of Open. |
Closed to Empty | The reference count for the Super Block has become zero, and the active reader count is zero The reference count is decremented when an LBA is rewritten, GC moves an LBA, or the Super Block transitions out of Open |
Empty to Deleted | The release of the Super Block is issued and moves immediately to Deleted. |
Meta to/from Deleted | At FTL shutdown, the persistence layer has allocated space to save the LUT and has released the old LUT back to the Virtual Device Super Block pool. |
Super blocks are released asynchronously as they become empty. This can be prevented by marking
a block as busy with SSBMarkBusy()
. The returned instance ID can be used to verify the block
hasn’t been released and reallocated between enumeration with SSBEnumBlocks()
or other calls
to SSBMarkBusy()
.