📄 stree.c
字号:
(*p_n_removed)++; tmp = get_block_num(p_n_unfm_pointer,0); put_block_num(p_n_unfm_pointer, 0, 0); journal_mark_dirty (th, p_s_sb, p_s_bh); inode->i_blocks -= p_s_sb->s_blocksize / 512; reiserfs_free_block(th, tmp); if ( item_moved (&s_ih, p_s_path) ) { need_research = 1; break ; } } /* a trick. If the buffer has been logged, this ** will do nothing. If we've broken the loop without ** logging it, it will restore the buffer ** */ reiserfs_restore_prepared_buffer(p_s_sb, p_s_bh); /* This loop can be optimized. */ } while ( (*p_n_removed < n_unfm_number || need_research) && search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_FOUND ); RFALSE( *p_n_removed < n_unfm_number, "PAP-5310: indirect item is not found"); RFALSE( item_moved (&s_ih, p_s_path), "after while, comp failed, retry") ; if (c_mode == M_CUT) pos_in_item (p_s_path) *= UNFM_P_SIZE; return c_mode; }}/* Calculate bytes number which will be deleted or cutted in the balance. */int calc_deleted_bytes_number( struct tree_balance * p_s_tb, char c_mode ) { int n_del_size; struct item_head * p_le_ih = PATH_PITEM_HEAD(p_s_tb->tb_path); if ( is_statdata_le_ih (p_le_ih) ) return 0; if ( is_direntry_le_ih (p_le_ih) ) { // return EMPTY_DIR_SIZE; /* We delete emty directoris only. */ // we can't use EMPTY_DIR_SIZE, as old format dirs have a different // empty size. ick. FIXME, is this right? // return ih_item_len(p_le_ih); } n_del_size = ( c_mode == M_DELETE ) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[0]; if ( is_indirect_le_ih (p_le_ih) ) n_del_size = (n_del_size/UNFM_P_SIZE)* (PATH_PLAST_BUFFER(p_s_tb->tb_path)->b_size);// - get_ih_free_space (p_le_ih); return n_del_size;}static void init_tb_struct( struct reiserfs_transaction_handle *th, struct tree_balance * p_s_tb, struct super_block * p_s_sb, struct path * p_s_path, int n_size ) { memset (p_s_tb,'\0',sizeof(struct tree_balance)); p_s_tb->transaction_handle = th ; p_s_tb->tb_sb = p_s_sb; p_s_tb->tb_path = p_s_path; PATH_OFFSET_PBUFFER(p_s_path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL; PATH_OFFSET_POSITION(p_s_path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0; p_s_tb->insert_size[0] = n_size;}void padd_item (char * item, int total_length, int length){ int i; for (i = total_length; i > length; ) item [--i] = 0;}/* Delete object item. */int reiserfs_delete_item (struct reiserfs_transaction_handle *th, struct path * p_s_path, /* Path to the deleted item. */ const struct cpu_key * p_s_item_key, /* Key to search for the deleted item. */ struct inode * p_s_inode,/* inode is here just to update i_blocks */ struct buffer_head * p_s_un_bh) /* NULL or unformatted node pointer. */{ struct super_block * p_s_sb = p_s_inode->i_sb; struct tree_balance s_del_balance; struct item_head s_ih; int n_ret_value, n_del_size, n_removed;#ifdef CONFIG_REISERFS_CHECK char c_mode; int n_iter = 0;#endif init_tb_struct(th, &s_del_balance, p_s_sb, p_s_path, 0/*size is unknown*/); while ( 1 ) { n_removed = 0;#ifdef CONFIG_REISERFS_CHECK n_iter++; c_mode =#endif prepare_for_delete_or_cut(th, p_s_inode, p_s_path, p_s_item_key, &n_removed, &n_del_size, max_reiserfs_offset (p_s_inode)); RFALSE( c_mode != M_DELETE, "PAP-5320: mode must be M_DELETE"); copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path)); s_del_balance.insert_size[0] = n_del_size; n_ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, 0); if ( n_ret_value != REPEAT_SEARCH ) break; // file system changed, repeat search n_ret_value = search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path); if (n_ret_value == IO_ERROR) break; if (n_ret_value == FILE_NOT_FOUND) { reiserfs_warning ("vs-5340: reiserfs_delete_item: " "no items of the file %K found\n", p_s_item_key); break; } } /* while (1) */ if ( n_ret_value != CARRY_ON ) { unfix_nodes(&s_del_balance); return 0; } // reiserfs_delete_item returns item length when success n_ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE); if ( p_s_un_bh ) { int off; char *data ; /* We are in direct2indirect conversion, so move tail contents to the unformatted node */ /* note, we do the copy before preparing the buffer because we ** don't care about the contents of the unformatted node yet. ** the only thing we really care about is the direct item's data ** is in the unformatted node. ** ** Otherwise, we would have to call reiserfs_prepare_for_journal on ** the unformatted node, which might schedule, meaning we'd have to ** loop all the way back up to the start of the while loop. ** ** The unformatted node must be dirtied later on. We can't be ** sure here if the entire tail has been deleted yet. ** ** p_s_un_bh is from the page cache (all unformatted nodes are ** from the page cache) and might be a highmem page. So, we ** can't use p_s_un_bh->b_data. But, the page has already been ** kmapped, so we can use page_address() ** -clm */ data = page_address(p_s_un_bh->b_page) ; off = ((le_ih_k_offset (&s_ih) - 1) & (PAGE_CACHE_SIZE - 1)); memcpy(data + off, B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value); } /* Perform balancing after all resources have been collected at once. */ do_balance(&s_del_balance, NULL, NULL, M_DELETE); /* Return deleted body length */ return n_ret_value;}/* Summary Of Mechanisms For Handling Collisions Between Processes: deletion of the body of the object is performed by iput(), with the result that if multiple processes are operating on a file, the deletion of the body of the file is deferred until the last process that has an open inode performs its iput(). writes and truncates are protected from collisions by use of semaphores. creates, linking, and mknod are protected from collisions with other processes by making the reiserfs_add_entry() the last step in the creation, and then rolling back all changes if there was a collision. - Hans*//* this deletes item which never gets split */void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th, struct key * key){ struct tree_balance tb; INITIALIZE_PATH (path); int item_len; int tb_init = 0 ; struct cpu_key cpu_key; int retval; le_key2cpu_key (&cpu_key, key); while (1) { retval = search_item (th->t_super, &cpu_key, &path); if (retval == IO_ERROR) { reiserfs_warning ("vs-5350: reiserfs_delete_solid_item: " "i/o failure occurred trying to delete %K\n", &cpu_key); break; } if (retval != ITEM_FOUND) { pathrelse (&path); reiserfs_warning ("vs-5355: reiserfs_delete_solid_item: %k not found", key); break; } if (!tb_init) { tb_init = 1 ; item_len = ih_item_len( PATH_PITEM_HEAD(&path) ); init_tb_struct (th, &tb, th->t_super, &path, - (IH_SIZE + item_len)); } retval = fix_nodes (M_DELETE, &tb, NULL, 0); if (retval == REPEAT_SEARCH) continue; if (retval == CARRY_ON) { do_balance (&tb, 0, 0, M_DELETE); break; } // IO_ERROR, NO_DISK_SPACE, etc reiserfs_warning ("vs-5360: reiserfs_delete_solid_item: " "could not delete %K due to fix_nodes failure\n", &cpu_key); unfix_nodes (&tb); break; } reiserfs_check_path(&path) ;}void reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode * inode){ inode->i_size = 0; /* for directory this deletes item containing "." and ".." */ reiserfs_do_truncate (th, inode, NULL, 0/*no timestamp updates*/); #if defined( USE_INODE_GENERATION_COUNTER ) if( !old_format_only ( th -> t_super ) ) { __u32 *inode_generation; inode_generation = &th -> t_super -> u.reiserfs_sb.s_rs -> s_inode_generation; *inode_generation = cpu_to_le32( le32_to_cpu( *inode_generation ) + 1 ); }/* USE_INODE_GENERATION_COUNTER */#endif reiserfs_delete_solid_item (th, INODE_PKEY (inode));}static int maybe_indirect_to_direct (struct reiserfs_transaction_handle *th, struct inode * p_s_inode, struct page *page, struct path * p_s_path, const struct cpu_key * p_s_item_key, loff_t n_new_file_size, char * p_c_mode ) { struct super_block * p_s_sb = p_s_inode->i_sb; int n_block_size = p_s_sb->s_blocksize; int cut_bytes; if (n_new_file_size != p_s_inode->i_size) BUG (); /* the page being sent in could be NULL if there was an i/o error ** reading in the last block. The user will hit problems trying to ** read the file, but for now we just skip the indirect2direct */ if (atomic_read(&p_s_inode->i_count) > 1 || !tail_has_to_be_packed (p_s_inode) || !page || (p_s_inode->u.reiserfs_i.i_flags & i_nopack_mask)) { // leave tail in an unformatted node *p_c_mode = M_SKIP_BALANCING; cut_bytes = n_block_size - (n_new_file_size & (n_block_size - 1)); pathrelse(p_s_path); return cut_bytes; } /* Permorm the conversion to a direct_item. */ /*return indirect_to_direct (p_s_inode, p_s_path, p_s_item_key, n_new_file_size, p_c_mode);*/ return indirect2direct (th, p_s_inode, page, p_s_path, p_s_item_key, n_new_file_size, p_c_mode);}/* we did indirect_to_direct conversion. And we have inserted direct item successesfully, but there were no disk space to cut unfm pointer being converted. Therefore we have to delete inserted direct item(s) */static void indirect_to_direct_roll_back (struct reiserfs_transaction_handle *th, struct inode * inode, struct path * path){ struct cpu_key tail_key; int tail_len; int removed; make_cpu_key (&tail_key, inode, inode->i_size + 1, TYPE_DIRECT, 4);// !!!! tail_key.key_length = 4; tail_len = (cpu_key_k_offset (&tail_key) & (inode->i_sb->s_blocksize - 1)) - 1; while (tail_len) { /* look for the last byte of the tail */ if (search_for_position_by_key (inode->i_sb, &tail_key, path) == POSITION_NOT_FOUND) reiserfs_panic (inode->i_sb, "vs-5615: indirect_to_direct_roll_back: found invalid item"); RFALSE( path->pos_in_item != ih_item_len(PATH_PITEM_HEAD (path)) - 1, "vs-5616: appended bytes found"); PATH_LAST_POSITION (path) --; removed = reiserfs_delete_item (th, path, &tail_key, inode, 0/*unbh not needed*/); RFALSE( removed <= 0 || removed > tail_len, "vs-5617: there was tail %d bytes, removed item length %d bytes", tail_len, removed); tail_len -= removed; set_cpu_key_k_offset (&tail_key, cpu_key_k_offset (&tail_key) - removed); } printk ("indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space\n"); //mark_file_without_tail (inode); mark_inode_dirty (inode);}/* (Truncate or cut entry) or delete object item. Returns < 0 on failure */int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th, struct path * p_s_path, struct cpu_key * p_s_item_key, struct inode * p_s_inode, struct page *page, loff_t n_new_file_size){ struct super_block * p_s_sb = p_s_inode->i_sb; /* Every function which is going to call do_balance must first create a tree_balance structure. Then it must fill up this structure by using the init_tb_struct and fix_nodes functions. After that we can make tree balancing. */ struct tree_balance s_cut_balance; int n_cut_size = 0, /* Amount to be cut. */ n_ret_value = CARRY_ON, n_removed = 0, /* Number of the removed unformatted nodes. */ n_is_inode_locked = 0; char c_mode; /* Mode of the balance. */ int retval2 = -1; init_tb_struct(th, &s_cut_balance, p_s_inode->i_sb, p_s_path, n_cut_size); /* Repeat this loop until we either cut the item without needing
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -