130 lines
3.9 KiB
C
130 lines
3.9 KiB
C
/*
|
|
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
#include "fsck.h"
|
|
|
|
/* g_disk_bitmap initially contains copy of disk bitmaps
|
|
(cautious version of it);
|
|
|
|
g_new_bitmap initially has marked only super block, bitmap blocks
|
|
and bits after the end of bitmap
|
|
|
|
in pass 1 we go through g_disk_bitmap.
|
|
|
|
If block does not look like formatted node, we skip it.
|
|
|
|
If block contains internal node, put 0 in g_disk_bitmap if block is
|
|
not used in new tree yet.
|
|
|
|
If block contains leaf and is used already (by an indirect item
|
|
handled already to this time) save all items. They will be inserted
|
|
into tree after pass 1.
|
|
|
|
If block looking like leaf is not used in the new tree, try to
|
|
insert in into tree. If it is not possible, mark block in
|
|
g_uninsertable_leaf_bitmap. Blocks marked in this bitmap will be inserted into tree in pass 2. They can not be
|
|
|
|
This means, that in pass 1 when we have
|
|
found block containing the internal nodes we mark it in
|
|
g_disk_bitmap as free (reiserfs_free_internal_block). When block
|
|
gets into new tree it is marked in g_new_bitmap (mark_block_used)
|
|
When collecting resources for do_balance, we mark new blocks with
|
|
mark_block_used. After do_balance we unmark unused new blocks in
|
|
g_new_bitmap (bitmap.c:/reiserfs_free_block)
|
|
|
|
Allocating of new blocks: look for 0 bit in g_disk_bitmap
|
|
(find_zero_bit_in_bitmap), make sure, that g_new_bitmap contains 0
|
|
at the corresponding bit (is_block_used).
|
|
|
|
*/
|
|
|
|
/* is blocks used (marked by 1 in new bitmap) in the tree which is being built
|
|
(as leaf, internal, bitmap, or unformatted node) */
|
|
int is_block_used(unsigned long block)
|
|
{
|
|
return reiserfs_bitmap_test_bit(fsck_new_bitmap(fs), block);
|
|
}
|
|
|
|
void mark_block_used(unsigned long block, int check_hardware)
|
|
{
|
|
if (!block)
|
|
return;
|
|
if (is_block_used(block)) {
|
|
if (check_hardware)
|
|
check_memory_msg();
|
|
die("mark_block_used: (%lu) used already", block);
|
|
}
|
|
|
|
reiserfs_bitmap_set_bit(fsck_new_bitmap(fs), block);
|
|
}
|
|
|
|
static void mark_block_free(unsigned long block)
|
|
{
|
|
if (!is_block_used(block))
|
|
die("mark_block_free: (%lu) is free already", block);
|
|
|
|
reiserfs_bitmap_clear_bit(fsck_new_bitmap(fs), block);
|
|
}
|
|
|
|
int is_block_uninsertable(unsigned long block)
|
|
{
|
|
return !reiserfs_bitmap_test_bit(fsck_uninsertables(fs), block);
|
|
}
|
|
|
|
/* uninsertable block is marked by bit clearing */
|
|
void mark_block_uninsertable(unsigned long block)
|
|
{
|
|
if (is_block_uninsertable(block))
|
|
die("mark_block_uninsertable: (%lu) is uninsertable already",
|
|
block);
|
|
|
|
reiserfs_bitmap_clear_bit(fsck_uninsertables(fs), block);
|
|
/* we do not need thsi actually */
|
|
pass_1_stat(fs)->uninsertable_leaves++;
|
|
}
|
|
|
|
/* FIXME: should be able to work around no disk space */
|
|
int reiserfsck_reiserfs_new_blocknrs(reiserfs_filsys_t *fs,
|
|
unsigned long *free_blocknrs,
|
|
unsigned long start, int amount_needed)
|
|
{
|
|
int i;
|
|
|
|
if (!are_there_allocable_blocks(amount_needed))
|
|
die("out of disk space");
|
|
for (i = 0; i < amount_needed; i++) {
|
|
free_blocknrs[i] = alloc_block();
|
|
if (!free_blocknrs[i])
|
|
die("reiserfs_new_blocknrs: 0 is allocated");
|
|
mark_block_used(free_blocknrs[i], 0);
|
|
}
|
|
return CARRY_ON;
|
|
}
|
|
|
|
// FIXME: do you check readability of a block? If f_read fails - you
|
|
// free block in bitmap or if you mark bad blocks used to avoid their
|
|
// allocation in future you should have bad block counter in a super
|
|
// block. Another minor issue: users of _get_new_buffer expect buffer
|
|
// to be filled with 0s
|
|
struct buffer_head *reiserfsck_get_new_buffer(unsigned long start)
|
|
{
|
|
unsigned long blocknr = 0;
|
|
struct buffer_head *bh = NULL;
|
|
|
|
reiserfs_new_blocknrs(fs, &blocknr, start, 1);
|
|
bh = getblk(fs->fs_dev, blocknr, fs->fs_blocksize);
|
|
return bh;
|
|
}
|
|
|
|
/* free block in new bitmap */
|
|
int reiserfsck_reiserfs_free_block(reiserfs_filsys_t *fs, unsigned long block)
|
|
{
|
|
mark_block_free(block);
|
|
|
|
/* put it back to pool of blocks for allocation */
|
|
make_allocable(block);
|
|
return 0;
|
|
}
|