当前位置:网站首页>EXT2 file system
EXT2 file system
2022-07-07 09:45:00 【Don't ask me y】
Catalog
One EXT2 Overview of file system structure 2
1.1 EXT2 File system structure block diagram 2
1.2 EXT2 Important data structures 3
3、 ... and EXT2 File system mount 7
3.1 register ext2 File system type 7
EXT2 Overview of file system structure
1.1 EXT2 File system structure block diagram

If the file is small , Its data block is less than 12 individual , Its data block index is placed in inode->i_blocks in , If the file is large , operation 12 One data block needs to allocate indirect blocks to save the data block index
1.2 EXT2 Important data structures
super_block yes VFS Standard structure in , Through members s_fs_info Connect to a specific file system
truct super_block | |
struct list_head s_list | Used to hang the super block to the global linked list super_blocks in |
dev_t s_dev | The device number of the device where the file system is located |
unsigned long s_blocksize | File system block size |
struct file_system_type *s_type | File system type , such as ext2_fs_type |
const struct super_operations *s_op | clothing inode The distribution of inode Metadata synchronization and so on |
struct dentry *s_root | Of the root directory of the file system dentry |
struct block_device *s_bdev | Corresponding to the block device where the file system is located block_device |
struct hlist_node s_instances | For hanging to the linked list file_system_type ->fs_supers |
void *s_fs_info | Points to the structure that holds a particular file system , such as ext2_sb_info |
struct list_head s_inodes | File system all open files inode Linked list |
…… | …… |
Structure ext2_sb_info Contains all information about a particular file system , Contains superblocks , Group descriptor and so on :
struct ext2_sb_info | |
unsigned long s_inodes_per_block | Every block How many can be stored in inode The descriptor |
unsigned long s_blocks_per_group | The number of data blocks contained in each block group |
unsigned long s_inodes_per_group | Each block group contains inode Count |
unsigned long s_itb_per_group | A block group is used to store inode The number of pieces |
unsigned long s_gdb_count | The number of blocks used to store the group descriptor |
unsigned long s_desc_per_block | A block stores the number of group descriptors |
unsigned long s_groups_count | Number of group descriptors |
struct buffer_head * s_sbh | Point to the cache where the original superblock is stored |
struct ext2_super_block * s_es | Point to s_sbh Super block structure in |
struct buffer_head ** s_group_desc | When reading the superblock, the group descriptor will also be read into memory |
int s_first_ino | The first non reserved in the file system inode Number |
struct rb_root s_rsv_window_root | Red and black trees with reserved windows |
struct ext2_reserve_window_node s_rsv_window_head | The first node of the red black tree |
…… | …… |
ext2_super_block The original superblock saved on disk
struct ext2_super_block | |
__le32 s_inodes_count | File system Inode The number of |
__le32 s_blocks_count | Number of blocks in the file system |
__le32 s_r_blocks_count | Number of blocks reserved |
__le32 s_free_blocks_count | Number of free blocks |
__le32 s_free_inodes_count | Idle inode Count |
__le32 s_first_data_block | The first data block number |
__le32 s_log_block_size | Block size |
__le32 s_blocks_per_group | Number of blocks per block group |
__le32 s_inodes_per_group | For each block group inode Count |
__le32 s_first_ino | The first one without reservation inode |
__le16 s_inode_size | Inode Size of structure |
__le16 s_block_group_nr | At present ext2_super_block Block group number , Superblocks have backups in each block group in the disk |
…… | …… |
Structure ext2_inode_info link VFS inode And primitive inode
struct ext2_inode_info | |
__le32 i_data[15]; | Inode Direct block of |
__u32 i_block_group; | Inode The block group to which it belongs |
struct inode vfs_inode; | VFS inode |
…… | …… |
Structure ext2_inode It is the original stored on disk inode
struct ext2_inode | |
__le16 i_mode | File mode , |
__le32 i_size | file size (bytes) |
__le32 i_blocks | file size ( block ) |
__le32 i_block[EXT2_N_BLOCKS] | Direct index block |
…… | …… |
Structure ext2_dir_entry_2 It is also a structure on the disk , It represents a directory item under the directory . That is, the contents of the directory ( Subdirectories or files ), The directory also has a inode, It also has data blocks , Every item stored on the data block is ext2_dir_entry_2 To express , for example :
[email protected]:~/workspace/kernel_4.12/linux-4.12.3/mm$ ls ~/workspace/
1496324869gf_common.h androidJ6 aosp dumpe2fs.txt gf_common.h kernel_4.12 log readme
struct ext2_dir_entry_2 | |
__le32 inode | This directory item corresponds to inode Number |
__le16 rec_len | rec_len From the end of the field to the next rec_len The migration , It is convenient to find the next directory item on the data block |
__u8 name_len | Length of directory item name |
__u8 file_type | file type , Catalog 、 Ordinary documents 、 The Conduit 、 Links, etc. |
char name[] | Directory entry name |
…… | …… |
struct ext2_group_desc | |
__le32 bg_block_bitmap | The block number of the data block bitmap |
__le32 bg_inode_bitmap | Inode The block number of the bitmap |
__le32 bg_inode_table | Inode Block number of the table |
__le16 bg_free_blocks_count | The number of free blocks in the block group |
__le16 bg_free_inodes_count | Free in block group inode The number of |
__le16 bg_used_dirs_count | Number of directories in the block group |
…… | …… |
Command dumpe2fs Sure dump Information about the file system :
[email protected]:~/workspace/kernel_4.12/linux-4.12.3/fs$ sudo dumpe2fs -h /dev/sda1
dumpe2fs 1.43.3 (04-Sep-2016)
Filesystem volume name: <none>
Last mounted on: /
Filesystem UUID: 22af4caf-a05b-4d8f-8004-30d531867b55
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 16252928
Block count: 65011456
Reserved block count: 3250572
Free blocks: 23809796
Free inodes: 14213383
First block: 0
Block size: 4096
Fragment size: 4096
Group descriptor size: 64
Reserved GDT blocks: 1024
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Fri Feb 17 21:00:51 2017
Last mount time: Sat Aug 12 10:26:31 2017
Last write time: Sat Aug 12 10:26:26 2017
Mount count: 32
Block cache
In the deep ext2 Before implementing the logic, let's insert a section of block cache , Let's first look at the cache structure :
struct buffer_head | |
unsigned long b_state | Cache status bitmap , for example BH_Mapped Associated to disk block ; BH_Dirty: Dirty lump ; BH_Uptodate: Data in the block is available |
struct buffer_head *b_this_page | Buffer ring linked list |
struct page *b_page | Page to which the buffer is mapped |
sector_t b_blocknr | Corresponding to the block number on the disk |
size_t b_size | Cache size |
char *b_data | Cache start address |
struct block_device *b_bdev | Block device , Specifies the source of the data |
…… | …… |
Block caching is mainly used in two places , Page cache and block device raw data reading ( Independent block cache ), For example, super block , Group descriptor block and so on . In the page cache, the block cache is attached to the page , After the page is released, the block cache is released . The independent block cache consists of a lru Cache to manage , At this time, the page is attached to the block cache , The block cache releases the page .
-
struct bh_lru {
-
struct buffer_head *bhs[BH_LRU_SIZE];
-
};
Both block caches are created with the following functions , Their difference lies in the different perspectives of management .
-
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
-
int retry)
EXT2 File system mount
3.1 register ext2 File system type
Static definition EXT2 File system type ext2_fs_type, And pass register_filesystem Add it to the global linked list file_systems On
-
static
struct file_system_type ext2_fs_type = {
-
.owner = THIS_MODULE,
-
.name =
"ext2",
-
.mount = ext2_mount,
-
.kill_sb = kill_block_super,
-
.fs_flags = FS_REQUIRES_DEV,
-
};
-
MODULE_ALIAS_FS(
"ext2");
-
-
-
static
int __
init init_ext2_fs(void)
-
{
-
int err;
-
-
-
err = init_inodecache();
-
if (err)
-
return err;
-
err = register_filesystem(&ext2_fs_type);
// take ext2_fs_type Linked to the global linked list file_systems On
-
if (err)
-
goto out;
-
return
0;
-
out:
-
destroy_inodecache();
-
return err;
-
}
3.2 ext2 File system mount
sget: Distribute super_block And will super_block Add to global linked list super_blocks and file_system_type ->fs_supers
fill_super: A function pointer , Here it points to ext2_fill_super, Used to read from the file system super_block, Let's go into details :
-
static int ext2_fill_super(struct super_block *sb, void *data, int silent)
-
{
-
struct buffer_head * bh;
-
struct ext2_sb_info * sbi;
-
struct ext2_super_block * es;
-
struct inode *root;
-
unsigned
long sb_block = get_sb_block(&data);
-
unsigned
long logic_sb_block;
-
unsigned
long offset =
0;
-
int blocksize = BLOCK_SIZE;
-
int db_count;
-
-
-
sbi = kzalloc(
sizeof(*sbi), GFP_KERNEL);
// Distribute ext2_sb_info structure
-
if (!sbi)
-
goto failed;
-
-
-
sb->s_fs_info = sbi;
//VFS Medium super_block adopt sb->s_fs_info And ext2_sb_info Connect
-
sbi->s_sb_block = sb_block;
-
-
-
blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
-
......
-
if (!(bh = sb_bread(sb, logic_sb_block))) {
// Read the original superblock structure from the disk ext2_super_block
-
ext2_msg(sb, KERN_ERR,
"error: unable to read superblock");
-
goto failed_sbi;
-
}
-
es = (struct ext2_super_block *) (((
char *)bh->b_data) + offset);
-
sbi->s_es = es;
-
......
-
sb->s_magic = le16_to_cpu(es->s_magic);
-
blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
-
-
-
/* If the actual block size of the super block is inconsistent with the assumed size, re read the super block , Because the super block occupies a block size , function sb_bread It also reads a block size from the specified block number , If the actual block size is inconsistent with the assumed block size, re read an accurate block
-
size */
-
if (sb->s_blocksize != blocksize) {
-
brelse(bh);
-
-
-
if (!sb_set_blocksize(sb, blocksize)) {
-
ext2_msg(sb, KERN_ERR,
-
"error: bad blocksize %d", blocksize);
-
goto failed_sbi;
-
}
-
logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
-
offset = (sb_block*BLOCK_SIZE) % blocksize;
-
bh = sb_bread(sb, logic_sb_block);
-
es = (struct ext2_super_block *) (((
char *)bh->b_data) + offset);
-
sbi->s_es = es;
-
}
-
......
-
sbi->s_frags_per_block = sb->s_blocksize / sbi->s_frag_size;
-
-
-
sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
-
sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
-
sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-
-
-
sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb);
-
sbi->s_itb_per_group = sbi->s_inodes_per_group /
-
sbi->s_inodes_per_block;
-
sbi->s_desc_per_block = sb->s_blocksize /
-
sizeof (struct ext2_group_desc);
-
sbi->s_sbh = bh;
// Give Way s_sbh Point to the original superblock data
-
sbi->s_mount_state = le16_to_cpu(es->s_state);
-
sbi->s_addr_per_block_bits =
-
ilog2 (EXT2_ADDR_PER_BLOCK(sb));
-
sbi->s_desc_per_block_bits =
-
ilog2 (EXT2_DESC_PER_BLOCK(sb));
-
......
-
sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
-
le32_to_cpu(es->s_first_data_block) -
1)
-
/ EXT2_BLOCKS_PER_GROUP(sb)) +
1;
-
db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) -
1) /
-
EXT2_DESC_PER_BLOCK(sb);
-
sbi->s_group_desc = kmalloc (db_count *
sizeof (struct buffer_head *), GFP_KERNEL);
-
......
-
for (i =
0; i < db_count; i++) {
// Read all group descriptors
-
block = descriptor_loc(sb, logic_sb_block, i);
-
sbi->s_group_desc[i] = sb_bread(sb, block);
-
if (!sbi->s_group_desc[i]) {
-
for (j =
0; j < i; j++)
-
brelse (sbi->s_group_desc[j]);
-
ext2_msg(sb, KERN_ERR,
-
"error: unable to read group descriptors");
-
goto failed_mount_group_desc;
-
}
-
}
-
sbi->s_gdb_count = db_count;
// Set the number of blocks occupied by the group descriptor
-
......
-
/* Initialize the preallocation window */
-
sbi->s_rsv_window_head.rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
-
sbi->s_rsv_window_head.rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
-
sbi->s_rsv_window_head.rsv_alloc_hit =
0;
-
sbi->s_rsv_window_head.rsv_goal_size =
0;
-
ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);
-
......
-
sb->s_op = &ext2_sops;
// Set up super_operations
-
......
-
root = ext2_iget(sb, EXT2_ROOT_INO);
-
if (IS_ERR(root)) {
-
ret = PTR_ERR(root);
-
goto failed_mount3;
-
}
-
-
-
sb->s_root = d_make_root(root);
// Create the root directory dentry
-
-
-
......
-
ext2_write_super(sb);
-
......
3.3 File system operations
inode Contains all information about file operations , When the file is opened file The structure initialization information page comes from inode, Here is inode The main logic when creating :
-
struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
-
{
-
struct ext2_inode_info *ei;
-
struct buffer_head * bh;
-
struct ext2_inode *raw_inode;
-
struct inode *inode;
-
-
inode = iget_locked(sb, ino);
// establish VFS inode and ext2_inode_info
-
-
ei = EXT2_I(inode);
-
ei->i_block_alloc_info =
NULL;
-
-
raw_inode = ext2_get_inode(inode->i_sb, ino, &bh);
// To inode Read the original from the block table inode
-
-
-
......
-
-
-
if (S_ISREG(inode->i_mode)) {
-
inode->i_op = &ext2_file_inode_operations;
-
if (test_opt(inode->i_sb, NOBH)) {
-
inode->i_mapping->a_ops = &ext2_nobh_aops;
-
inode->i_fop = &ext2_file_operations;
-
}
else {
-
inode->i_mapping->a_ops = &ext2_aops;
// Page cache operation function set
-
inode->i_fop = &ext2_file_operations;
// Set up file_operations
-
}
-
}
else
if (S_ISDIR(inode->i_mode)) {
-
inode->i_op = &ext2_dir_inode_operations;
-
......
-
}
File data read

-
int mpage_readpages(struct address_space *mapping, struct list_head *pages,
-
unsigned nr_pages,
get_block_t get_block)
-
{
-
……
-
for (page_idx =
0; page_idx < nr_pages; page_idx++) {
-
struct page *page = lru_to_page(pages);
-
-
prefetchw(&page->flags);
-
list_del(&page->lru);
-
if (!add_to_page_cache_lru(page, mapping, page->index, gfp)) {
// Circularly map multiple pages to file system data blocks
-
bio = do_mpage_readpage(bio, page,
-
nr_pages - page_idx,
-
&last_block_in_bio, &map_bh,
-
&first_logical_block,
-
get_block, gfp);
-
}
-
put_page(page);
-
}
-
if (bio)
-
mpage_bio_submit(REQ_OP_READ,
0, bio);
// Submit a data read request to the block device
-
return
0;
-
}
File data blocks are scattered on disk , To read and write data, you must first find the block number of the file data block , function do_mpage_readpage Our job is to find the corresponding data block number according to the file data position offset .map_bh For reading inode Mapping block of .
-
static struct bio *
-
do_mpage_readpage
(struct bio *bio, struct page *page, unsigned nr_pages,
-
sector_t *last_block_in_bio, struct buffer_head *map_bh,
-
unsigned
long *first_logical_block,
get_block_t get_block,
-
gfp_t gfp)
-
{
-
struct inode *inode = page->mapping->host;
-
const
unsigned blkbits = inode->i_blkbits;
-
const
unsigned blocks_per_page = PAGE_SIZE >> blkbits;
-
const
unsigned blocksize =
1 << blkbits;
-
unsigned first_hole = blocks_per_page;
-
......
-
block_in_file = (
sector_t)page->index << (PAGE_SHIFT - blkbits);
-
last_block = block_in_file + nr_pages * blocks_per_page;
-
last_block_in_file = (i_size_read(inode) + blocksize -
1) >> blkbits;
-
if (last_block > last_block_in_file)
-
last_block = last_block_in_file;
-
page_block =
0;
-
-
nblocks = map_bh->b_size >> blkbits;
-
if (buffer_mapped(map_bh) && block_in_file > *first_logical_block &&
-
block_in_file < (*first_logical_block + nblocks)) {
// If the mapping block has been read in the previous loop , Find the mapping relationship in it
-
unsigned map_offset = block_in_file - *first_logical_block;
-
unsigned last = nblocks - map_offset;
-
-
for (relative_block =
0; ; relative_block++) {
-
if (relative_block == last) {
-
clear_buffer_mapped(map_bh);
-
break;
-
}
-
if (page_block == blocks_per_page)
-
break;
-
blocks[page_block] = map_bh->b_blocknr + map_offset +
-
relative_block;
-
page_block++;
-
block_in_file++;
-
}
-
bdev = map_bh->b_bdev;
-
}
-
map_bh->b_page = page;
-
while (page_block < blocks_per_page) {
// Call function get_block Read mapping block , This function will be explained in detail later
-
map_bh->b_state =
0;
-
map_bh->b_size =
0;
-
-
if (block_in_file < last_block) {
-
map_bh->b_size = (last_block-block_in_file) << blkbits;
-
if (get_block(inode, block_in_file, map_bh,
0))
-
goto confused;
-
*first_logical_block = block_in_file;
-
}
-
......
-
nblocks = map_bh->b_size >> blkbits;
-
for (relative_block =
0; ; relative_block++) {
-
if (relative_block == nblocks) {
-
clear_buffer_mapped(map_bh);
-
break;
-
}
else
if (page_block == blocks_per_page)
-
break;
-
blocks[page_block] = map_bh->b_blocknr+relative_block;
-
page_block++;
-
block_in_file++;
-
}
-
bdev = map_bh->b_bdev;
-
}
-
......
-
alloc_new:
-
if (bio ==
NULL) {
-
if (first_hole == blocks_per_page) {
-
if (!bdev_read_page(bdev, blocks[
0] << (blkbits -
9),
-
page))
-
goto out;
-
}
-
bio = mpage_alloc(bdev, blocks[
0] << (blkbits -
9),
-
min_t(
int, nr_pages, BIO_MAX_PAGES), gfp);
// Initialize according to the data block number found above bio
-
if (bio ==
NULL)
-
goto confused;
-
}
-
-
length = first_hole << blkbits;
-
if (bio_add_page(bio, page, length,
0) < length) {
// Add memory pages to bio in
-
bio = mpage_bio_submit(REQ_OP_READ,
0, bio);
-
goto alloc_new;
-
}
-
-
......
-
out:
-
return bio;
-
......
Block mapping The function pointer mentioned earlier get_block Pointing function ext2_get_block, The logic is as follows :
-
struct ext2_sb_info {
-
.......
-
spinlock_t s_rsv_window_lock;
-
struct rb_root s_rsv_window_root;
// Red black tree of preallocation window
-
struct ext2_reserve_window_node s_rsv_window_head;
// The root node of the red black tree , Empty window
-
.......
-
};
-
-
-
struct ext2_inode_info {
-
......
-
struct ext2_block_alloc_info *i_block_alloc_info;
// Preallocated information structure
-
......
-
};
struct ext2_block_alloc_info | |
struct ext2_reserve_window_node rsv_window_node; | Reserved window information |
__u32 last_alloc_logical_block; | Last allocated logical block , That is, the block offset from the file |
ext2_fsblk_t last_alloc_physical_block; | Logic block , That is, the block number on the disk |
struct ext2_reserve_window_node | |
struct rb_node rsv_node | Used to add to ext2_sb_info In the red and black trees |
__u32 rsv_goal_size | Preallocated size |
struct ext2_reserve_window rsv_window | struct ext2_reserve_window { ext2_fsblk_t _rsv_start; // Starting position of pre allocation ext2_fsblk_t _rsv_end;// Preallocated end position }; |
inode Initialization of pre allocation window :
-
void ext2_init_block_alloc_info(struct inode *inode)
-
{
-
struct ext2_inode_info *ei = EXT2_I(inode);
-
struct ext2_block_alloc_info *block_i;
-
struct super_block *sb = inode->i_sb;
-
-
-
block_i = kmalloc(
sizeof(*block_i), GFP_NOFS);
-
if (block_i) {
-
struct ext2_reserve_window_node *rsv = &block_i->rsv_window_node;
-
-
-
rsv->rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
-
rsv->rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
// The identification pre allocation window is empty
-
-
-
if (!test_opt(sb, RESERVATION))
-
rsv->rsv_goal_size =
0;
-
else
-
rsv->rsv_goal_size = EXT2_DEFAULT_RESERVE_BLOCKS;
// The default preallocated window size is 8
-
rsv->rsv_alloc_hit =
0;
-
block_i->last_alloc_logical_block =
0;
-
block_i->last_alloc_physical_block =
0;
-
}
-
ei->i_block_alloc_info = block_i;
-
}
Now let's formally explain the allocation of blocks :
-
ext2_fsblk_t ext2_new_blocks(struct inode *inode,
ext2_fsblk_t goal,
-
unsigned
long *count,
int *errp)
-
{
-
......
-
struct ext2_super_block *es;
-
struct ext2_sb_info *sbi;
-
struct ext2_reserve_window_node *my_rsv = NULL;
-
struct ext2_block_alloc_info *block_i;
-
unsigned
short windowsz =
0;
-
unsigned
long ngroups;
-
unsigned
long num = *count;
-
-
-
sb = inode->i_sb;
-
-
-
-
-
sbi = EXT2_SB(sb);
-
-
-
block_i = EXT2_I(inode)->i_block_alloc_info;
-
if (block_i) {
-
windowsz = block_i->rsv_window_node.rsv_goal_size;
-
if (windowsz >
0)
-
my_rsv = &block_i->rsv_window_node;
-
}
-
-
-
group_no = (goal - le32_to_cpu(es->s_first_data_block)) /
-
EXT2_BLOCKS_PER_GROUP(sb);
// Calculation goal The block group in which it is located
-
goal_group = group_no;
-
retry_alloc:
-
gdp = ext2_get_group_desc(sb, group_no, &gdp_bh);
// Get group descriptor
-
if (!gdp)
-
goto io_error;
-
-
-
free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
-
-
-
if (free_blocks >
0) {
-
grp_target_blk = ((goal - le32_to_cpu(es->s_first_data_block)) %
-
EXT2_BLOCKS_PER_GROUP(sb));
-
bitmap_bh = read_block_bitmap(sb, group_no);
// Read block group data block bitmap
-
if (!bitmap_bh)
-
goto io_error;
-
grp_alloc_blk = ext2_try_to_allocate_with_rsv(sb, group_no,
-
bitmap_bh, grp_target_blk,
-
my_rsv, &num);
// Allocate data blocks , And realize data block pre allocation
-
if (grp_alloc_blk >=
0)
-
goto allocated;
-
}
-
-
-
ngroups = EXT2_SB(sb)->s_groups_count;
-
-
-
for (bgi =
0; bgi < ngroups; bgi++) {
// If in goal If there is no allocation in the block group, try to allocate from the first block group
-
......
-
}
-
if (my_rsv) {
-
my_rsv =
NULL;
-
windowsz =
0;
-
group_no = goal_group;
-
goto retry_alloc;
-
}
-
-
-
allocated:
-
ret_block = grp_alloc_blk + ext2_group_first_block_no(sb, group_no);
-
......
-
return ret_block;
// Return the block number of the assigned block group
-
......
The following function is the core function of block allocation , First, find a free space that can accommodate the pre allocated window size , Then set the corresponding position on the data block bitmap to 1, Indicates that has been allocated .
-
static ext2_grpblk_t
-
ext2_try_to_allocate_with_rsv
(struct super_block *sb, unsigned int group,
-
struct buffer_head *bitmap_bh, ext2_grpblk_t grp_goal,
-
struct ext2_reserve_window_node * my_rsv,
-
unsigned long *count)
-
{
-
ext2_fsblk_t group_first_block, group_last_block;
-
ext2_grpblk_t ret =
0;
-
unsigned
long num = *count;
-
-
if (my_rsv ==
NULL) {
// Directly allocate data blocks without pre allocation
-
return ext2_try_to_allocate(sb, group, bitmap_bh,
-
grp_goal, count,
NULL);
-
}
-
-
group_first_block = ext2_group_first_block_no(sb, group);
-
group_last_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) -
1);
-
-
while (
1) {
-
if (rsv_is_empty(&my_rsv->rsv_window) || (ret <
0) ||
-
!goal_in_my_reservation(&my_rsv->rsv_window,
-
grp_goal, group, sb)) {
// The pre allocation window is empty or the target block is not my_rsv in
-
if (my_rsv->rsv_goal_size < *count)
// my_rsv->rsv_goal_size The initial value is 8
-
my_rsv->rsv_goal_size = *count;
-
ret = alloc_new_reservation(my_rsv, grp_goal, sb,
-
group, bitmap_bh);
// Find a free space that can accommodate the pre allocated window size
-
if (ret <
0)
-
break;
/* failed */
-
-
if (!goal_in_my_reservation(&my_rsv->rsv_window,
-
grp_goal, group, sb))
-
grp_goal =
-1;
-
}
else
if (grp_goal >=
0) {
-
int curr = my_rsv->rsv_end -
-
(grp_goal + group_first_block) +
1;
-
-
if (curr < *count)
-
try_to_extend_reservation(my_rsv, sb,
-
*count - curr);
-
}
-
-
if ((my_rsv->rsv_start > group_last_block) ||
-
(my_rsv->rsv_end < group_first_block)) {
-
rsv_window_dump(&EXT2_SB(sb)->s_rsv_window_root,
1);
-
BUG();
-
}
-
ret = ext2_try_to_allocate(sb, group, bitmap_bh, grp_goal,
-
&num, &my_rsv->rsv_window);
// Set the corresponding position of the data block in the pre allocation window on the bitmap to 1
-
if (ret >=
0) {
-
my_rsv->rsv_alloc_hit += num;
// Count the number of pre allocation hits
-
*count = num;
-
break;
/* succeed */
-
}
-
num = *count;
// Returns the number of blocks allocated
-
}
-
return ret;
-
}
The following function is the core of pre allocation :
-
static int alloc_new_reservation(struct ext2_reserve_window_node *my_rsv,
-
ext2_grpblk_t grp_goal, struct super_block *sb,
-
unsigned
int group, struct buffer_head *bitmap_bh)
-
{
-
struct ext2_reserve_window_node *search_head;
-
ext2_fsblk_t group_first_block, group_end_block, start_block;
-
ext2_grpblk_t first_free_block;
-
struct rb_root *fs_rsv_root = &EXT2_SB(sb)->s_rsv_window_root;
-
unsigned
long size;
-
int ret;
-
spinlock_t *rsv_lock = &EXT2_SB(sb)->s_rsv_window_lock;
-
-
group_first_block = ext2_group_first_block_no(sb, group);
-
group_end_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) -
1);
-
-
start_block = grp_goal + group_first_block;
// Search the starting position of the space interval
-
-
size = my_rsv->rsv_goal_size;
-
-
search_head = search_reserve_window(fs_rsv_root, start_block);
// Find a distance start_block The nearest reserved window
-
-
retry:
-
ret = find_next_reservable_window(search_head, my_rsv, sb,
-
start_block, group_end_block);
// With search_head Find a starting point that can hold my_rsv Idle interval that does not overlap with other reserved windows
-
......
-
first_free_block = bitmap_search_next_usable_block(
-
my_rsv->rsv_start - group_first_block,
-
bitmap_bh, group_end_block - group_first_block +
1);
// Find the block group in the bit table rsv_start Next, the first free block , Because not all Block allocations are pre allocated , So some blocks may have been allocated but cannot be found in the reservation window
-
-
......
-
start_block = first_free_block + group_first_block;
-
-
if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
// Whether the free block is my_rsv in
-
return
0;
/* success */
-
search_head = my_rsv;
// If my_rsv The blocks in the interval are allocated with my_rsv Search again for the starting point
-
goto retry;
-
}
边栏推荐
- Dynamics 365online applicationuser creation method change
- Arthas simple instructions
- 如何成为一名高级数字 IC 设计工程师(5-2)理论篇:ULP 低功耗设计技术精讲(上)
- 有没有大佬帮忙看看这个报错,有啥排查思路,oracle cdc 2.2.1 flink 1.14.4
- VSCode+mingw64+cmake
- 创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值。同时,要求元素的值各不相同。
- ViewPager2和VIewPager的区别以及ViewPager2实现轮播图
- Kubernetes cluster capacity expansion to add node nodes
- Network request process
- **Grafana installation**
猜你喜欢
網易雲微信小程序
Unity shader (basic concept)
# Arthas 简单使用说明
The configuration and options of save actions are explained in detail, and you won't be confused after reading it
Information Security Experiment 2: using x-scanner scanning tool
VSCode+mingw64
Over 100000 words_ Ultra detailed SSM integration practice_ Manually implement permission management
Impression notes finally support the default markdown preview mode
Octopus future star won a reward of 250000 US dollars | Octopus accelerator 2022 summer entrepreneurship camp came to a successful conclusion
其实特简单,教你轻松实现酷炫的数据可视化大屏
随机推荐
Oracle安装增强功能出错
第一讲:包含min函数的栈
flex弹性布局
Unity uses mesh to realize real-time point cloud (I)
What development models did you know during the interview? Just read this one
Unity uses mesh to realize real-time point cloud (II)
Switching value signal anti shake FB of PLC signal processing series
软件建模与分析
[4g/5g/6g topic foundation-146]: Interpretation of white paper on 6G overall vision and potential key technologies-1-overall vision
VSCode+mingw64+cmake
数据库多表关联查询问题
Create an int type array with a length of 6. The values of the array elements are required to be between 1-30 and are assigned randomly. At the same time, the values of the required elements are diffe
flinkcdc采集oracle在snapshot阶段一直失败,这个得怎么调整啊?
JS reverse tutorial second issue - Ape anthropology first question
Communication mode between processes
Unity shader (pass user data to shader)
Information Security Experiment 1: implementation of DES encryption algorithm
How to solve the problem of golang select mechanism and timeout
有没有大佬帮忙看看这个报错,有啥排查思路,oracle cdc 2.2.1 flink 1.14.4
Unity shader (basic concept)