📄 journal.c
字号:
get_jp_journal_1st_block (sb_jp(sb)) != get_journal_start_must (fs) || get_jp_journal_size (sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { reiserfs_warning (stderr, "\nreiserfs_open_journal: wrong journal parameters found in the " "super block. \nYou should run reiserfsck with --rebuild-sb to " "check your superblock consistency.\n\n"); return 1; } } if (memcmp(&j_head->jh_journal, sb_jp (sb), sizeof(struct journal_params))) { if (!is_reiserfs_jr_magic_string (sb)) { reiserfs_warning (stderr, "\nreiserfs_open_journal: journal parameters from the superblock " "does not match \nto the journal headers ones. It looks like that " "you created your fs with old\nreiserfsprogs. Journal header is " "fixed.\n\n", fs->fs_j_file_name); memcpy(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); mark_buffer_dirty(fs->fs_jh_bh); bwrite(fs->fs_jh_bh); } else { reiserfs_warning (stderr, "\nreiserfs_open_journal: journal parameters from the super block " "does not match \nto journal parameters from the journal. You should " "run reiserfsck with --rebuild-sb to check your superblock consistency.\n\n"); return 1; } } return 0;}/* read journal header and make sure that it matches with the filesystem opened */int reiserfs_open_journal (reiserfs_filsys_t * fs, char * j_filename, int flags) { struct reiserfs_super_block * sb; __u64 count; sb = fs->fs_ondisk_sb; if (!j_filename) { /* if (is_reiserfs_jr_magic_string (sb)) { // create a special file to access journal return 1; } */ j_filename = fs->fs_file_name; } else if (!is_reiserfs_jr_magic_string (sb)) { /* make sure that name specified is a correct name */ if (strcmp (j_filename, fs->fs_file_name)) { reiserfs_warning (stderr, "Filesystem with standard journal found, " "wrong name of specified journal device %s \n", j_filename); return 2; } } fs->fs_journal_dev = open (j_filename, flags #if defined(O_LARGEFILE) | O_LARGEFILE#endif ); if (fs->fs_journal_dev == -1) return -1; asprintf (&fs->fs_j_file_name, "%s", j_filename); if (get_jp_journal_size(sb_jp(sb)) < JOURNAL_MIN_SIZE) { reiserfs_warning (stderr, "Journal of (%lu) block size found on " "specified journal device %s.\nMust be not less than (%lu).\n", get_jp_journal_size (sb_jp (sb)) + 1, j_filename, JOURNAL_MIN_SIZE + 1); close(fs->fs_journal_dev); return 1; } if (!(count = count_blocks (j_filename, fs->fs_blocksize))) { close(fs->fs_journal_dev); return -1; } if (get_jp_journal_1st_block (sb_jp (sb)) + get_jp_journal_size (sb_jp (sb)) + 1 > count) { reiserfs_warning (stderr, "Detected journal on specified device %s " "does not fit to the device.\nStart block (%lu) + " "size (%lu) less than device size (%lu).\n", j_filename, get_jp_journal_1st_block(sb_jp (sb)), get_jp_journal_size(sb_jp (sb)) + 1, count); close(fs->fs_journal_dev); return 1; } /* read journal header */ fs->fs_jh_bh = bread (fs->fs_journal_dev, get_jp_journal_1st_block (sb_jp (sb)) + get_jp_journal_size (sb_jp (sb)), fs->fs_blocksize); if (!fs->fs_jh_bh) { reiserfs_warning (stderr, "reiserfs_open_journal: bread failed " "reading journal header.\n"); close(fs->fs_journal_dev); return -1; } return 0;}/* initialize super block's journal related fields and journal header fields. * If len is 0 - make journal of default size */int reiserfs_create_journal( reiserfs_filsys_t * fs, char * j_device, /* journal device name */ unsigned long offset, /* journal offset on the j_device */ unsigned long len, /* including journal header */ int transaction_max_size){ struct stat st; struct buffer_head * bh; struct reiserfs_journal_header * jh; struct reiserfs_super_block * sb; unsigned long blocks; sb = fs->fs_ondisk_sb; if (!j_device || !strcmp (j_device, fs->fs_file_name)) { /* Journal is to be on the host device, check the amount space for the * journal on it. */ len = len ? len : journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1; offset = offset ? offset : get_journal_start_must(fs); if (offset < get_journal_start_must(fs)) { reiserfs_warning (stderr, "reiserfs_create_journal: offset is " "%lu, but it cannot be less then %llu on the device %s\n", offset, get_journal_start_must(fs), j_device); return 0; } if (!is_block_count_correct(offset, fs->fs_blocksize, get_sb_block_count(sb), len)) { /* host device does not contain enough blocks */ reiserfs_warning (stderr, "reiserfs_create_journal: cannot create " "a journal of %lu blocks with %lu offset on %d blocks\n", len, offset, get_sb_block_count(sb)); return 0; } j_device = fs->fs_file_name; st.st_rdev = 0; } else { /* journal is to be on separate device */ if (!(blocks = count_blocks (j_device, fs->fs_blocksize))) return 0; if (!len) { /* default size of a journal on a separate device is whole device */ if (blocks < offset) { reiserfs_warning (stderr, "reiserfs_create_journal: offset is " "%lu, blocks on device %lu\n", offset, blocks); return 0; } len = blocks - offset; } if (len > journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1) { fflush(stderr); reiserfs_warning (stdout, "NOTE: journal new size %lu is greater " "than default size %lu:\nthis may slow down initializing and " "mounting of the journal. Hope it is ok.\n\n", len, journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1); } if (blocks < offset + len) { reiserfs_warning (stderr, "reiserfs_create_journal: no enough " "blocks on device %lu, needed %lu\n", blocks, offset + len); return 0; } if (stat (j_device, &st) == -1) { reiserfs_warning (stderr, "reiserfs_create_journal: stat %s failed" ": %s\n", j_device, strerror(errno)); return 0; }/* if (!S_ISBLK (st.st_mode)) { reiserfs_warning (stderr, "reiserfs_create_journal: " "%s is not a block device (%x)\n", j_device, st.st_rdev); return 0; }*/ } fs->fs_journal_dev = open (j_device, O_RDWR #if defined(O_LARGEFILE) | O_LARGEFILE#endif ); if (fs->fs_journal_dev == -1) { reiserfs_warning (stderr, "reiserfs_create_journal: could not open " "%s: %s\n", j_device, strerror(errno)); return 0; } asprintf (&fs->fs_j_file_name, "%s", j_device); if (len < JOURNAL_MIN_SIZE + 1) { reiserfs_warning (stderr, "WARNING: Journal size (%u) is less, than " "minimal supported journal size (%u).\n", len, JOURNAL_MIN_SIZE + 1); return 0; } /* get journal header */ bh = getblk (fs->fs_journal_dev, offset + len - 1, fs->fs_blocksize); if (!bh) { reiserfs_warning (stderr, "reiserfs_create_journal: getblk failed\n"); return 0; } /* fill journal header */ jh = (struct reiserfs_journal_header *)bh->b_data; set_jp_journal_1st_block(&jh->jh_journal, offset); set_jp_journal_dev(&jh->jh_journal, st.st_rdev); set_jp_journal_magic(&jh->jh_journal, get_random()); set_jp_journal_size(&jh->jh_journal, len - 1); set_jp_journal_max_trans_len(&jh->jh_journal, advise_journal_max_trans_len( transaction_max_size, len - 1, fs->fs_blocksize, 1)); set_jp_journal_max_batch(&jh->jh_journal, advise_journal_max_batch( get_jp_journal_max_trans_len(&jh->jh_journal))); set_jp_journal_max_commit_age(&jh->jh_journal, advise_journal_max_commit_age()); set_jp_journal_max_trans_age(&jh->jh_journal, advise_journal_max_trans_age ()); mark_buffer_uptodate (bh, 1); mark_buffer_dirty (bh); fs->fs_jh_bh = bh; /* make a copy of journal header in the super block */ memcpy (sb_jp (sb), &jh->jh_journal, sizeof (struct journal_params)); mark_buffer_dirty (fs->fs_super_bh); return 1;}/* brelse journal header, flush all dirty buffers, close device, open, read journal header */void reiserfs_reopen_journal (reiserfs_filsys_t * fs, int flag){ unsigned long jh_block; if (!reiserfs_journal_opened (fs)) return; jh_block = fs->fs_jh_bh->b_blocknr; brelse (fs->fs_jh_bh); flush_buffers (fs->fs_journal_dev); invalidate_buffers (fs->fs_journal_dev); if (close (fs->fs_journal_dev)) die ("reiserfs_reopen_journal: closed failed: %s", strerror(errno)); fs->fs_journal_dev = open (fs->fs_j_file_name, flag #if defined(O_LARGEFILE) | O_LARGEFILE#endif ); if (fs->fs_journal_dev == -1) die ("reiserfs_reopen_journal: could not reopen journal device"); fs->fs_jh_bh = bread (fs->fs_journal_dev, jh_block, fs->fs_blocksize); if (!fs->fs_jh_bh) die ("reiserfs_reopen_journal: reading journal header failed");}int reiserfs_journal_opened (reiserfs_filsys_t * fs){ return fs->fs_jh_bh ? 1 : 0;}void reiserfs_flush_journal (reiserfs_filsys_t * fs){ if (!reiserfs_journal_opened (fs)) return; flush_buffers (fs->fs_journal_dev);}void reiserfs_free_journal (reiserfs_filsys_t * fs){ if (!reiserfs_journal_opened (fs)) return; brelse (fs->fs_jh_bh); fs->fs_jh_bh = 0; free (fs->fs_j_file_name); fs->fs_j_file_name = 0;}void reiserfs_close_journal (reiserfs_filsys_t * fs){ reiserfs_flush_journal (fs); reiserfs_free_journal (fs);}/* update journal header */static void update_journal_header (reiserfs_filsys_t * fs, struct buffer_head * bh_jh, reiserfs_trans_t *trans) { struct reiserfs_journal_header * j_head; j_head = (struct reiserfs_journal_header *)(bh_jh->b_data); /* update journal header */ set_jh_last_flushed (j_head, trans->trans_id); set_jh_mount_id (j_head, trans->mount_id); set_jh_replay_start_offset (j_head, trans->next_trans_offset); mark_buffer_dirty (bh_jh); bwrite (bh_jh); fsync(fs->fs_journal_dev);}/* fixme: what should be done when not all transactions can be replayed in proper order? */int replay_journal (reiserfs_filsys_t * fs){ struct buffer_head * bh; struct reiserfs_journal_header * j_head; reiserfs_trans_t cur, newest, control; int replayed, ret; if (!reiserfs_journal_opened (fs)) reiserfs_panic ("replay_journal: journal is not opened"); if (!is_opened_rw (fs)) reiserfs_panic ("replay_journal: fs is not opened with write perms"); reiserfs_warning (stderr, "Replaying journal..\n"); bh = fs->fs_jh_bh; j_head = (struct reiserfs_journal_header *)(bh->b_data); control.mount_id = get_jh_mount_id (j_head); control.trans_id = get_jh_last_flushed (j_head); control.desc_blocknr = get_jh_replay_start_offset (j_head); if (!get_boundary_transactions (fs, &cur, &newest)) { reiserfs_warning (stderr, "No transactions found\n"); return 0; } /* Smth strange with journal header or journal. We cannot say for sure what was the last replaied transaction, but relying on JH data is preferable. */ replayed = 0; ret = TRANS_FOUND; /* Looking to the first valid not replayed transaction. */ while (1) { if (cur.mount_id == control.mount_id && cur.trans_id > control.trans_id) break; if ((ret = next_transaction (fs, &cur, newest)) != TRANS_FOUND) break; } while (ret == TRANS_FOUND) { /* If not the next transaction to be replayed, break out here. */ if ((cur.mount_id != control.mount_id) || (cur.trans_id != control.trans_id + 1 && control.trans_id)) break; if (!transaction_check_content(fs, &cur)) { reiserfs_warning (stderr, "Trans broken: mountid %lu, transid %lu, desc %lu, " "len %lu, commit %lu, next trans offset %lu\n", cur.mount_id, cur.trans_id, cur.desc_blocknr, cur.trans_len, cur.commit_blocknr, cur.next_trans_offset); break; } reiserfs_warning (stderr, "Trans replayed: mountid %lu, transid %lu, desc %lu, " "len %lu, commit %lu, next trans offset %lu\n", cur.mount_id, cur.trans_id, cur.desc_blocknr, cur.trans_len, cur.commit_blocknr, cur.next_trans_offset); replay_one_transaction (fs, &cur); update_journal_header (fs, bh, &cur); control = cur; replayed ++; ret = next_transaction (fs, &cur, newest); } reiserfs_warning (stderr, "Reiserfs journal '%s' in blocks [%u..%u]: %d " "transactions replayed\n", fs->fs_j_file_name, get_jp_journal_1st_block(sb_jp(fs->fs_ondisk_sb)), get_jp_journal_1st_block(sb_jp(fs->fs_ondisk_sb)) + get_jp_journal_size(sb_jp(fs->fs_ondisk_sb)) + 1, replayed); mark_buffer_dirty (fs->fs_super_bh); bwrite (fs->fs_super_bh); update_journal_header (fs, bh, &newest); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -