static int _search_by_key (reiserfs_filsys_t fs, struct key * key, struct path * path) { struct buffer_head * bh; unsigned long block = SB_ROOT_BLOCK (fs); struct path_element * curr; int retval; path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET; while (1) { curr = PATH_OFFSET_PELEMENT (path, ++ path->path_length); bh = curr->pe_buffer = bread (fs->s_dev, block, fs->s_blocksize); if (bh == 0) { path->path_length --; pathrelse (path); return ITEM_NOT_FOUND; } retval = _bin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh), is_leaf_node (bh) ? IH_SIZE : KEY_SIZE, &(curr->pe_position), comp_keys); if (retval == ITEM_FOUND) { /* key found, return if this is leaf level */ if (is_leaf_node (bh)) { path->pos_in_item = 0; return ITEM_FOUND; } curr->pe_position ++; } else { /* key not found in the node */ if (is_leaf_node (bh)) return ITEM_NOT_FOUND; } block = B_N_CHILD_NUM (bh, curr->pe_position); } printf ("search_by_key: you can not get here\n"); return ITEM_NOT_FOUND; }
void reiserfsck_tree_check (check_function_t how_to_compare_neighbors) { g_left = 0; g_dkey = 0; reiserfsck_check_tree (fs->s_dev, SB_ROOT_BLOCK(fs), fs->s_blocksize, how_to_compare_neighbors); brelse (g_right); }
int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value) { int i, j; if (block == 0 || block >= SB_BLOCK_COUNT (s)) { reiserfs_warning (s, "vs-4010: is_reusable: block number is out of range %lu (%u)", block, SB_BLOCK_COUNT (s)); return 0; } /* it can't be one of the bitmap blocks */ for (i = 0; i < SB_BMAP_NR (s); i ++) if (block == SB_AP_BITMAP (s)[i].bh->b_blocknr) { reiserfs_warning (s, "vs: 4020: is_reusable: " "bitmap block %lu(%u) can't be freed or reused", block, SB_BMAP_NR (s)); return 0; } get_bit_address (s, block, &i, &j); if (i >= SB_BMAP_NR (s)) { reiserfs_warning (s, "vs-4030: is_reusable: there is no so many bitmap blocks: " "block=%lu, bitmap_nr=%d", block, i); return 0; } if ((bit_value == 0 && reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) || (bit_value == 1 && reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i].bh->b_data) == 0)) { reiserfs_warning (s, "vs-4040: is_reusable: corresponding bit of block %lu does not " "match required value (i==%d, j==%d) test_bit==%d", block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i].bh->b_data)); return 0; } if (bit_value == 0 && block == SB_ROOT_BLOCK (s)) { reiserfs_warning (s, "vs-4050: is_reusable: this is root block (%u), " "it must be busy", SB_ROOT_BLOCK (s)); return 0; } return 1; }
/* Get delimiting key of the buffer at the path and its right neighbor. */ const struct key * get_rkey(const struct path *p_s_chk_path, const struct reiserfs_sb_info *p_s_sbi) { struct buf *p_s_parent; int n_position, n_path_offset = p_s_chk_path->path_length; while (n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET) { /* Parent at the path is not in the tree now. */ if (!B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset))) return (&MIN_KEY); /* Check whether position in the parent is correct. */ if ((n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent)) return (&MIN_KEY); /* * Check whether parent at the path really points to the * child. */ if (B_N_CHILD_NUM(p_s_parent, n_position) != (PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blkno / btodb(p_s_sbi->s_blocksize))) return (&MIN_KEY); /* * Return delimiting key if position in the parent is not * the last one. */ if (n_position != B_NR_ITEMS(p_s_parent)) return (B_N_PDELIM_KEY(p_s_parent, n_position)); } /* Return MAX_KEY if we are in the root of the buffer tree. */ if ((PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blkno / btodb(p_s_sbi->s_blocksize)) == SB_ROOT_BLOCK(p_s_sbi)) return (&MAX_KEY); return (&MIN_KEY); }
/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom of the path, and going upwards. We must check the path's validity at each step. If the key is not in the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this case we return a special key, either MIN_KEY or MAX_KEY. */ static inline const struct reiserfs_key *get_lkey(const struct treepath *chk_path, const struct super_block *sb) { int position, path_offset = chk_path->path_length; struct buffer_head *parent; RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET, "PAP-5010: invalid offset in the path"); /* While not higher in path than first element. */ while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) { RFALSE(!buffer_uptodate (PATH_OFFSET_PBUFFER(chk_path, path_offset)), "PAP-5020: parent is not uptodate"); /* Parent at the path is not in the tree now. */ if (!B_IS_IN_TREE (parent = PATH_OFFSET_PBUFFER(chk_path, path_offset))) return &MAX_KEY; /* Check whether position in the parent is correct. */ if ((position = PATH_OFFSET_POSITION(chk_path, path_offset)) > B_NR_ITEMS(parent)) return &MAX_KEY; /* Check whether parent at the path really points to the child. */ if (B_N_CHILD_NUM(parent, position) != PATH_OFFSET_PBUFFER(chk_path, path_offset + 1)->b_blocknr) return &MAX_KEY; /* Return delimiting key if position in the parent is not equal to zero. */ if (position) return B_N_PDELIM_KEY(parent, position - 1); } /* Return MIN_KEY if we are in the root of the buffer tree. */ if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)-> b_blocknr == SB_ROOT_BLOCK(sb)) return &MIN_KEY; return &MAX_KEY; }
/* Get delimiting key of the buffer at the path and its right neighbor. */ inline struct key * get_rkey ( struct path * p_s_chk_path, struct super_block * p_s_sb ) { int n_position, n_path_offset = p_s_chk_path->path_length; struct buffer_head * p_s_parent; #ifdef CONFIG_REISERFS_CHECK if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET ) reiserfs_panic(p_s_sb,"PAP-5030: get_rkey: illegal offset in the path"); #endif while ( n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET ) { #ifdef CONFIG_REISERFS_CHECK if ( ! buffer_uptodate(PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) ) reiserfs_panic(p_s_sb, "PAP-5040: get_rkey: parent is not uptodate"); #endif /* Parent at the path is not in the tree now. */ if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) ) return &MIN_KEY; /* Check whether position in the parrent is correct. */ if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) ) return &MIN_KEY; /* Check whether parent at the path really points to the child. */ if ( B_N_CHILD_NUM(p_s_parent, n_position) != PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blocknr ) return &MIN_KEY; /* Return delimiting key if position in the parent is not the last one. */ if ( n_position != B_NR_ITEMS(p_s_parent) ) return B_N_PDELIM_KEY(p_s_parent, n_position); } /* Return MAX_KEY if we are in the root of the buffer tree. */ if ( PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr == SB_ROOT_BLOCK (p_s_sb) ) return &MAX_KEY; return &MIN_KEY; }
int search_by_key(struct reiserfs_sb_info *p_s_sbi, const struct cpu_key * p_s_key, /* Key to search. */ struct path * p_s_search_path, /* This structure was allocated and initialized by the calling function. It is filled up by this function. */ int n_stop_level) /* How far down the tree to search. To stop at leaf level - set to DISK_LEAF_NODE_LEVEL */ { int error; int n_node_level, n_retval; int n_block_number, expected_level, fs_gen; struct path_element *p_s_last_element; struct buf *p_s_bp, *tmp_bp; /* * As we add each node to a path we increase its count. This means that * we must be careful to release all nodes in a path before we either * discard the path struct or re-use the path struct, as we do here. */ decrement_counters_in_path(p_s_search_path); /* * With each iteration of this loop we search through the items in the * current node, and calculate the next current node(next path element) * for the next iteration of this loop... */ n_block_number = SB_ROOT_BLOCK(p_s_sbi); expected_level = -1; reiserfs_log(LOG_DEBUG, "root block: #%d\n", n_block_number); while (1) { /* Prep path to have another element added to it. */ reiserfs_log(LOG_DEBUG, "path element #%d\n", p_s_search_path->path_length); p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length); fs_gen = get_generation(p_s_sbi); /* * Read the next tree node, and set the last element in the * path to have a pointer to it. */ reiserfs_log(LOG_DEBUG, "reading block #%d\n", n_block_number); if ((error = bread(p_s_sbi->s_devvp, n_block_number * btodb(p_s_sbi->s_blocksize), p_s_sbi->s_blocksize, NOCRED, &tmp_bp)) != 0) { reiserfs_log(LOG_DEBUG, "error reading block\n"); p_s_search_path->path_length--; pathrelse(p_s_search_path); return (IO_ERROR); } reiserfs_log(LOG_DEBUG, "blkno = %ju, lblkno = %ju\n", (intmax_t)tmp_bp->b_blkno, (intmax_t)tmp_bp->b_lblkno); /* * As i didn't found a way to handle the lock correctly, * i copy the data into a fake buffer */ reiserfs_log(LOG_DEBUG, "allocating p_s_bp\n"); p_s_bp = malloc(sizeof *p_s_bp, M_REISERFSPATH, M_WAITOK); if (!p_s_bp) { reiserfs_log(LOG_DEBUG, "error allocating memory\n"); p_s_search_path->path_length--; pathrelse(p_s_search_path); brelse(tmp_bp); return (IO_ERROR); } reiserfs_log(LOG_DEBUG, "copying struct buf\n"); bcopy(tmp_bp, p_s_bp, sizeof(struct buf)); reiserfs_log(LOG_DEBUG, "allocating p_s_bp->b_data\n"); p_s_bp->b_data = malloc(p_s_sbi->s_blocksize, M_REISERFSPATH, M_WAITOK); if (!p_s_bp->b_data) { reiserfs_log(LOG_DEBUG, "error allocating memory\n"); p_s_search_path->path_length--; pathrelse(p_s_search_path); free(p_s_bp, M_REISERFSPATH); brelse(tmp_bp); return (IO_ERROR); } reiserfs_log(LOG_DEBUG, "copying buffer data\n"); bcopy(tmp_bp->b_data, p_s_bp->b_data, p_s_sbi->s_blocksize); brelse(tmp_bp); tmp_bp = NULL; reiserfs_log(LOG_DEBUG, "...done\n"); p_s_last_element->pe_buffer = p_s_bp; if (expected_level == -1) expected_level = SB_TREE_HEIGHT(p_s_sbi); expected_level--; reiserfs_log(LOG_DEBUG, "expected level: %d (%d)\n", expected_level, SB_TREE_HEIGHT(p_s_sbi)); /* XXX */ /* * It is possible that schedule occurred. We must check * whether the key to search is still in the tree rooted * from the current buffer. If not then repeat search * from the root. */ if (fs_changed(fs_gen, p_s_sbi) && (!B_IS_IN_TREE(p_s_bp) || B_LEVEL(p_s_bp) != expected_level || !key_in_buffer(p_s_search_path, p_s_key, p_s_sbi))) { reiserfs_log(LOG_DEBUG, "the key isn't in the tree anymore\n"); decrement_counters_in_path(p_s_search_path); /* * Get the root block number so that we can repeat * the search starting from the root. */ n_block_number = SB_ROOT_BLOCK(p_s_sbi); expected_level = -1; /* Repeat search from the root */ continue; } /* * Make sure, that the node contents look like a node of * certain level */ if (!is_tree_node(p_s_bp, expected_level)) { reiserfs_log(LOG_WARNING, "invalid format found in block %ju. Fsck?", (intmax_t)p_s_bp->b_blkno); pathrelse (p_s_search_path); return (IO_ERROR); } /* Ok, we have acquired next formatted node in the tree */ n_node_level = B_LEVEL(p_s_bp); reiserfs_log(LOG_DEBUG, "block info:\n"); reiserfs_log(LOG_DEBUG, " node level: %d\n", n_node_level); reiserfs_log(LOG_DEBUG, " nb of items: %d\n", B_NR_ITEMS(p_s_bp)); reiserfs_log(LOG_DEBUG, " free space: %d bytes\n", B_FREE_SPACE(p_s_bp)); reiserfs_log(LOG_DEBUG, "bin_search with :\n" " p_s_key = (objectid=%d, dirid=%d)\n" " B_NR_ITEMS(p_s_bp) = %d\n" " p_s_last_element->pe_position = %d (path_length = %d)\n", p_s_key->on_disk_key.k_objectid, p_s_key->on_disk_key.k_dir_id, B_NR_ITEMS(p_s_bp), p_s_last_element->pe_position, p_s_search_path->path_length); n_retval = bin_search(p_s_key, B_N_PITEM_HEAD(p_s_bp, 0), B_NR_ITEMS(p_s_bp), (n_node_level == DISK_LEAF_NODE_LEVEL) ? IH_SIZE : KEY_SIZE, &(p_s_last_element->pe_position)); reiserfs_log(LOG_DEBUG, "bin_search result: %d\n", n_retval); if (n_node_level == n_stop_level) { reiserfs_log(LOG_DEBUG, "stop level reached (%s)\n", n_retval == ITEM_FOUND ? "found" : "not found"); return (n_retval); } /* We are not in the stop level */ if (n_retval == ITEM_FOUND) /* * Item has been found, so we choose the pointer * which is to the right of the found one */ p_s_last_element->pe_position++; /* * If item was not found we choose the position which is * to the left of the found item. This requires no code, * bin_search did it already. */ /* * So we have chosen a position in the current node which * is an internal node. Now we calculate child block number * by position in the node. */ n_block_number = B_N_CHILD_NUM(p_s_bp, p_s_last_element->pe_position); } reiserfs_log(LOG_DEBUG, "done\n"); return (0); }
void check_cached_tree () { reiserfsck_check_cached_tree (fs->s_dev, SB_ROOT_BLOCK (fs), fs->s_blocksize); }
int main (int argc, char * argv[]) { char * file_name; int dev, i; #if 1 if (1) { /* ???? */ schedule (); iput (0); } #endif fprintf (stderr, "\n<-----------dumpreiserfs, version 0.99, 2000----------->\n"); file_name = parse_options (argc, argv); dev = open (file_name, O_RDONLY); if (dev == -1) die ("dumpreiserfs: Can not open device %s: %s\n", file_name, strerror (errno)); g_sb.s_dev = dev; if (uread_super_block (&g_sb)) die ("dumpreiserfs: no reiserfs found on %s", file_name); if (uread_bitmaps (&g_sb)) die ("dumpreiserfs: read_bitmap failed"); if (opt_pack || opt_pack_all) { pack_partition (&g_sb); } else { /* dump file system to stdout */ if (opt_block_to_print != -1) { print_one_block (opt_block_to_print); goto end; } print_block (SB_BUFFER_WITH_SB (&g_sb)); if (opt_print_journal) print_journal (&g_sb); if (opt_print_objectid_map == 1) print_objectid_map (&g_sb); if (opt_print_block_map) { print_bmap (&g_sb, opt_print_block_map == 1 ? 1 : 0); } if (opt_print_regular_file_content || opt_print_directory_contents || opt_print_leaf_items) { print_disk_tree (SB_ROOT_BLOCK (&g_sb)); /* print the statistic */ printf ("File system uses %d internal + %d leaves + %d unformatted nodes = %d blocks\n", g_stat_info.nr_internals, g_stat_info.nr_leaves, g_stat_info.nr_unformatted, g_stat_info.nr_internals + g_stat_info.nr_leaves + g_stat_info.nr_unformatted); } } end: /* brelse bitmaps */ if (SB_AP_BITMAP (&g_sb)) { for (i = 0; i < SB_BMAP_NR (&g_sb); i ++) { brelse (SB_AP_BITMAP (&g_sb)[i]); } freemem (SB_AP_BITMAP (&g_sb)); } /* brelse buffer containing super block */ brelse (SB_BUFFER_WITH_SB (&g_sb)); check_and_free_buffer_mem (); return 0; }
/* This function fills up the path from the root to the leaf as it descends the tree looking for the key. It uses reiserfs_bread to try to find buffers in the cache given their block number. If it does not find them in the cache it reads them from disk. For each node search_by_key finds using reiserfs_bread it then uses bin_search to look through that node. bin_search will find the position of the block_number of the next node if it is looking through an internal node. If it is looking through a leaf node bin_search will find the position of the item which has key either equal to given key, or which is the maximal key less than the given key. search_by_key returns a path that must be checked for the correctness of the top of the path but need not be checked for the correctness of the bottom of the path */ int search_by_key( struct super_block * p_s_sb, /* Super block. */ struct key * p_s_key, /* Key to search. */ struct path * p_s_search_path,/* This structure was allocated and initialized by the calling function. It is filled up by this function. */ int * p_n_repeat, /* Whether schedule occured. */ int n_stop_level /* How far down the tree to search.*/ ) { dev_t n_dev = p_s_sb->s_dev; int n_repeat, n_block_number = SB_ROOT_BLOCK (p_s_sb), expected_level = SB_TREE_HEIGHT (p_s_sb), n_block_size = p_s_sb->s_blocksize; struct buffer_head * p_s_bh; struct path_element * p_s_last_element; int n_retval; int right_neighbor_of_leaf_node; #ifdef CONFIG_REISERFS_CHECK int n_repeat_counter = 0; #endif /* As we add each node to a path we increase its count. This means that we must be careful to release all nodes in a path before we either discard the path struct or re-use the path struct, as we do here. */ pathrelse (p_s_search_path); *p_n_repeat = CARRY_ON; /* With each iteration of this loop we search through the items in the current node, and calculate the next current node(next path element) for the next iteration of this loop.. */ while ( 1 ) { #ifdef CONFIG_REISERFS_CHECK if ( !(++n_repeat_counter % 50000) ) printk ("PAP-5100: search_by_key(pid %u): there were %d searches from the tree_root lokking for key %p\n", current->pid, n_repeat_counter, p_s_key); #endif /* prep path to have another element added to it. */ p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length); expected_level --; n_repeat = CARRY_ON; /* Read the next tree node, and set the last element in the path to have a pointer to it. */ if ( ! (p_s_bh = p_s_last_element->pe_buffer = reiserfs_bread(n_dev, n_block_number, n_block_size, &n_repeat)) ) { p_s_search_path->path_length --; pathrelse(p_s_search_path); *p_n_repeat |= n_repeat; return IO_ERROR; } *p_n_repeat |= n_repeat; /* It is possible that schedule occured. We must check whether the key to search is still in the tree rooted from the current buffer. If not then repeat search from the root. */ if ( n_repeat != CARRY_ON && (!B_IS_IN_TREE (p_s_bh) || (! key_in_buffer(p_s_search_path, p_s_key, p_s_sb))) ) { pathrelse (p_s_search_path); /* Get the root block number so that we can repeat the search starting from the root. */ n_block_number = SB_ROOT_BLOCK (p_s_sb); expected_level = SB_TREE_HEIGHT (p_s_sb); right_neighbor_of_leaf_node = 0; /* repeat search from the root */ continue; } #ifdef CONFIG_REISERFS_CHECK if ( ! key_in_buffer(p_s_search_path, p_s_key, p_s_sb) ) reiserfs_panic(p_s_sb, "PAP-5130: search_by_key: key is not in the buffer"); if ( cur_tb ) { /* print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "5140");*/ reiserfs_panic(p_s_sb, "PAP-5140: search_by_key: schedule occurred in do_balance!"); } #endif // make sure, that the node contents look like a nod of // certain level if (!is_tree_node (p_s_bh, expected_level)) { print_block (stderr, 0, p_s_bh, 3, -1, -1); reiserfs_panic ("vs-5150: search_by_key: expeced level %d", expected_level); pathrelse (p_s_search_path); return IO_ERROR; } /* ok, we have acquired next formatted node in the tree */ n_retval = bin_search (p_s_key, B_N_PITEM_HEAD(p_s_bh, 0), B_NR_ITEMS(p_s_bh), is_leaf_node (p_s_bh) ? IH_SIZE : KEY_SIZE, &(p_s_last_element->pe_position)); if (node_level (p_s_bh) == n_stop_level) return n_retval; /* we are not in the stop level */ if (n_retval == ITEM_FOUND) /* item has been found, so we choose the pointer which is to the right of the found one */ p_s_last_element->pe_position++; /* if item was not found we choose the position which is to the left of the found item. This requires no code, bin_search did it already.*/ /* So we have chosen a position in the current node which is an internal node. Now we calculate child block number by position in the node. */ n_block_number = B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position); } }