895 lines
32 KiB
C
895 lines
32 KiB
C
/*
|
|
* 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 <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.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 ()
|
|
{
|
|
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;
|
|
}
|
|
*/
|