| /* |
| * Copyright 1999 Hans Reiser |
| */ |
| |
| #include "fsck.h" |
| |
| struct check_relocated { |
| __u32 old_dir_id; |
| __u32 old_objectid; |
| /*mode_t mode;*/ |
| struct check_relocated * next; |
| }; |
| |
| struct check_relocated * relocated_list; |
| |
| void to_be_relocated (struct key * key) |
| { |
| struct check_relocated * cur, * prev, * new_relocated; |
| |
| cur = relocated_list; |
| prev = 0; |
| |
| while (cur && comp_short_keys(key, (struct key *)cur) != 1) { |
| if (comp_short_keys (key, (struct key *)cur) == 0) |
| return; |
| prev = cur; |
| cur = cur->next; |
| } |
| |
| new_relocated = getmem (sizeof (struct check_relocated)); |
| copy_short_key ((struct key *)new_relocated, key); |
| |
| if (prev) { |
| new_relocated->next = prev->next; |
| prev->next = new_relocated; |
| } else { |
| new_relocated->next = 0; |
| relocated_list = new_relocated; |
| } |
| } |
| |
| int should_be_relocated (struct key * key) |
| { |
| struct check_relocated * cur, * next; |
| int ret = 0; |
| |
| cur = relocated_list; |
| |
| while (cur && comp_short_keys(key, (struct key *)cur) != 1) { |
| if (comp_short_keys (key, (struct key *)cur) == 0) { |
| ret = 1; |
| break; |
| } |
| cur = cur->next; |
| } |
| |
| while (relocated_list != cur) { |
| next = relocated_list->next; |
| freemem (relocated_list); |
| relocated_list = next; |
| } |
| return ret; |
| } |
| |
| // |
| // |
| // check S+ tree of the file system |
| // |
| // check_fs_tree stops and recommends to run fsck --rebuild-tree when: |
| // 1. read fails |
| // 2. node of wrong level found in the tree |
| // 3. something in the tree points to wrong block number |
| // out of filesystem boundary is pointed by tree |
| // to block marked as free in bitmap |
| // the same block is pointed from more than one place |
| // not data blocks (journal area, super block, bitmaps) |
| // 4. bad formatted node found |
| // 5. delimiting keys are incorrect |
| // |
| |
| |
| |
| /* mark every block we see in the tree in control bitmap, so, when to make |
| sure, that no blocks are pointed to from more than one place we use |
| additional bitmap (control_bitmap). If we see pointer to a block we set |
| corresponding bit to 1. If it is set already - run fsck with --rebuild-tree */ |
| static reiserfs_bitmap_t * control_bitmap; |
| static reiserfs_bitmap_t * source_bitmap; |
| |
| static int tree_scanning_failed = 0; |
| |
| |
| /* 1 if block is not marked as used in the bitmap */ |
| static int is_block_free (reiserfs_filsys_t * fs, unsigned long block) |
| { |
| return !reiserfs_bitmap_test_bit (source_bitmap, block); |
| } |
| |
| |
| /*static int hits = 0;*/ |
| |
| /* we have seen this block in the tree, mark corresponding bit in the |
| control bitmap */ |
| static void we_met_it (unsigned long block) |
| { |
| reiserfs_bitmap_set_bit (control_bitmap, block); |
| /*hits ++;*/ |
| } |
| |
| |
| /* have we seen this block somewhere in the tree before? */ |
| static int did_we_meet_it (unsigned long block) |
| { |
| return reiserfs_bitmap_test_bit (control_bitmap, block); |
| } |
| |
| |
| static void init_control_bitmap (reiserfs_filsys_t * fs) |
| { |
| int i; |
| unsigned long block; |
| unsigned long reserved; |
| |
| |
| control_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); |
| if (!control_bitmap) |
| die ("init_control_bitmap: could not create control bitmap"); |
| |
| /*printf ("Initially number of zeros in control bitmap %d\n", reiserfs_bitmap_zeros (control_bitmap));*/ |
| |
| /* skipped and super block */ |
| for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++) |
| we_met_it (i); |
| |
| /*printf ("SKIPPED: %d blocks marked used (%d)\n", hits, reiserfs_bitmap_zeros (control_bitmap)); |
| hits = 0;*/ |
| |
| /* bitmaps */ |
| block = fs->fs_super_bh->b_blocknr + 1; |
| for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) { |
| we_met_it (block); |
| |
| if (spread_bitmaps (fs)) |
| block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8); |
| else |
| block ++; |
| } |
| /*printf ("BITMAPS: %d blocks marked used (%d)\n", hits, reiserfs_bitmap_zeros (control_bitmap)); |
| hits = 0;*/ |
| |
| /* mark as used area of the main device either containing a journal or |
| reserved to hold it */ |
| |
| reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb); |
| |
| /* where does journal area (or reserved journal area) start from */ |
| |
| if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) && |
| !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) |
| die ("init_control_bitmap: wrong super block"); |
| |
| block = get_journal_start_must (fs); |
| |
| for (i = block; i < reserved + block; i ++) |
| we_met_it (i); |
| |
| if (fs->fs_badblocks_bm) |
| for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) { |
| if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) |
| we_met_it (i); |
| } |
| } |
| |
| |
| /* if we managed to complete tree scanning and if control bitmap and/or proper |
| amount of free blocks mismatch with bitmap on disk and super block's |
| s_free_blocks - we can fix that */ |
| static void handle_bitmaps (reiserfs_filsys_t * fs) |
| { |
| int diff, problem = 0; |
| |
| if (tree_scanning_failed) { |
| fsck_progress ("Could not scan whole tree. " |
| "--rebuild-tree is required\n"); |
| return; |
| } |
| |
| fsck_progress ("Comparing bitmaps.."); |
| |
| /* check free block counter */ |
| if (get_sb_free_blocks (fs->fs_ondisk_sb) != reiserfs_bitmap_zeros (control_bitmap)) { |
| fsck_log ("free block count %lu mismatches with a correct one %lu. \n", |
| get_sb_free_blocks (fs->fs_ondisk_sb), |
| reiserfs_bitmap_zeros (control_bitmap)); |
| problem++; |
| // one_more_corruption (fs, fatal); /* for now */ |
| } |
| |
| diff = reiserfs_bitmap_compare (source_bitmap, control_bitmap); |
| if (diff) { |
| fsck_log ("on-disk bitmap does not match to the correct one. \n", diff); |
| problem++; |
| } |
| |
| if (problem) { |
| if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { |
| fsck_progress ("Trying to fix bitmap ..\n", diff); |
| /* mark blocks as used in source bitmap if they are used in control bitmap */ |
| reiserfs_bitmap_disjunction (source_bitmap, control_bitmap); |
| /* change used blocks count accordinly source bitmap, |
| copy bitmap changes to on_disk bitmap */ |
| set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (source_bitmap)); |
| reiserfs_bitmap_copy (fs->fs_bitmap2, source_bitmap); |
| mark_buffer_dirty (fs->fs_super_bh); |
| /* check again */ |
| if ((diff = reiserfs_bitmap_compare (source_bitmap, control_bitmap)) != 0) { |
| /* do not mark them as fatal or fixable because one can live with leaked space. |
| So this is not a fatal corruption, and fix-fixable cannot fix it */ |
| // one_more_corruption (fs, fatal); |
| fsck_progress (" bitmaps were not recovered. \n" |
| "\tYou can either run rebuild-tree or live with %d leaked blocks\n", diff); |
| } else { |
| fsck_progress ("ok\n"); |
| } |
| } else { |
| while (problem) { |
| /* fixable corruptions because we can try to recover them w/out rebuilding the tree */ |
| one_more_corruption (fs, fixable); |
| problem --; |
| } |
| } |
| } else |
| fsck_progress ("ok\n"); |
| |
| return; |
| } |
| |
| |
| /* is this block legal to be pointed to by some place of the tree? */ |
| static int bad_block_number (reiserfs_filsys_t * fs, unsigned long block) |
| { |
| if (block >= get_sb_block_count (fs->fs_ondisk_sb) || |
| not_data_block (fs, block)) { |
| /* block has value which can not be used as a pointer in a tree */ |
| |
| return 1; |
| /* |
| if (is_unfm_pointer) { |
| // unformatted node pointer will be zeroed |
| one_more_corruption (fs, fixable); |
| return 1; |
| } |
| |
| // internal nodes can not have wrong pointer |
| one_more_corruption (fs, fatal); |
| return 1; |
| */ |
| |
| } |
| |
| if (is_block_free (fs, block)) { |
| /* block is marked free - bitmap problems will be handled later */ |
| //one_more_corruption (fs, fixable); |
| } |
| |
| return 0; |
| } |
| |
| |
| static int got_already (reiserfs_filsys_t * fs, unsigned long block) |
| { |
| #if 0 |
| if (0/*opt_fsck_mode == FSCK_FAST_REBUILD*/){ |
| if (is_block_used(block)){ |
| fsck_log ("block %lu is in tree already\n", block); |
| return 1; |
| } |
| } else { |
| #endif |
| |
| if (did_we_meet_it (block)) { |
| /* block is in tree at least twice */ |
| return 1; |
| } |
| we_met_it (block); |
| return 0; |
| } |
| |
| |
| /* 1 if some of fields in the block head of bh look bad */ |
| static int bad_block_head (reiserfs_filsys_t * fs, struct buffer_head * bh) |
| { |
| struct block_head * blkh; |
| int sum_length = 0; |
| |
| blkh = B_BLK_HEAD (bh); |
| if (get_blkh_nr_items (blkh) > (bh->b_size - BLKH_SIZE) / IH_SIZE) { |
| fsck_log ("block %lu has wrong blk_nr_items (%z)\n", |
| bh->b_blocknr, bh); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) { |
| fsck_log ("leaf %lu has wrong structure\n", bh->b_blocknr); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| sum_length = (get_blkh_nr_items (blkh) > 0) ? |
| get_ih_location (B_N_PITEM_HEAD (bh, get_blkh_nr_items (blkh) - 1)) : bh->b_size; |
| |
| if (get_blkh_free_space (blkh) != |
| sum_length - BLKH_SIZE - IH_SIZE * get_blkh_nr_items (blkh)) |
| { |
| fsck_log ("block (%lu) has wrong blk_free_space (%lu) should be (%lu)", |
| bh->b_blocknr, get_blkh_free_space (blkh), sum_length - BLKH_SIZE - IH_SIZE * get_blkh_nr_items (blkh) ); |
| if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { |
| set_blkh_free_space (blkh, sum_length - BLKH_SIZE - IH_SIZE * get_blkh_nr_items (blkh)); |
| fsck_log (" - fixed on (%lu)\n", get_blkh_free_space (blkh)); |
| mark_buffer_dirty (bh); |
| } else { |
| fsck_log ("\n"); |
| one_more_corruption (fs, fixable); |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| /* 1 if it does not look like reasonable stat data */ |
| static int bad_stat_data (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) |
| { |
| unsigned long objectid; |
| __u32 pos; |
| __u32 links; |
| struct stat_data * sd; |
| |
| /* |
| if (opt_fsck_mode == FSCK_FAST_REBUILD) |
| return 0; |
| */ |
| objectid = get_key_objectid (&ih->ih_key); |
| if (!is_objectid_used (fs, objectid)) { |
| /* FIXME: this could be cured right here */ |
| fsck_log ("\nbad_stat_data: %lu is marked free, but used by an object %k\n", |
| objectid, &ih->ih_key); |
| |
| /* if it is FIX_FIXABLE we flush objectid map at the end |
| no way to call one_less_corruption later |
| */ |
| if (fsck_mode (fs) != FSCK_FIX_FIXABLE) |
| one_more_corruption (fs, fixable); |
| } |
| |
| if (is_objectid_really_used (proper_id_map (fs), objectid, &pos)) { |
| fsck_log ("\nbad_stat_data: %lu is shared by at least two files\n", |
| objectid); |
| if (fsck_mode (fs) == FSCK_FIX_FIXABLE) |
| to_be_relocated (&ih->ih_key); |
| |
| one_more_corruption (fs, fixable); |
| |
| return 0; |
| } |
| |
| sd = (struct stat_data *)B_I_PITEM(bh,ih); |
| if (fsck_mode (fs) == FSCK_CHECK) { |
| get_sd_nlink (ih, sd, &links); |
| if (S_ISDIR(sd->sd_mode)) { |
| if (links < 2) { |
| fsck_log ("%s: block %lu, [%k], directory SD has bad nlink number\n", |
| __FUNCTION__, bh->b_blocknr, &ih->ih_key); |
| one_more_corruption (fs, fixable); |
| } |
| } else { |
| if (links == 0) { |
| fsck_log ("%s: block %lu, [%k], SD has bad nlink number\n", |
| __FUNCTION__, bh->b_blocknr, &ih->ih_key); |
| one_more_corruption (fs, fixable); |
| } |
| } |
| } else { |
| links = 0; |
| set_sd_nlink (ih, sd, &links); |
| mark_buffer_dirty (bh); |
| } |
| |
| __mark_objectid_really_used (proper_id_map (fs), objectid, pos); |
| return 0; |
| } |
| |
| |
| /* it looks like we can check item length only */ |
| static int bad_direct_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) |
| { |
| return 0; |
| } |
| |
| |
| inline void handle_one_pointer (reiserfs_filsys_t * fs, struct buffer_head * bh, __u32 * ptr) { |
| if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { |
| fsck_log (" - fixed"); |
| *ptr = 0; |
| mark_buffer_dirty (bh); |
| } else { |
| one_more_corruption (fs, fixable); |
| } |
| } |
| |
| /* |
| static int bad_badblocks_item (reiserfs_filsys_t * fs, struct buffer_head * bh, |
| struct item_head * ih) { |
| int i; |
| __u32 * ind = (__u32 *)B_I_PITEM (bh, ih); |
| |
| if (get_ih_item_len (ih) % 4) { |
| fsck_log ("%s: block %lu: item (%H) has bad length\n", __FUNCTION__, |
| bh->b_blocknr, ih); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| for (i = 0; i < I_UNFM_NUM (ih); i ++) { |
| // __u32 unfm_ptr; |
| |
| // unfm_ptr = le32_to_cpu (ind [i]); |
| if (!le32_to_cpu (ind [i])) { |
| fsck_log ("%s: block %lu: badblocks item (%H) has zero pointer."); |
| fsck_log ("Not an error, but could be deleted with --fix-fixable\n", |
| __FUNCTION__, bh->b_blocknr, ih); |
| continue; |
| } |
| |
| // check list of badblocks pointers |
| if (le32_to_cpu (ind [i]) >= get_sb_block_count (fs->fs_ondisk_sb)) { |
| fsck_log ("%s: badblock pointer (block %lu) points out of disk spase (%lu)", |
| __FUNCTION__, bh->b_blocknr, le32_to_cpu (ind [i])); |
| handle_one_pointer (fs, bh, &ind[i]); |
| fsck_log ("\n"); |
| } |
| |
| if (did_we_meet_it (le32_to_cpu (ind [i]))) { |
| // it can be |
| // 1. not_data_block |
| // delete pointer |
| // 2. ind [i] or internal/leaf |
| // advice to run fix-fixable if there is no fatal errors |
| // with list of badblocks, say that it could fix it. |
| |
| if (not_data_block (fs, le32_to_cpu (ind [i]))) { |
| fsck_log ("%s: badblock pointer (block %lu) points on fs metadata (%lu)", |
| __FUNCTION__, bh->b_blocknr, le32_to_cpu (ind [i])); |
| handle_one_pointer (fs, bh, &ind[i]); |
| fsck_log ("\n"); |
| } else { |
| one_more_corruption (fs, badblocks); |
| fsck_log ("%s: badblock item points to a block" |
| " which in the tree already. Use --badblock-file option" |
| " to fix the problem\n", __FUNCTION__); |
| } |
| } else { |
| we_met_it (le32_to_cpu (ind [i])); |
| } |
| } |
| |
| return 0; |
| } |
| */ |
| |
| /* for each unformatted node pointer: make sure it points to data area and |
| that it is not in the tree yet */ |
| static int bad_indirect_item (reiserfs_filsys_t * fs, struct buffer_head * bh, |
| struct item_head * ih) |
| { |
| int i; |
| __u32 * ind = (__u32 *)B_I_PITEM (bh, ih); |
| |
| if (get_ih_item_len (ih) % 4) { |
| fsck_log ("%s: block %lu: item (%H) has bad length\n", |
| __FUNCTION__, bh->b_blocknr, ih); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| for (i = 0; i < I_UNFM_NUM (ih); i ++) { |
| // __u32 unfm_ptr; |
| |
| fsck_check_stat (fs)->unfm_pointers ++; |
| // unfm_ptr = le32_to_cpu (ind [i]); |
| if (!le32_to_cpu (ind [i])) { |
| fsck_check_stat (fs)->zero_unfm_pointers ++; |
| continue; |
| } |
| |
| /* check unformatted node pointer and mark it used in the |
| control bitmap */ |
| if (bad_block_number (fs, le32_to_cpu (ind [i]))) { |
| fsck_log ("%s: block %lu: item %H has bad pointer %d: %lu", |
| __FUNCTION__, bh->b_blocknr, ih, i, le32_to_cpu (ind [i])); |
| handle_one_pointer (fs, bh, &ind[i]); |
| fsck_log ("\n"); |
| continue; |
| } |
| |
| if (got_already (fs, le32_to_cpu (ind [i]))) { |
| fsck_log ("%s: block %lu: item %H has a pointer %d " |
| "to the block %lu which is in tree already", |
| __FUNCTION__, bh->b_blocknr, ih, i, le32_to_cpu (ind [i])); |
| handle_one_pointer (fs, bh, &ind [i]); |
| fsck_log ("\n"); |
| continue; |
| } |
| } |
| |
| #if 0 |
| /* delete this check for 3.6 */ |
| if (get_ih_free_space (ih) > fs->fs_blocksize - 1) { |
| if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { |
| /*FIXME: fix it if needed*/ |
| } else { |
| fsck_log ("bad_indirect_item: %H has wrong ih_free_space\n", ih); |
| one_more_corruption (fs, fixable); |
| } |
| } |
| #endif |
| |
| return 0; |
| } |
| |
| |
| /* FIXME: this was is_bad_directory from pass0.c */ |
| static int bad_directory_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih) |
| { |
| int i; |
| char * name; |
| int namelen; |
| struct reiserfs_de_head * deh = B_I_DEH (bh, ih); |
| int min_entry_size = 1;/* we have no way to understand whether the |
| filesystem were created in 3.6 format or |
| converted to it. So, we assume that minimal name |
| length is 1 */ |
| __u16 state; |
| |
| |
| /* make sure item looks like a directory */ |
| if (get_ih_item_len (ih) / (DEH_SIZE + min_entry_size) < get_ih_entry_count (ih)) { |
| /* entry count can not be that big */ |
| fsck_log ("%s: block %lu: directory item %H has corrupted structure\n", |
| __FUNCTION__, bh->b_blocknr, ih); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (get_deh_location (&deh[get_ih_entry_count (ih) - 1]) != DEH_SIZE * get_ih_entry_count (ih)) { |
| /* last entry should start right after array of dir entry headers */ |
| fsck_log ("%s: block %lu: directory item %H has corrupted structure\n", |
| __FUNCTION__, bh->b_blocknr, ih); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| /* check name hashing */ |
| for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) { |
| namelen = name_in_entry_length (ih, deh, i); |
| name = name_in_entry (deh, i); |
| if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) { |
| fsck_log ("%s: block %lu: directory item %H has hashed bad entry\n", |
| __FUNCTION__, bh->b_blocknr, ih); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| } |
| |
| deh = B_I_DEH (bh, ih); |
| state = (1 << DEH_Visible2); |
| /* ok, items looks like a directory */ |
| for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) { |
| if (get_deh_state (deh) != state) { |
| fsck_log ("bad_directory_item: block %lu: item %H has entry " |
| "\"%.*s\" with wrong deh_state %o - expected %o", |
| bh->b_blocknr, ih, name_in_entry_length (ih, deh, i), |
| name_in_entry (deh, i), get_deh_state (deh), state ); |
| if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { |
| set_deh_state (deh, 1 << DEH_Visible2); |
| mark_buffer_dirty (bh); |
| fsck_log (" - fixed"); |
| } else |
| one_more_corruption (fs, fixable); |
| |
| fsck_log ("\n"); |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| static int bad_item (reiserfs_filsys_t * fs, struct buffer_head * bh, int num) |
| { |
| struct item_head * ih; |
| |
| ih = B_N_PITEM_HEAD (bh, num); |
| |
| if (get_key_dirid (&ih->ih_key) == (__u32)-1) { |
| if (get_key_objectid (&ih->ih_key) != (__u32)-1) { |
| /* safe link can be |
| -1 object_id 0x1 -2 (truncate) or |
| -1 object_id blocksize+1 -1 (unlink) |
| */ |
| |
| if (is_direct_ih(ih)) |
| if (get_offset(&ih->ih_key) == fs->fs_blocksize + 1) |
| if (get_ih_item_len (ih) == 4) { |
| /*fsck_log("vpf-00010: safe link found [%k]\n", &ih->ih_key);*/ |
| fsck_check_stat(fs)->safe ++; |
| return 0; |
| } |
| |
| if (is_indirect_ih(ih)) |
| if(get_offset(&ih->ih_key) == 0x1) |
| if (get_ih_item_len (ih) == 4) { |
| /*fsck_log("vpf-00020: safe link found [%k]\n", &ih->ih_key);*/ |
| fsck_check_stat(fs)->safe ++; |
| return 0; |
| } |
| |
| /* it does not look like safe link */ |
| |
| /* dir_id == -1 can be used only by safe links */ |
| one_more_corruption (fs, fatal); |
| fsck_log ("%s: vpf-10290: block %lu item with wrong key (%k) found\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key); |
| return 1; |
| } else { |
| |
| /* BAD BLOCK LIST SUPPORT |
| if (is_indirect_ih (ih)) { |
| // it looks like badblocks item |
| if (fs->fs_badblocks_bm) |
| return 0; |
| else |
| return bad_badblocks_item (fs, bh, ih); |
| } else {*/ |
| |
| one_more_corruption (fs, fatal); |
| fsck_log ("%s: vpf-10300: block %lu item with wrong key (%k) found\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key); |
| return 1; |
| } |
| } else if (get_key_objectid (&ih->ih_key) == (__u32)-1) { |
| one_more_corruption (fs, fatal); |
| fsck_log ("%s: vpf-10310: block %lu item with wrong key (%k) found\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key); |
| return 1; |
| } |
| |
| if (is_stat_data_ih (ih)) |
| return bad_stat_data (fs, bh, ih); |
| |
| if (is_direct_ih (ih)) |
| return bad_direct_item (fs, bh, ih); |
| |
| if (is_indirect_ih(ih)) |
| return bad_indirect_item (fs, bh, ih); |
| |
| return bad_directory_item (fs, bh, ih); |
| } |
| |
| |
| /* 1 if i-th and (i-1)-th items can not be neighbors in a leaf */ |
| int bad_pair (reiserfs_filsys_t * fs, struct buffer_head * bh, int pos) |
| { |
| struct item_head * ih; |
| |
| ih = B_N_PITEM_HEAD (bh, pos); |
| |
| if (comp_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1) { |
| if (fsck_mode (fs) != FSCK_REBUILD) |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (is_stat_data_ih (ih)) |
| /* left item must be of another object */ |
| if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1) { |
| if (fsck_mode (fs) != FSCK_REBUILD) |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (get_key_dirid (&ih->ih_key) == (__u32)-1) { |
| if (get_key_objectid (&ih->ih_key) == (__u32)-1) { |
| /* BAD BLOCK LIST SUPPORT |
| if (is_indirect_ih (ih) && comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != 0) |
| return 0; // badblocks item |
| */ |
| /* it does not look like badblocks item */ |
| } else { |
| /* safe link ? */ |
| if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) == 0) { |
| if (is_indirect_ih (ih - 1) && is_direct_ih(ih)) |
| return 0; /* safe link */ |
| /* they do not look like safe links */ |
| } else { |
| if (is_indirect_ih (ih) || is_direct_ih(ih)) |
| return 0; /* safe link */ |
| /* it does not look like safe link */ |
| } |
| } |
| } |
| |
| if (is_direct_ih(ih)) { |
| /* left item must be indirect or stat data item of the same |
| file */ |
| if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key)) { |
| if (fsck_mode (fs) != FSCK_REBUILD) |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (!((is_stat_data_ih (ih - 1) && get_offset (&ih->ih_key) == 1) || |
| (is_indirect_ih (ih - 1) && |
| get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih-1, bh->b_size) == |
| get_offset (&ih->ih_key)))) { |
| if (fsck_mode (fs) != FSCK_REBUILD) |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| } |
| |
| if (is_indirect_ih (ih) || is_direntry_ih (ih)) { |
| /* left item must be stat data of the same object */ |
| if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key) || |
| !is_stat_data_ih (ih - 1)) { |
| if (fsck_mode (fs) != FSCK_REBUILD) |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| /* 1 if block head or any of items is bad */ |
| static int bad_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh) |
| { |
| int i; |
| |
| if (bad_block_head (fs, bh)) { |
| return 1; |
| } |
| |
| for (i = 0; i < B_NR_ITEMS (bh); i ++) { |
| if (bad_item (fs, bh, i)) { |
| fsck_log ("bad_leaf: block %lu has invalid item %d: %H\n", |
| bh->b_blocknr, i, B_N_PITEM_HEAD (bh, i)); |
| } |
| |
| if (i && bad_pair (fs, bh, i)) { |
| fsck_log ("bad_leaf: block %lu has wrong order of items [%d, %d]: %k %k\n", |
| bh->b_blocknr, i-1, i, &B_N_PITEM_HEAD (bh, i-1)->ih_key, &B_N_PITEM_HEAD (bh, i)->ih_key); |
| } |
| } |
| return 0; |
| } |
| |
| /* 1 if bh does not look like internal node */ |
| static int bad_internal (reiserfs_filsys_t * fs, struct buffer_head * bh) |
| { |
| int i; |
| |
| for (i = 0; i <= B_NR_ITEMS (bh); i ++) { |
| if (i != B_NR_ITEMS (bh) && i != B_NR_ITEMS (bh) - 1) |
| /* make sure that keys are in increasing order */ |
| if (comp_keys (B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1)) != -1) { |
| fsck_log ("%s: vpf-10320: block %lu has wrong order of keys %k, %k\n", |
| __FUNCTION__, bh->b_blocknr, B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1)); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| /* make sure that the child is correct */ |
| if (bad_block_number (fs, get_dc_child_blocknr (B_N_CHILD (bh,i)))) { |
| fsck_log ("%s: vpf-10330: block %lu: has bad pointer %d: %lu\n", |
| __FUNCTION__, bh->b_blocknr, i, get_dc_child_blocknr (B_N_CHILD (bh,i))); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| |
| /* h == 0 for root level. block head's level == 1 for leaf level */ |
| static inline int h_to_level (reiserfs_filsys_t * fs, int h) |
| { |
| return get_sb_tree_height (fs->fs_ondisk_sb) - h - 1; |
| } |
| |
| |
| /* bh must be formatted node. blk_level must be tree_height - h + 1 */ |
| static int bad_node (reiserfs_filsys_t * fs, struct buffer_head ** path, |
| int h) |
| { |
| struct buffer_head ** pbh = &path[h]; |
| |
| if (B_LEVEL (*pbh) != h_to_level (fs, h)) { |
| fsck_log ("node (%lu) with wrong level (%d) found in the tree (should be %d)\n", |
| (*pbh)->b_blocknr, B_LEVEL (*pbh), h_to_level (fs, h)); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (bad_block_number (fs, (*pbh)->b_blocknr)) { |
| one_more_corruption (fs, fatal); |
| fsck_log ("%s: vpf-10340: wrong block number %lu found in the tree\n", |
| __FUNCTION__, (*pbh)->b_blocknr); |
| return 1; |
| } |
| |
| if (got_already (fs, (*pbh)->b_blocknr)) { |
| fsck_log ("%s: vpf-10350: block number %lu is already in the tree\n", |
| __FUNCTION__, (*pbh)->b_blocknr); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (is_leaf_node (*pbh)) { |
| fsck_check_stat (fs)->leaves ++; |
| return bad_leaf (fs, *pbh); |
| } |
| |
| fsck_check_stat (fs)->internals ++; |
| return bad_internal (fs, *pbh); |
| } |
| |
| |
| /* internal node bh must point to block */ |
| static int get_pos (struct buffer_head * bh, unsigned long block) |
| { |
| int i; |
| |
| for (i = 0; i <= B_NR_ITEMS (bh); i ++) { |
| if (get_dc_child_blocknr (B_N_CHILD (bh, i)) == block) |
| return i; |
| } |
| die ("get_pos: position for block %lu not found", block); |
| return 0; |
| } |
| |
| |
| /* path[h] - leaf node */ |
| static struct key * lkey (struct buffer_head ** path, int h) |
| { |
| int pos; |
| |
| while (h > 0) { |
| pos = get_pos (path[h - 1], path[h]->b_blocknr); |
| if (pos) |
| return B_N_PDELIM_KEY(path[h - 1], pos - 1); |
| h --; |
| } |
| return 0; |
| } |
| |
| |
| /* path[h] - leaf node */ |
| static struct key * rkey (struct buffer_head ** path, int h) |
| { |
| int pos; |
| |
| while (h > 0) { |
| pos = get_pos (path[h - 1], path[h]->b_blocknr); |
| if (pos != B_NR_ITEMS (path[h - 1])) |
| return B_N_PDELIM_KEY (path[h - 1], pos); |
| h --; |
| } |
| return 0; |
| } |
| |
| |
| /* are all delimiting keys correct */ |
| static int bad_path (reiserfs_filsys_t * fs, struct buffer_head ** path, int h1) |
| { |
| int h = 0; |
| struct key * dk; |
| int pos = 0; |
| |
| while (path[h]) |
| h ++; |
| |
| h--; |
| |
| // path[h] is leaf |
| if (h != h1) |
| die ("bad_path: wrong path"); |
| |
| if (h) |
| pos = get_pos (path[h - 1], path[h]->b_blocknr); |
| |
| dk = lkey (path, h); |
| if (dk && comp_keys (dk, B_N_PKEY (path[h], 0))) { |
| /* left delimiting key must be equal to the key of 0-th item in the |
| node */ |
| fsck_log ("bad_path: left delimiting key %k must be equal to %k (block %lu, pos %d)\n", |
| dk, B_N_PKEY (path[h], 0), path[h]->b_blocknr, 0); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| dk = rkey (path, h); |
| if (dk && comp_keys (dk, B_N_PKEY (path[h], |
| get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1)) != 1) { |
| /* right delimiting key must be bigger than the key of the last item |
| in the node */ |
| fsck_log ("bad_path: right delimiting key %k must be equal to %k (block %lu, pos %d)\n", |
| dk, B_N_PKEY (path[h], get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1), |
| path[h]->b_blocknr, get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1); |
| one_more_corruption (fs, fatal); |
| return 1; |
| } |
| |
| if (h && (get_dc_child_size (B_N_CHILD(path[h-1],pos)) + |
| get_blkh_free_space ((struct block_head *)path[h]->b_data) + |
| BLKH_SIZE != path[h]->b_size)) |
| { |
| /* wrong dc_size */ |
| |
| fsck_log ("bad_path: wrong sum of dc_size %d (block %lu, pos %d) ", |
| get_dc_child_size (B_N_CHILD(path[h-1],pos)), path[h-1]->b_blocknr, pos); |
| fsck_log ("free space %d (block %lu) and BLKH_SIZE %lu", |
| get_blkh_free_space ((struct block_head *)path[h]->b_data), |
| path[h]->b_blocknr, BLKH_SIZE); |
| |
| if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { |
| set_dc_child_size (B_N_CHILD(path[h-1],pos), path[h]->b_size - |
| get_blkh_free_space ((struct block_head *)path[h]->b_data) - BLKH_SIZE); |
| fsck_log (" - fixed (%lu)\n", get_dc_child_size (B_N_CHILD(path[h-1],pos))); |
| mark_buffer_dirty (path[h-1]); |
| } else { |
| one_more_corruption (fs, fixable); |
| fsck_log ("\n"); |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static void before_check_fs_tree (reiserfs_filsys_t * fs) { |
| init_control_bitmap (fs); |
| |
| source_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); |
| reiserfs_bitmap_copy (source_bitmap, fs->fs_bitmap2); |
| |
| proper_id_map (fs) = init_id_map (); |
| } |
| |
| static void after_check_fs_tree (reiserfs_filsys_t * fs) { |
| if (fsck_mode(fs) == FSCK_FIX_FIXABLE) { |
| fs->fs_dirt = 1; |
| reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs); |
| reiserfs_flush (fs); |
| } |
| reiserfs_delete_bitmap (source_bitmap); |
| reiserfs_delete_bitmap (control_bitmap); |
| flush_buffers (fs->fs_dev); |
| } |
| |
| /* pass the S+ tree of filesystem */ |
| void check_fs_tree (reiserfs_filsys_t * fs) |
| { |
| before_check_fs_tree (fs); |
| |
| fsck_progress ("Checking S+tree.."); |
| pass_through_tree (fs, bad_node, bad_path); |
| /* S+ tree is correct (including all objects have correct |
| sequences of items) */ |
| fsck_progress ("ok\n"); |
| |
| /* compare created bitmap with the original */ |
| handle_bitmaps (fs); |
| |
| after_check_fs_tree (fs); |
| } |
| |
| static int clean_attributes_handler (reiserfs_filsys_t * fs, struct buffer_head ** path, int h) { |
| struct buffer_head * bh = path[h]; |
| int i; |
| |
| if (B_LEVEL (bh) != h_to_level (fs, h)) { |
| reiserfs_panic ("node (%lu) with wrong level (%d) found in the tree (should be %d)\n", |
| bh->b_blocknr, B_LEVEL (bh), h_to_level (fs, h)); |
| } |
| |
| if (!is_leaf_node (bh)) |
| return 0; |
| |
| for (i = 0; i < B_NR_ITEMS (bh); i ++) { |
| if (is_stat_data_ih (B_N_PITEM_HEAD (bh, i)) && |
| get_ih_item_len (B_N_PITEM_HEAD (bh, i)) == SD_SIZE) { |
| set_sd_v2_sd_attrs((struct stat_data *)B_N_PITEM(bh, i), 0); |
| mark_buffer_dirty (bh); |
| } |
| } |
| |
| return 0; |
| } |
| |
| void do_clean_attributes (reiserfs_filsys_t * fs) { |
| pass_through_tree (fs, clean_attributes_handler, NULL); |
| set_sb_v2_flag (fs->fs_ondisk_sb, reiserfs_attrs_cleared); |
| mark_buffer_dirty (fs->fs_super_bh); |
| } |
| |
| #if 0 |
| |
| void remove_internal_pointer(struct super_block * s, struct buffer_head ** path) |
| { |
| int h = 0; |
| int pos, items; |
| __u32 block; |
| |
| |
| while (path[h]) |
| h ++; |
| |
| h--; |
| block = path[h]->b_blocknr; |
| printf("\nremove pointer to (%d) block", block); |
| brelse(path[h]); |
| path[h] = 0; |
| h--; |
| while (h>=0) |
| { |
| if (B_NR_ITEMS(path[h]) <= 1) |
| { |
| block = path[h]->b_blocknr; |
| brelse(path[h]); |
| path[h] = 0; |
| mark_block_free(block); |
| /*unmark_block_formatted(block);*/ |
| used_blocks++; |
| h --; |
| continue; |
| } |
| pos = get_pos (path[h], block); |
| if (pos) |
| { |
| memmove (B_N_CHILD(path[h],pos), B_N_CHILD(path[h],pos+1), |
| s->s_blocksize - BLKH_SIZE - B_NR_ITEMS(path[h])*KEY_SIZE - DC_SIZE*(pos+1)); |
| memmove(B_N_PDELIM_KEY(path[h],pos-1), B_N_PDELIM_KEY(path[h],pos), |
| s->s_blocksize - BLKH_SIZE - (pos)*KEY_SIZE); |
| }else{ |
| __u32 move_block = path[h]->b_blocknr; |
| int move_to_pos; |
| int height = h; |
| |
| while(--height >= 0) |
| { |
| move_to_pos = get_pos (path[height], move_block); |
| if (move_to_pos == 0){ |
| move_block = path[height]->b_blocknr; |
| continue; |
| } |
| *B_N_PDELIM_KEY(path[height], move_to_pos-1) = *B_N_PDELIM_KEY(path[h], 0); |
| break; |
| } |
| |
| memmove (B_N_CHILD(path[h], 0), B_N_CHILD(path[h], 1), |
| s->s_blocksize - BLKH_SIZE - B_NR_ITEMS(path[h])*KEY_SIZE - DC_SIZE); |
| memmove(B_N_PDELIM_KEY(path[h], 0), B_N_PDELIM_KEY(path[h], 1), |
| s->s_blocksize - BLKH_SIZE - KEY_SIZE); |
| } |
| set_node_item_number(path[h], node_item_number(path[h]) - 1); |
| mark_buffer_dirty(path[h], 1); |
| break; |
| } |
| if (h == -1) |
| { |
| SB_DISK_SUPER_BLOCK(s)->s_root_block = ~0; |
| SB_DISK_SUPER_BLOCK(s)->s_tree_height = ~0; |
| mark_buffer_dirty(SB_BUFFER_WITH_SB(s), 1); |
| } |
| } |
| |
| void handle_buffer(struct super_block * s, struct buffer_head * bh) |
| { |
| int i, j; |
| struct item_head * ih; |
| |
| if (is_leaf_node (bh)) |
| { |
| for (i = 0, ih = B_N_PITEM_HEAD (bh, 0); i < B_NR_ITEMS (bh); i ++, ih ++) |
| { |
| if (is_indirect_ih(ih)) |
| for (j = 0; j < I_UNFM_NUM (ih); j ++) |
| if (B_I_POS_UNFM_POINTER(bh,ih,j)){ |
| /*mark_block_unformatted(le32_to_cpu(B_I_POS_UNFM_POINTER(bh,ih,j)));*/ |
| mark_block_used(le32_to_cpu(B_I_POS_UNFM_POINTER(bh,ih,j))); |
| used_blocks++; |
| } |
| if (is_stat_data_ih (ih)) { |
| /*add_event (STAT_DATA_ITEMS);*/ |
| if (ih_key_format(ih) == KEY_FORMAT_1) |
| ((struct stat_data_v1 *)B_I_PITEM(bh,ih))->sd_nlink = 0; |
| else |
| ((struct stat_data *)B_I_PITEM(bh,ih))->sd_nlink = 0; |
| mark_buffer_dirty(bh, 1); |
| } |
| } |
| } |
| mark_block_used(bh->b_blocknr); |
| // we_met_it(s, bh->b_blocknr); |
| used_blocks++; |
| } |
| |
| /* bh must be formatted node. blk_level must be tree_height - h + 1 */ |
| static int handle_node (struct super_block * s, struct buffer_head ** path, int h) |
| { |
| if (bad_node(s, path, h)){ |
| remove_internal_pointer(s, path); |
| return 1; |
| } |
| handle_buffer(s, path[h]); |
| return 0; |
| } |
| |
| /* are all delimiting keys correct */ |
| static int handle_path (struct super_block * s, struct buffer_head ** path, int h) |
| { |
| if (bad_path(s, path, h)){ |
| remove_internal_pointer(s, path); |
| return 1; |
| } |
| return 0; |
| } |
| |
| //return 1 to run rebuild tree from scratch |
| void check_internal_structure(struct super_block * s) |
| { |
| /* control bitmap is used to keep all blocks we should not put into tree again */ |
| /* used bitmap is used to keep all inserted blocks. The same as control bitmap plus unfm blocks */ |
| // init_control_bitmap(s); |
| |
| printf ("Checking S+tree.."); |
| |
| pass_through_tree (s, handle_node, handle_path); |
| |
| // compare_bitmaps(s); |
| printf ("ok\n"); |
| } |
| |
| #endif |
| /* |
| int check_sb (reiserfs_filsys_t * fs) |
| { |
| |
| |
| reiserfs_panic ("Not ready"); |
| return 0; |
| #if 0 |
| int format_sb = 0; |
| int problem = 0; |
| struct reiserfs_super_block * sb; |
| __u32 block_count; |
| unsigned long j_1st_block; |
| int sb_version; |
| |
| sb = fs->fs_ondisk_sb; |
| j_1st_block = get_jp_journal_1st_block (sb_jp (sb)); |
| |
| // in (REISERFS_DISK_OFFSET_IN_BYTES / 4096) block |
| if ((is_reiser2fs_magic_string (sb) || is_reiser2fs_jr_magic_string (sb) )&& |
| j_1st_block == get_journal_new_start_must (fs)) { |
| // 3.6 or >=3.5.22 |
| printf("\t 3.6.x format SB found\n"); |
| format_sb = 1; |
| goto good_format; |
| } |
| |
| if ( (is_reiserfs_magic_string (sb) ||is_reiser2fs_jr_magic_string (sb) ) && |
| j_1st_block == get_journal_new_start_must (fs)) { |
| // >3.5.9(10) and <=3.5.21 |
| printf("\t>=3.5.9 format SB found\n"); |
| format_sb = 2; |
| goto good_format; |
| } |
| |
| // in 2 block |
| if ( (is_reiser2fs_magic_string (sb) || is_reiser2fs_jr_magic_string (sb) ) && |
| j_1st_block == get_journal_old_start_must (sb)) { |
| // <3.5.9(10) converted to new format |
| printf("\t< 3.5.9(10) SB converted to new format found \n"); |
| format_sb = 3; |
| goto good_format; |
| } |
| |
| if ( (is_reiserfs_magic_string (sb) ||is_reiser2fs_jr_magic_string (sb) ) && |
| j_1st_block == get_journal_old_start_must (sb)) { |
| // <3.5.9(10) |
| printf("\t< 3.5.9(10) format SB found\n"); |
| format_sb = 4; |
| goto good_format; |
| } |
| else |
| die("check SB: wrong SB format found\n"); |
| |
| good_format: |
| |
| printf("\n\t%d-%d\n", get_sb_block_count (sb), get_sb_free_blocks (sb)); |
| if (fs->fs_blocksize != 4096) { |
| //??? |
| fsck_log("check SB: specified block size (%d) is not correct must be 4096\n", |
| fs->fs_blocksize); |
| problem++; |
| } |
| |
| //for 4096 blocksize only |
| if ((get_sb_tree_height (sb) < DISK_LEAF_NODE_LEVEL + 1) || |
| (get_sb_tree_height (sb) > MAX_HEIGHT)){ |
| fsck_log ("check SB: wrong tree height (%d)\n", get_sb_tree_height (sb)); |
| problem++; |
| } |
| |
| block_count = count_blocks (fs->fs_file_name, fs->fs_blocksize); |
| |
| if (get_sb_block_count (sb) > block_count){ |
| fsck_log ("check SB: specified block number (%d) is too high\n", |
| get_sb_block_count (sb)); |
| problem++; |
| } |
| |
| if ((get_sb_root_block (sb) >= block_count)) { |
| fsck_log ("check SB: specified root block number (%d) is too high\n", |
| get_sb_root_block (sb)); |
| problem++; |
| } |
| |
| if (get_sb_free_blocks (sb) > get_sb_block_count (sb)) { |
| fsck_log ("check SB: specified free block number (%d) is too high\n", |
| get_sb_free_blocks (sb)); |
| problem++; |
| } |
| |
| if (get_sb_state (sb) != REISERFS_VALID_FS && get_sb_state (sb) != REISERFS_ERROR_FS){ |
| fsck_log ("check SB: unknown (%d) state\n", get_sb_state (sb)); |
| problem++; |
| } |
| |
| if (get_sb_bmap_nr (sb) != (get_sb_block_count (sb) + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8)) { |
| fsck_log("check SB: wrong bitmap number (%d)\n", get_sb_bmap_nr (sb)); |
| problem++; |
| } |
| |
| sb_version = get_sb_version (sb); |
| if (sb_version == REISERFS_VERSION_3 || sb_version == REISERFS_VERSION_2 || sb_version == REISERFS_VERSION_1) { |
| if (!((sb_version == REISERFS_VERSION_3 ||sb_version == REISERFS_VERSION_2) && (format_sb == 1 || format_sb == 3)) && |
| !(sb_version == REISERFS_VERSION_1 && (format_sb == 2 || format_sb == 4))) { |
| fsck_log("check SB: wrong SB version == %d, format == %d\n", |
| sb_version, format_sb); |
| problem++; |
| } |
| } else { |
| fsck_log ("check SB: wrong SB version (%d)\n", sb_version); |
| problem++; |
| } |
| |
| if ((sb_version == REISERFS_VERSION_3 ||sb_version == REISERFS_VERSION_2) && |
| // FIXME: |
| (get_sb_hash_code (sb) < 1 || get_sb_hash_code (sb) > 3)) { |
| fsck_log("check SB: wrong hash (%d)\n", get_sb_hash_code (sb)); |
| problem++; |
| } |
| |
| |
| if ((sb_version == REISERFS_VERSION_3 ||sb_version == REISERFS_VERSION_2) ? |
| (get_sb_oid_maxsize (sb) != ((fs->fs_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2)) : |
| (get_sb_oid_maxsize (sb) != ((fs->fs_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2))) { |
| fsck_log("check SB: objectid map corrupted max_size == %d\n", |
| get_sb_oid_maxsize (sb)); |
| problem++; |
| } |
| |
| if (get_sb_oid_cursize (sb) < 2 || |
| get_sb_oid_cursize (sb) > get_sb_oid_maxsize (sb)) { |
| fsck_log("check SB: objectid map corrupted cur_size == %d\n", |
| get_sb_oid_cursize (sb)); |
| problem++; |
| } |
| |
| if (get_jp_journal_size (sb_jp (sb)) < JOURNAL_DEFAULT_SIZE/32 ){ |
| fsck_log("check SB: specified journal size (%d) is not correct must be not less that %d\n", |
| get_jp_journal_size (sb_jp (sb)), JOURNAL_DEFAULT_SIZE/32); |
| problem++; |
| } |
| |
| if (!problem) { |
| fsck_progress ("\t No problem found\n"); |
| } else if (fsck_log_file (fs) != stderr) |
| fsck_progress ("Look for super block corruptions in the log file\n"); |
| |
| return format_sb; |
| |
| #endif |
| } |
| |
| */ |