Group Descriptor

As Figure 9-2 shows, each block group has a collection of group descriptors arranged directly after the superblock. The information they hold reflects the contents of each block group of the filesystem and therefore relates not only to the data blocks associated with the local block group but also to the data and inode blocks of other block groups.

The data structure used to define a single group descriptor is much shorter than the superblock structure, as the following section of kernel source code demonstrates:

struct ext2_group_desc {

The kernel uses a copy of this structure for each block group described in the group descriptor collection.

le32 bg_block_bitmap; le32 bg_inode_bitmap; le32 bg_inode_table;

/* Directories count */

/* Blocks bitmap block */ /* Inodes bitmap block */

le16 bg_free_blocks_count;

le16 bg_free_inodes_count;

le16 bg_used_dirs_count;

le16 bg_pad;

le32 bg_reserved[3];

The contents of each group descriptor include not only status entries indicating the number of free blocks (bg_free_blocks_count), and inodes (bg_free_inodes_count) as well as the number of directories (bg_used_dirs_count), but also, and more importantly, two pointers to blocks containing the bitmaps needed to organize used and free blocks and inodes. These are called bg_block_bitmap and bg_inode_bitmap and are implemented by means of a 32-bit number that uniquely describes a block on the hard disk.

The block to which bg_block_bitmap refers is not used to store data. Each of its bits stands for a data block of the current block group. If a bit is set, the block is being used by the filesystem; otherwise, the block is available. Because the position at which the first data block is located is known and all data blocks are in linear sequence, it is easy for the kernel to convert between bit positions in the block bitmap and the associated block positions.

The same method is applied for the inode pointer bg_inode_bitmap. It, too, points to a block whose individual bits are used to describe all inodes of a block group. Because it is also known in which blocks the inode structures are located and how big the inode structure is, the kernel can convert between the bitmap entries and the associated positions on the hard disk (see also Figure 9-2).

Each block group contains not just one but a large number of group descriptor structures — a copy for each block group in the filesystem. From each block group, it is therefore possible to determine the following information for every single block group in the system:

□ The position of the block and inode bitmaps.

□ The position of the inode table.

□ The number of free blocks and inodes.

The blocks used as block and inode bitmaps are not, however, duplicated in each block group for all other block groups: in fact, there is only one occurrence of them in the system. Each block group has a local block for the block bitmap and an extra block for the inode bitmap. Nevertheless, all data and inode bitmaps of the remaining groups can be accessed from every block group because their position can be determined with the help of the entries in the group descriptor.

Because the filesystem block size is variable, the number of blocks that can be represented by a block bitmap also changes accordingly. If the block size is set to 2,048 bytes, each block has exactly 2,048 x 8 = 16,384 bits that can be used to describe the state of data blocks. Similarly, block sizes of 1,024 and 4,096 bytes mean that exactly 8,192 and 32,768 blocks can be managed. This data are summarized in Table 9-2.

In our example, we use only 2 bytes to store the block bitmap so that exactly 16 blocks can be addressed. The data blocks that hold the actual contents of the filesystem files (and the data used for indirection) are at the end of the block group.

Table 9-2: Maximum Sizes in a Block Group

Block size

Number of blocks

1,024

8,192

2,048

16,384

4,096

32,768

The division of a partition into block groups makes sense for systematic reasons and also brings tangible benefits in terms of speed. The filesystem always attempts to store the contents of a file in a single block group to minimize the travel of the read/write head between inode, block bitmap, and data blocks. Normally, this can be achieved, but there are, of course, situations in which files are spread over several block groups because there is not enough space in a single block group. Because, depending on block size, a block group can accept only a certain number of data blocks, there are maximum limits for file sizes (see Table 9-2). If these are exceeded, files must be spread over several block groups at the price of longer read/write head travel and reduced performance.

Continue reading here: Inodes

Was this article helpful?

0 0