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 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 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 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