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  }