/* * Copyright 2001-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #include "fsck.h" #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) # include #endif #define fsck_conditional_log(sb_found, fmt, list...) { \ if (sb_found) \ fsck_log(fmt, ## list); \ } int what_fs_version() { size_t n = 0; char *answer = 0; int version; printf("\nwhat the version of ReiserFS do you use[1-4]\n" "\t(1) 3.6.x\n" "\t(2) >=3.5.9 (introduced in the middle of 1999) (if you use linux 2.2, choose this one)\n" "\t(3) < 3.5.9 converted to new format (don't choose if unsure)\n" "\t(4) < 3.5.9 (this is very old format, don't choose if unsure)\n" "\t(X) exit\n"); getline(&answer, &n, stdin); version = atoi(answer); if (version < 1 || version > 4) die("rebuild_sb: wrong version"); return version; } /* #define super_error(exit_code, text) { \ fsck_log(text); \ return exit_code; \ } int check_sb (reiserfs_filsys_t *fs) { int magic = 0, version = 0; if (!is_blocksize_correct (fs->fs_blocksize)) super_error(-1, "Wrong blocksize found in the super block\n"); if (is_reiserfs_3_6_magic_string (sb)) magic = 2; else if (is_reiserfs_3_5_magic_string (sb)) magic = 1; else if (is_reiserfs_jr_magic_string (sb)) magic = 3; else super_error(-1, "Invalid magic found in the super block.\n"); if (magic == 1 || magic == 2) { if (fsck_data (fs)->journal_dev_name) fsck_log("Reiserfs with standard journal found, but there was specified a " "journal dev\n"); standard_journal = 1; } else { if (!fsck_data (fs)->journal_dev_name) super_error(-1, "Reiserfs with non standard journal found, but there was not " "specified any journal dev\n"); standard_journal = 0; } if (get_sb_version (sb) != REISERFS_FORMAT_3_6 && get_sb_version (sb) != REISERFS_FORMAT_3_5) super_error(-1, "Invalid format found in the super block.\n"); if (is_new_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { if (magic == 3) version = get_sb_version (sb) == REISERFS_FORMAT_3_6 ? 1 : 2; else version = magic == 2 ? 1 : 2; } else if (is_old_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { if (magic == 3) version = get_sb_version (sb) == REISERFS_FORMAT_3_6 ? 3 : 4; else version = magic == 2 ? 3 : 4; } else die("Super block in the wong block(%d).\n", fs->fs_super_bh->b_blocknr); if (version == 0) die ("FS format must be figured out here.\n"); if (get_sb_block_count (sb) > count_blocks (filename, fs->fs_blocksize)) super_error(-1, "Invalid block count found in the super block.\n"); if (get_sb_block_size (sb) != fs->fs_blocksize) super_error(-1, "Invalid block size found in the super block (%lu).\n", get_sb_block_size (sb)); //Non needed from here p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_block_size (sb)) / sizeof(__u32) / 2 * 2; if (get_sb_oid_maxsize (sb) != p_oid_maxsize) super_error(-1, "Invalid objectid map max size found in the super block (%lu).\n", get_sb_oid_maxsize (sb)); if (get_sb_oid_cursize (sb) == 1 || get_sb_oid_cursize (sb) > get_sb_oid_maxsize (sb)) super_error(-1, "Invalid objectid map found in the super block (%lu).\n", get_sb_oid_cursize (sb)); if (get_sb_root_block (sb) > block_count && get_sb_root_block (sb) != ~0) fsck_log("Invalid root block found in the super block (%lu).\n", get_sb_root_block (sb)); if (get_sb_free_blocks (sb) > block_count) fsck_log ("Invalid free block count found in the super block (%lu).\n", get_sb_free_blocks (sb)); if (get_sb_tree_height (sb) && ((get_sb_tree_height (sb) < DISK_LEAF_NODE_LEVEL + 1) || (get_sb_tree_height (sb) > MAX_HEIGHT) && (get_sb_tree_height (sb) != ~0))) super_error(-1, "Invalid tree height found in the super block (%lu).\n", get_sb_tree_height (sb)); if (get_sb_hash_code (sb) && code2name (get_sb_hash_code (sb)) == 0) super_error(-1, "Invalid hash found in the super block (%lu).\n", get_sb_hash_code (sb)); if (version == 1 || version == 3) { if (!uuid_is_correct(sb->s_uuid)) fsck_log ("Invalid uuid found, you should generate a new one.\n"); if (sb->s_flags & 0xfffffffe) fsck_log ("rebuild-sb: super block flags found (%u), zeroed\n", sb->s_flags); } //Not needed till here. p_bmap_nr = (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8); if (get_sb_bmap_nr (sb) != p_bmap_nr) super_error(-1, "Invalid bitmap number found in the super block (%lu).\n", get_sb_bmap_nr (sb)); if (!fsck_skip_journal (fs) && standard_journal == 1) { if (get_jp_journal_dev (sb_jp(sb)) != 0) super_error(-1, "Invalid journal device found (%lu).\n", get_jp_journal_dev (sb_jp(sb))); if (get_jp_journal_1st_block (sb_jp(sb)) != get_journal_start_must (fs)) super_error(-1, "Invalid journal first block found (%lu).\n", get_jp_journal_1st_block (sb_jp(sb))); if (get_jp_journal_size (sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) super_error(-1, "Invalid journal size found (%lu).\n", get_jp_journal_size (sb_jp(sb)) + 1); if (get_jp_journal_max_batch (sb_jp(sb)) != advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max batch size occured (%lu), fixed (%d)\n", get_jp_journal_max_batch (sb_jp(sb)), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); set_jp_journal_max_batch (sb_jp(sb), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))); } if (get_jp_journal_max_commit_age (sb_jp(sb)) != advise_journal_max_commit_age()) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max commit age occured (%lu), fixed (%d)\n", get_jp_journal_max_commit_age (sb_jp(sb)), advise_journal_max_commit_age()); set_jp_journal_max_commit_age (sb_jp(sb), advise_journal_max_commit_age()); } if (get_jp_journal_max_trans_age (sb_jp(sb)) != advise_journal_max_trans_age()) { fsck_log ("rebuild-sb: wrong journal max commit age occured (%lu), fixed (0)\n", get_jp_journal_max_trans_age (sb_jp(sb)), advise_journal_max_trans_age()); set_jp_journal_max_trans_age (sb_jp(sb), advise_journal_max_trans_age()); } } */ void rebuild_sb(reiserfs_filsys_t *fs, char *filename, struct fsck_data *data) { int version = 0; struct reiserfs_super_block *ondisk_sb = 0; struct reiserfs_super_block *sb = 0; struct reiserfs_journal_header *j_head; int magic_was_found = 0; unsigned long block_count = 0; __u16 p_oid_maxsize; unsigned int bmap_nr; __u32 p_jp_journal_1st_block = 0; __u32 p_jp_dev_size = 0; int standard_journal = -1; char *journal_dev_name = 0; char *tmp; int sb_size; char *answer = 0; size_t n = 0; struct stat stat_buf; int retval, exit_code = EXIT_OK; if (!no_reiserfs_found(fs)) { sb = getmem(sizeof(*sb)); if (!is_opened_rw(fs)) { close(fs->fs_dev); fs->fs_dev = open(fs->fs_file_name, O_RDWR | O_LARGEFILE); } if (!is_blocksize_correct(fs->fs_blocksize)) { printf ("\nCannot find a proper blocksize, enter block size [4096]: \n"); getline(&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int)strtol(answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong block size specified\n"); if (!is_blocksize_correct(retval)) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong block size specified, " "only power of 2 from 512-8192 interval are supported.\n"); } else retval = 4096; fs->fs_blocksize = retval; } if (!(block_count = count_blocks(filename, fs->fs_blocksize))) exit(EXIT_OPER); /* save ondisk_sb somewhere and work in temp area */ ondisk_sb = fs->fs_ondisk_sb; memcpy(sb, fs->fs_ondisk_sb, sizeof(*sb)); fs->fs_ondisk_sb = sb; if (is_reiserfs_3_6_magic_string(sb)) { /* 3_6 magic */ if (fsck_data(fs)->journal_dev_name) /* journal dev must not be specified with standard journal */ reiserfs_exit(EXIT_USER, "ReiserFS with default journal " "is found, but there was specified a journal device."); if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 1; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 3; magic_was_found = 2; } else if (is_reiserfs_3_5_magic_string(sb)) { if (fsck_data(fs)->journal_dev_name) /* journal dev must not be specified with standard journal */ reiserfs_exit(EXIT_USER, "ReiserFS with default journal " "is found, but there was specified a journal device."); /* 3_5 magic */ if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 2; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 4; magic_was_found = 1; } else if (is_reiserfs_jr_magic_string(sb)) { if (!fsck_data(fs)->journal_dev_name && !fsck_skip_journal(fs)) /* journal dev must be specified with non standard journal */ reiserfs_exit(EXIT_USER, "ReiserFS with non default journal " "is found, but there was not specified any journal device."); if (get_sb_version(sb) == REISERFS_FORMAT_3_6) { /*non-standard magic + sb_format == 3_6 */ if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 1; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 3; magic_was_found = 3; } else if (get_sb_version(sb) == REISERFS_FORMAT_3_5) { /* non-standard magic + sb_format == 3_5 */ if (fs->fs_super_bh->b_blocknr == REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 2; else if (fs->fs_super_bh->b_blocknr == REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) version = 4; magic_was_found = 3; } else { /* non-standard magic + bad sb_format */ version = 0; magic_was_found = 3; } } else reiserfs_exit(EXIT_USER, "We opened device but there is no magic " "and there is no correct superblock format found."); if (magic_was_found == 1 || magic_was_found == 2) standard_journal = 1; else standard_journal = 0; if (version == 0) version = what_fs_version(); if (get_sb_block_count(sb) != block_count) { do { printf("\nDid you use resizer(y/n)[n]: "); getline(&answer, &n, stdin); } while (strcmp("y\n", answer) && strcmp("n\n", answer) && strcmp("\n", answer)); if (!strcmp("y\n", answer)) { printf("\nEnter partition size [%lu]: ", block_count); getline(&answer, &n, stdin); if (strcmp("\n", answer)) block_count = atoi(answer); } else { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong block count " "occured (%lu), fixed (%lu)\n", get_sb_block_count(sb), block_count); } set_sb_block_count(sb, block_count); } if (get_sb_block_size(sb) != fs->fs_blocksize) { fsck_log ("rebuild-sb: wrong block size occured (%lu), fixed (%lu)\n", get_sb_block_size(sb), fs->fs_blocksize); set_sb_block_size(sb, fs->fs_blocksize); } } /* if no reiserfs_found or bad data found in that SB, what was checked in previous * clause */ if (no_reiserfs_found(fs)) { int fd; fd = open(filename, O_RDWR | O_LARGEFILE); if (fd == -1) { reiserfs_exit(EXIT_OPER, "rebuils_sb: cannot open device %s", filename); } version = what_fs_version(); if (version == 3 || version == 4) { retval = 4096; } else { printf("\nEnter block size [4096]: \n"); getline(&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int)strtol(answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong block size specified\n"); if (!is_blocksize_correct(retval)) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong block size specified, " "only divisible by 1024 are supported currently\n"); } else retval = 4096; } if (!(block_count = count_blocks(filename, retval))) exit(EXIT_OPER); switch (version) { case 1: fs = reiserfs_create(filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 1); break; case 2: fs = reiserfs_create(filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 1); break; case 3: fs = reiserfs_create(filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 0); break; case 4: fs = reiserfs_create(filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 0); break; } if (fs == NULL) return; sb = fs->fs_ondisk_sb; fs->fs_vp = data; if (!fsck_skip_journal(fs)) { if (!fsck_data(fs)->journal_dev_name) { do { printf ("\nNo journal device was specified. (If journal is not " "available, re-run with --no-journal-available option specified).\n" "Is journal default? (y/n)[y]: "); getline(&answer, &n, stdin); } while (strcmp("y\n", answer) && strcmp("n\n", answer) && strcmp("\n", answer)); if (!strcmp("n\n", answer)) { printf ("\nSpecify journal device with -j option.\n"); exit(EXIT_USER); } standard_journal = 1; } else { standard_journal = 0; memcpy(fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING, strlen(REISERFS_JR_SUPER_MAGIC_STRING)); } } do { printf("\nDid you use resizer(y/n)[n]: "); getline(&answer, &n, stdin); } while (strcmp("y\n", answer) && strcmp("n\n", answer) && strcmp("\n", answer)); if (!strcmp("y\n", answer)) { printf("\nEnter partition size [%lu]: ", block_count); getline(&answer, &n, stdin); if (strcmp("\n", answer)) block_count = atoi(answer); set_sb_block_count(sb, block_count); } set_sb_fs_state(sb, FS_ERROR); } if (version == 1 || version == 3) { if (get_reiserfs_format(sb) != REISERFS_FORMAT_3_6) { fsck_log ("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", get_reiserfs_format(sb), REISERFS_FORMAT_3_6); set_sb_version(sb, REISERFS_FORMAT_3_6); } } else if (version == 2 || version == 4) { if (get_reiserfs_format(sb) != REISERFS_FORMAT_3_5) { fsck_log ("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", get_reiserfs_format(sb), REISERFS_FORMAT_3_5); set_sb_version(sb, REISERFS_FORMAT_3_5); } } p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_block_size(sb)) / sizeof(__u32) / 2 * 2; if (get_sb_oid_maxsize(sb) != p_oid_maxsize) { fsck_log ("rebuild-sb: wrong objectid map max size occured (%lu), fixed (%lu)\n", get_sb_oid_maxsize(sb), p_oid_maxsize); set_sb_oid_maxsize(sb, p_oid_maxsize); } bmap_nr = reiserfs_fs_bmap_nr(fs); if (reiserfs_bmap_over(bmap_nr) && get_sb_bmap_nr(sb) != 0) { fsck_log ("rebuild-sb: wrong bitmap number occured (%u), fixed (0) " "(really %u)\n", get_sb_bmap_nr(sb), bmap_nr); set_sb_bmap_nr(sb, 0); } else if (get_sb_bmap_nr(sb) != bmap_nr) { fsck_log("rebuild-sb: wrong bitmap number occured (%u), " "fixed (%u)\n", get_sb_bmap_nr(sb), bmap_nr); set_sb_bmap_nr(sb, bmap_nr); } if (get_sb_root_block(sb) > block_count) { fsck_log("rebuild-sb: wrong root block occured (%lu), zeroed\n", get_sb_root_block(sb)); set_sb_root_block(sb, 0); } if (get_sb_free_blocks(sb) > block_count) { fsck_log ("rebuild-sb: wrong free block count occured (%lu), zeroed\n", get_sb_free_blocks(sb)); set_sb_free_blocks(sb, 0); } if (get_sb_umount_state(sb) != FS_CLEANLY_UMOUNTED && get_sb_umount_state(sb) != FS_NOT_CLEANLY_UMOUNTED) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong umount state (%u), " "fixed to (FS_NOT_CLEANLY_UMOUNTED)\n", get_sb_umount_state(sb)); set_sb_umount_state(sb, FS_NOT_CLEANLY_UMOUNTED); } if (get_sb_oid_cursize(sb) == 1 || get_sb_oid_cursize(sb) > get_sb_oid_maxsize(sb)) { fsck_log ("rebuild-sb: wrong objectid map occured (%lu), zeroed\n", get_sb_oid_cursize(sb)); set_sb_oid_cursize(sb, 0); } if (get_sb_tree_height(sb) && ((get_sb_tree_height(sb) < DISK_LEAF_NODE_LEVEL + 1) || (get_sb_tree_height(sb) > MAX_HEIGHT))) { fsck_log("rebuild-sb: wrong tree height occured (%u), zeroed\n", get_sb_tree_height(sb)); set_sb_tree_height(sb, 0); } if (get_sb_hash_code(sb) && code2name(get_sb_hash_code(sb)) == 0) { fsck_log("rebuild-sb: wrong hash occured (%lu), zeroed\n", get_sb_hash_code(sb)); set_sb_hash_code(sb, 0); } if (version == 1 || version == 3) { #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) if (uuid_is_null(sb->s_uuid)) { uuid_generate(sb->s_uuid); fsck_log("rebuild-sb: no uuid found, a new uuid was " "generated (%U)\n", sb->s_uuid); } #endif if (sb->s_flags != 0 && sb->s_flags != 1) { fsck_log ("rebuild-sb: super block flags found (%u), zeroed\n", sb->s_flags); sb->s_flags = 0; } } /* if we have a standard journal reserved = 0 dev - same size = journal_default_size(fs->fs_super_bh->b_blocknr, fs) offset = journal_default_size(fs) if we have a non standard journal if we found magic string try to find a jhead and comare dev, size, offset there if params are not equal move to "if we did not find a magic string" clause if we did not find a magic string ask user about his journal try to find a jhead and comare dev, size, offset there if params are not equal exit with error */ p_jp_journal_1st_block = get_journal_start_must(fs); if (standard_journal == 1) { if (get_jp_journal_dev(sb_jp(sb)) != 0) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong journal device " "occured (%lu), fixed (0)\n", get_jp_journal_dev(sb_jp(sb))); set_jp_journal_dev(sb_jp(sb), 0); } if (get_sb_reserved_for_journal(sb) != 0) { fsck_log ("rebuild-sb: wrong size reserved for default journal occured " "(%lu), fixed (0)\n", get_sb_reserved_for_journal(sb)); set_sb_reserved_for_journal(sb, 0); } if (get_jp_journal_1st_block(sb_jp(sb)) != p_jp_journal_1st_block) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong journal first " "block occured (%lu), fixed (%lu)\n", get_jp_journal_1st_block(sb_jp (sb)), p_jp_journal_1st_block); set_jp_journal_1st_block(sb_jp(sb), p_jp_journal_1st_block); } if (get_jp_journal_size(sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong journal size " "occured (%lu), fixed (%lu)\n", get_jp_journal_size(sb_jp(sb)) + 1, journal_default_size(fs-> fs_super_bh-> b_blocknr, fs-> fs_blocksize) + 1); set_jp_journal_size(sb_jp(sb), journal_default_size(fs-> fs_super_bh-> b_blocknr, fs-> fs_blocksize)); } if ((retval = reiserfs_open_journal(fs, filename, O_RDWR | O_LARGEFILE))) { fsck_log ("\nrebuild-sb: Failed to open the journal device (%s).\n", filename); exit(retval < 0 ? EXIT_OPER : EXIT_USER); } } else if (!fsck_skip_journal(fs)) { /* Check that specified non-standard journal device exists. */ journal_dev_name = fsck_data(fs)->journal_dev_name; retval = stat(journal_dev_name, &stat_buf); if (retval == -1) reiserfs_exit(EXIT_USER, "rebuild_sb: error while detecting the " "specified journal device (%s): %s\n", journal_dev_name, strerror(errno)); retval = 0; if (magic_was_found) { /* Super block was found. Try to open the journal on the base of its * journal parameters. */ retval = reiserfs_open_journal(fs, journal_dev_name, O_RDWR | O_LARGEFILE); if (retval == 0) { j_head = (struct reiserfs_journal_header *)(fs-> fs_jh_bh-> b_data); retval = memcmp(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); if (retval) { /* journal parameters from the SB and from the J_Header does not * match. Close the jouranl, ask the user about correct journal * parameters. */ reiserfs_close_journal(fs); } } if (!reiserfs_journal_opened(fs)) { fsck_log ("Journal cannot be opened, assuming specified " "journal device is correct\n"); } } if (!reiserfs_journal_opened(fs)) { __u64 default_value; /* journal was not found or SB and J_Header parameters does not match. */ if (magic_was_found == 0) default_value = (!strcmp (fs->fs_file_name, journal_dev_name)) ? p_jp_journal_1st_block : 0; else default_value = get_jp_journal_1st_block(sb_jp(sb)); printf ("\nEnter journal offset on %s in blocks [%Lu]: \n", journal_dev_name, (unsigned long long)default_value); getline(&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int)strtol(answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong offset specified\n"); set_jp_journal_1st_block(sb_jp(sb), retval); } else set_jp_journal_1st_block(sb_jp(sb), default_value); if (! (p_jp_dev_size = count_blocks(journal_dev_name, fs->fs_blocksize))) exit(EXIT_OPER); /* some checks for journal offset */ if (strcmp(fs->fs_file_name, journal_dev_name) != 0) { if (p_jp_dev_size < get_jp_journal_1st_block(sb_jp(sb)) + 1) reiserfs_exit(EXIT_USER, "rebuild_sb: offset is much than device size\n"); } /* default size if magic was not found is device size - journal_1st_block; default size if magic was found is found value + 1 block for journal header */ if (magic_was_found == 0) default_value = (!strcmp (fs->fs_file_name, journal_dev_name)) ? journal_default_size(fs->fs_super_bh-> b_blocknr, fs->fs_blocksize) + 1 : p_jp_dev_size - get_jp_journal_1st_block(sb_jp(sb)); else default_value = get_jp_journal_size(sb_jp(sb)) + 1; printf ("\nEnter journal size (including 1 block for journal header) on " "%s in blocks [%Lu]: \n", journal_dev_name, (unsigned long long)default_value); getline(&answer, &n, stdin); if (strcmp(answer, "\n")) { retval = (int)strtol(answer, &tmp, 0); if ((*tmp && strcmp(tmp, "\n")) || retval < 0) reiserfs_exit(EXIT_USER, "rebuild_sb: wrong offset specified\n"); set_jp_journal_size(sb_jp(sb), retval - 1); } else { set_jp_journal_size(sb_jp(sb), default_value - 1); } /* some checks for journal size */ if (get_jp_journal_size(sb_jp(sb)) + get_jp_journal_1st_block(sb_jp(sb)) + 1 > p_jp_dev_size) reiserfs_exit(EXIT_USER, "rebuild_sb: journal offset + journal size is " "greater than device size\n"); /* some checks for journal size */ if (get_jp_journal_size(sb_jp(sb)) < JOURNAL_MIN_SIZE) reiserfs_exit(EXIT_USER, "rebuild_sb: journal size cannot be less than " "%lu blocks.\n", JOURNAL_MIN_SIZE + 1); if ((retval = reiserfs_open_journal(fs, journal_dev_name, O_RDWR | O_LARGEFILE))) { fsck_log ("\nrebuild-sb: Failed to open a journal device (%s).", journal_dev_name); exit(retval < 0 ? EXIT_OPER : EXIT_USER); } /* SB was found, but journal params were broken and have been recovered. * Futher work goes as SB would not be found. */ magic_was_found = 0; } if (strcmp(fs->fs_file_name, journal_dev_name)) set_jp_journal_dev(sb_jp(sb), stat_buf.st_rdev); else set_jp_journal_dev(sb_jp(sb), 0); } else { fsck_log ("\nJournal was specified as not available. reiserfstune is " "needed.\n\n"); set_jp_journal_magic(sb_jp(sb), NEED_TUNE); } if (reiserfs_journal_opened(fs)) { /* Journal was openned. Check/fix journal parameters and copy it the journal * header. */ if (get_jp_journal_max_trans_len(sb_jp(sb)) != advise_journal_max_trans_len(get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size(sb_jp(sb)), fs->fs_blocksize, 0)) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong journal max " "transaction length occured (%lu), fixed (%d)\n", get_jp_journal_max_trans_len(sb_jp (sb)), advise_journal_max_trans_len (get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size(sb_jp(sb)), fs->fs_blocksize, 0)); set_jp_journal_max_trans_len(sb_jp(sb), advise_journal_max_trans_len (get_jp_journal_max_trans_len (sb_jp(sb)), get_jp_journal_size(sb_jp (sb)), fs->fs_blocksize, 0)); } if (get_jp_journal_max_batch(sb_jp(sb)) != advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong journal max " "batch size occured (%lu), fixed (%d)\n", get_jp_journal_max_batch(sb_jp (sb)), advise_journal_max_batch (get_jp_journal_max_trans_len (sb_jp(sb)))); set_jp_journal_max_batch(sb_jp(sb), advise_journal_max_batch (get_jp_journal_max_trans_len (sb_jp(sb)))); } if (get_jp_journal_max_commit_age(sb_jp(sb)) != advise_journal_max_commit_age()) { fsck_conditional_log(magic_was_found, "rebuild-sb: wrong journal " "max commit age occured (%lu), fixed (%d)\n", get_jp_journal_max_commit_age(sb_jp (sb)), advise_journal_max_commit_age()); set_jp_journal_max_commit_age(sb_jp(sb), advise_journal_max_commit_age ()); } if (get_jp_journal_max_trans_age(sb_jp(sb)) != advise_journal_max_trans_age()) { fsck_log ("rebuild-sb: wrong journal max commit age occured (%u), " "fixed (%u)\n", get_jp_journal_max_trans_age(sb_jp(sb)), advise_journal_max_trans_age()); set_jp_journal_max_trans_age(sb_jp(sb), advise_journal_max_trans_age ()); } j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); if (standard_journal == 0) { if (get_jp_journal_magic(sb_jp(sb)) == 0 || get_jp_journal_magic(sb_jp(sb)) == NEED_TUNE) { int magic; magic = random(); fsck_log ("rebuild-sb: genarate the new journal magic (%d)\n", magic); set_jp_journal_magic(sb_jp(sb), magic); set_jp_journal_magic(&j_head->jh_journal, magic); } } retval = memcmp(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); if (retval) { if (standard_journal == 1) { fsck_log ("\nrebuild-sb: You either have a corrupted journal or have just " "changed\nthe start of the partition with some partition table editor. " "If you are\nsure that the start of the partition is ok, rebuild the " "journal header.\n"); } else if (!magic_was_found) { fsck_log ("\nrebuild-sb: journal header is not found. You either have " "a corrupted,\nbad configured(device/offset/size), not available " "journal or have just changed\nthe start of the journal partition " "with some partition table editor. In the \ncase of corrupted " "journal you need to use --no-journal-available. If you are\n" "sure that the start of the partition is ok and journal is " "available, rebuild\nthe journal header.\n"); } if (standard_journal || !magic_was_found) { if (!user_confirmed (stdout, "Do you want to rebuild the journal header? " "(y/n)[n]: ", "y\n")) { exit(EXIT_USER); } else exit_code = EXIT_FIXED; } memcpy(&j_head->jh_journal, sb_jp(sb), sizeof(struct journal_params)); mark_buffer_dirty(fs->fs_jh_bh); bwrite(fs->fs_jh_bh); } } /* whether journal header contains params with the same dev, offset, size will be checked in open_journal */ if (version == 1 || version == 3) sb_size = SB_SIZE; else sb_size = SB_SIZE_V1; if (ondisk_sb == NULL || memcmp(ondisk_sb, sb, sb_size - ((sb_size == SB_SIZE) ? sizeof(fs->fs_ondisk_sb-> s_unused) : 0))) { /* smth was changed in SB or a new one has been built */ set_sb_fs_state(sb, get_sb_fs_state(sb) | FS_ERROR); if (ondisk_sb) { /* if super_block was found, we keep sb in ondisk_sb */ fs->fs_ondisk_sb = ondisk_sb; memcpy(ondisk_sb, sb, sb_size); freemem(sb); } fflush(stdout); print_block(stderr, fs, fs->fs_super_bh); if (user_confirmed(stderr, "Is this ok ? (y/n)[n]: ", "y\n")) { mark_buffer_uptodate(fs->fs_super_bh, 1); mark_buffer_dirty(fs->fs_super_bh); bwrite(fs->fs_super_bh); fsck_progress ("The fs may still be unconsistent. Run reiserfsck --check.\n\n"); exit_code = EXIT_FIXED; } else { mark_buffer_clean(fs->fs_super_bh); fsck_progress("Super block was not written\n"); } } else { print_block(stderr, fs, fs->fs_super_bh); mark_buffer_clean(fs->fs_super_bh); fsck_progress("\nSuper block seems to be correct\n\n"); } exit(exit_code); } /* if (version == 0) { brelse (fs->fs_super_bh); freemem (fs); close (fs->fs_dev); fs = NULL; } */