📄 stree.c
字号:
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(p_s_sb, "vs-5340: reiserfs_delete_item: " "no items of the file %K found", 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); q_ih = get_ih(p_s_path); quota_cut_bytes = ih_item_len(q_ih); /* hack so the quota code doesn't have to guess if the file ** has a tail. On tail insert, we allocate quota for 1 unformatted node. ** We test the offset because the tail might have been ** split into multiple items, and we only want to decrement for ** the unfm node once */ if (!S_ISLNK(p_s_inode->i_mode) && is_direct_le_ih(q_ih)) { if ((le_ih_k_offset(q_ih) & (p_s_sb->s_blocksize - 1)) == 1) { quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE; } else { quota_cut_bytes = 0; } } 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. ** -clm */ data = kmap_atomic(p_s_un_bh->b_page, KM_USER0); 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); kunmap_atomic(data, KM_USER0); } /* Perform balancing after all resources have been collected at once. */ do_balance(&s_del_balance, NULL, NULL, M_DELETE);#ifdef REISERQUOTA_DEBUG reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "reiserquota delete_item(): freeing %u, id=%u type=%c", quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih));#endif DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes); /* 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 inode *inode, struct reiserfs_key *key){ struct tree_balance tb; INITIALIZE_PATH(path); int item_len = 0; int tb_init = 0; struct cpu_key cpu_key; int retval; int quota_cut_bytes = 0; BUG_ON(!th->t_trans_id); le_key2cpu_key(&cpu_key, key); while (1) { retval = search_item(th->t_super, &cpu_key, &path); if (retval == IO_ERROR) { reiserfs_warning(th->t_super, "vs-5350: reiserfs_delete_solid_item: " "i/o failure occurred trying to delete %K", &cpu_key); break; } if (retval != ITEM_FOUND) { pathrelse(&path); // No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir if (! ((unsigned long long) GET_HASH_VALUE(le_key_k_offset (le_key_version(key), key)) == 0 && (unsigned long long) GET_GENERATION_NUMBER(le_key_k_offset (le_key_version(key), key)) == 1)) reiserfs_warning(th->t_super, "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)); } quota_cut_bytes = ih_item_len(PATH_PITEM_HEAD(&path)); retval = fix_nodes(M_DELETE, &tb, NULL, NULL); if (retval == REPEAT_SEARCH) { PROC_INFO_INC(th->t_super, delete_solid_item_restarted); continue; } if (retval == CARRY_ON) { do_balance(&tb, NULL, NULL, M_DELETE); if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */#ifdef REISERQUOTA_DEBUG reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, "reiserquota delete_solid_item(): freeing %u id=%u type=%c", quota_cut_bytes, inode->i_uid, key2type(key));#endif DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes); } break; } // IO_ERROR, NO_DISK_SPACE, etc reiserfs_warning(th->t_super, "vs-5360: reiserfs_delete_solid_item: " "could not delete %K due to fix_nodes failure", &cpu_key); unfix_nodes(&tb); break; } reiserfs_check_path(&path);}int reiserfs_delete_object(struct reiserfs_transaction_handle *th, struct inode *inode){ int err; inode->i_size = 0; BUG_ON(!th->t_trans_id); /* for directory this deletes item containing "." and ".." */ err = reiserfs_do_truncate(th, inode, NULL, 0 /*no timestamp updates */ ); if (err) return err;#if defined( USE_INODE_GENERATION_COUNTER ) if (!old_format_only(th->t_super)) { __le32 *inode_generation; inode_generation = &REISERFS_SB(th->t_super)->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, INODE_PKEY(inode)); return err;}static void unmap_buffers(struct page *page, loff_t pos){ struct buffer_head *bh; struct buffer_head *head; struct buffer_head *next; unsigned long tail_index; unsigned long cur_index; if (page) { if (page_has_buffers(page)) { tail_index = pos & (PAGE_CACHE_SIZE - 1); cur_index = 0; head = page_buffers(page); bh = head; do { next = bh->b_this_page; /* we want to unmap the buffers that contain the tail, and ** all the buffers after it (since the tail must be at the ** end of the file). We don't want to unmap file data ** before the tail, since it might be dirty and waiting to ** reach disk */ cur_index += bh->b_size; if (cur_index > tail_index) { reiserfs_unmap_buffer(bh); } bh = next; } while (bh != head); } }}static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct treepath *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; BUG_ON(!th->t_trans_id); BUG_ON(n_new_file_size != p_s_inode->i_size); /* 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 || (REISERFS_I(p_s_inode)->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 treepath *path){ struct cpu_key tail_key; int tail_len; int removed; BUG_ON(!th->t_trans_id); 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, NULL /*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); } reiserfs_warning(inode->i_sb, "indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space"); //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 treepath *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; struct item_head *p_le_ih; 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; int quota_cut_bytes; loff_t tail_pos = 0; BUG_ON(!th->t_trans_id); 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 to balance, or we fix_nodes without schedule occurring */ while (1) { /* Determine the balance mode, position of the first byte to be cut, and size to be cut. In case of the indirect item free unformatted nodes which are pointed to by the cut pointers. */ c_mode = prepare_for_delete_or_cut(th, p_s_inode, p_s_path, p_s_item_key, &n_removed, &n_cut_size, n_new_file_size); if (c_mode == M_CONVERT) { /* convert last unformatted node to direct item or leave tail in the unformatted node */ RFALSE(n_ret_value != CARRY_ON, "PAP-5570: can not convert twice"); n_ret_value = maybe_indirect_to_direct(th, p_s_inode, page, p_s_path, p_s_item_key, n_new_file_size, &c_mode); if (c_mode == M_SKIP_BALANCING) /* tail has been left in the unformatted node */ return n_ret_value; n_is_inode_locked = 1; /* removing of last unformatted node will change value we have to return to truncate. Save it */ retval2 = n_ret_value; /*retval2 = p_s_sb->s_blocksize - (n_new_file_size & (p_s_sb->s_blocksize - 1)); */ /* So, we have performed the first part of the conversion: inserting the new direct item. Now we are removing the last unformatted node pointer. Set key to search for it. */ set_cpu_key_k_type(p_s_item_key, TYPE_INDIRECT); p_s_item_key->key_length = 4; n_new_file_size -= (n_new_file_size & (p_s_sb->s_blocksize - 1)); tail_pos = n_new_file_size; set_cpu_key_k_offset(p_s_item_key, n_new_file_size + 1); if (search_for_position_by_key (p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND) { print_block(PATH_PLAST_BUFFER(p_s_path), 3, PATH_LAST_POSITION(p_s_path) - 1, PATH_LAST_POSITION(p_s_path) + 1); reiserfs_panic(p_s_sb, "PAP-5580: reiserfs_cut_from_item: item to convert does not exist (%K)", p_s_item_key); } continue; } if (n_cut_size == 0) { pathrelse(p_s_path); return 0; } s_cut_balance.insert_size[0] = n_cut_size; n_ret_value = fix_nodes(c_mode, &s_cut_balance, NULL, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -