/* * Copyright 2002 by Hans Reiser, licensing governed by reiserfs/README */ #include "debugreiserfs.h" #include #include #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; struct item_head * ih; int is_there_unique_item; ih = B_N_PITEM_HEAD (bh, 0); is_there_unique_item = 0; for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); 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 < get_blkh_nr_items (B_BLK_HEAD (bh)); 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; */ total = reiserfs_bitmap_ones (input_bitmap (fs)); /* 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) { 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);*/ } }