📄 ufile.c
字号:
}/* delete all items and put them back (after that file should have correct sequence of items. if should_relocate is specified then it relocates items to a new id. if should_change_ih is specified then the key in ih is changed also. */void rewrite_file (struct item_head * ih, int should_relocate, int should_change_ih){ struct key key; struct si * si; __u32 new_objectid = 0; int moved_items; struct key old, new; int nothing_else = 0; /* starting with the leftmost one - look for all items of file, store and delete and */ key = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA); si = 0; nothing_else = 0; nothing_else = delete_N_items_after_key (&key, &si, should_relocate /* do not skip dir items */, 10); if (should_relocate && (si || should_change_ih)) { /* get new objectid for relocation or get objectid with which file was relocated already */ new_objectid = objectid_for_relocation (&ih->ih_key); if (should_change_ih) set_key_objectid (&ih->ih_key, new_objectid); if (si) { old = si->si_ih.ih_key; set_key_objectid (&(si->si_ih.ih_key), new_objectid); new = si->si_ih.ih_key; } } moved_items = 0; while (si) { while (si && (nothing_else || si->si_next)) { if (should_relocate) { set_key_objectid (&(si->si_ih.ih_key), new_objectid); moved_items ++; } insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/); si = remove_saved_item (si); } if (!nothing_else) nothing_else = delete_N_items_after_key (&key, &si, should_relocate /* do not skip dir items */, 10); } if (moved_items) fsck_log ("rewrite_file: %d items of file %K moved to %K\n", moved_items, &old, &new);}/* file must have correct sequence of items and tail must be stored in unformatted pointer; pos in bh is a position of SD */static int make_file_writeable (struct buffer_head * bh, int pos)/* struct item_head * sd_ih, void * sd */{ struct item_head *sd_ih = B_N_PITEM_HEAD (bh, pos); struct item_head sd_ih_copy; struct stat_data *sd = (struct stat_data *)B_N_PITEM (bh, pos); struct stat_data sd_copy; __u64 size; __u32 blocks; __u16 mode; int retval, symlink; sd_ih_copy = *sd_ih; memcpy (&sd_copy, sd, get_ih_item_len (sd_ih)); get_sd_mode (sd_ih, sd, &mode); symlink = S_ISLNK(mode); if (ih_writable(sd_ih)) return 1; else { mark_ih_writable(sd_ih); mark_buffer_dirty (bh); } retval = are_file_items_correct (&sd_ih_copy, &sd_copy, &size, &blocks, 0/*do not mark accessed*/, &symlink); if (retval == 1) /* file looks correct */ return 1; rewrite_file (sd_ih, 0, 0); /*fsck_data (fs)->rebuild.rewritten ++;*//*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ size = 0; if (are_file_items_correct (&sd_ih_copy, &sd_copy, &size, &blocks, 0/*do not mark accessed*/, &symlink) == 0) { fsck_log("WARNING: file was rewritten but still is not correct %K\n", &sd_ih->ih_key); return -1; }/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ return 1;}/* this inserts __first__ indirect item (having k_offset == 1 and only one unfm pointer) into tree */static int create_first_item_of_file (struct item_head * ih, char * item, struct path * path, int was_in_tree){ __u32 unfm_ptr; __u32 * ni = 0; struct buffer_head * unbh; struct item_head indih; unsigned int i; int retval; mark_item_unreachable (&indih); copy_key (&(indih.ih_key), &(ih->ih_key)); set_ih_item_len (&indih, UNFM_P_SIZE); set_ih_free_space (&indih, 0); if (get_offset (&ih->ih_key) > fs->fs_blocksize) { /* insert indirect item containing 0 unfm pointer */ unfm_ptr = 0; retval = 0; } else { if (is_direct_ih (ih)) { /* copy direct item to new unformatted node. Save information about it */ int len = get_bytes_number (ih, fs->fs_blocksize); unbh = reiserfsck_get_new_buffer (PATH_PLAST_BUFFER (path)->b_blocknr); memset (unbh->b_data, 0, unbh->b_size); unfm_ptr = cpu_to_le32 (unbh->b_blocknr); memcpy (unbh->b_data + get_offset (&ih->ih_key) - 1, item, len); set_ih_free_space (&indih, fs->fs_blocksize - len - (get_offset (&ih->ih_key) - 1)); mark_ih_was_tail (&indih); mark_buffer_dirty (unbh); mark_buffer_uptodate (unbh, 1); brelse (unbh); retval = len; } else { /* take first unformatted pointer from an indirect item */ //free_sp = ih_get_free_space(0, ih, item); set_ih_item_len (&indih, get_ih_item_len (ih)); ni = getmem (get_ih_item_len (ih)); memcpy (ni, (item), get_ih_item_len (ih)); if (!was_in_tree) { for (i = 0; i < I_UNFM_NUM (ih); i++) { if (still_bad_unfm_ptr_2 (d32_get(ni, i))) reiserfs_panic ("create_first_item_of_file: The file %K has a pointer to the bad block (%u)", &ih->ih_key, d32_get(ni, i)); mark_block_used (d32_get(ni, i), 0); } } retval = fs->fs_blocksize * get_ih_item_len (ih) / UNFM_P_SIZE; } } set_ih_key_format (&indih, get_ih_key_format (ih)); //ih_version(&indih) = ih_version(ih); set_offset (key_format (&(ih->ih_key)), &indih.ih_key, 1); set_type (key_format (&(ih->ih_key)), &indih.ih_key, TYPE_INDIRECT); if (ni) { reiserfsck_insert_item (path, &indih, (const char *)ni); freemem (ni); } else { reiserfsck_insert_item (path, &indih, (const char *)&unfm_ptr); } return retval;}/* path points to first part of tail. Function copies file tail into unformatted node and returns its block number. *//* we convert direct item that is on the path to indirect. we need a number of free block for unformatted node. reiserfs_new_blocknrs will start from block number returned by this function */static unsigned long block_to_start (struct path * path){ struct buffer_head * bh; struct item_head * ih; __u32 blk; bh = PATH_PLAST_BUFFER (path); ih = PATH_PITEM_HEAD (path); if (get_offset(&ih->ih_key) == 1 || PATH_LAST_POSITION (path) == 0) return bh->b_blocknr; ih --; blk = d32_get((__u32 *)B_I_PITEM(bh, ih), I_UNFM_NUM (ih) - 1); return (blk ? blk : bh->b_blocknr);}static void direct2indirect2 (unsigned long unfm, struct path * path){ struct item_head * ih; struct key key; struct buffer_head * unbh; __u32 ni; int copied = 0; int file_format; ih = PATH_PITEM_HEAD (path); copy_key (&key, &(ih->ih_key)); file_format = key_format (&key); if (get_offset (&key) % fs->fs_blocksize != 1) { /* look for first part of tail */ pathrelse (path); set_offset (file_format, &key, (get_offset (&key) & ~(fs->fs_blocksize - 1)) + 1); if (reiserfs_search_by_key_4 (fs, &key, path) != ITEM_FOUND) die ("direct2indirect: can not find first part of tail"); } unbh = reiserfsck_get_new_buffer (unfm ? unfm : block_to_start (path)); memset (unbh->b_data, 0, unbh->b_size); /* delete parts of tail coping their contents to new buffer */ do { __u64 len; ih = PATH_PITEM_HEAD (path); len = get_bytes_number(ih, fs->fs_blocksize); memcpy (unbh->b_data + copied, B_I_PITEM (PATH_PLAST_BUFFER (path), ih), len);// save_unfm_overwriting (unbh->b_blocknr, ih); copied += len; set_offset (file_format, &key, get_offset (&key) + len); reiserfsck_delete_item (path, 0); } while (reiserfs_search_by_key_4 (fs, &key, path) == ITEM_FOUND); pathrelse (path); /* paste or insert pointer to the unformatted node */ set_offset (file_format, &key, get_offset (&key) - copied);// set_offset (ih_key_format (ih), &key, get_offset (&key) - copied);// key.k_offset -= copied; ni = cpu_to_le32 (unbh->b_blocknr); if (usearch_by_position (fs, &key, file_format, path) == FILE_NOT_FOUND) { struct item_head insih; copy_key (&(insih.ih_key), &key); set_ih_key_format (&insih, file_format); set_type (get_ih_key_format (&insih), &insih.ih_key, TYPE_INDIRECT); set_ih_free_space (&insih, 0); mark_item_unreachable (&insih); set_ih_item_len (&insih, UNFM_P_SIZE); mark_ih_was_tail (&insih); reiserfsck_insert_item (path, &insih, (const char *)&(ni)); } else { ih = PATH_PITEM_HEAD (path); if (!is_indirect_ih(ih)) reiserfs_panic ("%s: The item, which is supposed to be deleted, found in the tree - %k", __FUNCTION__, &ih->ih_key); if (get_bytes_number (ih, fs->fs_blocksize) + get_offset (&ih->ih_key) != get_offset (&key)) reiserfs_panic ("%s: The item %k with the wrong offset found in the block %lu block", __FUNCTION__, &ih->ih_key, PATH_PLAST_BUFFER(path)->b_blocknr); mark_ih_was_tail (ih); mark_buffer_dirty (get_bh(path)); reiserfsck_paste_into_item (path, (const char *)&ni, UNFM_P_SIZE); } mark_buffer_dirty (unbh); mark_buffer_uptodate (unbh, 1); brelse (unbh); if (usearch_by_position (fs, &key, file_format, path) != POSITION_FOUND || !is_indirect_ih (PATH_PITEM_HEAD (path))) reiserfs_panic ("direct2indirect: The data %k, which are supposed to be converted, are not found", &key); return;}static int append_to_unformatted_node (struct item_head * comingih, struct item_head * ih, char * item, struct path * path, unsigned int coming_len){ struct buffer_head * bh, * unbh = NULL; __u64 end_of_data, free_space; __u16 offset = get_offset (&comingih->ih_key) % fs->fs_blocksize - 1; __u32 unfm_ptr; int zero_number; bh = PATH_PLAST_BUFFER (path); unfm_ptr = d32_get ((__u32 *)B_I_PITEM(bh, ih), I_UNFM_NUM (ih) - 1); /* append to free space of the last unformatted node of indirect item ih */ free_space = get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih) - get_offset (&comingih->ih_key); if (free_space < coming_len) reiserfs_panic ("%s: block %lu: The unformatted node %u, pointed by the file %k, does not have enough free space" "for appending %llu bytes", __FUNCTION__, bh->b_blocknr, unfm_ptr, &ih->ih_key, coming_len); if (fs->fs_blocksize < free_space) reiserfs_panic ("%s: block %lu: The unformatted node %u, pointed by the file %k, does not have enough free space" "for appending %llu bytes", __FUNCTION__, bh->b_blocknr, &ih->ih_key, unfm_ptr, &ih->ih_key, coming_len); end_of_data = fs->fs_blocksize - free_space; zero_number = offset - end_of_data; if (unfm_ptr && !not_data_block (fs, unfm_ptr)) { unbh = bread (fs->fs_dev, unfm_ptr, fs->fs_blocksize); if (!is_block_used (unfm_ptr)) reiserfs_panic ("%s: block %lu: The unformatted node %u, pointed by the file %k, is marked as unused", __FUNCTION__, bh->b_blocknr, unfm_ptr, &ih->ih_key); if (unbh == 0) unfm_ptr = 0; } if (!unfm_ptr || not_data_block (fs, unfm_ptr)) { /* indirect item points to block which can not be pointed or to 0, in any case we have to allocate new node */ /*if (unfm_ptr == 0 || unfm_ptr >= SB_BLOCK_COUNT (fs)) {*/ unbh = reiserfsck_get_new_buffer (bh->b_blocknr); memset (unbh->b_data, 0, unbh->b_size); d32_put ((__u32 *)B_I_PITEM(bh, ih), I_UNFM_NUM (ih) - 1, unbh->b_blocknr); /*mark_block_unformatted (unbh->b_blocknr);*/ mark_buffer_dirty (bh); } memset (unbh->b_data + end_of_data, 0, zero_number); memcpy (unbh->b_data + offset, item, coming_len);// save_unfm_overwriting (unbh->b_blocknr, comingih); free_space -= (zero_number + coming_len); set_ih_free_space(ih, get_ih_free_space(ih) - (zero_number + coming_len)); memset (unbh->b_data + offset + coming_len, 0, free_space);// mark_buffer_uptodate (unbh, 0); mark_buffer_uptodate (unbh, 1); mark_buffer_dirty (unbh); brelse (unbh); pathrelse (path); return coming_len;}/* this appends file with one unformatted node pointer (since balancing algorithm limitation). This pointer can be 0, or new allocated block or pointer from indirect item that is being inserted into tree */int reiserfsck_append_file (struct item_head * comingih, char * item, int pos, struct path * path, int was_in_tree){ __u32 * ni; struct buffer_head * unbh; int retval; struct item_head * ih = PATH_PITEM_HEAD (path); __u32 bytes_number; int i, count = 0; if (!is_indirect_ih (ih)) reiserfs_panic ("reiserfsck_append_file: Operation is not allowed for non-indirect item %k", &ih->ih_key); if (is_direct_ih (comingih)) { unsigned int coming_len = get_bytes_number (comingih, fs->fs_blocksize); if (get_offset (&comingih->ih_key) < get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih)) { /* direct item fits to free space of indirect item */ return append_to_unformatted_node (comingih, ih, item, path, coming_len); } unbh = reiserfsck_get_new_buffer (PATH_PLAST_BUFFER (path)->b_blocknr); memset (unbh->b_data, 0, unbh->b_size); memcpy (unbh->b_data + get_offset (&comingih->ih_key) % unbh->b_size - 1, item, coming_len); mark_buffer_dirty (unbh); mark_buffer_uptodate (unbh, 1); ni = getmem (UNFM_P_SIZE); d32_put (ni, 0, unbh->b_blocknr); count = 1; brelse (unbh); retval = coming_len; } else { /* coming item is indirect item */ bytes_number = get_bytes_number (ih, fs->fs_blocksize); if (get_offset (&comingih->ih_key) + pos * fs->fs_blocksize != get_offset (&ih->ih_key) + bytes_number) reiserfs_panic ("reiserfsck_append_file: file %K: Cannot append indirect pointers of the offset "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -