zoukankan      html  css  js  c++  java
  • [ext4] 磁盘布局

    传统的类Unix文件系统,比如Ext3,都是使用一个间接数据块映射表来记录每一个数据块的分配情况的。但是这种机制对于超大文件的存储是有缺陷的,特别是当对超大文件进行删除和截断操作时。映射表会对每一个数据块进行记录,而一个超大文件将占有很多的数据块,因此造成映射表将变得无比臃肿,难于维护。

    Ext4引入了一个新的概念,叫做“Extents”。一个Extents是一个地址连续的数据块(block)的集合。比如一个100MB的文件有可能被分配给一个单独的Extents,这样就不用像Ext3那样新增25600个数据块的记录(一个数据块是4KB)。而超大型文件会被分解在多个extents里。

    很明显,Extents的实现提高了文件系统的性能,减少了文件碎片。

    Exents是如何在磁盘上存放的哪?

    注:本文所介绍的结构体都是直接存放在磁盘上结构.

    在extent tree中,每一个节点都是一个block,对于存放extent tree节点信息的block,我们可以称之为extent block。当然其根节点是存放在inode table中,所以根节点所在的block就不这么称呼了。每个节点在其offset为0的地方都有一个结构体ext4_extent_header用于描述该节点。

    结构体header的大小为12bytes,其定义在文件ext4_extents.h中。

    /*

     * Each block(leaves and indexes), even inode-stored has header.

     */

    struct ext4_extent_header {

        /*ext4 extents标识0xF30A. */

        __le16  eh_magic;   /*probably will support different formats */

        /* 当前节点中有效entries的数目 */

        __le16  eh_entries; /*number of valid entries */

        /* 当前节点中entry的最大数目 */

        __le16  eh_max;     /*capacity of store in entries */

    /* 当前节点在树中的深度 */

        __le16  eh_depth;   /*has tree real underlying blocks? */

        __le32  eh_generation;  /*generation of the tree */

    };

    在该结构体中,针对当前节点在树中的深度说要说明的是:

    1. 叶子节点,深度为0,指向数据extent。

    2.tree中最大深度的节点是根节点;

    3. 深度最大为5:logic block number最大为2^32, 满足4*(((blocksize - 12)/12)^n) >= 2^32 条件的最小n是5。

    节点中存放的ext4_extent_header数据之后都是很多entry(即表项),每个entry大小为12bytes。如果是非叶子节点(所谓非叶子节点,即ext4_extent_header -> eh_depth > 0),每个entry中存放是index数据,由struct ext4_extent_idx描述,每一个entry索引都指向一个extent block;如果是叶子节点(所谓叶子节点,即ext4_extent_header -> eh_depth =0),每个entry都是指向一个extent,由struct ext4_extent描述。每个ext4_extent。

    我们先来分析一下ext4_extent_idx结构体,如前所述,ext4_extent_idx是用于描述extent block的一个结构体,通过该结构体,可以寻找到下一级的节点。

    struct ext4_extent_idx {

        /* 索引所覆盖的文件范围的起始block */

        __le32  ei_block;   /*index covers logical blocks from 'block' */

        /* 下一级extent block的逻辑地址的低32位 */

        __le32  ei_leaf_lo; /*pointer to the physical block of the next *

                     * level. leaf or next index could be there */

        /* 下一级extent block的逻辑地址的高16位 */

        __le16  ei_leaf_hi; /*high 16 bits of physical block */

        __u16   ei_unused;

    };

    ext4_extent是用于表示extent的数据结构:

    /*

     * This isthe extent on-disk structure.

     * It's usedat the bottom of the tree.

     */

    struct ext4_extent {

        /* extent的起始block地址 */

        __le32  ee_block;   /*first logical block extent covers */

        /*extent的长度 */

        __le16  ee_len;     /*number of blocks covered by extent */

        /*extent起始block的物理地址的高16位 */

        __le16  ee_start_hi;    /*high 16 bits of physical block */

        /*extent起始block的物理地址的低32位 */

        __le32  ee_start_lo;    /*low 32 bits of physical block */

    };

    关于extent的成员变量ee_len,需要说明的是:如果该值<=32768,那么这个extent已经初始化的。如果该值>32768,这个extent还没有初始化,并且extent长度是ee_len-32768.因此一个初始化的extent,其最大长度是32768,而一个未初始化的extent,最大长度是32767。

    前述已经介绍过checksums。Header和extent entries并未占用整个block。因为2^12 % 12 >= 4,因此block中至少还剩余4bytes的未用空间。那么32位的校验值可以存放在该空间中。当然inode中可能表示的4个extents并不需要校验,因为inode已经进行了校验。(为什么这么解释,原因是,除根节点外的所有的extent block都进行了校验)。

    存放校验值的结构体为ext4_extent_tail

    /*

     * This isthe extent tail on-disk structure.

     * All otherextent structures are 12 bytes long.  Itturns out that

     * block_size% 12 >= 4 for at least all powers of 2 greater than 512, which

     * covers allvalid ext4 block sizes.  Therefore, thistail structure can be

     * crammedinto the end of the block without having to rebalance the tree.

     */

    struct ext4_extent_tail {

        __le32  et_checksum;    /*crc32c(uuid+inum+extent_block) */

    };

     

    至此,extent tree所涉及的且存放在磁盘的变量数据均介绍完毕,那么我们可以画一幅图用于表示exent block的布局,如下:

    header

    entry

    ……

    entry

    tail

     

    欢迎提出建议。


    作者:Younger Liu,

    本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。


  • 相关阅读:
    将IIS中网站日志批量导入到mysql【python】
    Python网站日志分析
    python 获取文件版本号和修改时间
    python将IIS日志导入到SQL
    python2.7 MySQLdb模块在win32下安装
    《python核心编程》课后题第二版第十五章463页
    python批量文件重命名
    python随机生成彩票号码
    python获取IP归属地
    百度收录批量查询【python版】
  • 原文地址:https://www.cnblogs.com/youngerchina/p/5624478.html
Copyright © 2011-2022 走看看