<资料收集>Btrfs的磁盘结构

来源:http://bbs.chinaunix.net/archiver/?tid-1925448.html

Btrfs的磁盘结构
Btrfs超级块磁盘结构
超级块记录着一个分区的整体信息。
Btrfs磁盘super_block结构用btrfs_super_block来描述,其定义为:
---------------------------------------------------------------------
fs/btrfs/ctree.h
330 struct btrfs_super_block {
331         u8 csum;
332         /* the first 4 fields must match struct btrfs_header */
333         u8 fsid;    /* FS specific uuid */
334         __le64 bytenr; /* this block number */
335         __le64 flags;
336
337        /* allowed to be different from the btrfs_header from here own down */
338         __le64 magic;
339         __le64 generation;
340         __le64 root;
341         __le64 chunk_root;
342         __le64 log_root;
343
344        /* this will help find the new super based on the log root */
345         __le64 log_root_transid;
346         __le64 total_bytes;
347         __le64 bytes_used;
348         __le64 root_dir_objectid;
349         __le64 num_devices;
350         __le32 sectorsize;
351         __le32 nodesize;
352         __le32 leafsize;
353         __le32 stripesize;
354         __le32 sys_chunk_array_size;
355         __le64 chunk_root_generation;
356         __le64 compat_flags;
357         __le64 compat_ro_flags;
358         __le64 incompat_flags;
359         __le16 csum_type;
360         u8 root_level;
361         u8 chunk_root_level;
362         u8 log_root_level;
363         struct btrfs_dev_item dev_item;
364
365         char label;
366
367         /* future expansion */
368         __le64 reserved;
369         u8 sys_chunk_array;
370 } __attribute__ ((__packed__));
---------------------------------------------------------------------

每个磁盘超级块中都包含一个设备item,其定义如下:
---------------------------------------------------------------------
fs/btrfs/ctree.h
184 struct btrfs_dev_item {
185         /* the internal btrfs device id */
186         __le64 devid;
187
188         /* size of the device */
189         __le64 total_bytes;
190
191         /* bytes used */
192         __le64 bytes_used;
193
194         /* optimal io alignment for this device */
195         __le32 io_align;
196
197         /* optimal io width for this device */
198         __le32 io_width;
199
200         /* minimal io size for this device */
201         __le32 sector_size;
202
203         /* type and info about this device */
204         __le64 type;
205
206         /* expected generation for this device */
207         __le64 generation;
208
209         /*
210          * starting byte of this partition on the device,
211          * to allow for stripe alignment in the future
212          */
213         __le64 start_offset;
214
215         /* grouping information for allocation decisions */
216         __le32 dev_group;
217
218         /* seek speed 0-100 where 100 is fastest */
219         u8 seek_speed;
220
221         /* bandwidth 0-100 where 100 is fastest */
222         u8 bandwidth;
223
224         /* btrfs generated uuid for this device */
225         u8 uuid;
226
227         /* uuid of FS who owns this device */
228         u8 fsid;
229 } __attribute__ ((__packed__));
---------------------------------------------------------------------

关于磁盘超级块,还可以看到如下的一些宏:
---------------------------------------------------------------------
fs/btrfs/disk-io.h
22 #define BTRFS_SUPER_INFO_OFFSET (64 * 1024)
23 #define BTRFS_SUPER_INFO_SIZE 4096
24
25 #define BTRFS_SUPER_MIRROR_MAX   3
26 #define BTRFS_SUPER_MIRROR_SHIFT 12
---------------------------------------------------------------------
我们可以看到磁盘超级块在块设备上的偏移为64 * 1024,其大小为4096,并且在磁盘上有3个镜像。

得先了解一下btrfs管理元数据的方式。Btrfs 内部所有的元数据都采用 BTree 管理,拥有良好的可扩展性。 btrfs 内部不同的元数据由不同的 Tree 管理。在 superblock 中,有指针指向这些 BTree 的根。

FS Tree 管理文件相关的元数据,如 inode,dir等; Chunk tree管理设备,每一个磁盘设备都在Chunk Tree中有一个item;Extent Tree管理磁盘空间分配,btrfs每分配一段磁盘空间,便将该磁盘空间的信息插入到Extent tree。查询Extent Tree将得到空闲的磁盘空间信息;checksum Tree 保存数据块的校验和;Tree of tree root保存很多 BTree 的根节点。比如用户每建立一个快照,btrfs 便会创建一个FS Tree。

为了管理所有的树,btrfs 采用 Tree of tree root来保存所有树的根节点,(super_block->s_fs_info =  tree_root(struct btrfs_root), tree_root-> fs_info = fs_info(struct btrfs_fs_info)),也就是btrfs_fs_info结构,其定义为:
---------------------------------------------------------------------
fs/btrfs/ctree.h
802 struct btrfs_fs_info {
803         u8 fsid;
804         u8 chunk_tree_uuid;
805         struct btrfs_root *extent_root;
806         struct btrfs_root *tree_root;
807         struct btrfs_root *chunk_root;
808         struct btrfs_root *dev_root;
809         struct btrfs_root *fs_root;
810         struct btrfs_root *csum_root;
811
812    /* the log root tree is a directory of all the other log roots */
813         struct btrfs_root *log_root_tree;
814
815         spinlock_t fs_roots_radix_lock;
816         struct radix_tree_root fs_roots_radix;
817
818         /* block group cache stuff */
819         spinlock_t block_group_cache_lock;
820         struct rb_root block_group_cache_tree;
821
822         struct extent_io_tree freed_extents;
823         struct extent_io_tree *pinned_extents;
824
825         /* logical->physical extent mapping */
826         struct btrfs_mapping_tree mapping_tree;
827
828         u64 generation;
829         u64 last_trans_committed;

988
989         void *bdev_holder;
990 };
---------------------------------------------------------------------

既然说到了Btree,就不能不提btrfs中的一些Btree设施,先来看下extent_buffer。顾名思义,即是extent在内存中的缓冲,它是btrfs文件系统磁盘空间管理的核心,btrfs通过btree来管理各种元数据,比如inode、目录项,等。这些B+树的每一个节点(包括叶子节点和上层节点)都存储在一个单位的extent中,每次要读取元数据或者要向磁盘写入元数据,则通常先先将数据读入extent_buffer或者向extent_buffe写入数据。
---------------------------------------------------------------------
fs/btrfs/extent-io.h
struct extent_buffer {
        u64 start;
        unsigned long len;
        char *map_token;
        char *kaddr;
        unsigned long map_start;
        unsigned long map_len;
        struct page *first_page;
        unsigned long bflags;
        atomic_t refs;
        struct list_head leak_list;
        struct rb_node rb_node;

spinlock_t lock;

wait_queue_head_t lock_wq;
};
---------------------------------------------------------------------

接下来,来看这一个个的节点的构成,包括上层节点和叶子节点。
每一个树块(叶子或节点)都以header开始。其定义为:
---------------------------------------------------------------------
fs/btrfs/ctree.h
291 struct btrfs_header {
292    /* these first four must match the super block */
293    u8 csum;
294    u8 fsid; /* FS specific uuid */
295    __le64 bytenr; /* which block this node is supposed to live in */
296    __le64 flags;
297
298    /* allowed to be different from the super from here on down */
299    u8 chunk_tree_uuid;
300    __le64 generation;
301    __le64 owner;
302    __le32 nritems;
303    u8 level;
304 } __attribute__ ((__packed__));
---------------------------------------------------------------------

而一个上层节点则由一个结构表示,其定义为:
---------------------------------------------------------------------
fs/btrfs/ctree.h
411 struct btrfs_key_ptr {
412         struct btrfs_disk_key key;
413         __le64 blockptr;
414         __le64 generation;
415 } __attribute__ ((__packed__));

416
417 struct btrfs_node {
418         struct btrfs_header header;
419         struct btrfs_key_ptr ptrs[];
420 } __attribute__ ((__packed__));
---------------------------------------------------------------------

用于管理btrfs各种元数据的各种B+树最大的不同显然就在这个btrfs_leaf的内容了。叶子节点的其定义如下:
---------------------------------------------------------------------
fs/btrfs/ctree.h
389 struct btrfs_item {
390         struct btrfs_disk_key key;
391         __le32 offset;
392         __le32 size;
393 } __attribute__ ((__packed__));
394

402 struct btrfs_leaf {
403         struct btrfs_header header;
404         struct btrfs_item items[];
405 } __attribute__ ((__packed__));
---------------------------------------------------------------------
代码的注释中也有说明,叶子节点的结构大致如下图:
javascript:;
最主要区别就在于Data部分的内容,这部分内容则因树的类型的不同而不同,比如,如果是inode的btree,那么data部分的内容就是btrfs_inode_item结构,等等。

Btrfs磁盘inode结构
Btrfs磁盘上的inode结构用btrfs_inode_item结构来表示,其定义为:
---------------------------------------------------------------------
fs/btrfs/ctree.h
535 struct btrfs_inode_item {
536         /* nfs style generation number */
537         __le64 generation;
538         /* transid that last touched this inode */
539         __le64 transid;
540         __le64 size;
541         __le64 nbytes;
542         __le64 block_group;
543         __le32 nlink;
544         __le32 uid;
545         __le32 gid;
546         __le32 mode;
547         __le64 rdev;
548         __le64 flags;
549
550         /* modification sequence number for NFS */
551         __le64 sequence;

557         __le64 reserved;
558         struct btrfs_timespec atime;
559         struct btrfs_timespec ctime;
560         struct btrfs_timespec mtime;
561         struct btrfs_timespec otime;
562 } __attribute__ ((__packed__));
---------------------------------------------------------------------
上面atime、 ctime、mtime分别记录访问时间、改变时间和修改时间,其类型定义如下:
524 struct btrfs_timespec {
525         __le64 sec;
526         __le32 nsec;
527 } __attribute__ ((__packed__));

Btrfs磁盘目录项结构
Btrfs磁盘目录项使用一个btrfs_dir_item来表示,在磁盘上作为某个Btree的叶子节点的data项而存在,其定义为:
---------------------------------------------------------------------
fs/btrfs/ctree.h
568 struct btrfs_dir_item {
569         struct btrfs_disk_key location;
570         __le64 transid;
571         __le16 data_len;
572         __le16 name_len;
573         u8 type;
574 } __attribute__ ((__packed__));
---------------------------------------------------------------------
上面的location字段,顾名思义,指的应该是文件的位置,可为什么会是btrfs_disk_key,其实它指的是关联的文件在inode Btree中的关键字。Ext2 等文件系统中采用固定分配inode,磁盘目录项中含有文件索引节点号,而btrfs则使用关键字来定位文件。

上面的btrfs_disk_key定义如下:
---------------------------------------------------------------------
fs/btrfs/ctree.h

167 struct btrfs_disk_key {
168         __le64 objectid;
169         u8 type;
170         __le64 offset;
171 } __attribute__ ((__packed__));
172
173 struct btrfs_key {
174         u64 objectid;
175         u8 type;
176         u64 offset;
177 } __attribute__ ((__packed__));
---------------------------------------------------------------------
Btrfs使用一棵chunk数来管理磁盘设备
---------------------------------------------------------------------
fs/btrfs/ctree.h
237 struct btrfs_chunk {
238         /* size of this chunk in bytes */
239         __le64 length;
240
241         /* objectid of the root referencing this chunk */
242         __le64 owner;
243
244         __le64 stripe_len;
245         __le64 type;
246
247         /* optimal io alignment for this chunk */
248         __le32 io_align;
249
250         /* optimal io width for this chunk */
251         __le32 io_width;
252
253         /* minimal io size for this chunk */
254         __le32 sector_size;
255

259         __le16 num_stripes;
260
261         /* sub stripes only matter for raid10 */
262         __le16 sub_stripes;
263         struct btrfs_stripe stripe;
264         /* additional stripes go here */
265 } __attribute__ ((__packed__));

231 struct btrfs_stripe {
232         __le64 devid;
233         __le64 offset;
234         u8 dev_uuid;
235 } __attribute__ ((__packed__));
---------------------------------------------------------------------

在内核代码中还可以见到下面这各种磁盘存储结构,和计算机屏幕对视n久,也没太搞明白他们是干什么的,比如,它们是哪棵树的叶子节点的数据部分等,诸位高人,如果有明白的,还请多多指教。谢谢了。

---------------------------------------------------------------------
fs/btrfs/ctree.h
455 struct btrfs_extent_item {
456         __le64 refs;
457         __le64 generation;
458         __le64 flags;
459 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h
461 struct btrfs_extent_item_v0 {
462         __le32 refs;
463 } __attribute__ ((__packed__));

476 struct btrfs_tree_block_info {
477         struct btrfs_disk_key key;
478         u8 level;
479 } __attribute__ ((__packed__));
480
481 struct btrfs_extent_data_ref {
482         __le64 root;
483         __le64 objectid;
484         __le64 offset;
485         __le32 count;
486 } __attribute__ ((__packed__));
487
488 struct btrfs_shared_data_ref {
489         __le32 count;
490 } __attribute__ ((__packed__));
491
492 struct btrfs_extent_inline_ref {
493         u8 type;
494         __le64 offset;
495 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h
498 struct btrfs_extent_ref_v0 {
499         __le64 root;
500         __le64 generation;
501         __le64 objectid;
502         __le32 count;
503 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h

510 struct btrfs_dev_extent {
511         __le64 chunk_tree;
512         __le64 chunk_objectid;
513         __le64 chunk_offset;
514         __le64 length;
515         u8 chunk_tree_uuid;
516 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h
518 struct btrfs_inode_ref {
519         __le64 index;
520         __le16 name_len;
521         /* name goes here */
522 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h
564 struct btrfs_dir_log_item {
565         __le64 end;
566 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h
594 struct btrfs_root_ref {
595         __le64 dirid;
596         __le64 sequence;
597         __le16 name_len;
598 } __attribute__ ((__packed__));
---------------------------------------------------------------------

---------------------------------------------------------------------
fs/btrfs/ctree.h
604 struct btrfs_file_extent_item {

608         __le64 generation;

616         __le64 ram_bytes;
617

625         u8 compression;
626         u8 encryption;
627         __le16 other_encoding; /* spare for later use */

630         u8 type;
631

636         __le64 disk_bytenr;
637         __le64 disk_num_bytes;
645         __le64 offset;

650         __le64 num_bytes;
651
652 } __attribute__ ((__packed__));
---------------------------------------------------------------------

时间: 2024-10-28 14:54:00

<资料收集>Btrfs的磁盘结构的相关文章

&lt;资料收集&gt;新一代 Linux 文件系统 btrfs 简介

来自: http://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/ Btrfs 简介 文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3,ext 文件系统以其卓越的稳定性成为了事实上的 Linux 标准文件系统.近年来 ext2/3 暴露出了一些扩展性问题,于是便催生了 ext4 .在 2008 年发布的 Linux2.6.19 内核中集成了 ext4 的 dev 版本. 2.6.28 内核发布时,ext4 结束了开发版,开始

无法访问J盘显示磁盘结构损坏且无法读取的资料恢复办法

J盘打不开磁盘结构损坏且无法读取,是因为这个I盘的文件系统内部结构损坏导致的.要恢复里面的数据就必须要注意,这个盘不能格式化,否则数据会进一步损坏.具体的恢复方法看正文 工具/软件:星空数据恢复软件 步骤1:先百度搜索并下载程序运行后,直接双击需要恢复的分区,接着解压再右击软件图标选择<以管理员身份运行>软件(如果是xp系统可以直接双击打开软件)步骤2:软件打开后,直接双击需要恢复的分区步骤3:程序找出文件后,会放到与要恢复盘卷标名相同的目录中步骤4:将需要恢复的资料打钩,接着点右上角的保存,

E盘显示磁盘结构损坏且无法读取的资料恢复方案

问题描述:硬盘打不开磁盘结构损坏且无法读取,是因为这个I盘的文件系统内部结构损坏导致的.要恢复里面的数据就必须要注意,这个盘不能格式化,否则数据会进一步损坏.具体的恢复方法看正文工具/软件:极限数据恢复软件 步骤1:先下载并解压软件运行后,选中需要恢复的盘,然后点<开始恢复>按钮步骤2:程序找出资料后,会放到与要恢复盘卷标名相同的目录中步骤3:勾选所有需要恢复的文件,接着点右上角的<另存为>按钮,将勾选的文件复制出来.步骤4:等待软件将数据拷贝完毕就好了 .注意事项1:想要恢复硬盘

Maven的学习资料收集--(四)使用Maven构建Web项目-测试

2014-08-04 23:21 2人阅读 评论(0) 收藏 编辑 删除 目录(?)[+] [-] 在srcmainjava下新建一个Servlet 修改webxml 新建JSP 测试 在上一篇博客里,我们使用Maven构建了一个Web项目,我们在这里写一个简单的Servlet,测试一下. 1.在src/main/java下,新建一个Servlet [java] view plaincopyprint? <span style="font-weight: normal;">

Maven的学习资料收集--(三)使用Maven构建Web项目

新建Maven项目 File - New - Other 选择Maven Project 单击Next 保持默认即可单击Next 选择Archetype为 web app单击Next 输入一些必要信息单击Finish 项目结构如下图 配置项目 在项目上右键单击添加Source Folder 修改Build Path 配置 将项目转换为Dynamic Web Project 设置部署程序集Web Deployment Assembly 从网上查了一些资料,才算明白(也就是怎么操作吧),怎么使用Ma

Maven的学习资料收集--(六) 构建Hibernate项目

前面我们使用Maven构建了Struts2项目,这里我们来试一下Hibernate项目: 这里的例子,大体框架应该是正确的,但是,对于Maven的很多约定都没有掌握,估计包的命名都不是非常好,等以后,理解深刻了再改吧 1. 构建一个基本的Web项目 这里请参考前面的博客,一样的 2. 添加依赖,修改pom.xml [html] view plaincopy <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&

Maven的学习资料收集--(七) 构建Spring项目

在这里,使用Maven构建一个Spring项目 构建单独项目的话,其实都差不多 1. 新建一个Web项目 参考之前的博客 2.修改 pom.xml,添加Spring依赖 [html] view plaincopy <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=&

Feed系统架构资料收集(转)

add by zhj:有些链接已经失效,后续会修改. 原文:http://blog.csdn.net/zhangzhaokun/article/details/7834797 完全用nosql轻松打造千万级数据量的微博系统 微博feed系统的push和pull模式和时间分区拉模式架构探讨 关于如何构建一个微博型广播 关于如何构建一个微博型广播2 用 mongodb 储存多态消息/提醒类数据 构建高性能的微博系统-再谈新浪微博架构 人人网技术经理张铁安-Feed系统结构浅析 新浪微博Cache设计

硬盘无法访问磁盘结构损坏且无法读取,里面的数据怎么寻回

机械硬盘打不开磁盘结构损坏且无法读取,是因为这个I盘的文件系统内部结构损坏导致的.要恢复里面的数据就必须要注意,这个盘不能格式化,否则数据会进一步损坏.具体的恢复方法看正文 工具/软件:AuroraDataRecovery 步骤1:先下载并解压程序运行后,直接双击需要恢复的分区,然后右击软件图标选择<以管理员身份运行>(如果是xp系统可以直接双击打开软件) 步骤2:软件运行后,直接双击需要恢复的分区 步骤3:软件会很快将找出的文件,放到与要恢复盘同名的目录中 步骤4:打钩所有需要恢复的文件,然