/*
 * Copyright 1996-2004 by Hans Reiser, licensing governed by
 * reiserfsprogs/README
 */

#include "fsck.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, unsigned long 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);
	misc_set_bit(BH_Uptodate, (char *)&bh->b_state);
	return bh;
}

int is_item_reachable(struct item_head *ih)
{
	return ih_reachable(ih) ? 1 : 0;
}

void mark_item_unreachable(struct item_head *ih)
{
	clean_ih_flags(ih);
	mark_ih_unreachable(ih);

	if (is_indirect_ih(ih))
		set_ih_free_space(ih, 0);
}

void mark_item_reachable(struct item_head *ih, struct buffer_head *bh)
{
	mark_ih_reachable(ih);
	mark_buffer_dirty(bh);
}

static void stat_data_in_tree(struct buffer_head *bh, struct item_head *ih)
{
#if 0
	__u32 objectid;

	objectid = get_key_objectid(&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, ih_item_body(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 "";
}

/* 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)
{
	unsigned int i;
	__le32 *unp;
	__u32 unfm_ptr;
	int ret;

	unp = (__le32 *) ih_item_body(bh, ih);

	for (i = 0; i < I_UNFM_NUM(ih); i++) {
		unfm_ptr = d32_get(unp, i);
		if (unfm_ptr == 0)
			continue;
		if ((ret = still_bad_unfm_ptr_1(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 leaf_is_in_tree_now(struct buffer_head *bh)
{
	item_action_t actions[] = { stat_data_in_tree, indirect_in_tree,
				    NULL, NULL };

	mark_block_used((bh)->b_blocknr, 1);

	for_every_item(bh, mark_item_unreachable, actions);

	pass_1_stat(fs)->inserted_leaves++;

	mark_buffer_dirty(bh);
}

static void insert_pointer(struct buffer_head *bh, struct reiserfs_path *path)
{
	struct item_head *ih;
	char *body;
	int retval;
	struct tree_balance tb;

	init_tb_struct(&tb, fs, path, 0x7fff);

	/* fix_nodes & do_balance must work for internal nodes only */
	ih = NULL;

	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) == NULL)
			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 = NULL;
	body = (char *)bh;
	//memmode = 0;

	do_balance(&tb, ih, body, M_INTERNAL, 0);

	leaf_is_in_tree_now(bh);
}

/* return 1 if left and right can be joined. 0 otherwise */
static int balance_condition_fails(struct buffer_head *left,
				   struct buffer_head *right)
{
	if (B_FREE_SPACE(left) >= B_CHILD_SIZE(right) -
	    (are_items_mergeable
	     (item_head(left, B_NR_ITEMS(left) - 1),
	      item_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 */
static int balance_condition_2_fails(struct buffer_head *new,
				     struct reiserfs_path *path)
{
	struct buffer_head *bh;
	struct reiserfs_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 == NULL)
		/* 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_REISERFS_PATH(path_to_right_neighbor);

		if (reiserfs_search_by_key_4
		    (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__,
			     PATH_H_PBUFFER(path, 1)->b_blocknr, pos,
			     right_dkey,
			     get_dc_child_blocknr(B_N_CHILD(bh, pos + 1)));

		used_space =
		    B_CHILD_SIZE(PATH_PLAST_BUFFER(&path_to_right_neighbor));
		pathrelse(&path_to_right_neighbor);
	} else
		used_space = get_dc_child_size(B_N_CHILD(bh, pos + 1));

	if (B_FREE_SPACE(new) >= used_space -
	    (are_items_mergeable
	     (item_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 reiserfs_key *key)
{
	struct item_head *ih;

	ih = item_head(bh, B_NR_ITEMS(bh) - 1);
	copy_key(key, &(ih->ih_key));

	if (is_direntry_key(key)) {
		/* copy deh_offset 3-rd and 4-th key components of the last entry */
		set_offset(KEY_FORMAT_1, key,
			   get_deh_offset(B_I_DEH(bh, ih) +
					  get_ih_entry_count(ih) - 1));

	} 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);
}

int tree_is_empty(void)
{
	return (get_sb_root_block(fs->fs_ondisk_sb) == ~(__u32) 0 ||
		get_sb_root_block(fs->fs_ondisk_sb) == 0) ? 1 : 0;
}

void make_single_leaf_tree(struct buffer_head *bh)
{
	/* tree is empty, make tree root */
	set_sb_root_block(fs->fs_ondisk_sb, bh->b_blocknr);
	set_sb_tree_height(fs->fs_ondisk_sb, 2);
	mark_buffer_dirty(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 void try_to_insert_pointer_to_leaf(struct buffer_head *new_bh)
{
	INITIALIZE_REISERFS_PATH(path);
	struct buffer_head *bh;	/* last path buffer */
	struct reiserfs_key *first_bh_key, last_bh_key;	/* first and last keys of new buffer */
	struct reiserfs_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 = leaf_key(new_bh, 0);

	/* try to find place in the tree for the first key of the coming node */
	ret_value = reiserfs_search_by_key_4(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(leaf_key(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) != NULL ||
		    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 */

	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 fs, struct buffer_head *bh)
{
	unsigned int i, j;
	struct item_head *ih;
	__le32 *ind_item;
	__u32 unfm_ptr;
	int dirty = 0;

	ih = item_head(bh, 0);
	for (i = 0; i < B_NR_ITEMS(bh); i++, ih++) {
		if (is_direntry_ih(ih)) {
			struct reiserfs_de_head *deh;
			__u32 offset;
			char *name;
			int name_len;
			unsigned int hash_code;

			deh = B_I_DEH(bh, ih);
			offset = 0;
			for (j = 0; j < get_ih_entry_count(ih); j++) {
				name = name_in_entry(deh + j, j);
				name_len = name_in_entry_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_deh_offset(deh + j),
						     get_sb_hash_code(fs->
								      fs_ondisk_sb));
				if (hash_code !=
				    get_sb_hash_code(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,
					     code2name(hash_code),
					     code2name(get_sb_hash_code
						       (fs->fs_ondisk_sb)));
					if (get_ih_entry_count(ih) == 1) {
						delete_item(fs, bh, i);
						fsck_log
						    (" - the only entry - item was deleted\n");
						i--;
						ih--;
						break;
					} else {
						cut_entry(fs, bh, i, j, 1);
						fsck_log(" - deleted\n");
						j--;
						deh = B_I_DEH(bh, ih);
						continue;
					}
				}

				if (j && offset >= get_deh_offset(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,
					     get_deh_offset(deh + j), offset);
					cut_entry(fs, bh, i, j, 1);
					j--;
					deh = B_I_DEH(bh, ih);
					continue;
				}

				offset = get_deh_offset(deh + j);
			}
			continue;
		}

		if (!is_indirect_ih(ih))
			continue;

		/* correct indirect items */
		ind_item = (__le32 *) ih_item_body(bh, ih);

		for (j = 0; j < I_UNFM_NUM(ih); j++) {
			unfm_ptr = d32_get(ind_item, j);

			if (!unfm_ptr)
				continue;

			/* this corruption of indirect item had to be fixed in pass0 */
			if (not_data_block(fs, unfm_ptr)
			    || unfm_ptr >= get_sb_block_count(fs->fs_ondisk_sb))
				/*!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 (is_used_leaf(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 (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++;
					d32_put(ind_item, j, 0);
					pass_1_stat(fs)->non_unique_pointers++;
					continue;
				}
			} else
				pass_1_stat(fs)->correct_pointers++;
		}
	}

	if (dirty)
		mark_buffer_dirty(bh);
}

struct si *remove_saved_item(struct si *si)
{
	struct si *tmp = si->si_next;

	freemem(si->si_dnm_data);
	freemem(si);
	return tmp;
}

/* 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;

	fsck_new_bitmap(fs) =
	    reiserfs_create_bitmap(get_sb_block_count(fs->fs_ondisk_sb));

	/* 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;
	for (i = 0; i < reiserfs_fs_bmap_nr(fs); i++) {
		mark_block_used(block, 1);
		if (spread_bitmaps(fs))
			block =
			    (block / (fs->fs_blocksize * 8) +
			     1) * (fs->fs_blocksize * 8);
		else
			block++;
	}

	reserved = get_size_of_journal_or_reserved_area(fs->fs_ondisk_sb);
	/* where does journal area (or reserved journal area) start from */

	if (!is_new_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize) &&
	    !is_old_sb_location(fs->fs_super_bh->b_blocknr, fs->fs_blocksize))
		die("init_new_bitmap: Wrong super block location, you must run --rebuild-sb.");

	block = get_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 < get_sb_block_count(fs->fs_ondisk_sb); 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);
			}
		}
#if 0
	/* mark journal area as used if journal is standard or it is non standard
	   and initialy has been created on a main device */
	reserved = 0;
	if (!is_reiserfs_jr_magic_string(fs->fs_ondisk_sb))
		reserved = get_jp_journal_size(sb_jp(fs->fs_ondisk_sb));
	if (get_sb_reserved_for_journal(fs->fs_ondisk_sb))
		reserved = get_sb_reserved_for_journal(fs->fs_ondisk_sb);
	if (reserved) {
		for (i = 0; i <= reserved; i++)
			mark_block_used(i + get_jp_journal_1st_block(sb_jp
								     (fs->
								      fs_ondisk_sb)));
	}
#endif
}

/* 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_create_bitmap(get_sb_block_count(fs->fs_ondisk_sb));
	reiserfs_bitmap_fill(fsck_allocable_bitmap(fs));

	/* find how many leaves are not pointed by any indirect items */
	for (i = 0; i < get_sb_block_count(fs->fs_ondisk_sb); i++) {
		if (not_data_block(fs, i))
			/* journal (or reserved for it area), bitmaps, super block and
			   blocks before it */
			continue;

		if (is_good_unformatted(i) && is_bad_unformatted(i))
			die("find_allocable_blocks: The block (%lu) is masr as good and as bad at once.", i);

		if (is_good_unformatted(i) || is_bad_unformatted(i)) {
			/* blocks which were pointed once or more thn onec from indirect
			   items - they will not be allocated */
			continue;
		}

		/* make allocable not leaves, not bad blocks */
		if (!is_used_leaf(i) && (!fs->fs_badblocks_bm ||
					 !reiserfs_bitmap_test_bit(fs->
								   fs_badblocks_bm,
								   i))) {
			/* this is not leaf and it is not pointed by found indirect 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_reiserfs_new_blocknrs;
	fs->block_deallocator = reiserfsck_reiserfs_free_block;
}

static void before_pass_1(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_create_bitmap(get_sb_block_count(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_create_bitmap(get_sb_block_count(fs->fs_ondisk_sb));

	/* pass 1 does not deal with objectid */
}

static void save_pass_1_result(reiserfs_filsys_t fs)
{
	FILE *file;
	int retval;

	file = open_file("temp_fsck_file.deleteme", "w+");
	if (!file)
		return;

	/* to be able to get a new bitmap on pass2 we should flush it on disk
	   new_bitmap should not be flushed on disk if run without -d option, as
	   if fsck fails on pass1 we get wrong bitmap on the next fsck start */
	reiserfs_flush_to_ondisk_bitmap(fsck_new_bitmap(fs), fs);

	/* to be able to restart with pass 2 we need bitmap of
	   uninsertable blocks and bitmap of alocable blocks */
	reiserfs_begin_stage_info_save(file, PASS_1_DONE);
	reiserfs_bitmap_save(file, fsck_uninsertables(fs));
	reiserfs_bitmap_save(file, fsck_allocable_bitmap(fs));
	reiserfs_end_stage_info_save(file);
	close_file(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));
}

void load_pass_1_result(FILE * fp, reiserfs_filsys_t fs)
{
	fsck_new_bitmap(fs) =
	    reiserfs_create_bitmap(get_sb_block_count(fs->fs_ondisk_sb));
	reiserfs_bitmap_copy(fsck_new_bitmap(fs), fs->fs_bitmap2);

	fsck_uninsertables(fs) = reiserfs_bitmap_load(fp);
	fsck_allocable_bitmap(fs) = reiserfs_bitmap_load(fp);

	fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
	fs->block_deallocator = reiserfsck_reiserfs_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();
	/* Not implemented yet.
	   fetch_objectid_map (proper_id_map (fs), fs);
	 */

	fsck_progress("Pass 1 result loaded. %u blocks used, %u allocable, "
		      "still to be inserted %u\n",
		      reiserfs_bitmap_ones(fsck_new_bitmap(fs)),
		      reiserfs_bitmap_zeros(fsck_allocable_bitmap(fs)),
		      reiserfs_bitmap_zeros(fsck_uninsertables(fs)));
}

/* reads blocks marked in leaves_bitmap and tries to insert them into
   tree */
static void do_pass_1(reiserfs_filsys_t fs)
{
	struct buffer_head *bh;
	unsigned long i;
	int what_node;
	unsigned long done = 0, total;

	/* on pass0 we have found that amount of leaves */
	total = reiserfs_bitmap_ones(leaves_bitmap);

	/* read all leaves found on the pass 0 */
	for (i = 0; i < get_sb_block_count(fs->fs_ondisk_sb); i++) {
		if (!is_used_leaf(i))
			continue;

		print_how_far(fsck_progress_file(fs), &done, total, 1,
			      fsck_quiet(fs));

		/* at least one of nr_to_read blocks is to be checked */
		bh = bread(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 = who_is_this(bh->b_data, bh->b_size);
		if (what_node != THE_LEAF) {
			check_memory_msg();
			die("build_the_tree: Nothing but leaves are expected. Block %lu - %s\n", i, which_block(what_node));
		}

		if (is_block_used(i) && !(block_of_journal(fs, i) &&
					  fsck_data(fs)->rebuild.
					  use_journal_area))
			/* block is in new tree already */
			die("build_the_tree: The leaf (%lu) is in the tree already\n", i);

		/* fprintf (block_list, "leaf %d\n", i + j); */
		pass_1_stat(fs)->leaves++;

		/* the leaf may still contain indirect items with wrong
		   slots. Fix that */
		pass1_correct_leaf(fs, bh);

		if (get_blkh_nr_items(B_BLK_HEAD(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
			    ("is_leaf_bad: WARNING: The leaf (%lu) is formatted badly. Will be handled on the the pass2.\n",
			     bh->b_blocknr);
			mark_block_uninsertable(bh->b_blocknr);
			brelse(bh);
			continue;
		}

		if (block_of_journal(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;
				struct buffer_head *new_bh;

				block = alloc_block();
				if (!block)
					die("could not allocate block");
				new_bh = getblk(bh->b_dev, block, bh->b_size);
				memcpy(new_bh->b_data, bh->b_data, bh->b_size);
				mark_buffer_uptodate(new_bh, 1);
				mark_buffer_dirty(new_bh);
				make_single_leaf_tree(new_bh);
				brelse(new_bh);
				brelse(bh);
				continue;
			}

			/* other blocks of journal will be inserted in pass 2 */
			mark_block_uninsertable(bh->b_blocknr);
			brelse(bh);
			continue;
		}

		try_to_insert_pointer_to_leaf(bh);
		brelse(bh);
	}

	fsck_progress("\n");

}

static void after_pass_1(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. */

	set_sb_fs_state(fs->fs_ondisk_sb, PASS_1_DONE);
	mark_buffer_dirty(fs->fs_super_bh);

	/* write all dirty blocks */
	fsck_progress("Flushing..");
	fs->fs_dirt = 1;
	reiserfs_flush(fs);
	fsck_progress("finished\n");

	stage_report(1, fs);

	/* we do not need this anymore */
	delete_aux_bitmaps();
	reiserfs_delete_bitmap(bad_unfm_in_tree_once_bitmap);

	if (!fsck_run_one_step(fs)) {
		if (fsck_user_confirmed(fs, "Continue? (Yes):", "Yes\n", 1))
			/* reiserfsck continues */
			return;
	} else
		save_pass_1_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) = NULL;
	}

	time(&t);
	fsck_progress("###########\n"
		      "reiserfsck finished pass 1 at %s"
		      "###########\n", ctime(&t));
	fs->fs_dirt = 1;
	reiserfs_close(fs);
	exit(0);
}

void pass_1(reiserfs_filsys_t fs)
{
	fsck_progress("\nPass 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");

	before_pass_1(fs);

	/* try to insert leaves found during pass 0 */
	do_pass_1(fs);

	after_pass_1(fs);
}
