| /* |
| * Copyright 1996-2004 by Hans Reiser, licensing governed by |
| * reiserfsprogs/README |
| */ |
| |
| #include "reiserfs/libreiserfs.h" |
| #include <stdio.h> |
| |
| #if 0 |
| |
| #include "io.h" |
| #include "misc.h" |
| #include "reiserfs_lib.h" |
| |
| #include <string.h> |
| #include <errno.h> |
| #include <time.h> |
| #include <assert.h> |
| |
| #include "../version.h" |
| #endif |
| |
| /* main.c */ |
| extern reiserfs_filsys_t * fs; |
| |
| /* Exit codes. */ |
| #define EXIT_OK 0 |
| #define EXIT_FIXED 1 |
| #define EXIT_REBOOT 2 |
| #define EXIT_FATAL 4 |
| #define EXIT_FIXABLE 6 |
| #define EXIT_OPER 8 /* Some operation returns error. */ |
| #define EXIT_USER 16 |
| |
| /* |
| * modes |
| */ |
| #define DO_NOTHING 0 |
| #define FSCK_CHECK 1 |
| #define FSCK_FIX_FIXABLE 2 |
| #define FSCK_SB 3 |
| #define FSCK_REBUILD 4 |
| #define FSCK_ROLLBACK_CHANGES 5 |
| #define FSCK_CLEAN_ATTRIBUTES 7 |
| #define FSCK_AUTO 8 /* -a || -p specified */ |
| |
| /* temporary */ |
| #define DO_TEST 9 |
| |
| /* |
| * options |
| */ |
| |
| #define OPT_INTERACTIVE 1 << 0 |
| #define OPT_ADJUST_FILE_SIZE 1 << 1 /* not default yet */ |
| #define OPT_QUIET 1 << 2 /* no "speed" info */ |
| #define OPT_SILENT 1 << 3 /* no complains about found corruptions */ |
| #define OPT_BACKGROUND 1 << 4 |
| #define OPT_SKIP_JOURNAL 1 << 5 |
| #define OPT_HASH_DEFINED 1 << 6 |
| #define OPT_SAVE_PASSES_DUMP 1 << 7 |
| #define OPT_SAVE_ROLLBACK 1 << 8 |
| #define OPT_YES 1 << 9 |
| #define BADBLOCKS_FILE 1 << 10 |
| |
| /* set by fsck when pass-by-pass (-d), FS_FATAL flag included */ |
| enum fsck_state_flags { |
| PASS_0_DONE = 0xfa02, |
| PASS_1_DONE = 0xfb02, |
| TREE_IS_BUILT = 0xfc02, |
| SEMANTIC_DONE = 0xfd02, |
| LOST_FOUND_DONE = 0xfe02 |
| |
| }; |
| |
| /* Stage.c */ |
| |
| extern void fsck_stage_start_put (FILE * file, unsigned long stage); |
| extern void fsck_stage_end_put (FILE * file); |
| extern int fsck_stage_magic_check (FILE * fp); |
| |
| /* pass0.c */ |
| extern int pass0_block_isbad_unfm(unsigned long block); |
| extern int pass0_block_isgood_unfm(unsigned long block); |
| extern int pass0_block_isleaf(unsigned long block); |
| extern void pass0_block_clleaf(unsigned long block); |
| extern void fsck_pass0 (reiserfs_filsys_t *); |
| extern void fsck_pass0_load_result (FILE *, reiserfs_filsys_t *); |
| extern void make_allocable (unsigned long block); |
| extern int fsck_leaf_check(reiserfs_bh_t * bh); |
| extern unsigned long alloc_block (void); |
| extern void fsck_pass0_aux_fini (); |
| extern int fsck_leaf_item_check (reiserfs_bh_t * bh, reiserfs_ih_t *, char *); |
| extern int are_there_allocable_blocks (unsigned int amout_needed); |
| extern int fsck_leaf_check_header(reiserfs_filsys_t * fs, reiserfs_bh_t * bh); |
| |
| /* pass1.c */ |
| #define fsck_item_reach(ih) (reiserfs_ih_isreach (ih) ? 1 : 0) |
| #define fsck_item_mkunreach(ih) \ |
| ({ \ |
| reiserfs_ih_clflags (ih); \ |
| reiserfs_ih_mkunreach (ih); \ |
| \ |
| if (reiserfs_ih_ext (ih)) \ |
| reiserfs_ih_set_free (ih, 0); \ |
| }) |
| |
| #define fsck_item_mkreach(ih, bh) \ |
| ({ \ |
| reiserfs_ih_clunreach (ih); \ |
| reiserfs_buffer_mkdirty (bh); \ |
| }) |
| |
| extern void fsck_pass1 (reiserfs_filsys_t *); |
| extern void fsck_pass1_load_result (FILE *, reiserfs_filsys_t *); |
| extern void fsck_pass2 (reiserfs_filsys_t *); |
| extern void fsck_info_checkmem(void); |
| |
| /* pass2.c */ |
| typedef struct saveitem saveitem_t; |
| struct saveitem { |
| reiserfs_ih_t si_ih; |
| char * si_dnm_data; |
| saveitem_t * si_next; |
| __u32 si_blocknr; |
| |
| // changed by XB; |
| saveitem_t * last_known; |
| }; |
| |
| extern void fsck_pass2_load_result (reiserfs_filsys_t *); |
| |
| extern void fsck_item_save(reiserfs_path_t * path, |
| saveitem_t ** head); |
| |
| extern saveitem_t * fsck_item_free(saveitem_t * si); |
| |
| extern void fsck_tree_insert_item (reiserfs_ih_t * ih, |
| char * item, int was_in_tree); |
| |
| extern void fsck_tree_merge(reiserfs_path_t *path); |
| extern long long int must_there_be_a_hole (const reiserfs_ih_t *ih, |
| const reiserfs_key_t *key); |
| |
| extern int fsck_tree_insert_zero_ptr (reiserfs_filsys_t *fs, |
| reiserfs_key_t *key, |
| long long int p_count, |
| __u16 flags); |
| |
| extern void fsck_tree_rewrite(reiserfs_filsys_t *fs, |
| const reiserfs_key_t *start_key, |
| __u64 end, __u16 flags); |
| |
| typedef int (*tree_modify_t) (reiserfs_path_t *path, void *data); |
| |
| /* relocate.c */ |
| extern void fsck_relocate_mklinked(reiserfs_key_t *new_key); |
| extern __u32 fsck_relocate_get_oid (reiserfs_key_t * key); |
| extern __u32 fsck_relocate_oid(reiserfs_key_t * key); |
| extern void fsck_relocate_link_all (void); |
| extern __u32 fsck_relocate_check (reiserfs_ih_t * ih, int isdir); |
| |
| /* semantic.c */ |
| |
| /* return values for check_regular_file and check_semantic_tree */ |
| #define OK 0 |
| #define STAT_DATA_NOT_FOUND -1 |
| #define DIRECTORY_HAS_NO_ITEMS -2 |
| #define RELOCATED -3 |
| #define LOOP_FOUND -4 |
| |
| extern void fsck_semantic (reiserfs_filsys_t *); |
| extern void fsck_semantic_load_result (FILE *, reiserfs_filsys_t *); |
| extern void fsck_semantic_check (void); |
| extern int is_dot_dot (char * name, int namelen); |
| extern int is_dot (char * name, int namelen); |
| extern int not_a_directory (void * sd); |
| extern int not_a_regfile (void * sd); |
| extern void zero_nlink (reiserfs_ih_t * ih, void * sd); |
| extern int fix_obviously_wrong_sd_mode (reiserfs_path_t * path); |
| extern int wrong_st_blocks(const reiserfs_key_t * key, |
| __u32 * blocks, |
| __u32 sd_blocks, |
| __u16 mode, |
| int new_format); |
| extern int wrong_st_size (const reiserfs_key_t * key, |
| unsigned long long max_file_size, |
| int blocksize, |
| __u64 * size, |
| __u64 sd_size, |
| int type); |
| |
| extern int rebuild_semantic_pass (reiserfs_key_t * key, |
| const reiserfs_key_t * parent, |
| int is_dot_dot, |
| reiserfs_ih_t * new_ih); |
| |
| extern void relocate_dir (reiserfs_ih_t * ih); |
| |
| extern int rebuild_check_regular_file (reiserfs_path_t * path, |
| void * sd, |
| reiserfs_ih_t * new_ih); |
| |
| /* lost+found.c */ |
| extern void fsck_lost (reiserfs_filsys_t *); |
| extern void fsck_lost_load_result (reiserfs_filsys_t *); |
| |
| /* objectid.c */ |
| typedef struct id_map { |
| void **index; |
| __u32 count, last_used; |
| } id_map_t; |
| |
| extern void id_map_flush(struct id_map * map, reiserfs_filsys_t * fs); |
| extern void id_map_free(id_map_t *); |
| extern int id_map_mark(id_map_t *map, __u32 id); |
| extern id_map_t *id_map_init(); |
| extern __u32 id_map_alloc(id_map_t *map); |
| extern int id_map_test(id_map_t *map, __u32 id); |
| extern void fetch_objectid_map (struct id_map * map, |
| reiserfs_filsys_t * fs); |
| extern void reiserfs_objectid_map_save (FILE * fp, struct id_map * id_map); |
| extern struct id_map * reiserfs_objectid_map_load (FILE * fp); |
| |
| /* rollback.c */ |
| extern void fsck_rollback_fini (); |
| |
| extern void fsck_rollback_init (char * rollback_file, |
| unsigned int *bloksize, FILE * log); |
| |
| extern int fsck_rollback_prep (char * rollback_file, FILE * log); |
| |
| extern void fsck_rollback (int fd_device, |
| int fd_journal_device, |
| FILE * log); |
| |
| /* pass4.c */ |
| extern void fsck_cleanup (void); |
| |
| /* check_tree.c */ |
| extern void check_fs_tree (reiserfs_filsys_t *); |
| extern void fsck_tree_clean_attr (reiserfs_filsys_t * fs); |
| |
| extern int fsck_leaf_check_neigh (reiserfs_filsys_t *fs, |
| reiserfs_bh_t * bh, |
| int i); |
| |
| extern int fsck_tree_delete(reiserfs_key_t * start_key, |
| saveitem_t ** save_here, |
| int skip_dir_items, |
| tree_modify_t func, |
| void *data); |
| |
| |
| /* ubitmap.c */ |
| extern int is_block_used (unsigned long block); |
| extern void mark_block_used (unsigned long block, int check_hardware); |
| extern void fsck_bitmap_mkuninsert (unsigned long block); |
| extern int fsck_bitmap_isuninsert (unsigned long block); |
| extern void fsck_bitmap_cluninsert (unsigned long block); |
| extern int reiserfsck_new_blocknrs (reiserfs_filsys_t * fs, |
| unsigned long * pblocknrs, |
| unsigned long start_from, |
| int amount_needed); |
| |
| extern int reiserfsck_free_block (reiserfs_filsys_t * fs, |
| unsigned long block); |
| |
| extern reiserfs_bh_t * reiserfsck_get_new_buffer (unsigned long start); |
| |
| /* ufile.c */ |
| #define FSCK_MAX_GAP(bs) \ |
| (100 * REISERFS_ITEM_MAX(bs) / REISERFS_EXT_SIZE * bs) |
| |
| extern void fsck_file_relocate (reiserfs_key_t *key, |
| int update_key); |
| |
| extern int reiserfsck_file_write (reiserfs_ih_t * ih, |
| char * item, |
| int was_in_tree); |
| |
| extern int are_file_items_correct (reiserfs_ih_t * sd_ih, |
| void * sd, |
| __u64 * size, |
| __u32 * blocks, |
| int mark_passed_items, |
| int * symlink); |
| |
| /* ustree.c*/ |
| typedef int (*path_func_t) (reiserfs_filsys_t *, |
| reiserfs_path_t *); |
| |
| extern void fsck_tree_trav (reiserfs_filsys_t *, |
| path_func_t, |
| path_func_t, |
| int depth); |
| enum fsck_stage { |
| FS_CHECK = 0x0, |
| FS_PASS0 = 0x1, |
| FS_PASS1 = 0x2, |
| FS_PASS2 = 0x3, |
| FS_SEMANTIC = 0x4, |
| FS_LOST = 0x5, |
| FS_CLEANUP = 0x6, |
| FS_LAST |
| }; |
| |
| struct pass0_stat { |
| unsigned long dealt_with; /* number of blocks read during pass 0 */ |
| unsigned long leaves; /* blocks looking like reiserfs leaves found */ |
| unsigned long leaves_corrected; |
| unsigned long all_contents_removed; |
| unsigned long too_old_leaves; /* these are leaves which contains |
| direntries with different hash from the |
| one specified with -h */ |
| unsigned long wrong_pointers; /* pointers in extent items pointing to |
| wrong area */ |
| unsigned long pointed; /* pointers blocks of device pointed by all |
| extent items */ |
| |
| /* number of removed items. */ |
| unsigned long long removed; |
| }; |
| |
| |
| struct pass1_stat { |
| unsigned long leaves; /* leaves found in pass0 to build tree off */ |
| unsigned long inserted_leaves; /* number of leaves inserted by pointers */ |
| unsigned long pointed_leaves; /* pointers in extent items which pointed |
| to leaves (zeroed) */ |
| unsigned long uninsertable_leaves; |
| unsigned long non_unique_pointers; /* pointers to already pointed unformatted nodes */ |
| unsigned long correct_pointers; |
| unsigned long allocable_blocks; /* allocable blocks before pass 1 starts */ |
| }; |
| |
| |
| struct pass2_stat { |
| unsigned long leaves; /* leaves inserted item by item */ |
| unsigned long safe_non_unique_pointers; /* these are just the same pointers */ |
| unsigned long relocated; |
| unsigned long shared_objectids; |
| unsigned long rewritten; |
| }; |
| |
| |
| struct semantic_stat { |
| unsigned long regular_files; |
| unsigned long directories; |
| unsigned long symlinks; |
| unsigned long broken_files; |
| unsigned long others; |
| unsigned long fixed_sizes; |
| unsigned long oid_sharing; |
| unsigned long oid_sharing_dirs_relocated; |
| unsigned long oid_sharing_files_relocated; |
| unsigned long deleted_entries; |
| unsigned long added_sd; |
| unsigned long empty_lost_dirs; |
| unsigned long lost_found; |
| unsigned long lost_found_files; |
| unsigned long lost_found_dirs; |
| }; |
| |
| struct pass_4_stat { |
| unsigned long deleted_items; |
| }; |
| |
| |
| struct rebuild_info { |
| struct { |
| struct pass0_stat pass0; |
| struct pass1_stat pass1; |
| struct pass2_stat pass2; |
| struct semantic_stat semantic; |
| struct pass_4_stat pass4; |
| } pass_u; |
| |
| /* bitmaps */ |
| reiserfs_bitmap_t * source_bitmap; |
| reiserfs_bitmap_t * new_bitmap; |
| reiserfs_bitmap_t * allocable_bitmap; |
| reiserfs_bitmap_t * uninsertables; |
| |
| char * bitmap_file_name; |
| /*char * new_bitmap_file_name;*/ |
| char * passes_dump_file_name; /* after pass 0, 1 or 2 reiserfsck can store |
| data with which it will be able to start |
| from the point it stopped last time at */ |
| |
| unsigned short mode; |
| unsigned long options; |
| |
| /* rollback file */ |
| char * rollback_file; |
| |
| /* hash hits stat */ |
| int hash_amount; |
| unsigned long * hash_hits; |
| char * defined_hash; |
| |
| #define USED_BLOCKS 1 |
| #define EXTERN_BITMAP 2 |
| #define ALL_BLOCKS 3 |
| int scan_area; |
| int use_journal_area; |
| int test; |
| }; |
| |
| |
| struct check_info { |
| unsigned long bad_nodes; |
| unsigned long fatal_corruptions; |
| unsigned long fixable_corruptions; |
| // unsigned long badblocks_corruptions; |
| unsigned long leaves; |
| unsigned long internals; |
| unsigned long dirs; |
| unsigned long files; |
| unsigned long safe; |
| unsigned long unfm_pointers; |
| unsigned long zero_unfm_pointers; |
| reiserfs_bitmap_t * deallocate_bitmap; |
| }; |
| |
| |
| struct fsck_data { |
| unsigned short mode; /* check, rebuild, etc*/ |
| unsigned long options; |
| unsigned long mounted; |
| |
| struct rebuild_info rebuild; |
| struct check_info check; |
| |
| char * journal_dev_name; |
| /* log file name and handle */ |
| char * log_file_name; |
| FILE * log; |
| |
| /* this is a file where reiserfsck will explain what it is doing. This is |
| usually stderr. But when -g is specified - reiserfsck runs in the |
| background and append progress information into 'fsck.run' */ |
| FILE * progress; |
| |
| /* objectid maps */ |
| id_map_t * proper_id_map; |
| id_map_t * semantic_id_map; /* this objectid map is used to |
| cure objectid sharing problem */ |
| }; |
| |
| |
| #define fsck_data(fs) ((struct fsck_data *)((fs)->fs_vp)) |
| #define pass_0_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass0)) |
| #define pass_1_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass1)) |
| #define pass_2_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass2)) |
| #define sem_pass_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.semantic)) |
| #define pass_4_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass4)) |
| |
| #define fsck_check_stat(fs) (&(fsck_data(fs)->check)) |
| |
| |
| #define proper_id_map(s) fsck_data(s)->proper_id_map |
| #define semantic_id_map(s) fsck_data(s)->semantic_id_map |
| |
| #define fsck_source_bitmap(fs) fsck_data(fs)->rebuild.source_bitmap |
| #define fsck_new_bitmap(fs) fsck_data(fs)->rebuild.new_bitmap |
| #define fsck_allocable_bitmap(fs) fsck_data(fs)->rebuild.allocable_bitmap |
| #define fsck_uninsertables(fs) fsck_data(fs)->rebuild.uninsertables |
| |
| #define fsck_deallocate_bitmap(fs) fsck_data(fs)->check.deallocate_bitmap |
| |
| #define fsck_interactive(fs) (fsck_data(fs)->options & OPT_INTERACTIVE) |
| //#define fsck_fix_fixable(fs) (fsck_data(fs)->options & OPT_FIX_FIXABLE) |
| |
| #define fsck_run_one_step(fs) (fsck_data(fs)->options & OPT_SAVE_PASSES_DUMP) |
| |
| #define fsck_save_rollback(fs) (fsck_data(fs)->options & OPT_SAVE_ROLLBACK) |
| |
| /* change unknown modes (corrupted) to mode of regular files, fix file |
| sizes which are bigger than a real file size, relocate files with |
| shared objectids (this slows fsck down (when there are too many |
| files sharing the same objectid), it will also remove other names |
| pointing to this file */ |
| #define fsck_adjust_file_size(fs) (fsck_data(fs)->options & OPT_ADJUST_FILE_SIZE) |
| #define fsck_quiet(fs) (fsck_data(fs)->options & OPT_QUIET) |
| #define fsck_silent(fs) (fsck_data(fs)->options & OPT_SILENT) |
| #define fsck_in_background(fs) (fsck_data(fs)->options & OPT_BACKGROUND) |
| #define fsck_hash_defined(fs) (fsck_data(fs)->options & OPT_HASH_DEFINED) |
| #define fsck_skip_journal(fs) (fsck_data(fs)->options & OPT_SKIP_JOURNAL) |
| #define fsck_yes_all(fs) (fsck_data(fs)->options & OPT_YES) |
| |
| |
| #define fsck_mode(fs) (fsck_data(fs)->mode) |
| #define fsck_log_file(fs) (fsck_data(fs)->log) |
| #define fsck_progress_file(fs) ((fs && fsck_data(fs)->progress) ? fsck_data(fs)->progress : stderr) |
| |
| /* name of file where we store information for continuing */ |
| #define state_dump_file(fs) fsck_data(fs)->rebuild.passes_dump_file_name |
| |
| /* name of file where we store rollback data */ |
| #define state_rollback_file(fs) fsck_data(fs)->rebuild.rollback_file |
| |
| int fsck_info_ask (reiserfs_filsys_t * fs, |
| char * q, char * a, |
| int default_answer); |
| |
| void fsck_stage_report (int, reiserfs_filsys_t *); |
| |
| /*pass1: rebuild super block*/ |
| void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data); |
| |
| |
| /* special type for symlink not conflicting to any of item types. */ |
| #define TYPE_SYMLINK 4 |
| |
| |
| #define fsck_log(fmt, list...) \ |
| {\ |
| if (!fsck_silent (fs))\ |
| reiserfs_warning (fsck_log_file (fs), fmt, ## list);\ |
| } |
| |
| #define fsck_progress(fmt, list...) \ |
| {\ |
| reiserfs_warning (fsck_progress_file(fs), fmt, ## list);\ |
| fflush (fsck_progress_file(fs));\ |
| } |
| |
| #define FATAL 1 |
| #define FIXABLE 2 |
| |
| enum entry_type { |
| ET_NAME = 0x0, |
| ET_DOT = 0x1, |
| ET_DOT_DOT = 0x2, |
| ET_LOST_FOUND = 0x3, |
| ET_LAST |
| }; |
| |
| #define fsck_exit(fmt, list...) \ |
| {\ |
| reiserfs_warning (fsck_progress_file(fs), fmt, ## list);\ |
| exit (EXIT_USER);\ |
| } |
| |
| #define one_more_corruption(fs,kind) \ |
| ({ \ |
| if (kind == FATAL) \ |
| fsck_check_stat (fs)->fatal_corruptions++; \ |
| else if (kind == FIXABLE) \ |
| fsck_check_stat (fs)->fixable_corruptions++; \ |
| }) |
| |
| #define one_less_corruption(fs,kind) \ |
| ({ \ |
| if (kind == FATAL) \ |
| fsck_check_stat (fs)->fatal_corruptions--; \ |
| else if (kind == FIXABLE) \ |
| fsck_check_stat (fs)->fixable_corruptions--; \ |
| }) |