| /* |
| * Copyright 2001-2004 by Hans Reiser, licensing governed by |
| * reiserfsprogs/README |
| */ |
| |
| #include "fsck.h" |
| |
| #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) |
| # include <uuid/uuid.h> |
| #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; |
| __u16 p_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 defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) |
| char uuid[37]; |
| |
| uuid[36] = '\0'; |
| #endif |
| |
| 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); |
| } |
| |
| p_bmap_nr = (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8); |
| if (get_sb_bmap_nr (sb) != p_bmap_nr) { |
| fsck_log("rebuild-sb: wrong bitmap number occured (%lu), fixed (%lu)\n", |
| get_sb_bmap_nr (sb), p_bmap_nr); |
| set_sb_bmap_nr (sb, |
| (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8)); |
| } |
| |
| 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; |
| } |
| */ |