⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stree.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -