📄 journal.c
字号:
/* * Copyright 2002-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */#define _GNU_SOURCE#include "includes.h"/* compares description block with commit block. returns 0 if they differ, 1 if they match */static int does_desc_match_commit (struct buffer_head *d_bh, struct buffer_head *c_bh) { return (get_commit_trans_id (c_bh) == get_desc_trans_id (d_bh) && get_commit_trans_len (c_bh) == get_desc_trans_len (d_bh));}/* d_bh is descriptor, return number of block where commit block of this transaction is to be */unsigned long commit_expected (reiserfs_filsys_t * fs, struct buffer_head * d_bh){ unsigned long offset; struct journal_params * sb_jp; sb_jp = sb_jp (fs->fs_ondisk_sb); //desc = (struct reiserfs_journal_desc *)d_bh->b_data; offset = d_bh->b_blocknr - get_jp_journal_1st_block (sb_jp); return get_jp_journal_1st_block (sb_jp) + ((offset + get_desc_trans_len (d_bh) + 1) % get_jp_journal_size (sb_jp));}/* d_bh contains journal descriptor, returns number of block where descriptor block of next transaction should be */unsigned long next_desc_expected (reiserfs_filsys_t * fs, struct buffer_head * d_bh){ unsigned long offset; struct journal_params * sb_jp; sb_jp = sb_jp (fs->fs_ondisk_sb); //desc = (struct reiserfs_journal_desc *)d_bh->b_data; offset = d_bh->b_blocknr - get_jp_journal_1st_block (sb_jp); return get_jp_journal_1st_block (sb_jp) + ((offset + get_desc_trans_len (d_bh) + 2) % get_jp_journal_size (sb_jp));}/* common checks for validness of a transaction */int transaction_check_content (reiserfs_filsys_t * fs, reiserfs_trans_t * trans) { struct buffer_head *d_bh, *c_bh; struct reiserfs_journal_desc * desc; struct reiserfs_journal_commit * commit; unsigned long block; unsigned int trans_half, i; d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize); if (!d_bh || who_is_this (d_bh->b_data, d_bh->b_size) != THE_JDESC) goto error_desc_brelse; /* read expected commit block and compare with descriptor block */ c_bh = bread (fs->fs_journal_dev, commit_expected (fs, d_bh), fs->fs_blocksize); if (!c_bh) goto error_desc_brelse; if (!does_desc_match_commit (d_bh, c_bh)) goto error_commit_brelse; /* Check that all target blocks are journalable */ desc = (struct reiserfs_journal_desc *)(d_bh->b_data); commit = (struct reiserfs_journal_commit *)(c_bh->b_data); trans_half = journal_trans_half (d_bh->b_size); for (i = 0; i < get_desc_trans_len(d_bh); i++) { if (i < trans_half) block = le32_to_cpu (desc->j2_realblock[i]); else block = le32_to_cpu (commit->j3_realblock[i - trans_half]); if (not_journalable(fs, block)) goto error_commit_brelse; } brelse (d_bh); brelse (c_bh); return 1; error_commit_brelse: brelse (c_bh);error_desc_brelse: brelse(d_bh); return 0;}/* common checks for validness of a transaction */int transaction_check_desc(reiserfs_filsys_t * fs, struct buffer_head * d_bh) { struct buffer_head * c_bh; int ret = 1; if (!d_bh || who_is_this (d_bh->b_data, d_bh->b_size) != THE_JDESC) return 0; /* read expected commit block and compare with descriptor block */ c_bh = bread (fs->fs_journal_dev, commit_expected (fs, d_bh), fs->fs_blocksize); if (!c_bh) return 0; if (!does_desc_match_commit (d_bh, c_bh)) ret = 0; brelse (c_bh); return ret;}/* read the journal and find the oldest and newest transactions, return number of transactions found */int get_boundary_transactions (reiserfs_filsys_t * fs, reiserfs_trans_t * oldest, reiserfs_trans_t * newest){ struct reiserfs_super_block * sb; unsigned long j_cur; unsigned long j_start; unsigned long j_size; struct buffer_head * d_bh; __u32 newest_trans_id, oldest_trans_id, trans_id; int trans_nr; sb = fs->fs_ondisk_sb; j_start = get_jp_journal_1st_block (sb_jp (sb)); j_size = get_jp_journal_size (sb_jp (sb)); oldest_trans_id = 0xffffffff; newest_trans_id = 0; trans_nr = 0; for (j_cur = 0; j_cur < j_size; j_cur ++) { d_bh = bread (fs->fs_journal_dev, j_start + j_cur, fs->fs_blocksize); if (!transaction_check_desc (fs, d_bh)) { brelse (d_bh); continue; } trans_nr ++; trans_id = get_desc_trans_id (d_bh); if (trans_id < oldest_trans_id) { oldest_trans_id = trans_id; oldest->mount_id = get_desc_mount_id (d_bh); oldest->trans_id = get_desc_trans_id (d_bh); oldest->desc_blocknr = d_bh->b_blocknr; oldest->trans_len = get_desc_trans_len (d_bh); oldest->commit_blocknr = commit_expected (fs, d_bh); oldest->next_trans_offset = next_desc_expected (fs, d_bh) - j_start; } if (trans_id > newest_trans_id) { newest_trans_id = trans_id; newest->mount_id = get_desc_mount_id (d_bh); newest->trans_id = get_desc_trans_id (d_bh); newest->desc_blocknr = d_bh->b_blocknr; newest->trans_len = get_desc_trans_len (d_bh); newest->commit_blocknr = commit_expected (fs, d_bh); newest->next_trans_offset = next_desc_expected (fs, d_bh) - j_start; } j_cur += get_desc_trans_len (d_bh) + 1; brelse (d_bh); } return trans_nr;}#define TRANS_FOUND 1#define TRANS_NOT_FOUND 0/* trans is a valid transaction. Look for valid transaction with smallest trans id which is greater than the id of the current one */int next_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, reiserfs_trans_t break_trans){ struct buffer_head * d_bh, * next_d_bh; int found; unsigned long j_start; unsigned long j_offset; unsigned long block; j_start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); found = TRANS_NOT_FOUND; if (trans->trans_id == break_trans.trans_id) return found; /* make sure that 'trans' is a valid transaction */ d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize); if (!transaction_check_desc (fs, d_bh)) die ("next_transaction: valid transaction is expected"); block = next_desc_expected (fs, d_bh); j_offset = block - j_start; while (1) { next_d_bh = bread (fs->fs_journal_dev, block, fs->fs_blocksize); if (transaction_check_desc (fs, next_d_bh)) break; brelse (next_d_bh); j_offset ++; block = j_start + (j_offset % get_jp_journal_size (sb_jp (fs->fs_ondisk_sb))); } //next_desc = (struct reiserfs_journal_desc *)next_d_bh->b_data; if (break_trans.trans_id >= get_desc_trans_id (next_d_bh)) { /* found transaction is newer */ trans->mount_id = get_desc_mount_id (next_d_bh); trans->trans_id = get_desc_trans_id (next_d_bh); trans->desc_blocknr = next_d_bh->b_blocknr; trans->trans_len = get_desc_trans_len (next_d_bh); trans->commit_blocknr = commit_expected (fs, next_d_bh); trans->next_trans_offset = next_desc_expected (fs, next_d_bh) - j_start; found = TRANS_FOUND; } brelse (d_bh); brelse (next_d_bh); return found;}static void read_journal_write_in_place (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, unsigned int index, unsigned long in_journal, unsigned long in_place){ struct buffer_head * j_bh, * bh; j_bh = bread (fs->fs_journal_dev, in_journal, fs->fs_blocksize); if (!j_bh) { fprintf (stderr, "replay_one_transaction: transaction %lu: reading %lu block failed\n", trans->trans_id, in_journal); return; } if (not_journalable (fs, in_place)) { fprintf (stderr, "replay_one_transaction: transaction %lu: block %ld should not be journalled (%lu)\n", trans->trans_id, in_journal, in_place); brelse (j_bh); return; } bh = getblk (fs->fs_dev, in_place, fs->fs_blocksize); memcpy (bh->b_data, j_bh->b_data, bh->b_size); mark_buffer_dirty (bh); mark_buffer_uptodate (bh, 1); bwrite (bh); brelse (bh); brelse (j_bh); }/* go through all blocks of transaction and call 'action' each of them */void for_each_block (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, action_on_block_t action){ struct buffer_head * d_bh, * c_bh; struct reiserfs_journal_desc * desc; struct reiserfs_journal_commit * commit; unsigned long j_start, j_offset, j_size; unsigned int i, trans_half; unsigned long block; d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize); if (!d_bh) { reiserfs_warning (stdout, "reading descriptor block %lu failed\n", trans->desc_blocknr); return; } c_bh = bread (fs->fs_journal_dev, trans->commit_blocknr, fs->fs_blocksize); if (!c_bh) { reiserfs_warning (stdout, "reading commit block %lu failed\n", trans->commit_blocknr); brelse (d_bh); return; } desc = (struct reiserfs_journal_desc *)(d_bh->b_data); commit = (struct reiserfs_journal_commit *)(c_bh->b_data); /* first block of journal and size of journal */ j_start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb)); j_size = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); /* offset in the journal where the transaction starts */ j_offset = trans->desc_blocknr - j_start + 1; trans_half = journal_trans_half (d_bh->b_size); for (i = 0; i < trans->trans_len; i ++, j_offset ++) { if (i < trans_half) block = le32_to_cpu (desc->j2_realblock[i]); else block = le32_to_cpu (commit->j3_realblock[i - trans_half]); action (fs, trans, i, j_start + (j_offset % j_size), block); } brelse (d_bh); brelse (c_bh);}/* transaction is supposed to be valid */int replay_one_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans){ for_each_block (fs, trans, read_journal_write_in_place); fsync(fs->fs_dev); return 0;}void for_each_transaction (reiserfs_filsys_t * fs, action_on_trans_t action){ reiserfs_trans_t oldest, newest; int ret = 0; if (!get_boundary_transactions (fs, &oldest, &newest)) return; while (1) { action (fs, &oldest); if ((ret = next_transaction (fs, &oldest, newest)) == TRANS_NOT_FOUND) break; }}unsigned long get_size_of_journal_or_reserved_area( struct reiserfs_super_block * sb){ if (is_reiserfs_jr_magic_string (sb)) return get_sb_reserved_for_journal (sb); /* with standard journal */ return get_jp_journal_size (sb_jp (sb)) + 1;}__u32 advise_journal_max_trans_len (__u32 desired, __u32 journal_size /* no j_header */, int blocksize, int verbose){ __u32 saved; __u32 ratio = 1; if (blocksize < 4096) ratio = 4096/blocksize; saved = desired; if (!desired) desired = JOURNAL_TRANS_MAX/ratio; if (journal_size / desired < JOURNAL_MIN_RATIO) desired = journal_size / JOURNAL_MIN_RATIO; if (desired > JOURNAL_TRANS_MAX/ratio) desired = JOURNAL_TRANS_MAX/ratio; if (desired < JOURNAL_TRANS_MIN/ratio) desired = JOURNAL_TRANS_MIN/ratio; if (verbose) { if (saved && saved != desired) reiserfs_warning (stderr, "WARNING: wrong transaction max size (%u). Changed to %u\n", saved, desired); } return desired;}#if 0 __u32 ret_val; ret_val = 0; if (!desired) ret_val = JOURNAL_TRANS_MAX; if (desired<journal_size/8) ret_val = journal_size/8; if (desired>journal_size/2) ret_val = journal_size/2; if (desired>JOURNAL_TRANS_MAX) ret_val = JOURNAL_TRANS_MAX; if (ret_val) { reiserfs_warning (stderr, "WARNING: Journal max trans length is wrong seting: %u, resetting to available possible %u\n", desired, ret_val); } else { ret_val = desired; } return ret_val;}#endif__u32 advise_journal_max_batch (unsigned long journal_trans_max){ return journal_trans_max*JOURNAL_MAX_BATCH/JOURNAL_TRANS_MAX;}__u32 advise_journal_max_commit_age (void){ return JOURNAL_MAX_COMMIT_AGE;}__u32 advise_journal_max_trans_age (void){ return JOURNAL_MAX_TRANS_AGE;}int reiserfs_journal_params_check (reiserfs_filsys_t * fs) { struct reiserfs_journal_header * j_head; struct reiserfs_super_block * sb = fs->fs_ondisk_sb; j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); /* Check the superblock's journal parameters. */ if (!is_reiserfs_jr_magic_string (sb)) { if (get_jp_journal_dev (sb_jp(sb)) != 0 ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -