📄 semantic_rebuild.c
字号:
get_sd_blocks (ih, sd, &saved_blocks); get_sd_mode (ih, sd, &mode); /* release path pointing to stat data */ pathrelse (&path); /* make sure that "." and ".." exist */ reiserfs_add_entry (fs, key, ".", name_length (".", dir_format), key, 1 << IH_Unreachable); reiserfs_add_entry (fs, key, "..", name_length ("..", dir_format), parent, 1 << IH_Unreachable); set_key_dirid (&item_key, get_key_dirid (key)); set_key_objectid (&item_key, get_key_objectid (key)); set_key_offset_v1 (&item_key, DOT_OFFSET); set_key_uniqueness (&item_key, DIRENTRY_UNIQUENESS); dir_size = 0; while ((dir_item = get_next_directory_item (&item_key, parent, &tmp_ih, &pos_in_item)) != 0) { /* dir_item is copy of the item in separately allocated memory, item_key is a key of next item in the tree */ int i; char * name = 0; int namelen, entry_len; struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item; for (i = pos_in_item; i < get_ih_entry_count (&tmp_ih); i ++, deh ++) { struct item_head relocated_ih; if (name) { free (name); name = 0; } namelen = name_in_entry_length (&tmp_ih, deh, i); asprintf (&name, "%.*s", namelen, name_in_entry (deh, i)); entry_len = entry_length (&tmp_ih, deh, i); get_object_key (deh, &object_key, &entry_key, &tmp_ih); if ((dir_format == KEY_FORMAT_2) && (entry_len % 8 != 0)) { /* not alighed directory of new format - delete it */ fsck_log ("Entry %K (\"%.*s\") in the directory %K is not formated properly - fixed.\n", (struct key *)&(deh->deh2_dir_id), namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); entry_len = name_length (name, dir_format); reiserfs_add_entry (fs, key, name, entry_len, (struct key *)&(deh->deh2_dir_id), 0); }/* if ((dir_format == KEY_FORMAT_1) && (namelen != entry_len)) { // aligned entry in directory of old format - remove and insert it back fsck_log ("Entry %K (\"%.*s\") in the directory %K is not formated properly - deleted\n", (struct key *)&(deh->deh2_dir_id), namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); entry_len = name_length (name, dir_format); reiserfs_add_entry (fs, key, name, entry_len, (struct key *)&(deh->deh2_dir_id), 0); }*/ if (is_dot (name, namelen)) { dir_size += DEH_SIZE + entry_len; continue; } print_name (name, namelen); if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) reiserfs_panic ("rebuild_semantic_pass: Hash mismatch detected for (\"%.*s\") in directory %K\n", namelen, name, &tmp_ih.ih_key); retval1 = rebuild_semantic_pass (&object_key, key, is_dot_dot (name, namelen), &relocated_ih); erase_name (namelen); switch (retval1) { case OK: dir_size += DEH_SIZE + entry_len; break; case STAT_DATA_NOT_FOUND: case DIRECTORY_HAS_NO_ITEMS: if (get_offset (&entry_key) == DOT_DOT_OFFSET && get_key_objectid (&object_key) == REISERFS_ROOT_PARENT_OBJECTID) { /* ".." of root directory can not be found */ dir_size += DEH_SIZE + entry_len; continue; } fsck_log ("%s: The entry %K (\"%.*s\") in directory %K points to nowhere - is removed\n", __FUNCTION__, &object_key, namelen, name, &tmp_ih.ih_key); reiserfs_remove_entry (fs, &entry_key); sem_pass_stat (fs)->deleted_entries ++; break; case RELOCATED: /* file was relocated, update key in corresponding directory entry */ if (reiserfs_search_by_entry_key (fs, &entry_key, &path) != POSITION_FOUND) { fsck_log ("WARNING: Cannot find the name of the relocated file %K in the directory %K\n", &object_key, &tmp_ih.ih_key); } else { /* update key dir entry points to */ struct reiserfs_de_head * tmp_deh; tmp_deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item; fsck_log ("The entry %K (\"%.*s\") in directory %K updated to point to ", &object_key, namelen, name, &tmp_ih.ih_key); set_deh_dirid (tmp_deh, get_key_dirid (&relocated_ih.ih_key)); set_deh_objectid (tmp_deh, get_key_objectid (&relocated_ih.ih_key)); fsck_log ("%K\n", &tmp_deh->deh2_dir_id); mark_buffer_dirty (get_bh (&path)); } dir_size += DEH_SIZE + entry_len; pathrelse (&path); break; } } /* for */ freemem (dir_item); free (name); name = 0; if (not_of_one_file (&item_key, key)) /* next key is not of this directory */ break; } /* while (dir_item) */ if (dir_size == 0) /* FIXME: is it possible? */ return DIRECTORY_HAS_NO_ITEMS; /* calc correct value of sd_blocks field of stat data */ blocks = dir_size2st_blocks (dir_size); fix_sd = 0; fix_sd += wrong_st_blocks (key, &blocks, saved_blocks, mode, is_new_dir); fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1, fs->fs_blocksize, &dir_size, saved_size, TYPE_DIRENTRY); if (fix_sd) { /* we have to fix either sd_size or sd_blocks, so look for stat data again */ if (reiserfs_search_by_key_4 (fs, key, &path) != ITEM_FOUND) reiserfs_panic ("rebuild_semantic_pass: The StatData of the file %K was not found", key); bh = get_bh (&path); ih = get_ih (&path); sd = get_item (&path); set_sd_size (ih, sd, &dir_size); set_sd_blocks (ih, sd, &blocks); mark_buffer_dirty (bh); pathrelse (&path); } return retval;}int is_dot (char * name, int namelen){ return (namelen == 1 && name[0] == '.') ? 1 : 0;}int is_dot_dot (char * name, int namelen){ return (namelen == 2 && name[0] == '.' && name[1] == '.') ? 1 : 0;}int not_a_directory (void * sd){ /* mode is at the same place and of the same size in both stat datas (v1 and v2) */ struct stat_data_v1 * sd_v1 = sd; return !(S_ISDIR (le16_to_cpu (sd_v1->sd_mode)));}int not_a_regfile (void * sd){ /* mode is at the same place and of the same size in both stat datas (v1 and v2) */ struct stat_data_v1 * sd_v1 = sd; return !(S_ISREG (le16_to_cpu (sd_v1->sd_mode)));}void zero_nlink (struct item_head * ih, void * sd){ int zero = 0; if (get_ih_item_len (ih) == SD_V1_SIZE && get_ih_key_format (ih) != KEY_FORMAT_1) { fsck_log ("zero_nlink: The StatData %k of the wrong format version (%d) - corrected to (%d)\n", ih, get_ih_key_format (ih), KEY_FORMAT_1); set_ih_key_format (ih, KEY_FORMAT_1); } if (get_ih_item_len (ih) == SD_SIZE && get_ih_key_format (ih) != KEY_FORMAT_2) { fsck_log ("zero_nlink: The StatData %k of the wrong format version (%d) - corrected to (%d)\n", ih, get_ih_key_format (ih), KEY_FORMAT_2); set_ih_key_format (ih, KEY_FORMAT_2); } set_sd_nlink (ih, sd, &zero);}void modify_item (struct item_head * ih, void * item){ zero_nlink (ih, item); mark_item_unreachable (ih); }/* mkreiserfs should have created this */static void make_sure_lost_found_exists (reiserfs_filsys_t * fs){ int retval; INITIALIZE_PATH (path); unsigned int gen_counter; __u32 objectid; __u64 sd_size; __u32 sd_blocks; struct buffer_head * bh; struct item_head * ih; void * sd; int item_len; /* look for "lost+found" in the root directory */ retval = reiserfs_find_entry (fs, &root_dir_key, "lost+found", &gen_counter, &lost_found_dir_key); if (!retval) { objectid = id_map_alloc(proper_id_map(fs)); if (!objectid) { fsck_progress ("Could not allocate an objectid for \"/lost+found\", \ lost files will not be linked\n"); return; } set_key_dirid (&lost_found_dir_key, REISERFS_ROOT_OBJECTID); set_key_objectid (&lost_found_dir_key, objectid); } /* look for stat data of "lost+found" */ retval = reiserfs_search_by_key_4 (fs, &lost_found_dir_key, &path); if (retval == ITEM_NOT_FOUND) lost_found_dir_format = create_dir_sd (fs, &path, &lost_found_dir_key, modify_item); else { struct item_head * ih = get_ih (&path); if (!is_stat_data_ih (ih)) reiserfs_panic ("It must be lost+found's stat data %k\n", &ih->ih_key); fix_obviously_wrong_sd_mode (&path); if (not_a_directory (get_item (&path))) { fsck_progress ("\"/lost+found\" exists, but it is not a directory, \ lost files will not be linked\n"); set_key_objectid (&lost_found_dir_key, 0); pathrelse (&path); return; } lost_found_dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1; pathrelse (&path); } /* add "." and ".." if any of them do not exist */ reiserfs_add_entry (fs, &lost_found_dir_key, ".", name_length (".", lost_found_dir_format), &lost_found_dir_key, 1 << IH_Unreachable); reiserfs_add_entry (fs, &lost_found_dir_key, "..", name_length ("..", lost_found_dir_format), &root_dir_key, 1 << IH_Unreachable); item_len = reiserfs_add_entry (fs, &root_dir_key, "lost+found", name_length ("lost+found", root_dir_format), &lost_found_dir_key, 1 << IH_Unreachable); if (item_len) { if (reiserfs_search_by_key_4 (fs, &root_dir_key, &path) == ITEM_NOT_FOUND) reiserfs_panic ("%s: StatData of the root directory must exists", __FUNCTION__); bh = get_bh (&path); ih = get_ih (&path); sd = get_item(&path); get_sd_size (ih, sd, &sd_size); sd_size += item_len; set_sd_size (ih, sd, &sd_size); sd_blocks = dir_size2st_blocks (sd_size); set_sd_blocks (ih, sd, &sd_blocks); mark_buffer_dirty (bh); pathrelse (&path); } return;}/* Result of the rebuild pass will be saved in the state file which is needed to start * fsck again from the next pass. */static void save_rebuild_semantic_result (reiserfs_filsys_t * fs) { FILE * file; int retval; file = open_file ("temp_fsck_file.deleteme", "w+"); if (!file) return; reiserfs_begin_stage_info_save (file, SEMANTIC_DONE); /* Method not implemented yet. reiserfs_objectid_map_save (file, semantic_id_map (fs)); */ reiserfs_end_stage_info_save (file); close_file (file); retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs)); if (retval != 0) fsck_progress ("%s: Could not rename the temporary file temp_fsck_file.deleteme to %s", __FUNCTION__, state_dump_file (fs));}/* we have nothing to load from a state file, but we have to fetch on-disk bitmap, copy it to allocable bitmap, and fetch objectid map */void load_semantic_result (FILE * file, reiserfs_filsys_t * fs){ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2); fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb)); reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2); fs->block_allocator = reiserfsck_reiserfs_new_blocknrs; fs->block_deallocator = reiserfsck_reiserfs_free_block; /* we need objectid map on semantic pass to be able to relocate files */ proper_id_map (fs) = id_map_init(); /* Not implemented yet. fetch_objectid_map (proper_id_map (fs), fs); semantic_id_map (fs) = reiserfs_objectid_map_load (file); */}static void before_pass_3 (reiserfs_filsys_t * fs){ semantic_id_map (fs) = id_map_init();}static void after_pass_3 (reiserfs_filsys_t * fs){ /* update super block: objectid map, fsck state */ set_sb_fs_state (fs->fs_ondisk_sb, SEMANTIC_DONE); mark_buffer_dirty (fs->fs_super_bh); /* write all dirty blocks */ fsck_progress ("Flushing.."); id_map_flush(proper_id_map (fs), fs); fs->fs_dirt = 1; reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap(fs), fs); reiserfs_flush (fs); fsck_progress ("finished\n"); stage_report (3, fs); if (!fsck_run_one_step (fs)) { if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) /* reiserfsck continues */ return; } save_rebuild_semantic_result (fs); id_map_free(proper_id_map (fs)); proper_id_map (fs) = 0; fs->fs_dirt = 1; reiserfs_close (fs); exit(0);}/* this is part of rebuild tree */void pass_3_semantic (reiserfs_filsys_t * fs){ before_pass_3 (fs); fsck_progress ("Pass 3 (semantic):\n"); /* when warnings go not to stderr - separate them in the log */ if (fsck_log_file (fs) != stderr) fsck_log ("####### Pass 3 #########\n"); if (!fs->fs_hash_function) reiserfs_panic ("Hash function should be selected already"); make_sure_root_dir_exists (fs, modify_item, 1 << IH_Unreachable); make_sure_lost_found_exists (fs); id_map_mark(proper_id_map(fs), get_key_objectid(&root_dir_key)); id_map_mark(proper_id_map(fs), get_key_objectid(&lost_found_dir_key)); /* link all relocated files into /lost+found directory */ link_relocated_files (); rebuild_semantic_pass (&root_dir_key, &parent_root_dir_key, 0/*!dot_dot*/, 0/*reloc_ih*/); add_badblock_list(fs, 1); after_pass_3 (fs);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -