前言磁盘块与文件 inode entry 的申请和开释的解决机制总体上是统一的,所以就放到一起进行分享。在之前的文章中介绍了ext2文件系统磁盘的的总体布局,为了不便阐明,这里就假如磁盘只有一个块组。
块组布局
块组描述符: 与超级块作用相似,记录该块组的根本属性信息数据块位图/inode位图: 以 bit 作为基本操作对象,示意一个数据块或者 inode entry 的状态。置 0 示意闲暇,置 1 示意占用inode表: 集中寄存 inode entry数据块: 存储文件的数据与元数据发问1: 超级块保留的是磁盘整体的信息,为什么每个块组中都蕴含一份?
这样做就是为了保留多个备份,有利于磁盘被损坏时的数据恢复。有的磁盘文件系统并没有采纳此种设计,就比方 ufs,它是在某些特定磁盘块寄存超级块数据的备份 (印象中是有3份)。发问2: 每块区域的大小是如何确定的?
个别是采纳估算法来确定的。用户能够依据本身的理论应用状况,预设每个文件均匀占用的磁盘块数。因为文件肯定会惟一对应一个 inode 数据结构,这样就能够计算出 inode entry 的大抵个数。再进一步,能够计算失去 inode 位图和 inode 表的大小。超级块和块组描述符个别会占用残缺的一个或者几个磁盘块,确定之后就能够计算失去数据块位图和数据块两个区域的大小。每个区域的大小尽量设置为磁盘块大小的整数倍。如果存储空间比拟拮据,倡议保障磁盘块大小是数据结构大小的整数倍(可能会造成一些空间节约),益处是升高代码实现的复杂度。
次要函数剖析咱们次要关注 freebsd/usr/src/sys/fs/ext2fs 下的 ext2_alloc.c 和 ext2_balloc.c 两个文件。int ext2_alloc(...) :从磁盘申请一个闲暇数据块
/* * Allocate a block in the filesystem. * * A preference may be optionally specified. If a preference is given * the following hierarchy is used to allocate a block: * 1) allocate the requested block. * 2) allocate a rotationally optimal block in the same cylinder. * 3) allocate a block in the same cylinder group. * 4) quadradically rehash into other cylinder groups, until an * available block is located. * If no block preference is given the following hierarchy is used * to allocate a block: * 1) allocate a block in the cylinder group that contains the * inode for the file. * 2) quadradically rehash into other cylinder groups, until an * available block is located. */intext2_alloc(struct inode *ip, daddr_t lbn, e4fs_daddr_t bpref, int size, struct ucred *cred, e4fs_daddr_t *bnp){ struct m_ext2fs *fs; struct ext2mount *ump; e4fs_daddr_t bno; int cg; *bnp = 0; fs = ip->i_e2fs; ump = ip->i_ump; mtx_assert(EXT2_MTX(ump), MA_OWNED);#ifdef INVARIANTS if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) { vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n", (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt); panic("ext2_alloc: bad size"); } if (cred == NOCRED) panic("ext2_alloc: missing credential");#endif /* INVARIANTS */ if (size == fs->e2fs_bsize && fs->e2fs_fbcount == 0) goto nospace; if (cred->cr_uid != 0 && fs->e2fs_fbcount < fs->e2fs_rbcount) goto nospace; if (bpref >= fs->e2fs_bcount) bpref = 0; if (bpref == 0) cg = ino_to_cg(fs, ip->i_number); else cg = dtog(fs, bpref); bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2_alloccg); if (bno > 0) { /* set next_alloc fields as done in block_getblk */ ip->i_next_alloc_block = lbn; ip->i_next_alloc_goal = bno; ip->i_blocks += btodb(fs->e2fs_bsize); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); }nospace: EXT2_UNLOCK(ump); ext2_fserr(fs, cred->cr_uid, "filesystem full"); uprintf("\n%s: write failed, filesystem is full\n", fs->e2fs_fsmnt); return (ENOSPC);}参数剖析:
...