Imported reiserfsprogs-3.6.20
This commit is contained in:
1 parent
0ed773997f
commit
dac518d099
189 files changed
+43353
-29787
No files matched your search
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
||||
* reiserfsprogs/README
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "fsck.h"
|
||||
#include "misc/unaligned.h"
|
||||
#include "misc/malloc.h"
|
||||
#include "util/device.h"
|
||||
#include "util/misc.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
reiserfs_bitmap_t * bad_unfm_in_tree_once_bitmap;
|
||||
#define is_bad_unfm_in_tree_once(block) \
|
||||
reiserfs_bitmap_test_bit(bad_unfm_in_tree_once_bitmap, block)
|
||||
#define mark_bad_unfm_in_tree_once(block) \
|
||||
reiserfs_bitmap_set_bit(bad_unfm_in_tree_once_bitmap, block)
|
||||
|
||||
static void stat_data_in_tree (reiserfs_bh_t *bh,
|
||||
reiserfs_ih_t * ih)
|
||||
{
|
||||
#if 0
|
||||
__u32 objectid;
|
||||
|
||||
objectid = reiserfs_key_get_oid (&ih->ih_key);
|
||||
|
||||
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, reiserfs_item_by_ih (bh, ih));
|
||||
}
|
||||
|
||||
static char *still_bad_unfm_ptr_to_string (int val) {
|
||||
switch (val) {
|
||||
case 1:
|
||||
return "a leaf";
|
||||
case 2:
|
||||
return "shared between a few files";
|
||||
case 3:
|
||||
return "not a data block";
|
||||
case 4:
|
||||
return "not used in on-disk bitmap";
|
||||
case 5:
|
||||
return "out of partition boundary";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static int still_bad_unfm_ptr (unsigned long block) {
|
||||
if (!block)
|
||||
return 0;
|
||||
|
||||
if (pass0_block_isleaf (block))
|
||||
return 1;
|
||||
|
||||
if (pass0_block_isbad_unfm (block) &&
|
||||
!is_bad_unfm_in_tree_once (block))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (reiserfs_fs_block(fs, block) != BT_UNKNOWN)
|
||||
return 3;
|
||||
|
||||
/* if (!was_block_used (block))
|
||||
return 4; */
|
||||
|
||||
if (block >= reiserfs_sb_get_blocks (fs->fs_ondisk_sb))
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* this just marks blocks pointed by an extent item as used in the
|
||||
new bitmap */
|
||||
static void extent_in_tree (reiserfs_bh_t * bh,
|
||||
reiserfs_ih_t * ih)
|
||||
{
|
||||
unsigned int i;
|
||||
__u32 * unp;
|
||||
__u32 unfm_ptr;
|
||||
int ret;
|
||||
|
||||
unp = (__u32 *)reiserfs_item_by_ih (bh, ih);
|
||||
|
||||
for (i = 0; i < reiserfs_ext_count (ih); i ++) {
|
||||
unfm_ptr = d32_get (unp, i);
|
||||
if (unfm_ptr == 0)
|
||||
continue;
|
||||
if ((ret = still_bad_unfm_ptr (unfm_ptr)))
|
||||
reiserfs_panic ("%s: block %lu: The file %k points to the "
|
||||
"block (%u) which is %s", __FUNCTION__,
|
||||
bh->b_blocknr, &ih->ih_key, unfm_ptr,
|
||||
still_bad_unfm_ptr_to_string(ret));
|
||||
|
||||
mark_block_used (unfm_ptr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void cb_mkunreach(reiserfs_ih_t *ih) {
|
||||
fsck_item_mkunreach(ih);
|
||||
}
|
||||
|
||||
static void leaf_is_in_tree_now (reiserfs_bh_t * bh) {
|
||||
item_func_t actions[] = {stat_data_in_tree, extent_in_tree, 0, 0};
|
||||
|
||||
mark_block_used ((bh)->b_blocknr, 1);
|
||||
|
||||
reiserfs_leaf_traverse (bh, cb_mkunreach, actions);
|
||||
|
||||
pass_1_stat (fs)->inserted_leaves ++;
|
||||
|
||||
reiserfs_buffer_mkdirty (bh);
|
||||
}
|
||||
|
||||
|
||||
static void insert_pointer (reiserfs_bh_t * bh, reiserfs_path_t * path) {
|
||||
reiserfs_ih_t * ih;
|
||||
char * body;
|
||||
int retval;
|
||||
reiserfs_tb_t tb;
|
||||
|
||||
reiserfs_tb_init (&tb, fs, path, 0x7fff);
|
||||
|
||||
/* reiserfs_fix_nodes & reiserfs_tb_balance must work
|
||||
for internal nodes only */
|
||||
ih = 0;
|
||||
|
||||
retval = reiserfs_fix_nodes (M_INTERNAL, &tb, ih);
|
||||
if (retval != CARRY_ON)
|
||||
misc_die ("insert_pointer: reiserfs_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 (REISERFS_PATH_LEAF_POS (path) == 0 && path->pos_in_item == 0)
|
||||
REISERFS_PATH_UPPARENT_POS (path, 0) = -1;
|
||||
else if (REISERFS_PATH_UPPARENT (path, 0) == 0) {
|
||||
REISERFS_PATH_UPPARENT_POS (path, 0) = 0;
|
||||
}
|
||||
|
||||
ih = 0;
|
||||
body = (char *)bh;
|
||||
|
||||
reiserfs_tb_balance (&tb, ih, body, M_INTERNAL, 0);
|
||||
leaf_is_in_tree_now (bh);
|
||||
}
|
||||
|
||||
|
||||
/* return 1 if new can be joined with last node on the path or with
|
||||
its right neighbor, 0 otherwise */
|
||||
static int balance_condition_2_fails (reiserfs_bh_t * new,
|
||||
reiserfs_path_t * path)
|
||||
{
|
||||
const reiserfs_key_t *right_dkey;
|
||||
int pos, used_space;
|
||||
reiserfs_bh_t *bh;
|
||||
reiserfs_ih_t *ih;
|
||||
|
||||
bh = REISERFS_PATH_LEAF (path);
|
||||
|
||||
if (reiserfs_tree_node_mergeable (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 = reiserfs_tree_rkey (path, fs);
|
||||
if (!reiserfs_key_comp (right_dkey, &MAX_KEY))
|
||||
/* there is no right neighbor */
|
||||
return 0;
|
||||
|
||||
pos = REISERFS_PATH_UPPOS (path, 1);
|
||||
if (pos == reiserfs_node_items (bh = REISERFS_PATH_UPBUFFER (path, 1))) {
|
||||
/* we have to read parent of right neighbor. For simplicity we
|
||||
call search_item, which will read right neighbor as well */
|
||||
REISERFS_PATH_INIT(path_to_right_neighbor);
|
||||
|
||||
if (reiserfs_tree_search_item (fs, right_dkey, &path_to_right_neighbor)
|
||||
!= ITEM_FOUND)
|
||||
{
|
||||
reiserfs_panic("%s: block %lu, pointer %d: The left delimiting "
|
||||
"key %k of the block (%lu) is wrong, the item "
|
||||
"cannot be found", __FUNCTION__,
|
||||
REISERFS_PATH_UPBUFFER(path, 1)->b_blocknr,
|
||||
pos, right_dkey,
|
||||
reiserfs_dc_get_nr(reiserfs_int_at (bh, pos + 1)));
|
||||
}
|
||||
|
||||
used_space = reiserfs_node_used
|
||||
(REISERFS_PATH_LEAF(&path_to_right_neighbor));
|
||||
|
||||
reiserfs_tree_pathrelse (&path_to_right_neighbor);
|
||||
} else {
|
||||
used_space = reiserfs_dc_get_size (reiserfs_int_at (bh, pos + 1));
|
||||
}
|
||||
|
||||
ih = reiserfs_ih_at (new, reiserfs_node_items (new) - 1);
|
||||
if (reiserfs_node_free (new) >= used_space -
|
||||
(reiserfs_leaf_mergeable (ih, (reiserfs_ih_t *)right_dkey, new->b_size)
|
||||
? REISERFS_IH_SIZE : 0))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void get_max_buffer_key (reiserfs_bh_t * bh,
|
||||
reiserfs_key_t * key)
|
||||
{
|
||||
reiserfs_ih_t * ih;
|
||||
|
||||
ih = reiserfs_ih_at (bh, reiserfs_node_items (bh) - 1);
|
||||
reiserfs_key_copy (key, &(ih->ih_key));
|
||||
|
||||
if (reiserfs_key_dir (key)) {
|
||||
/* copy deh_offset 3-rd and 4-th key components of the last entry */
|
||||
reiserfs_key_set_off (KEY_FORMAT_1, key,
|
||||
reiserfs_deh_get_off (reiserfs_deh (bh, ih) +
|
||||
reiserfs_ih_get_entries (ih) - 1));
|
||||
|
||||
} else if (!reiserfs_key_stat (key))
|
||||
/* get key of the last byte, which is contained in the item */
|
||||
reiserfs_key_set_off (reiserfs_key_format (key), key,
|
||||
reiserfs_key_get_off (key) +
|
||||
reiserfs_leaf_ibytes (ih, bh->b_size) - 1);
|
||||
}
|
||||
|
||||
static int tree_is_empty (void)
|
||||
{
|
||||
return (reiserfs_sb_get_root (fs->fs_ondisk_sb) == ~(__u32)0 ||
|
||||
reiserfs_sb_get_root (fs->fs_ondisk_sb) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static void make_single_leaf_tree (reiserfs_bh_t * bh) {
|
||||
/* tree is empty, make tree root */
|
||||
reiserfs_sb_set_root (fs->fs_ondisk_sb, bh->b_blocknr);
|
||||
reiserfs_sb_set_height (fs->fs_ondisk_sb, 2);
|
||||
reiserfs_buffer_mkdirty (fs->fs_super_bh);
|
||||
leaf_is_in_tree_now (bh);
|
||||
}
|
||||
|
||||
|
||||
/* inserts pointer to leaf into tree if possible. If not, marks node as
|
||||
uninsertable in special bitmap */
|
||||
static int try_to_insert_pointer_to_leaf (reiserfs_bh_t * new_bh) {
|
||||
/* first and last keys of new buffer */
|
||||
reiserfs_key_t * first_bh_key, last_bh_key;
|
||||
reiserfs_key_t last_path_buffer_last_key;
|
||||
const reiserfs_key_t *dkey;
|
||||
REISERFS_PATH_INIT (path);
|
||||
reiserfs_bh_t * bh; /* last path buffer */
|
||||
int ret_value;
|
||||
|
||||
if (tree_is_empty () == 1) {
|
||||
make_single_leaf_tree (new_bh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
first_bh_key = reiserfs_ih_key_at (new_bh, 0);
|
||||
|
||||
/* try to find place in the tree for the first key of the coming node */
|
||||
ret_value = reiserfs_tree_search_item (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 = REISERFS_PATH_LEAF (&path);
|
||||
if (reiserfs_key_comp (reiserfs_ih_key_at (bh, 0),
|
||||
&last_bh_key) == 1/* first is greater*/)
|
||||
{
|
||||
/* new buffer falls before the leftmost leaf */
|
||||
if (reiserfs_tree_node_mergeable (new_bh, bh))
|
||||
goto cannot_insert;
|
||||
|
||||
dkey = reiserfs_tree_lkey (&path, fs);
|
||||
if ((dkey && reiserfs_key_comp (dkey, &MIN_KEY) != 0) ||
|
||||
REISERFS_PATH_LEAF_POS (&path) != 0)
|
||||
{
|
||||
misc_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 (reiserfs_key_comp (&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;
|
||||
}
|
||||
|
||||
dkey = reiserfs_tree_rkey (&path, fs);
|
||||
if (dkey && reiserfs_key_comp (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);
|
||||
reiserfs_tree_pathrelse (&path);
|
||||
return 0;
|
||||
|
||||
cannot_insert:
|
||||
reiserfs_tree_pathrelse (&path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* everything should be correct already in the leaf but contents of extent
|
||||
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 * fs,
|
||||
reiserfs_bh_t * bh)
|
||||
{
|
||||
unsigned int i, j;
|
||||
reiserfs_ih_t * ih;
|
||||
__u32 * ind_item;
|
||||
__u32 unfm_ptr;
|
||||
int dirty = 0;
|
||||
|
||||
|
||||
ih = reiserfs_ih_at (bh, 0);
|
||||
for (i = 0; i < reiserfs_node_items (bh); i ++, ih ++) {
|
||||
if (reiserfs_ih_dir (ih)) {
|
||||
reiserfs_deh_t * deh;
|
||||
__u32 offset;
|
||||
char * name;
|
||||
int name_len;
|
||||
unsigned int hash_code;
|
||||
|
||||
deh = reiserfs_deh (bh, ih);
|
||||
offset = 0;
|
||||
for (j = 0; j < reiserfs_ih_get_entries (ih); j ++) {
|
||||
name = reiserfs_deh_name (deh + j, j);
|
||||
name_len = reiserfs_direntry_name_len (ih, deh + j, j);
|
||||
|
||||
if ((j == 0 && is_dot (name, name_len)) ||
|
||||
(j == 1 && is_dot_dot (name, name_len))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hash_code = reiserfs_hash_find (
|
||||
name, name_len, reiserfs_deh_get_off (deh + j),
|
||||
reiserfs_sb_get_hash (fs->fs_ondisk_sb));
|
||||
|
||||
if (hash_code != reiserfs_sb_get_hash (fs->fs_ondisk_sb)) {
|
||||
fsck_log ("pass1: block %lu, item %d, entry %d: The "
|
||||
"entry \"%.*s\" of the %k is hashed with %s "
|
||||
"whereas proper hash is %s", bh->b_blocknr,
|
||||
i, j, name_len, name, &ih->ih_key,
|
||||
reiserfs_hash_name (hash_code),
|
||||
reiserfs_hash_name (
|
||||
reiserfs_sb_get_hash (fs->fs_ondisk_sb)));
|
||||
|
||||
if (reiserfs_ih_get_entries (ih) == 1) {
|
||||
reiserfs_leaf_delete_item (fs, bh, i);
|
||||
fsck_log(" - the only entry - item was deleted\n");
|
||||
i --;
|
||||
ih --;
|
||||
break;
|
||||
} else {
|
||||
reiserfs_leaf_delete_entry (fs, bh, i, j, 1);
|
||||
fsck_log(" - deleted\n");
|
||||
j --;
|
||||
deh = reiserfs_deh (bh, ih);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (j && offset >= reiserfs_deh_get_off (deh + j)) {
|
||||
fsck_log ("pass1: block %lu, item %d, entry %d: The entry "
|
||||
"\"%.*s\" of the %k has hash offset %lu not "
|
||||
"larger smaller than the previous one %lu. The "
|
||||
"entry is deleted.\n", bh->b_blocknr,
|
||||
i, j, name_len, name, &ih->ih_key,
|
||||
reiserfs_deh_get_off(deh + j), offset);
|
||||
reiserfs_leaf_delete_entry (fs, bh, i, j, 1);
|
||||
j --;
|
||||
deh = reiserfs_deh (bh, ih);
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = reiserfs_deh_get_off (deh + j);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!reiserfs_ih_ext (ih))
|
||||
continue;
|
||||
|
||||
/* correct extent items */
|
||||
ind_item = (__u32 *)reiserfs_item_by_ih (bh, ih);
|
||||
|
||||
for (j = 0; j < reiserfs_ext_count (ih); j ++) {
|
||||
unfm_ptr = d32_get (ind_item, j);
|
||||
|
||||
if (!unfm_ptr)
|
||||
continue;
|
||||
|
||||
/* this corruption of extent item had to be fixed in pass0 */
|
||||
if (reiserfs_fs_block(fs, unfm_ptr) != BT_UNKNOWN)
|
||||
/*!was_block_used (unfm_ptr))*/
|
||||
reiserfs_panic ("%s: block %lu, item %d, pointer %d: The "
|
||||
"wrong pointer (%u) in the file %K. Must "
|
||||
"be fixed on pass0.", __FUNCTION__,
|
||||
bh->b_blocknr, i, j, unfm_ptr, &ih->ih_key);
|
||||
|
||||
/* 1. zero slots pointing to a leaf */
|
||||
if (pass0_block_isleaf (unfm_ptr)) {
|
||||
dirty ++;
|
||||
d32_put (ind_item, j, 0);
|
||||
pass_1_stat (fs)->pointed_leaves ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 2. zero pointers to blocks which are pointed already */
|
||||
if (pass0_block_isbad_unfm (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 ++;
|
||||
d32_put (ind_item, j, 0);
|
||||
pass_1_stat (fs)->non_unique_pointers ++;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
pass_1_stat (fs)->correct_pointers ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
reiserfs_buffer_mkdirty (bh);
|
||||
}
|
||||
|
||||
/* fsck starts creating of this bitmap on pass 1. It will then become
|
||||
on-disk bitmap */
|
||||
static void init_new_bitmap (reiserfs_filsys_t * fs)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long block;
|
||||
unsigned long reserved;
|
||||
unsigned long count, bmap_nr;
|
||||
|
||||
count = reiserfs_sb_get_blocks (fs->fs_ondisk_sb);
|
||||
|
||||
fsck_new_bitmap (fs) = reiserfs_bitmap_create(count);
|
||||
|
||||
/* mark_block_used skips 0, set the bit explicitly */
|
||||
reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), 0);
|
||||
|
||||
/* mark other skipped blocks and super block used */
|
||||
for (i = 1; i <= fs->fs_super_bh->b_blocknr; i ++)
|
||||
mark_block_used (i, 1);
|
||||
|
||||
/* mark bitmap blocks as used */
|
||||
block = fs->fs_super_bh->b_blocknr + 1;
|
||||
|
||||
bmap_nr = reiserfs_bmap_nr(count, fs->fs_blocksize);
|
||||
|
||||
for (i = 0; i < bmap_nr; i ++) {
|
||||
mark_block_used (block, 1);
|
||||
if (reiserfs_bitmap_spread (fs)) {
|
||||
block = (block / (fs->fs_blocksize * 8) + 1) *
|
||||
(fs->fs_blocksize * 8);
|
||||
} else {
|
||||
block ++;
|
||||
}
|
||||
}
|
||||
|
||||
reserved = reiserfs_journal_hostsize (fs->fs_ondisk_sb);
|
||||
/* where does journal area (or reserved journal area) start from */
|
||||
|
||||
if (!reiserfs_new_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) &&
|
||||
!reiserfs_old_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize))
|
||||
{
|
||||
misc_die ("init_new_bitmap: Wrong super block location, "
|
||||
"you must run --rebuild-sb.");
|
||||
}
|
||||
|
||||
block = reiserfs_journal_start_must (fs);
|
||||
|
||||
for (i = block; i < reserved + block; i ++)
|
||||
mark_block_used (i, 1);
|
||||
|
||||
|
||||
if (fs->fs_badblocks_bm)
|
||||
for (i = 0; i < count; i ++) {
|
||||
if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) {
|
||||
if (reiserfs_bitmap_test_bit (fsck_new_bitmap (fs), i))
|
||||
reiserfs_panic ("%s: The block pointer to not data area, "
|
||||
"must be fixed on the pass0.\n",
|
||||
__FUNCTION__);
|
||||
|
||||
reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* this makes a map of blocks which can be allocated when fsck will
|
||||
continue */
|
||||
static void find_allocable_blocks (reiserfs_filsys_t * fs) {
|
||||
unsigned long i;
|
||||
|
||||
fsck_progress ("Looking for allocable blocks .. ");
|
||||
|
||||
fsck_allocable_bitmap (fs) = reiserfs_bitmap_create
|
||||
(reiserfs_sb_get_blocks (fs->fs_ondisk_sb));
|
||||
reiserfs_bitmap_fill (fsck_allocable_bitmap (fs));
|
||||
|
||||
/* find how many leaves are not pointed by any extent items */
|
||||
for (i = 0; i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb); i ++) {
|
||||
if (reiserfs_fs_block(fs, i) != BT_UNKNOWN) {
|
||||
/* journal (or reserved for it area), bitmaps, super block and
|
||||
blocks before it */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pass0_block_isgood_unfm (i) && pass0_block_isbad_unfm (i)) {
|
||||
misc_die ("%s: The block (%lu) is marked as good and "
|
||||
"as bad at once.", __FUNCTION__, i);
|
||||
}
|
||||
|
||||
if (pass0_block_isgood_unfm (i) || pass0_block_isbad_unfm (i)) {
|
||||
/* blocks which were pointed once or more then once
|
||||
from extent items - they will not be allocated */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* make allocable not leaves, not bad blocks */
|
||||
if (!pass0_block_isleaf (i))
|
||||
if (!fs->fs_badblocks_bm ||
|
||||
!reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))
|
||||
{
|
||||
/* this is not leaf and it is not pointed by found extent
|
||||
items, so it does not contains anything valuable */
|
||||
make_allocable (i);
|
||||
pass_1_stat (fs)->allocable_blocks ++;
|
||||
}
|
||||
}
|
||||
|
||||
fsck_progress ("finished\n");
|
||||
|
||||
fs->block_allocator = reiserfsck_new_blocknrs;
|
||||
fs->block_deallocator = reiserfsck_free_block;
|
||||
}
|
||||
|
||||
static void fsck_pass1_prep (reiserfs_filsys_t * fs) {
|
||||
/* this will become an on-disk bitmap */
|
||||
init_new_bitmap (fs);
|
||||
|
||||
/* bitmap of leaves which could not be inserted on pass 1.
|
||||
FIXME: no need to have 1 bit per block */
|
||||
fsck_uninsertables (fs) = reiserfs_bitmap_create
|
||||
(reiserfs_sb_get_blocks (fs->fs_ondisk_sb));
|
||||
reiserfs_bitmap_fill (fsck_uninsertables (fs));
|
||||
|
||||
/* find blocks which can be allocated */
|
||||
find_allocable_blocks (fs);
|
||||
|
||||
/* bitmap of bad unformatted nodes which are in the tree already */
|
||||
bad_unfm_in_tree_once_bitmap = reiserfs_bitmap_create
|
||||
(reiserfs_sb_get_blocks (fs->fs_ondisk_sb));
|
||||
|
||||
/* pass 1 does not deal with objectid */
|
||||
}
|
||||
|
||||
static void fsck_pass1_save_result (reiserfs_filsys_t * fs) {
|
||||
FILE * file;
|
||||
int retval;
|
||||
|
||||
if (!(file = util_file_open("temp_fsck_file.deleteme", "w+")))
|
||||
return;
|
||||
|
||||
|
||||
/* to be able to restart with pass 2 we need bitmap of
|
||||
uninsertable blocks and bitmap of alocable blocks */
|
||||
fsck_stage_start_put (file, PASS_1_DONE);
|
||||
reiserfs_bitmap_save (file, fsck_uninsertables (fs));
|
||||
reiserfs_bitmap_save (file, fsck_allocable_bitmap(fs));
|
||||
reiserfs_bitmap_save (file, fsck_new_bitmap(fs));
|
||||
fsck_stage_end_put (file);
|
||||
fclose (file);
|
||||
retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs));
|
||||
if (retval != 0)
|
||||
fsck_progress ("pass 1: Could not rename the temporary file "
|
||||
"temp_fsck_file.deleteme to %s",
|
||||
state_dump_file (fs));
|
||||
|
||||
/* to be able to pack/unpack metadata after pass2 in stage-by-stage mode,
|
||||
save into on-disk bitmap all blocks that are involved.
|
||||
it should not be flushed on disk not in stage-by-stage mode, as if fsck
|
||||
fails on pass1 we get wrong bitmap on the next fsck start */
|
||||
reiserfs_bitmap_flush (fsck_allocable_bitmap(fs), fs);
|
||||
}
|
||||
|
||||
|
||||
void fsck_pass1_load_result (FILE * fp, reiserfs_filsys_t * fs) {
|
||||
fsck_uninsertables (fs) = reiserfs_bitmap_load (fp);
|
||||
fsck_allocable_bitmap (fs) = reiserfs_bitmap_load (fp);
|
||||
fsck_new_bitmap (fs) = reiserfs_bitmap_load(fp);
|
||||
|
||||
fs->block_allocator = reiserfsck_new_blocknrs;
|
||||
fs->block_deallocator = reiserfsck_free_block;
|
||||
|
||||
if (!fsck_new_bitmap (fs) || !fsck_allocable_bitmap (fs) ||
|
||||
!fsck_allocable_bitmap (fs))
|
||||
{
|
||||
fsck_exit ("State dump file seems corrupted. Run without -d");
|
||||
}
|
||||
|
||||
/* we need objectid map on pass 2 to be able to relocate files */
|
||||
proper_id_map (fs) = id_map_init();
|
||||
fetch_objectid_map (proper_id_map (fs), fs);
|
||||
|
||||
fsck_progress ("Pass 1 result loaded. %d blocks used, %d allocable, "
|
||||
"still to be inserted %d\n",
|
||||
reiserfs_bitmap_ones (fsck_new_bitmap (fs)),
|
||||
reiserfs_bitmap_zeros (fsck_allocable_bitmap (fs)),
|
||||
reiserfs_bitmap_zeros (fsck_uninsertables (fs)));
|
||||
}
|
||||
|
||||
|
||||
extern reiserfs_bitmap_t * leaves_bitmap;
|
||||
|
||||
/* reads blocks marked in leaves_bitmap and tries to insert them into
|
||||
tree */
|
||||
static void do_pass_1 (reiserfs_filsys_t * fs)
|
||||
{
|
||||
unsigned long done = 0, total;
|
||||
reiserfs_bh_t * bh;
|
||||
unsigned long i, n;
|
||||
int what_node;
|
||||
|
||||
|
||||
/* on pass0 we have found that amount of leaves */
|
||||
total = reiserfs_bitmap_ones (leaves_bitmap);
|
||||
|
||||
/* read all leaves found on the pass 0 */
|
||||
for (n = 0; n < 2; n++) {
|
||||
for (i = 0; i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb); i ++) {
|
||||
if (!pass0_block_isleaf (i))
|
||||
continue;
|
||||
|
||||
if (n && !fsck_bitmap_isuninsert(i))
|
||||
continue;
|
||||
|
||||
if (!fsck_quiet(fs)) {
|
||||
util_misc_progress (fsck_progress_file (fs),
|
||||
&done, total, 1, 0);
|
||||
}
|
||||
|
||||
/* at least one of nr_to_read blocks is to be checked */
|
||||
bh = reiserfs_buffer_read (fs->fs_dev, i, fs->fs_blocksize);
|
||||
if (!bh) {
|
||||
/* we were reading one block at time, and failed, so mark
|
||||
block bad */
|
||||
fsck_progress ("pass1: Reading of the block %lu failed\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
what_node = reiserfs_node_type (bh);
|
||||
if ( what_node != NT_LEAF ) {
|
||||
fsck_info_checkmem();
|
||||
misc_die ("build_the_tree: Nothing but leaves "
|
||||
"are expected. Block %lu - %s\n",
|
||||
i, reiserfs_node_type_name(what_node));
|
||||
}
|
||||
|
||||
if (is_block_used (i))
|
||||
if (!(reiserfs_journal_block (fs, i) &&
|
||||
fsck_data(fs)->rebuild.use_journal_area))
|
||||
{
|
||||
/* block is in new tree already */
|
||||
misc_die ("build_the_tree: The leaf (%lu) "
|
||||
"is in the tree already\n", i);
|
||||
}
|
||||
|
||||
/* fprintf (block_list, "leaf %d\n", i + j);*/
|
||||
if (n == 0) {
|
||||
pass_1_stat (fs)->leaves ++;
|
||||
|
||||
/* the leaf may still contain extent items with wrong
|
||||
slots. Fix that */
|
||||
pass1_correct_leaf (fs, bh);
|
||||
|
||||
if (reiserfs_nh_get_items (NODE_HEAD (bh)) == 0) {
|
||||
/* all items were deleted on pass 0 or pass 1 */
|
||||
reiserfs_buffer_mkclean (bh);
|
||||
reiserfs_buffer_close (bh);
|
||||
make_allocable (i);
|
||||
pass_1_stat (fs)->allocable_blocks ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fsck_leaf_check(bh)) {
|
||||
/* FIXME: will die */
|
||||
fsck_log ("%s: WARNING: The leaf (%lu) is formatted "
|
||||
"badly. Will be handled on the the pass2.\n",
|
||||
__FUNCTION__, bh->b_blocknr);
|
||||
|
||||
fsck_bitmap_mkuninsert (bh->b_blocknr);
|
||||
reiserfs_buffer_close (bh);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (reiserfs_journal_block (fs, i) &&
|
||||
fsck_data(fs)->rebuild.use_journal_area)
|
||||
{
|
||||
/* FIXME: temporary thing */
|
||||
if (tree_is_empty ()) {
|
||||
/* we insert inot tree only first leaf of journal */
|
||||
unsigned long block;
|
||||
reiserfs_bh_t * new_bh;
|
||||
|
||||
block = alloc_block ();
|
||||
if (!block)
|
||||
misc_die ("could not allocate block");
|
||||
|
||||
new_bh = reiserfs_buffer_open (bh->b_dev, block,
|
||||
bh->b_size);
|
||||
|
||||
memcpy (new_bh->b_data, bh->b_data, bh->b_size);
|
||||
reiserfs_buffer_mkuptodate (new_bh, 1);
|
||||
reiserfs_buffer_mkdirty (new_bh);
|
||||
make_single_leaf_tree (new_bh);
|
||||
reiserfs_buffer_close (new_bh);
|
||||
reiserfs_buffer_close (bh);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* other blocks of journal will be inserted in pass 2 */
|
||||
fsck_bitmap_mkuninsert (bh->b_blocknr);
|
||||
reiserfs_buffer_close (bh);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!try_to_insert_pointer_to_leaf(bh)) {
|
||||
/* Inserted successfully. */
|
||||
if (n) {
|
||||
fsck_bitmap_cluninsert (i);
|
||||
}
|
||||
} else {
|
||||
if (!n) {
|
||||
/* Not inserted on the 1st pass. */
|
||||
fsck_bitmap_mkuninsert (i);
|
||||
done--;
|
||||
}
|
||||
}
|
||||
|
||||
reiserfs_buffer_close (bh);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fsck_quiet(fs))
|
||||
fsck_progress ("\n");
|
||||
}
|
||||
|
||||
|
||||
static void fsck_pass1_fini (reiserfs_filsys_t * fs) {
|
||||
time_t t;
|
||||
|
||||
/* update fsck_state */
|
||||
|
||||
/* we should not flush bitmaps on disk after pass1, because
|
||||
new_bitmap contains only those blocks which are good leaves or
|
||||
just allocated internal blocks. */
|
||||
|
||||
reiserfs_sb_set_state (fs->fs_ondisk_sb, PASS_1_DONE);
|
||||
reiserfs_buffer_mkdirty (fs->fs_super_bh);
|
||||
|
||||
/* write all dirty blocks */
|
||||
fsck_progress ("Flushing..");
|
||||
fs->fs_dirt = 1;
|
||||
reiserfs_fs_flush (fs);
|
||||
fsck_progress ("finished\n");
|
||||
|
||||
fsck_stage_report (FS_PASS1, fs);
|
||||
|
||||
/* we do not need this anymore */
|
||||
fsck_pass0_aux_fini();
|
||||
reiserfs_bitmap_delete (bad_unfm_in_tree_once_bitmap);
|
||||
|
||||
if (!fsck_run_one_step (fs)) {
|
||||
if (fsck_info_ask (fs, "Continue? (Yes):", "Yes\n", 1))
|
||||
/* reiserfsck continues */
|
||||
return;
|
||||
} else
|
||||
fsck_pass1_save_result (fs);
|
||||
|
||||
if (proper_id_map (fs)) {
|
||||
/* when we run pass 1 only - we do not have proper_id_map */
|
||||
id_map_free(proper_id_map (fs));
|
||||
proper_id_map (fs) = 0;
|
||||
}
|
||||
|
||||
time (&t);
|
||||
fsck_progress ("###########\n"
|
||||
"reiserfsck finished pass 1 at %s"
|
||||
"###########\n", ctime (&t));
|
||||
fs->fs_dirt = 1;
|
||||
reiserfs_fs_close (fs);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void fsck_pass1 (reiserfs_filsys_t * fs) {
|
||||
fsck_progress ("Pass 1 (will try to insert %lu leaves):\n",
|
||||
reiserfs_bitmap_ones (fsck_source_bitmap (fs)));
|
||||
if (fsck_log_file (fs) != stderr)
|
||||
fsck_log ("####### Pass 1 #######\n");
|
||||
|
||||
|
||||
fsck_pass1_prep (fs);
|
||||
|
||||
/* try to insert leaves found during pass 0 */
|
||||
do_pass_1 (fs);
|
||||
|
||||
fsck_pass1_fini (fs);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user