如何恢复 Linux 上删除的文件-reiserfs 文件系统原理(4)
- UID
- 1066743
|
如何恢复 Linux 上删除的文件-reiserfs 文件系统原理(4)
STAT 条目stat 数据(TYPE_STAT_DATA)非常类似于 ext2 中的索引节点,其中保存了诸如文件权限、MAC(modified、accessed、changed)时间信息等数据。在3.6 版本的 reiserfs 中,stat 数据使用一个stat_data 结构表示,该结构大小为 44 字节,其定义如清单 7 所示:
清单7. stat_data 结构定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| 835 /* Stat Data on disk (reiserfs version of UFS disk inode minus the
836 address blocks) */
837 struct stat_data {
838 __le16 sd_mode; /* file type, permissions */
839 __le16 sd_attrs; /* persistent inode flags */
840 __le32 sd_nlink; /* number of hard links */
841 __le64 sd_size; /* file size */
842 __le32 sd_uid; /* owner */
843 __le32 sd_gid; /* group */
844 __le32 sd_atime; /* time of last access */
845 __le32 sd_mtime; /* time file was last modified */
846 __le32 sd_ctime; /* time inode (stat data) was last changed */
/* (except changes to sd_atime and sd_mtime) */
847 __le32 sd_blocks;
848 union {
849 __le32 sd_rdev;
850 __le32 sd_generation;
851 //__le32 sd_first_direct_byte;
852 /* first byte of file which is stored in a
853 direct item: except that if it equals 1
854 it is a symlink and if it equals
855 ~(__u32)0 there is no direct item. The
856 existence of this field really grates
857 on me. Let's replace it with a macro
858 based on sd_size and our tail
859 suppression policy? */
860 } __attribute__ ((__packed__)) u;
861 } __attribute__ ((__packed__));
862 //
863 // this is 44 bytes long
864 //
|
stat_data 条目使用的关键字中,offset 和 type 的值总是 0,这样就能确保 stat 数据是相同对象(object-id)中的第一个条目,从而能够加快访问速度。
与 ext2 的 ext2_indoe 结构对比一下就会发现,stat_data 中既没有记录数据块位置的地方,也没有记录删除时间,而这正是我们在 ext2/ext3 中恢复删除文件的基础,因此可以猜测得到,在reiserfs 文件系统中要想恢复已经删除的文件,难度会变得更大。
目录条目目录条目中记录了目录项信息。目录条目由目录头和目录项数据(即文件或子目录名)组成。如果一个目录中包含的目录项太多,可以扩充到多个目录条目中存储。为了方便管理某个目录中子目录或文件的增减,目录条目也采用了与条目头类似的设计:从两端向中间扩充,其布局结构如图 5 所示。
图 5. 目录条目存储结构目录头是一个 reiserfs_de_head 结构,大小为 16 字节,其定义如清单 8 所示。
清单8. reiserfs_de_head 结构定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| 920 /*
921 Q: How to get key of object pointed to by entry from entry?
922
923 A: Each directory entry has its header. This header has
deh_dir_id and deh_objectid fields, those are key
924 of object, entry points to */
925
926 /* NOT IMPLEMENTED:
927 Directory will someday contain stat data of object */
928
929 struct reiserfs_de_head {
930 __le32 deh_offset; /* third component of the directory entry key */
931 __le32 deh_dir_id; /* objectid of the parent directory of the object,
932 that is referenced by directory entry */
933 __le32 deh_objectid; /* objectid of the object, that is referenced */
/* by directory entry */
934 __le16 deh_location; /* offset of name in the whole item */
935 __le16 deh_state; /* whether 1) entry contains stat data (for future),
936 and 2) whether entry is hidden (unlinked) */
937 } __attribute__ ((__packed__));
|
reiserfs_de_head 结构中包含了 deh_dir_id 和 deh_objectid fields 这两个字段,它们就是其父目录关键字中对应的两个字段。deh_offset 的 7 到 30 位是文件名的 hash 值,0 到 6 位用来解决 hash 冲突的问题(reiserfs 中可以使用 3 种 hash 函数:tea、rupasov 和 r5,默认为 r5)。文件名的位置保存在 deh_location 字段中,而 deh_state 的第 2 位表示该目录条目是否是可见的(该位为 1 则表示该目录条目是可见的,为 0 表示不可见)。文件名是一个字符串,以空字符结束,按照 8 字节对齐。
直接条目与间接条目在 reiserfs 中,文件数据可以通过两种方式进行存取:直接条目(direct item)和间接条目(indirect item)。对于小文件来说,文件数据本身和 stat 数据可以一起存储到叶子节点中,这种条目就称为直接条目。直接条目就采用图 4 所示的存储结构,不过每个条目数据体就是文件数据本身。对于大文件来说,单个叶子节点无法存储下所有数据,因此会将部分数据存储到未格式化数据块中,并通过间接条目中存储的指针来访问这些数据块。未格式化数据块都是整块使用的,最后一个未格式化数据块中可能会遗留一部分剩余空间,大小是由对应条目头的 ih_free_space_reserved 字段指定的。图 6 给出了间接条目的存储结构。
图 6. 间接条目存储结构对于缺省的 4096 字节的数据块来说,一个间接条目所能存储的数据最大可达 4048 KB(4096*(4096-48)/4 字节),更大的文件需要使用多个间接条目进行存储,它们之间的顺序是通过关键字中的 offset 进行标识的。
另外,文件末尾不足一个数据块的部分也可以像小文件一样存储到直接条目中,这种技术就称为尾部封装(tail packing)。在这种情况下,存储一个文件至少需要使用一个间接条目和一个直接条目。 |
|
|
|
|
|