1 /*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: recover.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ext2fs.h>
13 #include <linux/jbd.h>
14 #include <linux/ext3_fs.h>
15
16 /* GLOBALS ***************************************************************/
17
18 extern PEXT2_GLOBAL Ext2Global;
19
20 /* DEFINITIONS *************************************************************/
21
22 #ifdef ALLOC_PRAGMA
23 #pragma alloc_text(PAGE, Ext2LoadInternalJournal)
24 #pragma alloc_text(PAGE, Ext2CheckJournal)
25 #pragma alloc_text(PAGE, Ext2RecoverJournal)
26 #endif
27
28 PEXT2_MCB
Ext2LoadInternalJournal(PEXT2_VCB Vcb,ULONG jNo)29 Ext2LoadInternalJournal(
30 PEXT2_VCB Vcb,
31 ULONG jNo
32 )
33 {
34 PEXT2_MCB Jcb = NULL;
35
36 Jcb = Ext2AllocateMcb(Vcb, NULL, NULL, 0);
37 if (!Jcb) {
38 goto errorout;
39 }
40
41 Jcb->Inode.i_ino = jNo;
42 Jcb->Inode.i_sb = &Vcb->sb;
43 if (!Ext2LoadInode(Vcb, &Jcb->Inode)) {
44 DbgBreak();
45 Ext2FreeMcb(Vcb, Jcb);
46 goto errorout;
47 }
48
49 errorout:
50
51 return Jcb;
52 }
53
54 INT
Ext2CheckJournal(PEXT2_VCB Vcb,PULONG jNo)55 Ext2CheckJournal(
56 PEXT2_VCB Vcb,
57 PULONG jNo
58 )
59 {
60 struct ext3_super_block* esb = NULL;
61
62 /* check ext3 super block */
63 esb = (struct ext3_super_block *)Vcb->SuperBlock;
64 if (IsFlagOn(esb->s_feature_incompat,
65 EXT3_FEATURE_INCOMPAT_RECOVER)) {
66 SetLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER);
67 }
68
69 /* must stop here if volume is read-only */
70 if (IsVcbReadOnly(Vcb)) {
71 goto errorout;
72 }
73
74 /* journal is external ? */
75 if (esb->s_journal_inum == 0) {
76 goto errorout;
77 }
78
79 /* oops: volume is corrupted */
80 if (esb->s_journal_dev) {
81 goto errorout;
82 }
83
84 /* return the journal inode number */
85 *jNo = esb->s_journal_inum;
86
87 return TRUE;
88
89 errorout:
90
91 return FALSE;
92 }
93
94 INT
Ext2RecoverJournal(PEXT2_IRP_CONTEXT IrpContext,PEXT2_VCB Vcb)95 Ext2RecoverJournal(
96 PEXT2_IRP_CONTEXT IrpContext,
97 PEXT2_VCB Vcb
98 )
99 {
100 INT rc = 0;
101 ULONG jNo = 0;
102 PEXT2_MCB jcb = NULL;
103 struct block_device * bd = &Vcb->bd;
104 #ifndef __REACTOS__
105 struct super_block * sb = &Vcb->sb;
106 #endif
107 struct inode * ji = NULL;
108 journal_t * journal = NULL;
109 struct ext3_super_block *esb;
110
111 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
112
113 /* check journal inode number */
114 if (!Ext2CheckJournal(Vcb, &jNo)) {
115 rc = -1;
116 goto errorout;
117 }
118
119 /* allocate journal Mcb */
120 jcb = Ext2LoadInternalJournal(Vcb, jNo);
121 if (!jcb) {
122 rc = -6;
123 goto errorout;
124 }
125
126 /* allocate journal inode */
127 ji = &jcb->Inode;
128
129 /* initialize journal file from inode */
130 journal = journal_init_inode(ji);
131
132 /* initialzation succeeds ? */
133 if (!journal) {
134 iput(ji);
135 rc = -8;
136 goto errorout;
137 }
138
139 /* start journal recovery */
140 rc = journal_load(journal);
141 if (0 != rc) {
142 rc = -9;
143 DbgPrint("Ext2Fsd: recover_journal: failed "
144 "to recover journal data.\n");
145 }
146
147 /* reload super_block and group_description */
148 Ext2RefreshSuper(IrpContext, Vcb);
149 Ext2RefreshGroup(IrpContext, Vcb);
150
151 /* wipe journal data and clear recover flag in sb */
152 if (rc == 0) {
153 journal_wipe_recovery(journal);
154 ClearLongFlag(
155 Vcb->SuperBlock->s_feature_incompat,
156 EXT3_FEATURE_INCOMPAT_RECOVER );
157 Ext2SaveSuper(IrpContext, Vcb);
158 sync_blockdev(bd);
159 ClearLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER);
160 }
161
162 errorout:
163
164 /* destroy journal structure */
165 if (journal) {
166 journal_destroy(journal);
167 }
168
169 /* destory journal Mcb */
170 if (jcb) {
171 Ext2FreeMcb(Vcb, jcb);
172 }
173
174 ExReleaseResourceLite(&Vcb->MainResource);
175
176 return rc;
177 }
178