/** * journal_t * journal_init_inode () - creates a journal which maps to a inode. * @inode: An inode to create the journal in * * journal_init_inode creates a journal which maps an on-disk inode as * the journal. The inode must exist already, must support bmap() and * must have all data blocks preallocated. */ journal_t * journal_init_inode (struct inode *inode) { struct buffer_head *bh; journal_t *journal = journal_init_common(); int err; int n; unsigned long blocknr; if (!journal) return NULL; journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev; journal->j_inode = inode; jbd_debug(1, "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n", journal, inode->i_sb->s_id, inode->i_ino, (s64) inode->i_size, inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize); journal->j_maxlen = (unsigned int)(inode->i_size >> inode->i_sb->s_blocksize_bits); journal->j_blocksize = inode->i_sb->s_blocksize; /* journal descriptor can store up to n blocks -bzzz */ n = journal->j_blocksize / sizeof(journal_block_tag_t); journal->j_wbufsize = n; journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", __FUNCTION__); J_ASSERT(journal->j_revoke != NULL); if (journal->j_revoke) journal_destroy_revoke(journal); kfree(journal); return NULL; } err = journal_bmap(journal, 0, &blocknr); /* If that failed, give up */ if (err) { printk(KERN_ERR "%s: Cannnot locate journal superblock\n", __FUNCTION__); J_ASSERT(journal->j_revoke != NULL); if (journal->j_revoke) journal_destroy_revoke(journal); J_ASSERT(journal->j_wbuf != NULL); kfree(journal->j_wbuf); kfree(journal); return NULL; } bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); J_ASSERT(bh != NULL); journal->j_sb_buffer = bh; journal->j_superblock = (journal_superblock_t *)bh->b_data; return journal; }
static errcode_t recover_ext3_journal(e2fsck_t ctx) { journal_t *journal; int retval; journal_init_revoke_caches(); retval = e2fsck_get_journal(ctx, &journal); if (retval) return retval; retval = e2fsck_journal_load(journal); if (retval) goto errout; retval = journal_init_revoke(journal, 1024); if (retval) goto errout; retval = -journal_recover(journal); if (retval) goto errout; if (journal->j_superblock->s_errno) { ctx->fs->super->s_state |= EXT2_ERROR_FS; ext2fs_mark_super_dirty(ctx->fs); journal->j_superblock->s_errno = 0; mark_buffer_dirty(journal->j_sb_buffer); } errout: journal_destroy_revoke(journal); journal_destroy_revoke_caches(); e2fsck_journal_release(ctx, journal, 1, 0); return retval; }
errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j) { journal_t *journal; errcode_t retval; journal_init_revoke_caches(); retval = ext2fs_get_journal(fs, &journal); if (retval) return retval; retval = ext2fs_journal_load(journal); if (retval) goto errout; retval = journal_init_revoke(journal, 1024); if (retval) goto errout; if (journal->j_failed_commit) { journal->j_superblock->s_errno = -EINVAL; mark_buffer_dirty(journal->j_sb_buffer); } *j = journal; return 0; errout: journal_destroy_revoke(journal); journal_destroy_revoke_caches(); ext2fs_journal_release(fs, journal, 1, 0); return retval; }
errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j) { journal_t *journal = *j; journal_destroy_revoke(journal); journal_destroy_revoke_caches(); ext2fs_journal_release(fs, journal, 0, 0); *j = NULL; return 0; }
/** * void journal_destroy() - Release a journal_t structure. * @journal: Journal to act on. * * Release a journal_t structure once it is no longer in use by the * journaled object. */ void journal_destroy(journal_t *journal) { #if 0 /* Wait for the commit thread to wake up and die. */ journal_kill_thread(journal); /* Force a final log commit */ if (journal->j_running_transaction) journal_commit_transaction(journal); /* Force any old transactions to disk */ /* Totally anal locking here... */ jbd_lock(&journal->j_list_lock); while (journal->j_checkpoint_transactions != NULL) { jbd_unlock(&journal->j_list_lock); log_do_checkpoint(journal); jbd_lock(&journal->j_list_lock); } J_ASSERT(journal->j_running_transaction == NULL); J_ASSERT(journal->j_committing_transaction == NULL); J_ASSERT(journal->j_checkpoint_transactions == NULL); jbd_unlock(&journal->j_list_lock); /* We can now mark the journal as empty. */ journal->j_tail = 0; journal->j_tail_sequence = ++journal->j_transaction_sequence; if (journal->j_sb_buffer) { journal_update_superblock(journal, 1); brelse(journal->j_sb_buffer); } #endif if (journal->j_sb_buffer) { brelse(journal->j_sb_buffer); } if (journal->j_inode) iput(journal->j_inode); if (journal->j_revoke) journal_destroy_revoke(journal); kfree(journal->j_wbuf); kfree(journal); }
static errcode_t recover_ext3_journal(e2fsck_t ctx) { struct problem_context pctx; journal_t *journal; int retval; clear_problem_context(&pctx); journal_init_revoke_caches(); retval = e2fsck_get_journal(ctx, &journal); if (retval) return retval; retval = e2fsck_journal_load(journal); if (retval) goto errout; retval = journal_init_revoke(journal, 1024); if (retval) goto errout; retval = -journal_recover(journal); if (retval) goto errout; if (journal->j_failed_commit) { pctx.ino = journal->j_failed_commit; fix_problem(ctx, PR_0_JNL_TXN_CORRUPT, &pctx); journal->j_superblock->s_errno = -EINVAL; mark_buffer_dirty(journal->j_sb_buffer); } errout: journal_destroy_revoke(journal); journal_destroy_revoke_caches(); e2fsck_journal_release(ctx, journal, 1, 0); return retval; }