This patch just removes trailing whitespace. Signed-off-by: Jeff Mahoney <jeffm@suse.com>
299 lines
7.4 KiB
C
299 lines
7.4 KiB
C
/*
|
|
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
#include "fsck.h"
|
|
#include "progbar.h"
|
|
|
|
struct tree_balance *cur_tb = 0;
|
|
|
|
void reiserfsck_paste_into_item(struct reiserfs_path *path, const char *body,
|
|
int size)
|
|
{
|
|
struct tree_balance tb;
|
|
|
|
init_tb_struct(&tb, fs, path, size);
|
|
if (fix_nodes( /*tb.transaction_handle, */ M_PASTE, &tb, 0 /*ih */ ) !=
|
|
CARRY_ON)
|
|
//fix_nodes(options, tree_balance, ih_to_option, body_to_option)
|
|
|
|
die("reiserfsck_paste_into_item: fix_nodes failed");
|
|
|
|
do_balance( /*tb.transaction_handle, */ &tb, 0, body, M_PASTE,
|
|
0 /*zero num */ );
|
|
}
|
|
|
|
void reiserfsck_insert_item(struct reiserfs_path *path, struct item_head *ih,
|
|
const char *body)
|
|
{
|
|
struct tree_balance tb;
|
|
|
|
init_tb_struct(&tb, fs, path, IH_SIZE + get_ih_item_len(ih));
|
|
if (fix_nodes
|
|
( /*tb.transaction_handle, */ M_INSERT, &tb,
|
|
ih /*, body */ ) != CARRY_ON)
|
|
die("reiserfsck_insert_item: fix_nodes failed");
|
|
do_balance( /*tb.transaction_handle, */ &tb, ih, body, M_INSERT,
|
|
0 /*zero num */ );
|
|
}
|
|
|
|
static void free_unformatted_nodes(struct item_head *ih, struct buffer_head *bh)
|
|
{
|
|
__u32 *punfm = (__u32 *) B_I_PITEM(bh, ih);
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < I_UNFM_NUM(ih); i++) {
|
|
__u32 unfm = d32_get(punfm, i);
|
|
if (unfm != 0) {
|
|
struct buffer_head *to_be_forgotten;
|
|
|
|
to_be_forgotten =
|
|
find_buffer(fs->fs_dev, unfm, fs->fs_blocksize);
|
|
if (to_be_forgotten) {
|
|
//atomic_inc(&to_be_forgotten->b_count);
|
|
to_be_forgotten->b_count++;
|
|
bforget(to_be_forgotten);
|
|
}
|
|
|
|
reiserfs_free_block(fs, unfm);
|
|
}
|
|
}
|
|
}
|
|
|
|
void reiserfsck_delete_item(struct reiserfs_path *path, int temporary)
|
|
{
|
|
struct tree_balance tb;
|
|
struct item_head *ih = PATH_PITEM_HEAD(path);
|
|
|
|
if (is_indirect_ih(ih) && !temporary)
|
|
free_unformatted_nodes(ih, PATH_PLAST_BUFFER(path));
|
|
|
|
init_tb_struct(&tb, fs, path, -(IH_SIZE + get_ih_item_len(ih)));
|
|
|
|
if (fix_nodes( /*tb.transaction_handle, */ M_DELETE, &tb, 0 /*ih */ ) !=
|
|
CARRY_ON)
|
|
die("reiserfsck_delete_item: fix_nodes failed");
|
|
|
|
do_balance( /*tb.transaction_handle, */ &tb, 0, 0, M_DELETE,
|
|
0 /*zero num */ );
|
|
}
|
|
|
|
void reiserfsck_cut_from_item(struct reiserfs_path *path, int cut_size)
|
|
{
|
|
struct tree_balance tb;
|
|
struct item_head *ih;
|
|
|
|
if (cut_size >= 0)
|
|
die("reiserfsck_cut_from_item: cut size == %d", cut_size);
|
|
|
|
if (is_indirect_ih(ih = PATH_PITEM_HEAD(path))) {
|
|
struct buffer_head *bh = PATH_PLAST_BUFFER(path);
|
|
__u32 unfm_ptr =
|
|
d32_get((__u32 *) B_I_PITEM(bh, ih), I_UNFM_NUM(ih) - 1);
|
|
if (unfm_ptr != 0) {
|
|
struct buffer_head *to_be_forgotten;
|
|
|
|
to_be_forgotten =
|
|
find_buffer(fs->fs_dev, unfm_ptr, fs->fs_blocksize);
|
|
if (to_be_forgotten) {
|
|
//atomic_inc(&to_be_forgotten->b_count);
|
|
to_be_forgotten->b_count++;
|
|
bforget(to_be_forgotten);
|
|
}
|
|
reiserfs_free_block(fs, unfm_ptr);
|
|
}
|
|
}
|
|
|
|
init_tb_struct(&tb, fs, path, cut_size);
|
|
|
|
if (fix_nodes( /*tb.transaction_handle, */ M_CUT, &tb, 0) != CARRY_ON)
|
|
die("reiserfsck_cut_from_item: fix_nodes failed");
|
|
|
|
do_balance( /*tb.transaction_handle, */ &tb, 0, 0, M_CUT,
|
|
0 /*zero num */ );
|
|
}
|
|
|
|
/* uget_rkey is utils clone of stree.c/get_rkey */
|
|
/*
|
|
struct reiserfs_key *uget_rkey (struct reiserfs_path *path)
|
|
{
|
|
int pos, offset = path->path_length;
|
|
struct buffer_head * bh;
|
|
|
|
if (offset < FIRST_PATH_ELEMENT_OFFSET)
|
|
die ("uget_rkey: illegal offset in the path (%d)", offset);
|
|
|
|
while (offset-- > FIRST_PATH_ELEMENT_OFFSET) {
|
|
if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)))
|
|
die ("uget_rkey: parent is not uptodate");
|
|
|
|
// Parent at the path is not in the tree now.
|
|
if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset)))
|
|
die ("uget_rkey: buffer on the path is not in tree");
|
|
|
|
// Check whether position in the parrent is correct.
|
|
if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh))
|
|
die ("uget_rkey: invalid position (%d) in the path", pos);
|
|
|
|
// Check whether parent at the path really points to the child.
|
|
if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
|
|
die ("uget_rkey: invalid block number (%d). Must be %ld",
|
|
get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
|
|
|
|
// Return delimiting key if position in the parent is not the last one.
|
|
if (pos != B_NR_ITEMS (bh))
|
|
return B_N_PDELIM_KEY(bh, pos);
|
|
}
|
|
|
|
// there is no right delimiting key
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
static unsigned long first_child(struct buffer_head *bh)
|
|
{
|
|
return get_dc_child_blocknr(B_N_CHILD(bh, 0));
|
|
}
|
|
|
|
#if 0
|
|
static unsigned long last_child(struct buffer_head *bh)
|
|
{
|
|
return child_block_number(bh, node_item_number(bh));
|
|
}
|
|
#endif
|
|
|
|
static unsigned long get_child(int pos, struct buffer_head *parent)
|
|
{
|
|
if (pos == -1)
|
|
return -1;
|
|
|
|
if (pos > B_NR_ITEMS(parent))
|
|
die("get_child: no child found, should not happen: %d of %d",
|
|
pos, B_NR_ITEMS(parent));
|
|
return get_dc_child_blocknr(B_N_CHILD(parent, pos));
|
|
|
|
}
|
|
|
|
static void print(int cur, int total)
|
|
{
|
|
if (fsck_quiet(fs))
|
|
return;
|
|
printf("/%3d (of %3d)", cur, total);
|
|
fflush(stdout);
|
|
}
|
|
|
|
/* erase /XXX(of XXX) */
|
|
static void erase(void)
|
|
{
|
|
if (fsck_quiet(fs))
|
|
return;
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
|
printf(" ");
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
|
fflush(stdout);
|
|
}
|
|
|
|
void pass_through_tree(reiserfs_filsys_t *fs, do_after_read_t action1,
|
|
do_on_full_path_t action2, int depth)
|
|
{
|
|
struct buffer_head *path[MAX_HEIGHT] = { 0, };
|
|
int total[MAX_HEIGHT] = { 0, };
|
|
int cur[MAX_HEIGHT] = { 0, };
|
|
int h = 0;
|
|
unsigned long block = get_sb_root_block(fs->fs_ondisk_sb);
|
|
int problem;
|
|
struct spinner spinner;
|
|
|
|
spinner_init(&spinner, fsck_progress_file(fs));
|
|
|
|
if (block >= get_sb_block_count(fs->fs_ondisk_sb)
|
|
|| not_data_block(fs, block)) {
|
|
die("\nBad root block %lu. (--rebuild-tree did not complete)\n",
|
|
block);
|
|
}
|
|
|
|
while (1) {
|
|
problem = 0;
|
|
|
|
if (path[h])
|
|
die("pass_through_tree: empty slot expected");
|
|
if (h)
|
|
print(cur[h - 1], total[h - 1]);
|
|
|
|
if (fs->fs_badblocks_bm
|
|
&& reiserfs_bitmap_test_bit(fs->fs_badblocks_bm, block)) {
|
|
fsck_log
|
|
("%s: block %lu specified in badblock list found in tree, whole subtree skipped\n",
|
|
__FUNCTION__, block);
|
|
fsck_data(fs)->check.bad_nodes++;
|
|
one_more_corruption(fs, FATAL);
|
|
|
|
if (h == 0) {
|
|
brelse(path[h]);
|
|
path[h] = 0;
|
|
break;
|
|
}
|
|
problem = 1;
|
|
} else {
|
|
|
|
spinner_touch(&spinner);
|
|
path[h] = bread(fs->fs_dev, block, fs->fs_blocksize);
|
|
if (path[h] == 0)
|
|
/* FIXME: handle case when read failed */
|
|
die("pass_through_tree: unable to read %lu block on device 0x%x\n", block, fs->fs_dev);
|
|
|
|
if (action1)
|
|
if ((problem = action1(fs, path, h))) {
|
|
fsck_log
|
|
(" the problem in the internal node occured (%lu), whole subtree is skipped\n",
|
|
path[h]->b_blocknr);
|
|
fsck_data(fs)->check.bad_nodes++;
|
|
|
|
if (h == 0) {
|
|
brelse(path[h]);
|
|
path[h] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Time to stop. */
|
|
if (h == depth)
|
|
problem++;
|
|
|
|
if (problem || is_leaf_node(path[h])) {
|
|
if (!problem && action2)
|
|
action2(fs, path, h);
|
|
|
|
brelse(path[h]);
|
|
if (h)
|
|
erase();
|
|
|
|
while (h && (cur[h - 1] == total[h - 1] || problem)) {
|
|
problem = 0;
|
|
path[h] = 0;
|
|
h--;
|
|
brelse(path[h]);
|
|
if (h)
|
|
erase();
|
|
}
|
|
|
|
if (h == 0) {
|
|
path[h] = 0;
|
|
break;
|
|
}
|
|
|
|
block = get_child(cur[h - 1], path[h - 1]);
|
|
cur[h - 1]++;
|
|
path[h] = 0;
|
|
continue;
|
|
}
|
|
total[h] = B_NR_ITEMS(path[h]) + 1;
|
|
cur[h] = 1;
|
|
block = first_child(path[h]);
|
|
h++;
|
|
}
|
|
spinner_clear(&spinner);
|
|
}
|