summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl/ext/disklayout/block_group.go
blob: ad6f4fef81347b14f77318b59d734c8431449426 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2019 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package disklayout

// BlockGroup represents a Linux ext block group descriptor. An ext file system
// is split into a series of block groups. This provides an access layer to
// information needed to access and use a block group.
//
// Location:
//   - The block group descriptor table is always placed in the blocks
//     immediately after the block containing the superblock.
//   - The 1st block group descriptor in the original table is in the
//      (sb.FirstDataBlock() + 1)th block.
//   - See SuperBlock docs to see where the block group descriptor table is
//     replicated.
//   - sb.BgDescSize() must be used as the block group descriptor entry size
//     while reading the table from disk.
//
// See https://www.kernel.org/doc/html/latest/filesystems/ext4/globals.html#block-group-descriptors.
type BlockGroup interface {
	// InodeTable returns the absolute block number of the block containing the
	// inode table. This points to an array of Inode structs. Inode tables are
	// statically allocated at mkfs time. The superblock records the number of
	// inodes per group (length of this table) and the size of each inode struct.
	InodeTable() uint64

	// BlockBitmap returns the absolute block number of the block containing the
	// block bitmap. This bitmap tracks the usage of data blocks within this block
	// group and has its own checksum.
	BlockBitmap() uint64

	// InodeBitmap returns the absolute block number of the block containing the
	// inode bitmap. This bitmap tracks the usage of this group's inode table
	// entries and has its own checksum.
	InodeBitmap() uint64

	// ExclusionBitmap returns the absolute block number of the snapshot exclusion
	// bitmap.
	ExclusionBitmap() uint64

	// FreeBlocksCount returns the number of free blocks in the group.
	FreeBlocksCount() uint32

	// FreeInodesCount returns the number of free inodes in the group.
	FreeInodesCount() uint32

	// DirectoryCount returns the number of inodes that represent directories
	// under this block group.
	DirectoryCount() uint32

	// UnusedInodeCount returns the number of unused inodes beyond the last used
	// inode in this group's inode table. As a result, we needn’t scan past the
	// (InodesPerGroup - UnusedInodeCount())th entry in the inode table.
	UnusedInodeCount() uint32

	// BlockBitmapChecksum returns the block bitmap checksum. This is calculated
	// using crc32c(FS UUID + group number + entire bitmap).
	BlockBitmapChecksum() uint32

	// InodeBitmapChecksum returns the inode bitmap checksum. This is calculated
	// using crc32c(FS UUID + group number + entire bitmap).
	InodeBitmapChecksum() uint32

	// Checksum returns this block group's checksum.
	//
	// If SbMetadataCsum feature is set:
	//     - checksum is crc32c(FS UUID + group number + group descriptor
	//       structure) & 0xFFFF.
	//
	// If SbGdtCsum feature is set:
	//     - checksum is crc16(FS UUID + group number + group descriptor
	//       structure).
	//
	// SbMetadataCsum and SbGdtCsum should not be both set.
	// If they are, Linux warns and asks to run fsck.
	Checksum() uint16

	// Flags returns BGFlags which represents the block group flags.
	Flags() BGFlags
}

// These are the different block group flags.
const (
	// BgInodeUninit indicates that inode table and bitmap are not initialized.
	BgInodeUninit uint16 = 0x1

	// BgBlockUninit indicates that block bitmap is not initialized.
	BgBlockUninit uint16 = 0x2

	// BgInodeZeroed indicates that inode table is zeroed.
	BgInodeZeroed uint16 = 0x4
)

// BGFlags represents all the different combinations of block group flags.
type BGFlags struct {
	InodeUninit bool
	BlockUninit bool
	InodeZeroed bool
}

// ToInt converts a BGFlags struct back to its 16-bit representation.
func (f BGFlags) ToInt() uint16 {
	var res uint16

	if f.InodeUninit {
		res |= BgInodeUninit
	}
	if f.BlockUninit {
		res |= BgBlockUninit
	}
	if f.InodeZeroed {
		res |= BgInodeZeroed
	}

	return res
}

// BGFlagsFromInt converts the 16-bit flag representation to a BGFlags struct.
func BGFlagsFromInt(flags uint16) BGFlags {
	return BGFlags{
		InodeUninit: flags&BgInodeUninit > 0,
		BlockUninit: flags&BgBlockUninit > 0,
		InodeZeroed: flags&BgInodeZeroed > 0,
	}
}