Files
reiserfsprogs/fsck/pass1.c
T

882 lines
23 KiB
C

/*
* Copyright 1996-1999 Hans Reiser
*/
#include "fsck.h"
#include <stdlib.h>
reiserfs_bitmap_t bad_unfm_in_tree_once_bitmap;
//int step = 0; // 0 - find stat_data or any item ; 1 - find item ; 2 - already found
/* allocates buffer head and copy buffer content */
struct buffer_head * make_buffer (int dev, int blocknr, int size, char * data)
{
struct buffer_head * bh;
bh = getblk (dev, blocknr, size);
if (buffer_uptodate (bh))
return bh;
// die ("make_buffer: uptodate buffer found");
memcpy (bh->b_data, data, size);
set_bit (BH_Uptodate, (char *)&bh->b_state);
return bh;
}
int find_not_of_one_file(struct key * to_find, struct key * key)
{
if ((to_find->k_objectid != -1) &&
(to_find->k_objectid != key->k_objectid))
return 1;
if ((to_find->k_dir_id != -1) &&
(to_find->k_dir_id != key->k_dir_id))
return 1;
return 0;
}
int is_item_reachable (struct item_head * ih)
{
return ih_reachable (ih) ? 1 : 0;
}
void mark_item_unreachable (struct item_head * ih)
{
mark_ih_unreachable (ih);
if (is_indirect_ih (ih))
set_free_space (ih, 0);
}
void mark_item_reachable (struct item_head * ih, struct buffer_head * bh)
{
mark_ih_ok (ih);
mark_buffer_dirty (bh);
}
static void stat_data_in_tree (struct buffer_head *bh,
struct item_head * ih)
{
#if 0
__u32 objectid;
objectid = le32_to_cpu (ih->ih_key.k_objectid);
if (mark_objectid_really_used (proper_id_map (fs), objectid)) {
stat_shared_objectid_found (fs);
mark_objectid_really_used (shared_id_map (fs), objectid);
}
#endif
zero_nlink (ih, B_I_PITEM (bh, ih));
}
/* this just marks blocks pointed by an indirect item as used in the
new bitmap */
static void indirect_in_tree (struct buffer_head * bh,
struct item_head * ih)
{
int i;
__u32 * unp;
unsigned long unfm_ptr;
unp = (__u32 *)B_I_PITEM (bh, ih);
for (i = 0; i < I_UNFM_NUM (ih); i ++) {
unfm_ptr = le32_to_cpu (unp[i]);
if (unfm_ptr == 0)
continue;
if (still_bad_unfm_ptr_1 (unfm_ptr))
reiserfs_panic ("mark_unformatted_used: (%lu: %k) "
"still has bad pointer %lu",
bh->b_blocknr, &ih->ih_key, unfm_ptr);
mark_block_used (unfm_ptr);
}
}
static void leaf_is_in_tree_now (struct buffer_head * bh)
{
item_action_t actions[] = {stat_data_in_tree, indirect_in_tree, 0, 0};
mark_block_used ((bh)->b_blocknr);
for_every_item (bh, mark_item_unreachable, actions);
stats(fs)->inserted_leaves ++;
mark_buffer_dirty (bh);
}
static void insert_pointer (struct buffer_head * bh, struct path * path)
{
struct item_head * ih;
char * body;
int zeros_number;
int retval;
struct tree_balance tb;
init_tb_struct (&tb, fs, path, 0x7fff);
/* fix_nodes & do_balance must work for internal nodes only */
ih = 0;
retval = fix_nodes (/*tb.transaction_handle,*/ M_INTERNAL, &tb, ih);
if (retval != CARRY_ON)
die ("insert_pointer: fix_nodes failed with retval == %d", retval);
/* child_pos: we insert after position child_pos: this feature of the insert_child */
/* there is special case: we insert pointer after
(-1)-st key (before 0-th key) in the parent */
if (PATH_LAST_POSITION (path) == 0 && path->pos_in_item == 0)
PATH_H_B_ITEM_ORDER (path, 0) = -1;
else {
if (PATH_H_PPARENT (path, 0) == 0)
PATH_H_B_ITEM_ORDER (path, 0) = 0;
/* PATH_H_B_ITEM_ORDER (path, 0) = PATH_H_PPARENT (path, 0) ? PATH_H_B_ITEM_ORDER (path, 0) : 0;*/
}
ih = 0;
body = (char *)bh;
//memmode = 0;
zeros_number = 0;
do_balance (&tb, ih, body, M_INTERNAL, zeros_number);
leaf_is_in_tree_now (bh);
}
/* return 1 if left and right can be joined. 0 otherwise */
int balance_condition_fails (struct buffer_head * left, struct buffer_head * right)
{
if (B_FREE_SPACE (left) >= B_CHILD_SIZE (right) -
(are_items_mergeable (B_N_PITEM_HEAD (left, B_NR_ITEMS (left) - 1), B_N_PITEM_HEAD (right, 0), left->b_size) ? IH_SIZE : 0))
return 1;
return 0;
}
/* return 1 if new can be joined with last node on the path or with
its right neighbor, 0 otherwise */
int balance_condition_2_fails (struct buffer_head * new, struct path * path)
{
struct buffer_head * bh;
struct key * right_dkey;
int pos, used_space;
bh = PATH_PLAST_BUFFER (path);
if (balance_condition_fails (bh, new))
/* new node can be joined with last buffer on the path */
return 1;
/* new node can not be joined with its left neighbor */
right_dkey = uget_rkey (path);
if (right_dkey == 0)
/* there is no right neighbor */
return 0;
pos = PATH_H_POSITION (path, 1);
if (pos == B_NR_ITEMS (bh = PATH_H_PBUFFER (path, 1))) {
/* we have to read parent of right neighbor. For simplicity we
call search_by_key, which will read right neighbor as well */
INITIALIZE_PATH(path_to_right_neighbor);
if (usearch_by_key (fs, right_dkey, &path_to_right_neighbor) != ITEM_FOUND)
die ("get_right_neighbor_free_space: invalid right delimiting key");
used_space = B_CHILD_SIZE (PATH_PLAST_BUFFER (&path_to_right_neighbor));
pathrelse (&path_to_right_neighbor);
}
else
used_space = B_N_CHILD (bh, pos + 1)->dc_size;
if (B_FREE_SPACE (new) >= used_space -
(are_items_mergeable (B_N_PITEM_HEAD (new, B_NR_ITEMS (new) - 1), (struct item_head *)right_dkey, new->b_size) ? IH_SIZE : 0))
return 1;
return 0;
}
static void get_max_buffer_key (struct buffer_head * bh, struct key * key)
{
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, B_NR_ITEMS (bh) - 1);
copy_key (key, &(ih->ih_key));
if (is_direntry_key (key)) {
/* copy 3-rd and 4-th key components of the last entry */
//set_le_key_k_offset (ih_version(ih), key, B_I_DEH (bh, ih)[I_ENTRY_COUNT (ih) - 1].deh_offset);
//set_le_key_k_type (ih_version(ih), key, TYPE_DIRENTRY);
set_offset (KEY_FORMAT_1, key,
le32_to_cpu (B_I_DEH (bh, ih)[ih_entry_count (ih) - 1].deh_offset));
} else if (!is_stat_data_key (key))
/* get key of the last byte, which is contained in the item */
set_offset (key_format (key), key, get_offset (key) + get_bytes_number (ih, bh->b_size) - 1);
//set_le_key_k_offset(ih_version(ih), key,
// le_key_k_offset(ih_version(ih), key) + get_bytes_number (bh, ih, 0, CHECK_FREE_BYTES) - 1 );
}
static int tree_is_empty (void)
{
return (SB_ROOT_BLOCK (fs) == ~0) ? 1 : 0;
}
static void make_single_leaf_tree (struct buffer_head * bh)
{
/* tree is empty, make tree root */
set_root_block (fs->s_rs, bh->b_blocknr);
set_tree_height (fs->s_rs, 2);
mark_buffer_dirty (fs->s_sbh);
leaf_is_in_tree_now (bh);
}
/* inserts pointer to leaf into tree if possible. If not, marks node as
uninsertable in special bitmap */
static void try_to_insert_pointer_to_leaf (struct buffer_head * new_bh)
{
INITIALIZE_PATH (path);
struct buffer_head * bh; /* last path buffer */
struct key * first_bh_key, last_bh_key; /* first and last keys of new buffer */
struct key last_path_buffer_last_key, * right_dkey;
int ret_value;
if (tree_is_empty () == 1) {
make_single_leaf_tree (new_bh);
return;
}
first_bh_key = B_N_PKEY (new_bh, 0);
/* try to find place in the tree for the first key of the coming node */
ret_value = usearch_by_key (fs, first_bh_key, &path);
if (ret_value == ITEM_FOUND)
goto cannot_insert;
/* get max key in the new node */
get_max_buffer_key (new_bh, &last_bh_key);
bh = PATH_PLAST_BUFFER (&path);
if (comp_keys (B_N_PKEY (bh, 0), &last_bh_key) == 1/* first is greater*/) {
/* new buffer falls before the leftmost leaf */
if (balance_condition_fails (new_bh, bh))
goto cannot_insert;
if (uget_lkey (&path) != 0 || PATH_LAST_POSITION (&path) != 0)
die ("try_to_insert_pointer_to_leaf: bad search result");
path.pos_in_item = 0;
goto insert;
}
/* get max key of buffer, that is in tree */
get_max_buffer_key (bh, &last_path_buffer_last_key);
if (comp_keys (&last_path_buffer_last_key, first_bh_key) != -1/* second is greater */)
/* first key of new buffer falls in the middle of node that is in tree */
goto cannot_insert;
right_dkey = uget_rkey (&path);
if (right_dkey && comp_keys (right_dkey, &last_bh_key) != 1 /* first is greater */)
goto cannot_insert;
if (balance_condition_2_fails (new_bh, &path))
goto cannot_insert;
insert:
insert_pointer (new_bh, &path);
goto out;
cannot_insert:
/* statistic */
stats (fs)->uninsertable_leaves ++;
mark_block_uninsertable (new_bh->b_blocknr);
out:
pathrelse (&path);
return;
}
/* everything should be correct already in the leaf but contents of indirect
items. So we only
1. zero slots pointing to a leaf
2. zero pointers to blocks which are pointed already
3. what we should do with directory entries hashed by another hash?
they are deleted for now
*/
static void pass1_correct_leaf (reiserfs_filsys_t s,
struct buffer_head * bh)
{
int i, j;
struct item_head * ih;
__u32 * ind_item;
unsigned long unfm_ptr;
int dirty = 0;
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
if (is_direntry_ih (ih)) {
struct reiserfs_de_head * deh;
char * name;
int name_len;
int hash_code;
deh = B_I_DEH (bh, ih);
for (j = 0; j < ih_entry_count (ih); j ++) {
name = name_in_entry (deh + j, j);
name_len = name_length (ih, deh + j, j);
if ((j == 0 && is_dot (name, name_len)) ||
(j == 1 && is_dot_dot (name, name_len))) {
continue;
}
hash_code = find_hash_in_use (name, name_len,
GET_HASH_VALUE (deh_offset (deh + j)),
rs_hash (fs->s_rs));
if (hash_code != rs_hash (fs->s_rs)) {
fsck_log ("pass1: block %lu, %H, entry \"%.*s\" "
"hashed with %s whereas proper hash is %s\n",
bh->b_blocknr, ih, name_len, name,
code2name (hash_code), code2name (rs_hash (fs->s_rs)));
if (ih_entry_count (ih) == 1) {
delete_item (fs, bh, i);
i --;
ih --;
break;
} else {
cut_entry (fs, bh, i, j, 1);
j --;
deh = B_I_DEH (bh, ih);
}
}
}
continue;
}
if (!is_indirect_ih (ih))
continue;
/* correct indirect items */
ind_item = (__u32 *)B_I_PITEM (bh, ih);
for (j = 0; j < I_UNFM_NUM (ih); j ++, ind_item ++) {
unfm_ptr = le32_to_cpu (*ind_item);
if (!unfm_ptr)
continue;
/* this corruption of indirect item had to be fixed in pass0 */
if (not_data_block (s, unfm_ptr) || unfm_ptr >= SB_BLOCK_COUNT (s))
/*!was_block_used (unfm_ptr))*/
reiserfs_panic ("pass1_correct_leaf: (%lu: %k), %d-th slot is not fixed",
bh->b_blocknr, &ih->ih_key, j);
/* 1. zero slots pointing to a leaf */
if (is_used_leaf (unfm_ptr)) {
dirty ++;
*ind_item = 0;
stats(fs)->wrong_pointers ++;
continue;
}
/* 2. zero pointers to blocks which are pointed already */
if (is_bad_unformatted (unfm_ptr)) {
/* this unformatted pointed more than once. Did we see it already? */
if (!is_bad_unfm_in_tree_once (unfm_ptr))
/* keep first reference to it and mark about that in
special bitmap */
mark_bad_unfm_in_tree_once (unfm_ptr);
else {
/* Yes, we have seen this pointer already, zero other pointers to it */
dirty ++;
*ind_item = 0;
stats(fs)->wrong_pointers ++;
continue;
}
}
}
}
if (dirty)
mark_buffer_dirty (bh);
}
/*######### has to die ##########*/
/* append item to end of list. Set head if it is 0. For indirect item
set wrong unformatted node pointers to 0 */
void save_item (struct si ** head, struct buffer_head * bh, struct item_head * ih, char * item)
{
struct si * si, * cur;
if (is_bad_item (bh, ih, item/*, fs->s_blocksize, fs->s_dev*/)) {
return;
}
if (is_indirect_ih (ih)) {
fsck_progress ("save_item: %H (should not happen)\n", ih);
}
stats(fs)->saved_on_pass1 ++;
si = getmem (sizeof (*si));
si->si_dnm_data = getmem (ih_item_len(ih));
/*si->si_blocknr = blocknr;*/
memcpy (&(si->si_ih), ih, IH_SIZE);
memcpy (si->si_dnm_data, item, ih_item_len(ih));
// changed by XB
si->last_known = NULL;
if (*head == 0)
*head = si;
else {
cur = *head;
// changed by XB
// while (cur->si_next)
// cur = cur->si_next;
{
int count = 0;
int speedcount = 0;
while (cur->si_next) {
if (cur->last_known!=NULL) {
cur = cur->last_known; // speed up to the end if the chain
speedcount++;
} else {
cur = cur->si_next;
count++;
}
}
if ((*head)!=cur) // no self referencing loop please
(*head)->last_known = cur;
}
cur->si_next = si;
}
return;
}
static void save_items (struct si ** head, struct buffer_head * bh)
{
int i;
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
save_item (head, bh, ih, B_I_PITEM (bh, ih));
}
}
struct si * remove_saved_item (struct si * si)
{
struct si * tmp = si->si_next;
freemem (si->si_dnm_data);
freemem (si);
return tmp;
}
/* insert_item_separately */
static void put_saved_items_into_tree_1 (struct si * si)
{
while (si) {
insert_item_separately (&(si->si_ih), si->si_dnm_data,
0/*was not in tree*/);
si = remove_saved_item (si);
}
}
/* reads the device by set of 8 blocks, takes leaves and tries to
insert them into tree */
void pass_1_pass_2_build_the_tree (void)
{
struct buffer_head * bh;
int i;
int what_node;
unsigned long done = 0, total;
struct si * saved_items = 0;
if (fsck_log_file (fs) != stderr)
fsck_log ("####### Pass 1 #######\n");
bad_unfm_in_tree_once_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
/* on pass0 we have found that amount of leaves */
total = how_many_leaves_were_there ();
fsck_progress ("\nPass1:\n");
/* read all leaves found on the pass 0 */
for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) {
if (!is_used_leaf (i))
continue;
print_how_far (&done, total, 1, fsck_quiet (fs));
/* at least one of nr_to_read blocks is to be checked */
bh = bread (fs->s_dev, i, fs->s_blocksize);
if (!bh) {
/* we were reading one block at time, and failed, so mark
block bad */
fsck_progress ("pass1: reading block %lu failed\n", i);
continue;
}
what_node = who_is_this (bh->b_data, fs->s_blocksize);
if ( what_node != THE_LEAF ) {
fsck_progress ("build_the_tree: nothing but leaves are expected. "
"Block %lu - %s\n", i,
(what_node == THE_INTERNAL) ? "internal" : "??");
brelse (bh);
continue;
}
if (is_block_used (i))
/* block is in new tree already */
die ("build_the_tree: leaf (%lu) is in tree already\n", i);
/* fprintf (block_list, "leaf %d\n", i + j);*/
stats(fs)->analyzed ++;
/* the leaf may still contain indirect items with wrong
slots. Fix that */
pass1_correct_leaf (fs, bh);
if (node_item_number (bh) == 0) {
/* all items were deleted on pass 0 or pass 1 */
mark_buffer_clean (bh);
brelse (bh);
continue;
}
if (is_leaf_bad (bh)) {
/* FIXME: will die */
fsck_log ("pass1: (is_leaf_bad) bad leaf (%lu)\n", bh->b_blocknr);
/* Save good items only to put them into tree at the
end of this pass */
save_items (&saved_items, bh);
brelse (bh);
continue;
}
try_to_insert_pointer_to_leaf (bh);
brelse (bh);
}
#if 0
/* read all leaves found on the pass 0 */
for (i = 0; i < SB_BLOCK_COUNT (fs); i += nr_to_read) {
to_scan = how_many_to_scan (fs, i, nr_to_read);
if (to_scan) {
print_how_far (&done, total, to_scan, fsck_quiet (fs));
/* at least one of nr_to_read blocks is to be checked */
bbh = bread (fs->s_dev, i / nr_to_read, fs->s_blocksize * nr_to_read);
if (bbh) {
for (j = 0; j < nr_to_read; j ++) {
if (!is_used_leaf (i + j))
continue;
data = bbh->b_data + j * fs->s_blocksize;
what_node = who_is_this (data, fs->s_blocksize);
if ( what_node != THE_LEAF ) {
fsck_progress ("build_the_tree: nothing but leaves are expected. "
"Block %lu - %s\n", i + j,
(what_node == THE_INTERNAL) ? "internal" : "??");
continue;
}
if (is_block_used (i + j))
/* block is in new tree already */
die ("build_the_tree: leaf (%lu) is in tree already\n",
i + j);
/* fprintf (block_list, "leaf %d\n", i + j);*/
bh = make_buffer (fs->s_dev, i + j, fs->s_blocksize, data);
stats(fs)->analyzed ++;
/* the leaf may still contain indirect items with wrong
slots. Fix that */
pass1_correct_leaf (fs, bh);
if (node_item_number (bh) == 0) {
/* all items were deleted on pass 0 or pass 1 */
mark_buffer_clean (bh);
brelse (bh);
continue;
}
if (is_leaf_bad (bh)) {
/* FIXME: will die */
fsck_log ("pass1: (is_leaf_bad) bad leaf (%lu)\n", bh->b_blocknr);
/* Save good items only to put them into tree at the
end of this pass */
save_items (&saved_items, bh);
brelse (bh);
continue;
}
try_to_insert_pointer_to_leaf (bh);
brelse (bh);
}
bforget (bbh);
} else {
done -= to_scan;
/* bread failed */
if (nr_to_read != 1) {
/* we tryied to read bunch of blocks. Try to read them by one */
nr_to_read = 1;
i --;
continue;
} else {
/* we were reading one block at time, and failed, so mark
block bad */
fsck_progress ("pass0: block %lu is bad, marked used\n", i);
}
}
}
if (nr_to_read == 1 && ((i + 1) % NR_TO_READ) == 0) {
/* we have read NR_TO_READ blocks one at time, switch back to
reading NR_TO_READ blocks at time */
i -= (NR_TO_READ - 1);
nr_to_read = NR_TO_READ;
}
}
#endif
fsck_progress ("\n");
/* Pass 1a (this should die) */
/* put saved items into tree. These items were in leaves, those could not
be inserted into tree because some indirect items point to those
leaves. Rather than lookup for corresponding unfm pointers in the tree,
we save items of those leaves and put them into tree separately */
if (how_many_items_were_saved ()) {
fsck_progress ("There were %lu saved items\nPass 1a - ",
how_many_items_were_saved ());
fflush (stdout);
put_saved_items_into_tree_1 (saved_items);
}
stage_report (1, fs);
/* end of pass 1 */
if (SB_ROOT_BLOCK(fs) == -1)
die ("\n\nNo reiserfs metadata found");
/* pass 2 */
pass_2_take_bad_blocks_put_into_tree ();
flush_buffers ();
stage_report (2, fs);
fsck_progress ("Tree is built. Checking it - "); fflush (stdout);
reiserfsck_check_pass1 ();
fsck_progress ("done\n"); fflush (stdout);
reiserfs_delete_bitmap (bad_unfm_in_tree_once_bitmap);
}
#if 0
/* pass the S+ tree of filesystem */
void recover_internal_tree (struct super_block * s)
{
check_internal_structure(s);
build_the_tree();
}
#endif
void rebuild_sb (reiserfs_filsys_t fs)
{
int version;
struct buffer_head * bh;
struct reiserfs_super_block * rs;
__u32 blocks;
if (no_reiserfs_found (fs)) {
char * answer = 0;
size_t n = 0;
printf("\nwhat is version of ReiserFS you use[1-4]\n"
"\t(1) 3.6.x\n"
"\t(2) >=3.5.9\n"
"\t(3) < 3.5.9 converted to new format\n"
"\t(4) < 3.5.9\n"
"\t(X) exit\n");
getline (&answer, &n, stdin);
version = atoi (answer);
if (version < 1 || version > 4)
die ("rebuild_sb: wrong version");
fs->s_blocksize = 4096;
switch(version){
case 1:
case 2:
bh = getblk (fs->s_dev, (REISERFS_DISK_OFFSET_IN_BYTES / fs->s_blocksize),
fs->s_blocksize);
break;
case 3:
case 4:
bh = getblk (fs->s_dev, (2), fs->s_blocksize);
break;
default:
exit(0);
}
if (!bh)
die ("rebuild_sb: can't bread");
rs = (struct reiserfs_super_block *)bh->b_data;
fs->s_rs = rs;
}
else
{
/* reiserfs super block is found */
version = check_sb(fs);
if (!user_confirmed ("\nDo you want to remake your super block\n"
"(say no if you use resizer)[Yes/no]: ", "Yes\n"))
return;
rs = fs->s_rs;
bh = fs->s_sbh;
}
// set block number on the device and number of bitmap blocks needed to
// address all blocks
blocks = (count_blocks ("", fs->s_blocksize, fs->s_dev) / 8) * 8;
set_block_count (rs, blocks);
//rs->s_block_count = cpu_to_le32(blocks);
set_bmap_nr (rs, (blocks + (fs->s_blocksize * 8 - 1)) / (fs->s_blocksize * 8));
set_journal_size(rs, JOURNAL_BLOCK_COUNT);
//rs->s_bmap_nr = cpu_to_le16( blocks / (g_sb.s_blocksize * 8) +
// ((blocks % (g_sb.s_blocksize * 8)) ? 1 : 0) );
switch (version){
case 1:
// super block v2 at 64k offset
set_blocksize (rs, fs->s_blocksize);
strncpy (rs->s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING,
strlen(REISER2FS_SUPER_MAGIC_STRING));
set_journal_start (rs, get_journal_start_must (fs->s_blocksize));
set_version (rs, REISERFS_VERSION_2);
set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2);
break;
case 2:
// super block v1 at 64k offset
set_blocksize (rs, fs->s_blocksize);
strncpy (rs->s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING,
strlen(REISERFS_SUPER_MAGIC_STRING));
set_journal_start (rs, get_journal_start_must (fs->s_blocksize));
set_version (rs, REISERFS_VERSION_1);
set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2);
break;
case 3:
// super block v2 at 8k offset
set_blocksize (rs, fs->s_blocksize);
strncpy (rs->s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING,
strlen(REISER2FS_SUPER_MAGIC_STRING));
set_journal_start (rs, get_journal_old_start_must (rs));
set_version (rs, REISERFS_VERSION_2);
set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2);
break;
case 4:
// super block v1 at 8k offset
set_blocksize (rs, fs->s_blocksize);
strncpy (rs->s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING,
strlen(REISERFS_SUPER_MAGIC_STRING));
set_journal_start (rs, get_journal_old_start_must (rs));
set_version (rs, REISERFS_VERSION_1);
set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2);
break;
}
print_block (stderr, fs, bh);
if (user_confirmed ("Is this ok ? [N/Yes]: ", "Yes\n")) {
mark_buffer_uptodate (bh, 1);
mark_buffer_dirty (bh);
bwrite (bh);
fsck_progress ("\nDo not forget to run reiserfsck --rebuild-tree\n\n");
} else
fsck_progress ("Super block was not written\n");
brelse (bh);
}
/*
check_sb and rebuild-sb don't touch these fields:
__u32 s_journal_dev;
__u32 s_journal_trans_max ;
__u32 s_journal_block_count ;
__u32 s_journal_max_batch ;
__u32 s_journal_max_commit_age ;
__u32 s_journal_max_trans_age ;
others are checked and set in either rebuild_sb or rebuild-tree
*/