上一篇中,我们介绍了Ext3文件系统的日志可以看做一个文件,由JBD进行管理。自然而然引出如下这些问题:

1)如何定位ext3日志文件和查看日志文件的裸数据?

2)ext3日志文件数据在物理上是如何布局的?

3)JBD如何利用日志文件进行数据恢复?

带着这些问题,开始这次探索之旅。

JBD日志定位

首先找到ext3 日志文件的inode

  1. / # /dumpe2fs /dev/sda1
  2. dumpe2fs 1.42 (29-Nov-2011)
  3. Filesystem volume name: shouxian<none>
  4. Last mounted on: <not available>
  5. Filesystem UUID: 513c186a-108b-4840-ad98-aa8e8f62d4c8
  6. Filesystem magic number: 0xEF53
  7. Filesystem revision #: 1 (dynamic)
  8. Filesystem features: has_journal ext_attr resize_inode dir_index filetype sparse_super large_file
  9. Filesystem flags: signed_directory_hash
  10. Default mount options: user_xattr acl
  11. Filesystem state: clean
  12. Errors behavior: Continue
  13. Filesystem OS type: Linux
  14. Inode count: 513072
  15. Block count: 2048276
  16. Reserved block count: 102413
  17. Free blocks: 1978758
  18. Free inodes: 513061
  19. First block: 0
  20. Block size: 4096
  21. Fragment size: 4096
  22. Reserved GDT blocks: 500
  23. Blocks per group: 32768
  24. Fragments per group: 32768
  25. Inodes per group: 8144
  26. Inode blocks per group: 509
  27. Filesystem created: Sat Mar 21 11:39:13 2015
  28. Last mount time: n/a
  29. Last write time: Sat Mar 21 11:39:14 2015
  30. Mount count: 0
  31. Maximum mount count: -1
  32. Last checked: Sat Mar 21 11:39:13 2015
  33. Check interval: 0 (<none>)
  34. Reserved blocks uid: 0 (user root)
  35. Reserved blocks gid: 0 (group root)
  36. First inode: 11
  37. Inode size: 256
  38. Required extra isize: 28
  39. Desired extra isize: 28
  40. Journal inode: 8
  41. Default directory hash: half_md4
  42. Directory Hash Seed: 08091c3c-7a35-4f5b-8477-7af597c5eb50
  43. Journal backup: inode blocks
  44. Journal features: (none)
  45. Journal size: 128M
  46. Journal length: 32768
  47. Journal sequence: 0x00000001
  48. Journal start: 0

  

然后找到inode所在的数据块

  1. # /debugfs -R 'imap <8>' /dev/sda1
  2. debugfs 1.42 (29-Nov-2011)
  3. Inode 8 is part of block group 0
  4. located at block 504, offset 0x0700

根据块号、块大小和偏移,换算出inode所在数据块的物理偏移(以256B为单位)

  1. >>> (504*4096+0x700)/256.
  2. 8071.0

读出这个inode的数据

  1. # dd if=/dev/sda1 of=inode.8 bs=256 count=1 skip=8071
  2. 1+0 records in
  3. 1+0 records out
  4. 256 bytes (256B) copied, 0.000955 seconds, 261.8KB/s
  5.  
  6. /usr/lib # hexdump inode.8
  7. 0000000 8081 0000 0000 0008 6258 0d55 6258 0d55
  8. 0000010 6258 0d55 0000 0000 0000 0100 0801 0400
  9. 0000020 0000 0000 0000 0000 ff01 0f00 0002 0f00
  10. 0000030 0102 0f00 0202 0f00 0302 0f00 0402 0f00
  11. 0000040 0502 0f00 0602 0f00 0702 0f00 0802 0f00
  12. 0000050 0902 0f00 0a02 0f00 0b02 0f00 0c06 0f00
  13. 0000060 0000 0000 0000 0000 0000 0000 0000 0000
  14. *
  15. 0000080 1c00 0000 0000 0000 0000 0000 0000 0000
  16. 0000090 6258 0d55 0000 0000 0000 0000 0000 0000
  17. 00000a0 0000 0000 0000 0000 0000 0000 0000 0000
  18. *
  19. 0000100

对照inode数据结构,找到其管理的数据块块号(蓝色标示),前12映射槽是直接映射,直接管理的数据块块号从0x0f01ff(983551)到0x0f020b,属于group 30。

  1. Group 30: (Blocks 983040-1015807)
  2. Block bitmap at 983040 (+0), Inode bitmap at 983041 (+1)
  3. Inode table at 983042-983550 (+2)
  4. 0 free blocks, 8144 free inodes, 0 directories
  5. Free blocks:
  6. Free inodes: 244321-252464

至此,终于可以dump出日志文件数据块内容。

  1. # dd if=/dev/sda1 of=inode.8.data bs=4096 count=12 skip=983551
  2. 1+0 records in
  3. 1+0 records out
  4. 4096 bytes (4.0KB) copied, 0.000942 seconds, 4.1MB/s
  5.  
  6. 0000000 c03b 3998 0000 0004 0000 0000 0000 1000
  7. 0000010 0000 8000 0000 0001 0000 0002 0000 0001
  8. 0000020 0000 0000 0000 0000 0000 0000 0000 0000
  9. 0000030 513c 186a 108b 4840 ad98 aa8e 8f62 d4c8
  10. 0000040 0000 0001 0000 0000 0000 0000 0000 0000
  11. 0000050 0000 0000 0000 0000 0000 0000 0000 0000
  12. *
  13. 0001000 c03b 3998 0000 0001 0000 0002 0000 01f8
  14. 0001010 0000 0008 0000 0000 0000 0000 0000 0000
  15. 0001020 0000 0000 0000 0000 0000 0000 0000 0000
  16. *
  17. 0002000 0000 0000 0000 0000 6158 0d55 6158 0d55
  18. 0002010 6158 0d55 0000 0000 0000 0000 0000 0000
  19. 0002020 0000 0000 0000 0000 0000 0000 0000 0000
  20. *
  21. 0002100 ed41 0000 0010 0000 d75d 0d55 6158 0d55
  22. 0002110 6158 0d55 0000 0000 0000 0300 0800 0000
  23. 0002120 0000 0000 0000 0000 f503 0000 0000 0000
  24. 0002130 0000 0000 0000 0000 0000 0000 0000 0000
  25. *
  26. 0002180 1c00 0000 0000 0000 0000 0000 0000 0000
  27. 0002190 6158 0d55 0000 0000 0000 0000 0000 0000
  28. 00021a0 0000 0000 0000 0000 0000 0000 0000 0000
  29. *
  30. 0002600 8081 0000 00c0 4000 6158 0d55 6158 0d55
  31. 0002610 6158 0d55 0000 0000 0000 0100 a88c 0000
  32. 0002620 0000 0000 0000 0000 0000 0000 0000 0000
  33. *
  34. 0002650 0000 0000 0000 0000 0000 0000 fa03 0000
  35. 0002660 0000 0000 0000 0000 0000 0000 0100 0000
  36. 0002670 0000 0000 0000 0000 0000 0000 0000 0000
  37. 0002680 1c00 0000 0000 0000 0000 0000 0000 0000
  38. 0002690 6158 0d55 0000 0000 0000 0000 0000 0000
  39. 00026a0 0000 0000 0000 0000 0000 0000 0000 0000
  40. *
  41. 0002700 8081 0000 0000 0008 6258 0d55 6258 0d55
  42. 0002710 6258 0d55 0000 0000 0000 0100 0801 0400
  43. 0002720 0000 0000 0000 0000 ff01 0f00 0002 0f00
  44. 0002730 0102 0f00 0202 0f00 0302 0f00 0402 0f00
  45. 0002740 0502 0f00 0602 0f00 0702 0f00 0802 0f00
  46. 0002750 0902 0f00 0a02 0f00 0b02 0f00 0c06 0f00
  47. 0002760 0000 0000 0000 0000 0000 0000 0000 0000
  48. *
  49. 0002780 1c00 0000 0000 0000 0000 0000 0000 0000
  50. 0002790 6258 0d55 0000 0000 0000 0000 0000 0000
  51. 00027a0 0000 0000 0000 0000 0000 0000 0000 0000
  52. *
  53. 0002a00 c041 0000 0040 0000 6158 0d55 6158 0d55
  54. 0002a10 6158 0d55 0000 0000 0000 0200 2000 0000
  55. 0002a20 0000 0000 0000 0000 f603 0000 f703 0000
  56. 0002a30 f803 0000 f903 0000 0000 0000 0000 0000
  57. 0002a40 0000 0000 0000 0000 0000 0000 0000 0000
  58. *
  59. 0002a80 1c00 0000 0000 0000 0000 0000 0000 0000
  60. 0002a90 6158 0d55 0000 0000 0000 0000 0000 0000
  61. 0002aa0 0000 0000 0000 0000 0000 0000 0000 0000
  62. *
  63. 0003000 c03b 3998 0000 0002 0000 0002 0000 0000
  64. 0003010 0000 0000 0000 0000 0000 0000 0000 0000
  65. *
  66. 以下略

JBD日志分析

0000000 -- 0001000 数据块:

  日志超级块段,存储的是journal_superblock_t数据,从中可以看出块类型为JFS_SUPERBLOCK_V2(4),日志块大小: 0x1000; 日志块个数: 0x8000。进而可以计算出日志总大小为:0x1000 * 0x8000 = 128M。

  1. /*
  2. * Standard header for all descriptor blocks:
  3. */
  4. typedef struct journal_header_s
  5. {
  6. __be32 h_magic;
  7. __be32 h_blocktype;
  8. __be32 h_sequence;
  9. } journal_header_t;
  10.  
  11. /*
  12. * The journal superblock. All fields are in big-endian byte order.
  13. */
  14. typedef struct journal_superblock_s
  15. {
  16. /* 0x0000 */
  17. journal_header_t s_header;
  18.  
  19. /* 0x000C */
  20. /* Static information describing the journal */
  21. __be32 s_blocksize; /* journal device blocksize */
  22. __be32 s_maxlen; /* total blocks in journal file */
  23. __be32 s_first; /* first block of log information */
  24.  
  25. /* 0x0018 */
  26. /* Dynamic information describing the current state of the log */
  27. __be32 s_sequence; /* first commit ID expected in log */
  28. __be32 s_start; /* blocknr of start of log */
  29.  
  30. /* 0x0020 */
  31. /* Error value, as set by journal_abort(). */
  32. __be32 s_errno;
  33.  
  34. /* 0x0024 */
  35. /* Remaining fields are only valid in a version-2 superblock */
  36. __be32 s_feature_compat; /* compatible feature set */
  37. __be32 s_feature_incompat; /* incompatible feature set */
  38. __be32 s_feature_ro_compat; /* readonly-compatible feature set */
  39. /* 0x0030 */
  40. __u8 s_uuid[16]; /* 128-bit uuid for journal */
  41.  
  42. /* 0x0040 */
  43. __be32 s_nr_users; /* Nr of filesystems sharing log */
  44.  
  45. __be32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
  46.  
  47. /* 0x0048 */
  48. __be32 s_max_transaction; /* Limit of journal blocks per trans.*/
  49. __be32 s_max_trans_data; /* Limit of data blocks per trans. */
  50.  
  51. /* 0x0050 */
  52. __u32 s_padding[44];
  53.  
  54. /* 0x0100 */
  55. __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
  56. /* 0x0400 */
  57. } journal_superblock_t;

0001000 -- 0002000 数据块:

  日志描述符块,开头存储的是journal_header_t,然后紧跟着journal_block_tag_t数据表。从中可以看出块类型为JFS_DESCRIPTOR_BLOCK(1), transaction id为2。只有一个tag,tag的block号为0x1f8, flag为JFS_FLAG_LAST_TAG(8)。此外,第一个tag后面会额外跟着一个16个字节的j_uuid,具有相同uuid的tag以JFS_FLAG_SAME_UUID(2)标示,最后一个tag flag以JFS_FLAG_LAST_TAG置位标示。

  1. /*
  2. * The block tag: used to describe a single buffer in the journal
  3. */
  4. typedef struct journal_block_tag_s
  5. {
  6. __be32 t_blocknr; /* The on-disk block number */
  7. __be32 t_flags; /* See below */
  8. } journal_block_tag_t;

0002000 -- 0003000 数据块:

  元数据块,紧跟着DESCRIPTOR_BLOCK,一个tag对应一个块,块的个数由tag的个数决定。此示例中只有一个tag,所以只有一个数据块。这个块中的数据,在日志恢复或journal load时会写到存储设备文件系统的真实物理块(即tag的t_blocknr)上。

0003000 -- 0004000 数据块:

  日志提交块。表示一个完整的transaction。从中可以看出块类型为JFS_COMMIT_BLOCK(2), transaction id为2,与前面的日志描述块匹配。

JBD日志恢复

如果文件系统崩溃或者unclean umount 重启造成文件系统损坏,当再次mount日志文件系统后,ext3文件系统会根据JBD日志文件进行日志恢复动作。

JBD的日志恢复分3个阶段:
第一个阶段PASS_SCAN
  完成日志一致性检查,查找日志尾部,获取start_transaction和end_transaction ID等信息;
第二个阶段PASS_REVOKE
  搜索revoke块(revoke块中存储需要丢弃的块号),统计nr_revokes个数,构造revoke块hash表;避免回放revoke块,破坏数据块内容,造成文件系统损坏;
第三个阶段PASS_REPLAY
  对日志中满足条件的数据块进行回放;拷贝日志中的数据块到文件系统真实位置:
  1)块号不在revoke块hash表中;
  2)此数据块所在的描述块commit ID大于revoke块的commit ID,即在revoke块后面;

然后设置日志的j_transaction_sequence为下个transaction ID,保证日志中已存在的日志记录都无效;
清空revoke块列表,同步存储设备,至此ext3日志完成恢复。

--EOF--

JBD日志的定位、分析和恢复的更多相关文章

  1. SpringCloud微服务实战——搭建企业级开发框架(三十八):搭建ELK日志采集与分析系统

      一套好的日志分析系统可以详细记录系统的运行情况,方便我们定位分析系统性能瓶颈.查找定位系统问题.上一篇说明了日志的多种业务场景以及日志记录的实现方式,那么日志记录下来,相关人员就需要对日志数据进行 ...

  2. hadoop实战 -- 网站日志KPI指标分析

    本项目分析apache服务器产生的日志,分析pv.独立ip数和跳出率等指标.其实这些指标在第三方系统中都可以检测到,在生产环境中通常用来分析用户交易等核心数据,此处只是用于演示说明日志数据的分析流程. ...

  3. MYSQL启用日志,查看日志,利用mysqlbinlog工具恢复MySQL数据库【转载】

    转自 MYSQL启用日志,查看日志,利用mysqlbinlog工具恢复MySQL数据库 - _安静 - 博客园http://www.cnblogs.com/xionghui/archive/2012/ ...

  4. LCD 显示异常定位分析方法

    第一种情况: 进入kernel或android 后,如果LCM图像示异常,可以通过如下步骤来判断问题出现在哪个层面. step1:通过DMMS截图,来判断上面刷到LCM的数据是否有问题. 若DMMS获 ...

  5. 【原创】大叔案例分享(4)定位分析--见证scala的强大

    一 场景分析 定位分析广泛应用,比如室外基站定位,室内蓝牙beacon定位,室内wifi探针定位等,实现方式是三点定位 Trilateration 理想情况 这种理想情况要求3个基站‘同时’采集‘准确 ...

  6. vsftp日志xferlog格式分析

    vsftp日志xferlog格式分析 [日期:2014-06-25] 来源:Linux社区  作者:Linux [字体:大 中 小]   1.开始vsftp记录日志.修改/etc/vsftpd/vsf ...

  7. odoo开发笔记 -- 后台日志输出及分析

    odoo开发笔记 -- 后台日志输出及分析 附:日志分析软件

  8. 说说openjdk及G1回收器日志内容详细分析

    谈谈openjdk: 在正式往下学习JVM之前,这里谈谈openjdk这个网站,这个在学习java并发时也用过它来分析过锁的底层实现,如:https://www.cnblogs.com/webor20 ...

  9. Linux下单机部署ELK日志收集、分析环境

    一.ELK简介 ELK是elastic 公司旗下三款产品ElasticSearch .Logstash .Kibana的首字母组合,主要用于日志收集.分析与报表展示. ELK Stack包含:Elas ...

随机推荐

  1. sobel算子的一些细节

    1. 形式 Gy 上下颠倒的 (*A表示卷积图像,忽略先): 看得出来,sobel算子感觉并不统一,特别是方向,我们知道matlab的图像格式是,x轴从左到右,y轴从上到下,原点在左上角. 所以,第二 ...

  2. yaf学习资料

    yaf学习资料 文档 鸟哥的官方文档 Yaf框架结合PHPUnit的集成测试 php yaf框架扩展实践六--单元测试.计划任务.第三方库等 php yaf框架扩展实践一--配置篇 yaf实战例子 y ...

  3. javaweb学习总结(五)——Servlet开发(一)

    一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...

  4. SQLite的时候判断语句是否纯在:出现RuntimeException

    写SQLite的时候判断语句是否纯在: public boolean exist(long id) { String filter = FRIEND_KEY_ID + "=" + ...

  5. PhpStorm 8.x/9.x 快捷键设置/个性化设置,如何多项目共存?如何更换主题?

    1."自定义"常用快捷键(设置成跟Eclipse差不多) 按照路径:File -> Settings -> Appearance & Behavior -> ...

  6. Github.com的Git和TortoiseGit图文教程

    图文介绍Windows系统下使用 Github账户 + msysgit + TortoiseGit 进行文件管理的方法. 安装 安装mysysgit 下载地址:msysgit 安装过程: 0.启动 1 ...

  7. PHP数组函数: array_walk()

    定义和用法 array_walk() 函数对数组中的每个元素应用回调函数.如果成功则返回 TRUE,否则返回 FALSE. 典型情况下 function 接受两个参数.array 参数的值作为第一个, ...

  8. 关于 JSONP跨域示例

    1.脚本文件Jsonp,代码如下: $(function () { TestJsonP(); function TestJsonP() { var xhrurl = 'http://localhost ...

  9. jQuery源码笔记(二):定义了一些变量和函数 jQuery = function(){}

    笔记(二)也分为三部分: 一. 介绍: 注释说明:v2.0.3版本.Sizzle选择器.MIT软件许可注释中的#的信息索引.查询地址(英文版)匿名函数自执行:window参数及undefined参数意 ...

  10. 【GWAS文献解读】疟原虫青蒿素抗药性的全基因组关联分析

    英文名:Genetic architecture of artemisinin-resistant Plasmodium falciparum 中文名:疟原虫青蒿素抗药性的全基因组关联分析 期刊:Na ...