github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/ext/disklayout/block_group.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package disklayout 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/marshal" 19 ) 20 21 // BlockGroup represents a Linux ext block group descriptor. An ext file system 22 // is split into a series of block groups. This provides an access layer to 23 // information needed to access and use a block group. 24 // 25 // Location: 26 // - The block group descriptor table is always placed in the blocks 27 // immediately after the block containing the superblock. 28 // - The 1st block group descriptor in the original table is in the 29 // (sb.FirstDataBlock() + 1)th block. 30 // - See SuperBlock docs to see where the block group descriptor table is 31 // replicated. 32 // - sb.BgDescSize() must be used as the block group descriptor entry size 33 // while reading the table from disk. 34 // 35 // See https://www.kernel.org/doc/html/latest/filesystems/ext4/globals.html#block-group-descriptors. 36 type BlockGroup interface { 37 marshal.Marshallable 38 39 // InodeTable returns the absolute block number of the block containing the 40 // inode table. This points to an array of Inode structs. Inode tables are 41 // statically allocated at mkfs time. The superblock records the number of 42 // inodes per group (length of this table) and the size of each inode struct. 43 InodeTable() uint64 44 45 // BlockBitmap returns the absolute block number of the block containing the 46 // block bitmap. This bitmap tracks the usage of data blocks within this block 47 // group and has its own checksum. 48 BlockBitmap() uint64 49 50 // InodeBitmap returns the absolute block number of the block containing the 51 // inode bitmap. This bitmap tracks the usage of this group's inode table 52 // entries and has its own checksum. 53 InodeBitmap() uint64 54 55 // ExclusionBitmap returns the absolute block number of the snapshot exclusion 56 // bitmap. 57 ExclusionBitmap() uint64 58 59 // FreeBlocksCount returns the number of free blocks in the group. 60 FreeBlocksCount() uint32 61 62 // FreeInodesCount returns the number of free inodes in the group. 63 FreeInodesCount() uint32 64 65 // DirectoryCount returns the number of inodes that represent directories 66 // under this block group. 67 DirectoryCount() uint32 68 69 // UnusedInodeCount returns the number of unused inodes beyond the last used 70 // inode in this group's inode table. As a result, we needn’t scan past the 71 // (InodesPerGroup - UnusedInodeCount())th entry in the inode table. 72 UnusedInodeCount() uint32 73 74 // BlockBitmapChecksum returns the block bitmap checksum. This is calculated 75 // using crc32c(FS UUID + group number + entire bitmap). 76 BlockBitmapChecksum() uint32 77 78 // InodeBitmapChecksum returns the inode bitmap checksum. This is calculated 79 // using crc32c(FS UUID + group number + entire bitmap). 80 InodeBitmapChecksum() uint32 81 82 // Checksum returns this block group's checksum. 83 // 84 // If SbMetadataCsum feature is set: 85 // - checksum is crc32c(FS UUID + group number + group descriptor 86 // structure) & 0xFFFF. 87 // 88 // If SbGdtCsum feature is set: 89 // - checksum is crc16(FS UUID + group number + group descriptor 90 // structure). 91 // 92 // SbMetadataCsum and SbGdtCsum should not be both set. 93 // If they are, Linux warns and asks to run fsck. 94 Checksum() uint16 95 96 // Flags returns BGFlags which represents the block group flags. 97 Flags() BGFlags 98 } 99 100 // These are the different block group flags. 101 const ( 102 // BgInodeUninit indicates that inode table and bitmap are not initialized. 103 BgInodeUninit uint16 = 0x1 104 105 // BgBlockUninit indicates that block bitmap is not initialized. 106 BgBlockUninit uint16 = 0x2 107 108 // BgInodeZeroed indicates that inode table is zeroed. 109 BgInodeZeroed uint16 = 0x4 110 ) 111 112 // BGFlags represents all the different combinations of block group flags. 113 type BGFlags struct { 114 InodeUninit bool 115 BlockUninit bool 116 InodeZeroed bool 117 } 118 119 // ToInt converts a BGFlags struct back to its 16-bit representation. 120 func (f BGFlags) ToInt() uint16 { 121 var res uint16 122 123 if f.InodeUninit { 124 res |= BgInodeUninit 125 } 126 if f.BlockUninit { 127 res |= BgBlockUninit 128 } 129 if f.InodeZeroed { 130 res |= BgInodeZeroed 131 } 132 133 return res 134 } 135 136 // BGFlagsFromInt converts the 16-bit flag representation to a BGFlags struct. 137 func BGFlagsFromInt(flags uint16) BGFlags { 138 return BGFlags{ 139 InodeUninit: flags&BgInodeUninit > 0, 140 BlockUninit: flags&BgBlockUninit > 0, 141 InodeZeroed: flags&BgInodeZeroed > 0, 142 } 143 }