| /* |
| * Copyright 2002-2003 by Hans Reiser, licensing governed by |
| * reiserfsprogs/README |
| */ |
| |
| #include "debugreiserfs.h" |
| #include <search.h> |
| #include <obstack.h> |
| |
| #define obstack_chunk_alloc malloc |
| #define obstack_chunk_free free |
| |
| |
| /* try to find blocks which contain only items which are */ |
| |
| |
| /* read blocks marked in debug_bitmap and collect statistic of it: |
| number of stat data */ |
| struct { |
| unsigned long all; |
| unsigned long items [5]; |
| unsigned long unique_keys; /* keys of stat datas */ |
| unsigned long unique_entry_keys; /* keys which appear in directory entries */ |
| unsigned long names; /* dir entries but "." and ".." */ |
| unsigned long dir_blocks; /* block containing only one directory item */ |
| unsigned long unique_items; |
| unsigned long leaves; |
| unsigned long blocks_to_skip; |
| } fs_stat; |
| |
| |
| /* store unique item heads */ |
| struct obstack items; |
| |
| /* tree sorting item heades by comp_items_1 */ |
| void * items_tree; |
| |
| |
| static int comp_items_1 (const void * p1, const void * p2) |
| { |
| int retval; |
| struct item_head * ih1, * ih2; |
| |
| /* |
| if (*(int *)p1 != *(int *)p2) |
| retval = 1; |
| else |
| retval = 0; |
| */ |
| retval = comp_keys (p1, p2); |
| /*retval = comp_short_keys (p1, p2);*/ |
| if (retval) |
| return retval; |
| |
| |
| ih1 = (struct item_head *)p1; |
| ih2 = (struct item_head *)p2; |
| |
| if (get_ih_item_len (ih1) < get_ih_item_len (ih2)) |
| return -1; |
| if (get_ih_item_len (ih1) > get_ih_item_len (ih2)) |
| return 1; |
| if (get_ih_entry_count (ih1) < get_ih_entry_count (ih2)) |
| return -1; |
| if (get_ih_entry_count (ih1) > get_ih_entry_count (ih2)) |
| return 1; |
| |
| return 0; |
| } |
| |
| |
| /* |
| static void print_node (const void *nodep, VISIT value, int level) |
| { |
| int i; |
| |
| if (value == leaf) { |
| for (i = 0; i < level; i ++) |
| reiserfs_warning (stdout, "\t"); |
| reiserfs_warning (stdout, "%H\n", *(struct item_head **)nodep); |
| return; |
| } |
| if (value == postorder) { |
| for (i = 0; i < level; i ++) |
| reiserfs_warning (stdout, "\t"); |
| reiserfs_warning (stdout, "%H\n", *(struct item_head **)nodep); |
| } |
| } |
| */ |
| |
| |
| static int is_unique_item (struct obstack * ostack, void ** tree, void * ih) |
| { |
| void * res; |
| void * key1; |
| |
| key1 = obstack_copy (ostack, ih, IH_SIZE); |
| res = tsearch (key1, tree, comp_items_1); |
| if (!res) |
| reiserfs_panic ("Too many keys found"); |
| |
| /* twalk (*tree, print_node);*/ |
| /* reiserfs_warning (stderr, "\n\n");*/ |
| if (*(void **)res != key1) { |
| /* key is in tree already, remove it from obstack */ |
| /*reiserfs_warning (stdout, "%H is skipped\n", ih);fflush (stdout);*/ |
| obstack_free (ostack, key1); |
| return 0; |
| } |
| |
| /*reiserfs_warning (stdout, "%k is added\n", ih);fflush (stdout);*/ |
| return 1; |
| } |
| |
| |
| static void stat1_the_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) |
| { |
| int i, i_num; |
| struct item_head * ih; |
| int is_there_unique_item; |
| |
| |
| ih = B_N_PITEM_HEAD (bh, 0); |
| is_there_unique_item = 0; |
| i_num = leaf_item_number_estimate(bh); |
| for (i = 0; i < i_num; i ++, ih ++) { |
| /* count all items */ |
| fs_stat.all ++; |
| |
| if (is_unique_item (&items, &items_tree, ih)) { |
| /* this is item we have not seen yet */ |
| fs_stat.unique_items ++; |
| is_there_unique_item ++; |
| } |
| } |
| |
| if (!is_there_unique_item) { |
| /* the node contains only items we have seen already. so we will skip |
| it */ |
| fs_stat.blocks_to_skip ++; |
| reiserfs_bitmap_clear_bit (input_bitmap (fs), bh->b_blocknr); |
| } else { |
| ih = B_N_PITEM_HEAD (bh, 0); |
| /* node contains at least one unique item. We will put it in, count items of each type */ |
| for (i = 0; i < i_num; i ++, ih ++) { |
| fs_stat.items [get_type (&ih->ih_key)] ++; |
| } |
| } |
| } |
| |
| /* |
| static void stat2_the_leaf (struct buffer_head * bh) |
| { |
| int i; |
| struct item_head * ih; |
| |
| ih = B_N_PITEM_HEAD (bh, 0); |
| for (i = 0; i < node_item_number (bh); i ++, ih ++) { |
| |
| } |
| } |
| */ |
| |
| void do_stat (reiserfs_filsys_t * fs) |
| { |
| unsigned long i; |
| unsigned long done, total; |
| struct buffer_head * bh; |
| int type; |
| FILE * fp; |
| |
| |
| obstack_init (&items); |
| items_tree = 0; |
| |
| /* |
| bh = bread (fs->s_dev, 8211, fs->s_blocksize); |
| stat1_the_leaf (fs, bh); |
| |
| return; |
| */ |
| |
| /* pass 0 of stating */ |
| total = reiserfs_bitmap_ones (input_bitmap (fs)); |
| done = 0; |
| for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { |
| if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i)) |
| continue; |
| |
| print_how_far (stderr, &done, total, 1, be_quiet (fs)); |
| |
| bh = bread (fs->fs_dev, i, fs->fs_blocksize); |
| if (!bh) { |
| printf ("could not read block %lu\n", i); |
| continue; |
| } |
| type = who_is_this (bh->b_data, bh->b_size); |
| if (type != THE_LEAF && type != HAS_IH_ARRAY) { |
| reiserfs_bitmap_clear_bit (input_bitmap (fs), i); |
| brelse (bh); |
| continue; |
| } |
| fs_stat.leaves ++; |
| stat1_the_leaf (fs, bh); |
| brelse (bh); |
| } |
| |
| reiserfs_warning (stderr, "\nThere were %lu leaves\n" |
| "\ttotal number of items %lu there\n" |
| "\tblocks containing at least one unique item %lu\n" |
| "\tblocks which can be skipped %lu\n" |
| "\t\tstat data %lu\n" |
| "\t\tindirect %lu\n" |
| "\t\tdirect %lu\n" |
| "\t\tdirectory items %lu\n" |
| "\tunique items %lu\n", |
| /* |
| "\tnames there (but \".\" and \"..\") %lu\n" |
| "\tpointing to unique keys %lu\n" |
| "other items %lu\n" |
| "blocks containing only 1 dir item %lu\n", |
| */ |
| fs_stat.leaves, |
| fs_stat.all, |
| fs_stat.leaves - fs_stat.blocks_to_skip, |
| fs_stat.blocks_to_skip, |
| fs_stat.items [TYPE_STAT_DATA], |
| fs_stat.items [TYPE_INDIRECT], |
| fs_stat.items [TYPE_DIRECT], |
| fs_stat.items [TYPE_DIRENTRY], |
| fs_stat.unique_items); |
| /* |
| fs_stat.names, |
| fs_stat.unique_keys, |
| fs_stat.items [4], |
| fs_stat.dir_blocks); |
| */ |
| if (!input_bitmap_file_name(fs)) |
| return; |
| |
| fp = fopen (input_bitmap_file_name(fs), "w"); |
| if (!fp) |
| reiserfs_panic ("stat: could not open %s to save bitmap: %m\n", |
| input_bitmap_file_name(fs)); |
| reiserfs_warning (stderr, "Updated bitmap contains %d blocks marked\n", |
| reiserfs_bitmap_ones (input_bitmap (fs))); |
| reiserfs_bitmap_save (fp, input_bitmap (fs)); |
| fclose (fp); |
| return; |
| |
| |
| /* pass 2 of stating */ |
| reiserfs_warning (stderr, "Looking for blocks containing only keys not pointed by any of entries\n"); |
| total = reiserfs_bitmap_ones (input_bitmap (fs)); |
| done = 0; |
| for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { |
| if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i)) |
| continue; |
| |
| print_how_far (stderr, &done, total, 1, be_quiet (fs)); |
| |
| bh = bread (fs->fs_dev, i, fs->fs_blocksize); |
| if (!bh) { |
| printf ("could not read block %lu\n", i); |
| continue; |
| } |
| /*stat2_the_leaf (bh);*/ |
| } |
| |
| } |