ext2文件系统源代码之balloc.c文件解析

本文详细解读了ext2文件系统中balloc.c文件的代码,主要涉及块的分配和销毁过程。通过ext2_get_group_desc函数获取组描述符,read_block_bitmap函数读取数据块位图,以及reserve_blocks和release_blocks分别用于预留和释放块。通过对超级块、组描述符和位图的管理,实现了ext2文件系统中数据块的高效管理。
摘要由CSDN通过智能技术生成
前面把ext2的acl.c和acl.h文件分析过了,今天来看一个比较重要的文件,就是balloc.c,这个文件是用来做块的分配方面工作的,在文件系统是属于较低层的,可能有点困难,我努力讲解的通俗一点,大家有什么问题欢迎提问啦。
/*	作者方面的信息
 *  linux/fs/ext2/balloc.c
 *
 * Copyright (C) 1992, 1993, 1994, 1995
 * Remy Card (card@masi.ibp.fr)
 * Laboratoire MASI - Institut Blaise Pascal
 * Universite Pierre et Marie Curie (Paris VI)
 *
 *  Enhanced block allocation by Stephen Tweedie (sct@redhat.com), 1993
 *  Big-endian to little-endian byte-swapping/bitmaps by
 *        David S. Miller (davem@caip.rutgers.edu), 1995
 */


#include "ext2.h"
#include <linux/quotaops.h>
#include <linux/sched.h>
#include <linux/buffer_head.h>
#include <linux/capability.h>


/*balloc.c 包含块的分配和销毁方面的程序*/


/*在ext2文件系统,块的管理是通过位图来实现的,一个文件系统包含若干个块组,每一个块组有一个针对数据块的位图,还有一个针对inode的位图,文件系统的组描述符在超级块的后边,每一个组描述符都有空闲块的数目记录,组描述符都会在挂载文件系统的时候读到内存里。(ext2_fill_super) */


/*很简单的宏,判断b是不是在一个以first为头指针,长度为len的内存里,相信有点c语言功底的都能看懂*/
#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)


/*获得组描述符,block_group代表是第几个组,bh参数如果不为空,就把buffer_head形式的组描述符放在bh里*/
struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
					     unsigned int block_group,
					     struct buffer_head ** bh)
{
	unsigned long group_desc;
	unsigned long offset;
	struct ext2_group_desc * desc;
	/*从super_block里获得ext2_sb_info结构体,super_block是vfs便于管理设置的统一的超级块结构体,ext2_sb_info是ext2文件系统的放在内存里的超级块结构体,super_block的s_fs_info字段就是ext2_sb_info结构体,转化还是挺方便的*/
	struct ext2_sb_info *sbi = EXT2_SB(sb);
	/*如果参数大于组的数目,说明参数有问题,报错,返回NULL*/
	if (block_group >= sbi->s_groups_count) {
		ext2_error (sb, "ext2_get_group_desc",
			    "block_group >= groups_count - "
			    "block_group = %d, groups_count = %lu",
			    block_group, sbi->s_groups_count);


		return NULL;
	}
	/*EXT2_DESC_PER_BLOCK_BITS宏返回块拥有组描述符的数目转换成二进制位的位数,右移这些位就等于是除以一个块拥有组描述符的数目。我猜我这么说肯定大家不懂,还是举例子吧。比如ext2的ext2_group_desc是32字节,按照ext2的一个块有1K大小来算,一个块就有32个组描述符,所以就是5位,右移五位,除以32,块组描述符是聚集在一起的,有几个块是专门房块组描述符的,在超级块里有记录,我们知道了是第几个块组,但是接下来要知道是在块组描述符群组里的第几个块,比如我们要去第45个块组,45/32=1,所以就得到了是在第二个块里,偏移就是45%32=13,也可以与位,45&(32-1)=13*/
	group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(sb);
	/*这里的offset就是在块内的第几个描述符*/
	offset = block_group & (EXT2_DESC_PER_BLOCK(sb) - 1);
	/*sbi->s_group_desc就存放着块组描述符好几个块哦,如果为空,就说明ext2出问题了,并且很严重,报错*/
	if (!sbi->s_group_desc[group_desc]) {
		ext2_error (sb, "ext2_get_group_desc",
			    "Group descriptor not loaded - "
			    "block_group = %d, group_desc = %lu, desc = %lu",
			     block_group, group_desc, offset);
		return NULL;
	}
	/*描述符指针指向对应的buffer_head->b_data就是组描述符所在组的第一个组描述符*/
	desc = (struct ext2_group_desc *) sbi->s_group_desc[group_desc]->b_data;
	/*如果参数bh不为空,就赋值组描述符的buffer_head给bh*/
	if (bh)
		*bh = sbi->s_group_desc[group_desc];
	/*返回想要的组描述符*/
	return desc + offset;
}


/*阅读给定的块组的数据块位图,如果成功,返回位图的buffer_head,失败返回NULL*/
static struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
	struct ext2_group_desc * desc;
	struct buffer_head * bh = NULL;
	/*上边的函数,刚讲过哦,根据block_group得到块组描述符*/
	desc = ext2_get_group_desc (sb, block_group, NULL);
	/*失败的话,返回NULL*/
	if (!desc)
		goto error_out;
	/*调用底层驱动函数,读取数据块位图,desc->bg_block_bitmap代表着数据块位图的块号码,返回数据块位图的buffer_head格式,sb_bread是块设备驱动和文件系统的连接函数,很重要,以后我会好好研究下它*/
	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
	/*没读出来,就报错*/
	if (!bh)
		ext2_error (sb, "read_block_bitmap",
			    "Cannot read block bitmap - "
			    "block_group = %d, block_bitmap = %u",
			    block_group, le32_to_cpu(desc->bg_block_bitmap));
error_out:
	return bh;
}


/*把空闲的一部分放到保留块里边,保留块是为了防止ext2出现问题,预先保留一部分以备不测,一般是5%左右,count参数就是需要放到保留块里的块数目,需要知道,空闲块的数目也包括保留块的数目,保留块肯定也是空闲块,空闲块不一定是保留块
 * Set sb->s_dirt here because the superblock was "logically" altered.  We
 * need to recalculate its free blocks count and flush it out.
 */
static int reserve_blocks(struct super_block *sb, int count)
{
	struct ext2_sb_info *sbi = EXT2_SB(sb);
	struct ext2_super_block *es = sbi->s_es;
	unsigned free_blocks;
	unsigned root_blocks;
	/*percpu_counter_read_positive函数是为了防止多处理器并发导致的读取失败,从ext2_sb_info->s_freeblocks_counter得到的是当前ext2的空闲的数据块数目*/
	free_blocks = percpu_counter_read_positive(&sbi->s_freebloc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值