github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/bat/blockAllocationTable.go (about)

     1  package bat
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/Microsoft/azure-vhd-utils/vhdcore"
     7  )
     8  
     9  // BlockAllocationTable type represents the Block Allocation Table (BAT) of the disk, BAT served as
    10  // index to access the disk's blocks.
    11  // A block is a unit of expansion for dynamic and differencing hard disks. All blocks within a given
    12  // image must be the same size.
    13  // The number of entries in the BAT is the number of blocks needed to store the contents of the disk
    14  // when fully expanded. Each entry in this table is the absolute sector offset to a block. Each entry
    15  // is four bytes long. if the disk is not fully expanded then, even though BAT has entries reserved
    16  // for unexpanded blocks, the corresponding block will not exists. All such unused table entries
    17  // are initialized to 0xFFFFFFFF.
    18  // A block consists of two sections 'data section' and 'block bitmap section'. The 'BlockSize' field
    19  // of the disk header is the size of the 'data section' of the block, it does not include the size of
    20  // the 'block bitmap section'. Each bit in the bitmap indicates the state of the corresponding sector
    21  // in 'data section', 1 indicates sector contains valid data, 0 indicates the sector have never been
    22  // modified.
    23  //
    24  type BlockAllocationTable struct {
    25  	BATEntriesCount uint32
    26  	BAT             []uint32
    27  	blockSize       uint32
    28  }
    29  
    30  // NewBlockAllocationTable creates an instance of BlockAllocationTable, BAT is the block allocation table,
    31  // each entry in this table is the absolute sector offset to a block, blockSize is the size of block's
    32  // 'data section' in bytes.
    33  //
    34  func NewBlockAllocationTable(blockSize uint32, bat []uint32) *BlockAllocationTable {
    35  	return &BlockAllocationTable{BATEntriesCount: uint32(len(bat)), blockSize: blockSize, BAT: bat}
    36  }
    37  
    38  // GetBitmapSizeInBytes returns the size of the 'block bitmap section' that stores the state
    39  // of the sectors in block's 'data section'. This means the number of bits in the bitmap is equivalent
    40  // to the number of sectors in 'data section', dividing this number by 8 will yield the number of bytes
    41  // required to store the bitmap.
    42  // As per vhd specification sectors per block must be power of two. The sector length is always 512 bytes.
    43  // This means the block size will be power of two as well e.g. 512 * 2^3, 512 * 2^4, 512 * 2^5 etc..
    44  //
    45  func (b *BlockAllocationTable) GetBitmapSizeInBytes() int32 {
    46  	return int32(b.blockSize / uint32(vhdcore.VhdSectorLength) / 8)
    47  }
    48  
    49  // GetSectorPaddedBitmapSizeInBytes returns the size of the 'block bitmap section' in bytes which is
    50  // padded to a 512-byte sector boundary. The bitmap of a block is always padded to a 512-byte sector
    51  // boundary.
    52  func (b *BlockAllocationTable) GetSectorPaddedBitmapSizeInBytes() int32 {
    53  	sectorSizeInBytes := float64(vhdcore.VhdSectorLength)
    54  	bitmapSizeInBytes := float64(b.GetBitmapSizeInBytes())
    55  	return int32(math.Ceil(bitmapSizeInBytes/sectorSizeInBytes) * sectorSizeInBytes)
    56  }
    57  
    58  // GetBitmapAddress returns the address of the 'block bitmap section' of a given block. Address is the
    59  // absolute byte offset of the 'block bitmap section'. A block consists of 'block bitmap section' and
    60  // 'data section'
    61  //
    62  func (b *BlockAllocationTable) GetBitmapAddress(blockIndex uint32) int64 {
    63  	return int64(b.BAT[blockIndex]) * vhdcore.VhdSectorLength
    64  }
    65  
    66  // GetBlockDataAddress returns the address of the 'data section' of a given block. Address is the absolute
    67  // byte offset of the 'data section'. A block consists of 'block bitmap section' and 'data section'
    68  //
    69  func (b *BlockAllocationTable) GetBlockDataAddress(blockIndex uint32) int64 {
    70  	return b.GetBitmapAddress(blockIndex) + int64(b.GetSectorPaddedBitmapSizeInBytes())
    71  }
    72  
    73  // HasData returns true if the given block has not yet expanded hence contains no data.
    74  //
    75  func (b *BlockAllocationTable) HasData(blockIndex uint32) bool {
    76  	return blockIndex != vhdcore.VhdNoDataInt && b.BAT[blockIndex] != vhdcore.VhdNoDataInt
    77  }