reactos/drivers/filesystems/ext2/src/ext3/recover.c
Pierre Schweitzer a1d7e9936d
[EXT2] Upgrade to 0.69
CORE-13980
2017-11-12 10:48:17 +01:00

178 lines
3.8 KiB
C

/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: recover.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <ext2fs.h>
#include <linux/jbd.h>
#include <linux/ext3_fs.h>
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LoadInternalJournal)
#pragma alloc_text(PAGE, Ext2CheckJournal)
#pragma alloc_text(PAGE, Ext2RecoverJournal)
#endif
PEXT2_MCB
Ext2LoadInternalJournal(
PEXT2_VCB Vcb,
ULONG jNo
)
{
PEXT2_MCB Jcb = NULL;
Jcb = Ext2AllocateMcb(Vcb, NULL, NULL, 0);
if (!Jcb) {
goto errorout;
}
Jcb->Inode.i_ino = jNo;
Jcb->Inode.i_sb = &Vcb->sb;
if (!Ext2LoadInode(Vcb, &Jcb->Inode)) {
DbgBreak();
Ext2FreeMcb(Vcb, Jcb);
goto errorout;
}
errorout:
return Jcb;
}
INT
Ext2CheckJournal(
PEXT2_VCB Vcb,
PULONG jNo
)
{
struct ext3_super_block* esb = NULL;
/* check ext3 super block */
esb = (struct ext3_super_block *)Vcb->SuperBlock;
if (IsFlagOn(esb->s_feature_incompat,
EXT3_FEATURE_INCOMPAT_RECOVER)) {
SetLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER);
}
/* must stop here if volume is read-only */
if (IsVcbReadOnly(Vcb)) {
goto errorout;
}
/* journal is external ? */
if (esb->s_journal_inum == 0) {
goto errorout;
}
/* oops: volume is corrupted */
if (esb->s_journal_dev) {
goto errorout;
}
/* return the journal inode number */
*jNo = esb->s_journal_inum;
return TRUE;
errorout:
return FALSE;
}
INT
Ext2RecoverJournal(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb
)
{
INT rc = 0;
ULONG jNo = 0;
PEXT2_MCB jcb = NULL;
struct block_device * bd = &Vcb->bd;
#ifndef __REACTOS__
struct super_block * sb = &Vcb->sb;
#endif
struct inode * ji = NULL;
journal_t * journal = NULL;
struct ext3_super_block *esb;
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
/* check journal inode number */
if (!Ext2CheckJournal(Vcb, &jNo)) {
rc = -1;
goto errorout;
}
/* allocate journal Mcb */
jcb = Ext2LoadInternalJournal(Vcb, jNo);
if (!jcb) {
rc = -6;
goto errorout;
}
/* allocate journal inode */
ji = &jcb->Inode;
/* initialize journal file from inode */
journal = journal_init_inode(ji);
/* initialzation succeeds ? */
if (!journal) {
iput(ji);
rc = -8;
goto errorout;
}
/* start journal recovery */
rc = journal_load(journal);
if (0 != rc) {
rc = -9;
DbgPrint("Ext2Fsd: recover_journal: failed "
"to recover journal data.\n");
}
/* reload super_block and group_description */
Ext2RefreshSuper(IrpContext, Vcb);
Ext2RefreshGroup(IrpContext, Vcb);
/* wipe journal data and clear recover flag in sb */
if (rc == 0) {
journal_wipe_recovery(journal);
ClearLongFlag(
Vcb->SuperBlock->s_feature_incompat,
EXT3_FEATURE_INCOMPAT_RECOVER );
Ext2SaveSuper(IrpContext, Vcb);
sync_blockdev(bd);
ClearLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER);
}
errorout:
/* destroy journal structure */
if (journal) {
journal_destroy(journal);
}
/* destory journal Mcb */
if (jcb) {
Ext2FreeMcb(Vcb, jcb);
}
ExReleaseResourceLite(&Vcb->MainResource);
return rc;
}