/* * Copyright 2001-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "fsck.h" #include "misc/malloc.h" #include "misc/device.h" #include "util/print.h" #include #include #include #include #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 () { char answer[256]; 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"); fgets(answer, sizeof(answer), stdin); version = atoi (answer); if (version < 1 || version > 4) misc_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 (!reiserfs_fs_blksize_check (fs->fs_blocksize)) super_error(-1, "Wrong blocksize found in the super block\n"); if (reiserfs_super_36_magic (sb)) magic = 2; else if (reiserfs_super_35_magic (sb)) magic = 1; else if (reiserfs_super_jr_magic (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 (reiserfs_sb_get_version (sb) != REISERFS_FORMAT_3_6 && reiserfs_sb_get_version (sb) != REISERFS_FORMAT_3_5) super_error(-1, "Invalid format found in the super block.\n"); if (reiserfs_new_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { if (magic == 3) version = reiserfs_sb_get_version (sb) == REISERFS_FORMAT_3_6 ? 1 : 2; else version = magic == 2 ? 1 : 2; } else if (reiserfs_old_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) { if (magic == 3) version = reiserfs_sb_get_version (sb) == REISERFS_FORMAT_3_6 ? 3 : 4; else version = magic == 2 ? 3 : 4; } else misc_die("Super block in the wong block(%d).\n", fs->fs_super_bh->b_blocknr); if (version == 0) misc_die ("FS format must be figured out here.\n"); if (reiserfs_sb_get_blocks (sb) > misc_device_count_blocks (filename, fs->fs_blocksize)) super_error(-1, "Invalid block count found in the super block.\n"); if (reiserfs_sb_get_blksize (sb) != fs->fs_blocksize) super_error(-1, "Invalid block size found in the super block (%lu).\n", reiserfs_sb_get_blksize (sb)); //Non needed from here p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_size (sb)) / sizeof(__u32) / 2 * 2; if (reiserfs_sb_get_mapmax (sb) != p_oid_maxsize) super_error(-1, "Invalid objectid map max size found in the super block (%lu).\n", reiserfs_sb_get_mapmax (sb)); if (reiserfs_sb_get_mapcur (sb) == 1 || reiserfs_sb_get_mapcur (sb) > reiserfs_sb_get_mapmax (sb)) super_error(-1, "Invalid objectid map found in the super block (%lu).\n", reiserfs_sb_get_mapcur (sb)); if (reiserfs_sb_get_root (sb) > block_count && reiserfs_sb_get_root (sb) != ~0) fsck_log("Invalid root block found in the super block (%lu).\n", reiserfs_sb_get_root (sb)); if (reiserfs_sb_get_free (sb) > block_count) fsck_log ("Invalid free block count found in the super block (%lu).\n", reiserfs_sb_get_free (sb)); if (reiserfs_sb_get_height (sb) && ((reiserfs_sb_get_height (sb) < LEAF_LEVEL + 1) || (reiserfs_sb_get_height (sb) > REISERFS_TREE_HEIGHT_MAX) && (reiserfs_sb_get_height (sb) != ~0))) super_error(-1, "Invalid tree height found in the super block (%lu).\n", reiserfs_sb_get_height (sb)); if (reiserfs_sb_get_hash (sb) && reiserfs_hash_name (reiserfs_sb_get_hash (sb)) == 0) super_error(-1, "Invalid hash found in the super block (%lu).\n", reiserfs_sb_get_hash (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 (reiserfs_sb_get_bmaps (sb) != p_bmap_nr) super_error(-1, "Invalid bitmap number found in the super block (%lu).\n", reiserfs_sb_get_bmaps (sb)); if (!fsck_skip_journal (fs) && standard_journal == 1) { if (reiserfs_jp_get_dev (reiserfs_sb_jp(sb)) != 0) super_error(-1, "Invalid journal device found (%lu).\n", reiserfs_jp_get_dev (reiserfs_sb_jp(sb))); if (reiserfs_jp_get_start (reiserfs_sb_jp(sb)) != reiserfs_journal_start_must (fs)) super_error(-1, "Invalid journal first block found (%lu).\n", reiserfs_jp_get_start (reiserfs_sb_jp(sb))); if (reiserfs_jp_get_size (reiserfs_sb_jp(sb)) != reiserfs_journal_default(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) super_error(-1, "Invalid journal size found (%lu).\n", reiserfs_jp_get_size (reiserfs_sb_jp(sb)) + 1); if (reiserfs_jp_get_max_batch (reiserfs_sb_jp(sb)) != reiserfs_journal_batch(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)))) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max batch size occured (%lu), fixed (%d)\n", reiserfs_jp_get_max_batch (reiserfs_sb_jp(sb)), reiserfs_journal_batch(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)))); reiserfs_jp_set_max_batch (reiserfs_sb_jp(sb), reiserfs_journal_batch(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)))); } if (reiserfs_jp_get_commit_age (reiserfs_sb_jp(sb)) != reiserfs_journal_commit_age()) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max commit age occured (%lu), fixed (%d)\n", reiserfs_jp_get_commit_age (reiserfs_sb_jp(sb)), reiserfs_journal_commit_age()); reiserfs_jp_set_commit_age (reiserfs_sb_jp(sb), reiserfs_journal_commit_age()); } if (reiserfs_jp_get_trans_age (reiserfs_sb_jp(sb)) != reiserfs_journal_trans_age()) { fsck_log ("rebuild-sb: wrong journal max commit age occured (%lu), fixed (0)\n", reiserfs_jp_get_trans_age (reiserfs_sb_jp(sb)), reiserfs_journal_trans_age()); reiserfs_jp_set_trans_age (reiserfs_sb_jp(sb), reiserfs_journal_trans_age()); } } */ void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data) { struct reiserfs_journal_header *j_head; __u32 p_jp_journal_1st_block = 0; int retval, exit_code = EXIT_OK; reiserfs_sb_t * ondisk_sb = 0; unsigned long block_count = 0; char * journal_dev_name = 0; int standard_journal = -1; int magic_was_found = 0; __u32 p_jp_dev_size = 0; reiserfs_sb_t * sb = 0; struct stat stat_buf; __u16 p_oid_maxsize; char answer[256]; __u32 p_bmap_nr; int version = 0; int sb_size; char * tmp; #if defined(HAVE_LIBUUID) && defined(HAVE_UUID_UUID_H) char uuid[37]; uuid[36] = '\0'; #endif if (fs != NULL) { sb = misc_getmem (sizeof (*sb)); if (!reiserfs_fs_rw (fs)) { close (fs->fs_dev); fs->fs_dev = open (fs->fs_file_name, O_RDWR #ifdef O_LARGEFILE | O_LARGEFILE #endif ); } if (!reiserfs_fs_blksize_check (fs->fs_blocksize)) { printf("\nCannot find a proper blocksize, enter block size [4096]: \n"); fgets(answer, sizeof(answer), 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 (!reiserfs_fs_blksize_check (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 = misc_device_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 (reiserfs_super_36_magic (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 (reiserfs_super_35_magic (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 (reiserfs_super_jr_magic (sb)) { if (reiserfs_sb_get_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 (reiserfs_sb_get_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 (reiserfs_sb_get_blocks (sb) != block_count) { do { printf("\nDid you use resizer(y/n)[n]: "); fgets(answer, sizeof(answer), 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); fgets(answer, sizeof(answer), 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", reiserfs_sb_get_blocks(sb), block_count); } reiserfs_sb_set_blocks (sb, block_count); } if (reiserfs_sb_get_blksize (sb) != fs->fs_blocksize) { fsck_log("rebuild-sb: wrong block size occured (%lu), fixed (%lu)\n", reiserfs_sb_get_blksize (sb), fs->fs_blocksize); reiserfs_sb_set_blksize (sb, fs->fs_blocksize); } } /* if no reiserfs_found or bad data found in that SB, what was checked in previous * clause */ if (fs == NULL) { int fd; fd = open (filename, O_RDWR #ifdef O_LARGEFILE | O_LARGEFILE #endif ); 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"); fgets(answer, sizeof(answer), 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 (!reiserfs_fs_blksize_check (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 = misc_device_count_blocks (filename, retval))) exit(EXIT_OPER); switch(version){ case 1: fs = reiserfs_fs_create (filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 1); break; case 2: fs = reiserfs_fs_create (filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 1); break; case 3: fs = reiserfs_fs_create (filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 0); break; case 4: fs = reiserfs_fs_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]: "); fgets(answer, sizeof(answer), 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]: "); fgets(answer, sizeof(answer), 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); fgets(answer, sizeof(answer), stdin); if (strcmp ("\n", answer)) block_count = atoi (answer); reiserfs_sb_set_blocks (sb, block_count); } reiserfs_sb_set_state (sb, FS_ERROR); } if (version == 1 || version == 3) { if (reiserfs_super_format (sb) != REISERFS_FORMAT_3_6) { fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", reiserfs_super_format (sb), REISERFS_FORMAT_3_6); reiserfs_sb_set_version (sb, REISERFS_FORMAT_3_6); } } else if (version == 2 || version == 4) { if (reiserfs_super_format (sb) != REISERFS_FORMAT_3_5) { fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", reiserfs_super_format (sb), REISERFS_FORMAT_3_5); reiserfs_sb_set_version (sb, REISERFS_FORMAT_3_5); } } p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_size (sb)) / sizeof(__u32) / 2 * 2; if (reiserfs_sb_get_mapmax (sb) != p_oid_maxsize) { fsck_log("rebuild-sb: wrong objectid map max size occured (%lu), fixed (%lu)\n", reiserfs_sb_get_mapmax (sb), p_oid_maxsize); reiserfs_sb_set_mapmax (sb, p_oid_maxsize); } p_bmap_nr = reiserfs_bmap_nr(block_count, fs->fs_blocksize); p_bmap_nr = reiserfs_bmap_over(p_bmap_nr) ? 0 : p_bmap_nr; if (reiserfs_sb_get_bmaps (sb) != p_bmap_nr) { fsck_log("rebuild-sb: wrong bitmap number occured (%lu), fixed (%lu)\n", reiserfs_sb_get_bmaps (sb), p_bmap_nr); reiserfs_sb_set_bmaps (sb, (__u16)p_bmap_nr); } if (reiserfs_sb_get_root (sb) > block_count) { fsck_log("rebuild-sb: wrong root block occured (%lu), zeroed\n", reiserfs_sb_get_root (sb)); reiserfs_sb_set_root (sb, 0); } if (reiserfs_sb_get_free (sb) > block_count) { fsck_log ("rebuild-sb: wrong free block count occured (%lu), zeroed\n", reiserfs_sb_get_free (sb)); reiserfs_sb_set_free (sb, 0); } if (reiserfs_sb_get_umount (sb) != FS_CLEANLY_UMOUNTED && reiserfs_sb_get_umount (sb) != FS_NOT_CLEANLY_UMOUNTED) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong umount state (%u), " "fixed to (FS_NOT_CLEANLY_UMOUNTED)\n", reiserfs_sb_get_umount (sb)); reiserfs_sb_set_umount (sb, FS_NOT_CLEANLY_UMOUNTED); } if (reiserfs_sb_get_mapcur (sb) == 1 || reiserfs_sb_get_mapcur (sb) > reiserfs_sb_get_mapmax (sb)) { fsck_log("rebuild-sb: wrong objectid map occured (%lu), zeroed\n", reiserfs_sb_get_mapcur (sb)); reiserfs_sb_set_mapcur (sb, 0); } if ( reiserfs_sb_get_height (sb) && ((reiserfs_sb_get_height (sb) < LEAF_LEVEL + 1) || (reiserfs_sb_get_height (sb) > REISERFS_TREE_HEIGHT_MAX)) ) { fsck_log("rebuild-sb: wrong tree height occured (%u), zeroed\n", reiserfs_sb_get_height (sb)); reiserfs_sb_set_height (sb, 0); } if (reiserfs_sb_get_hash (sb) && reiserfs_hash_name (reiserfs_sb_get_hash (sb)) == 0) { fsck_log("rebuild-sb: wrong hash occured (%lu), zeroed\n", reiserfs_sb_get_hash (sb)); reiserfs_sb_set_hash (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 = reiserfs_journal_default(fs->fs_super_bh->b_blocknr, fs) offset = reiserfs_journal_default(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 = reiserfs_journal_start_must (fs); if (standard_journal == 1) { if (reiserfs_jp_get_dev (reiserfs_sb_jp(sb)) != 0) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal device " "occured (%lu), fixed (0)\n", reiserfs_jp_get_dev (reiserfs_sb_jp(sb))); reiserfs_jp_set_dev (reiserfs_sb_jp(sb), 0); } if (reiserfs_sb_get_reserved (sb) != 0) { fsck_log ("rebuild-sb: wrong size reserved for default journal occured " "(%lu), fixed (0)\n", reiserfs_sb_get_reserved (sb)); reiserfs_sb_set_reserved (sb, 0); } if (reiserfs_jp_get_start (reiserfs_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", reiserfs_jp_get_start (reiserfs_sb_jp(sb)), p_jp_journal_1st_block); reiserfs_jp_set_start (reiserfs_sb_jp(sb) , p_jp_journal_1st_block); } if (reiserfs_jp_get_size (reiserfs_sb_jp(sb)) != reiserfs_journal_default(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", reiserfs_jp_get_size (reiserfs_sb_jp(sb)) + 1, reiserfs_journal_default (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1); reiserfs_jp_set_size (reiserfs_sb_jp(sb), reiserfs_journal_default (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)); } if ((retval = reiserfs_journal_open(fs, filename, O_RDWR #ifdef O_LARGEFILE | O_LARGEFILE #endif ))) { 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 = 0; if (magic_was_found) { /* Super block was found. Try to open the journal on the base of its * journal parameters. */ retval = reiserfs_journal_open(fs, journal_dev_name, O_RDWR #ifdef O_LARGEFILE | O_LARGEFILE #endif ); if (retval == 0) { journal_dev_name = fs->fs_j_file_name; j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); retval = memcmp(&j_head->jh_journal, reiserfs_sb_jp(sb), sizeof(reiserfs_journal_param_t)); 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_journal_close(fs); } } if (!reiserfs_journal_opened(fs)) { fsck_log ("Journal cannot be opened, assuming the " "journal device %s is correct\n", journal_dev_name); } } 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 = reiserfs_jp_get_start (reiserfs_sb_jp(sb)); printf("\nEnter journal offset on %s in blocks [%Lu]: \n", journal_dev_name, (unsigned long long)default_value); fgets(answer, sizeof(answer), 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"); reiserfs_jp_set_start (reiserfs_sb_jp(sb), retval); } else reiserfs_jp_set_start (reiserfs_sb_jp(sb), default_value); if (!(p_jp_dev_size = misc_device_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 < reiserfs_jp_get_start (reiserfs_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)) ? reiserfs_journal_default (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1 : p_jp_dev_size - reiserfs_jp_get_start (reiserfs_sb_jp(sb)); else default_value = reiserfs_jp_get_size (reiserfs_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); fgets(answer, sizeof(answer), 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"); reiserfs_jp_set_size (reiserfs_sb_jp(sb), retval - 1); } else { reiserfs_jp_set_size (reiserfs_sb_jp(sb), default_value - 1); } /* some checks for journal size */ if (reiserfs_jp_get_size (reiserfs_sb_jp(sb)) + reiserfs_jp_get_start (reiserfs_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 (reiserfs_jp_get_size (reiserfs_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_journal_open(fs, journal_dev_name, O_RDWR #ifdef O_LARGEFILE | O_LARGEFILE #endif ))) { 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; } 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)); if (strcmp (fs->fs_file_name, journal_dev_name)) reiserfs_jp_set_dev (reiserfs_sb_jp(sb), stat_buf.st_rdev); else reiserfs_jp_set_dev (reiserfs_sb_jp(sb), 0); } else { fsck_log ("\nJournal was specified as not available. reiserfstune is " "needed.\n\n"); reiserfs_jp_set_magic (reiserfs_sb_jp(sb), NEED_TUNE); } if (reiserfs_journal_opened(fs)) { /* Journal was openned. Check/fix journal parameters and copy it the journal * header. */ if (reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)) != reiserfs_journal_tlen(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)), reiserfs_jp_get_size (reiserfs_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", reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)), reiserfs_journal_tlen(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)), reiserfs_jp_get_size (reiserfs_sb_jp(sb)), fs->fs_blocksize, 0)); reiserfs_jp_set_tlen (reiserfs_sb_jp(sb), reiserfs_journal_tlen(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)), reiserfs_jp_get_size (reiserfs_sb_jp(sb)), fs->fs_blocksize, 0)); } if (reiserfs_jp_get_max_batch (reiserfs_sb_jp(sb)) != reiserfs_journal_batch(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)))) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max " "batch size occured (%lu), fixed (%d)\n", reiserfs_jp_get_max_batch (reiserfs_sb_jp(sb)), reiserfs_journal_batch(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)))); reiserfs_jp_set_max_batch (reiserfs_sb_jp(sb), reiserfs_journal_batch(reiserfs_jp_get_tlen (reiserfs_sb_jp(sb)))); } if (reiserfs_jp_get_commit_age (reiserfs_sb_jp(sb)) != reiserfs_journal_commit_age()) { fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal " "max commit age occured (%lu), fixed (%d)\n", reiserfs_jp_get_commit_age (reiserfs_sb_jp(sb)), reiserfs_journal_commit_age()); reiserfs_jp_set_commit_age (reiserfs_sb_jp(sb), reiserfs_journal_commit_age()); } if (reiserfs_jp_get_trans_age (reiserfs_sb_jp(sb)) != reiserfs_journal_trans_age()) { fsck_log ("rebuild-sb: wrong journal transaction age occured (%u), " "fixed (%u)\n", reiserfs_jp_get_trans_age (reiserfs_sb_jp(sb)), reiserfs_journal_trans_age()); reiserfs_jp_set_trans_age (reiserfs_sb_jp(sb), reiserfs_journal_trans_age()); } j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data); if (standard_journal == 0) { if (reiserfs_jp_get_magic (reiserfs_sb_jp(sb)) == 0 || reiserfs_jp_get_magic (reiserfs_sb_jp(sb)) == NEED_TUNE) { int magic; magic = random(); fsck_log ("rebuild-sb: genarate the new journal magic (%d)\n", magic); reiserfs_jp_set_magic (reiserfs_sb_jp(sb), magic); reiserfs_jp_set_magic (&j_head->jh_journal, magic); } } retval = memcmp(&j_head->jh_journal, reiserfs_sb_jp(sb), sizeof(reiserfs_journal_param_t)); 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 (!util_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, reiserfs_sb_jp(sb), sizeof(reiserfs_journal_param_t)); reiserfs_buffer_mkdirty(fs->fs_jh_bh); reiserfs_buffer_write (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 = REISERFS_SB_SIZE; else sb_size = REISERFS_SB_SIZE_V1; if (ondisk_sb == NULL || memcmp(ondisk_sb, sb, sb_size - ((sb_size == REISERFS_SB_SIZE) ? sizeof(fs->fs_ondisk_sb->s_unused) : 0))) { /* smth was changed in SB or a new one has been built */ reiserfs_sb_set_state (sb, reiserfs_sb_get_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); misc_freemem(sb); } fflush(stdout); reiserfs_node_print (stderr, fs, fs->fs_super_bh); if (util_user_confirmed (stderr, "Is this ok ? (y/n)[n]: ", "y\n")) { reiserfs_buffer_mkuptodate (fs->fs_super_bh, 1); reiserfs_buffer_mkdirty (fs->fs_super_bh); reiserfs_buffer_write (fs->fs_super_bh); fsck_progress ("The fs may still be unconsistent. Run reiserfsck --check.\n\n"); exit_code = EXIT_FIXED; } else { reiserfs_buffer_mkclean (fs->fs_super_bh); fsck_progress ("Super block was not written\n"); } } else { reiserfs_node_print (stderr, fs, fs->fs_super_bh); reiserfs_buffer_mkclean (fs->fs_super_bh); fsck_progress ("\nSuper block seems to be correct\n\n"); } exit(exit_code); } /* if (version == 0) { reiserfs_buffer_close (fs->fs_super_bh); misc_freemem (fs); close (fs->fs_dev); fs = NULL; } */