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

📄 stree.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (n_ret_value != REPEAT_SEARCH)			break;		PROC_INFO_INC(p_s_sb, cut_from_item_restarted);		n_ret_value =		    search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);		if (n_ret_value == POSITION_FOUND)			continue;		reiserfs_warning(p_s_sb,				 "PAP-5610: reiserfs_cut_from_item: item %K not found",				 p_s_item_key);		unfix_nodes(&s_cut_balance);		return (n_ret_value == IO_ERROR) ? -EIO : -ENOENT;	}			/* while */	// check fix_nodes results (IO_ERROR or NO_DISK_SPACE)	if (n_ret_value != CARRY_ON) {		if (n_is_inode_locked) {			// FIXME: this seems to be not needed: we are always able			// to cut item			indirect_to_direct_roll_back(th, p_s_inode, p_s_path);		}		if (n_ret_value == NO_DISK_SPACE)			reiserfs_warning(p_s_sb, "NO_DISK_SPACE");		unfix_nodes(&s_cut_balance);		return -EIO;	}	/* go ahead and perform balancing */	RFALSE(c_mode == M_PASTE || c_mode == M_INSERT, "invalid mode");	/* Calculate number of bytes that need to be cut from the item. */	quota_cut_bytes =	    (c_mode ==	     M_DELETE) ? ih_item_len(get_ih(p_s_path)) : -s_cut_balance.	    insert_size[0];	if (retval2 == -1)		n_ret_value = calc_deleted_bytes_number(&s_cut_balance, c_mode);	else		n_ret_value = retval2;	/* For direct items, we only change the quota when deleting the last	 ** item.	 */	p_le_ih = PATH_PITEM_HEAD(s_cut_balance.tb_path);	if (!S_ISLNK(p_s_inode->i_mode) && is_direct_le_ih(p_le_ih)) {		if (c_mode == M_DELETE &&		    (le_ih_k_offset(p_le_ih) & (p_s_sb->s_blocksize - 1)) ==		    1) {			// FIXME: this is to keep 3.5 happy			REISERFS_I(p_s_inode)->i_first_direct_byte = U32_MAX;			quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE;		} else {			quota_cut_bytes = 0;		}	}#ifdef CONFIG_REISERFS_CHECK	if (n_is_inode_locked) {		struct item_head *le_ih =		    PATH_PITEM_HEAD(s_cut_balance.tb_path);		/* we are going to complete indirect2direct conversion. Make		   sure, that we exactly remove last unformatted node pointer		   of the item */		if (!is_indirect_le_ih(le_ih))			reiserfs_panic(p_s_sb,				       "vs-5652: reiserfs_cut_from_item: "				       "item must be indirect %h", le_ih);		if (c_mode == M_DELETE && ih_item_len(le_ih) != UNFM_P_SIZE)			reiserfs_panic(p_s_sb,				       "vs-5653: reiserfs_cut_from_item: "				       "completing indirect2direct conversion indirect item %h "				       "being deleted must be of 4 byte long",				       le_ih);		if (c_mode == M_CUT		    && s_cut_balance.insert_size[0] != -UNFM_P_SIZE) {			reiserfs_panic(p_s_sb,				       "vs-5654: reiserfs_cut_from_item: "				       "can not complete indirect2direct conversion of %h (CUT, insert_size==%d)",				       le_ih, s_cut_balance.insert_size[0]);		}		/* it would be useful to make sure, that right neighboring		   item is direct item of this file */	}#endif	do_balance(&s_cut_balance, NULL, NULL, c_mode);	if (n_is_inode_locked) {		/* we've done an indirect->direct conversion.  when the data block		 ** was freed, it was removed from the list of blocks that must		 ** be flushed before the transaction commits, make sure to		 ** unmap and invalidate it		 */		unmap_buffers(page, tail_pos);		REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask;	}#ifdef REISERQUOTA_DEBUG	reiserfs_debug(p_s_inode->i_sb, REISERFS_DEBUG_CODE,		       "reiserquota cut_from_item(): freeing %u id=%u type=%c",		       quota_cut_bytes, p_s_inode->i_uid, '?');#endif	DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);	return n_ret_value;}static void truncate_directory(struct reiserfs_transaction_handle *th,			       struct inode *inode){	BUG_ON(!th->t_trans_id);	if (inode->i_nlink)		reiserfs_warning(inode->i_sb,				 "vs-5655: truncate_directory: link count != 0");	set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), DOT_OFFSET);	set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_DIRENTRY);	reiserfs_delete_solid_item(th, inode, INODE_PKEY(inode));	reiserfs_update_sd(th, inode);	set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), SD_OFFSET);	set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_STAT_DATA);}/* Truncate file to the new size. Note, this must be called with a transaction   already started */int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p_s_inode,	/* ->i_size contains new												   size */			 struct page *page,	/* up to date for last block */			 int update_timestamps	/* when it is called by						   file_release to convert						   the tail - no timestamps						   should be updated */    ){	INITIALIZE_PATH(s_search_path);	/* Path to the current object item. */	struct item_head *p_le_ih;	/* Pointer to an item header. */	struct cpu_key s_item_key;	/* Key to search for a previous file item. */	loff_t n_file_size,	/* Old file size. */	 n_new_file_size;	/* New file size. */	int n_deleted;		/* Number of deleted or truncated bytes. */	int retval;	int err = 0;	BUG_ON(!th->t_trans_id);	if (!	    (S_ISREG(p_s_inode->i_mode) || S_ISDIR(p_s_inode->i_mode)	     || S_ISLNK(p_s_inode->i_mode)))		return 0;	if (S_ISDIR(p_s_inode->i_mode)) {		// deletion of directory - no need to update timestamps		truncate_directory(th, p_s_inode);		return 0;	}	/* Get new file size. */	n_new_file_size = p_s_inode->i_size;	// FIXME: note, that key type is unimportant here	make_cpu_key(&s_item_key, p_s_inode, max_reiserfs_offset(p_s_inode),		     TYPE_DIRECT, 3);	retval =	    search_for_position_by_key(p_s_inode->i_sb, &s_item_key,				       &s_search_path);	if (retval == IO_ERROR) {		reiserfs_warning(p_s_inode->i_sb,				 "vs-5657: reiserfs_do_truncate: "				 "i/o failure occurred trying to truncate %K",				 &s_item_key);		err = -EIO;		goto out;	}	if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {		reiserfs_warning(p_s_inode->i_sb,				 "PAP-5660: reiserfs_do_truncate: "				 "wrong result %d of search for %K", retval,				 &s_item_key);		err = -EIO;		goto out;	}	s_search_path.pos_in_item--;	/* Get real file size (total length of all file items) */	p_le_ih = PATH_PITEM_HEAD(&s_search_path);	if (is_statdata_le_ih(p_le_ih))		n_file_size = 0;	else {		loff_t offset = le_ih_k_offset(p_le_ih);		int bytes =		    op_bytes_number(p_le_ih, p_s_inode->i_sb->s_blocksize);		/* this may mismatch with real file size: if last direct item		   had no padding zeros and last unformatted node had no free		   space, this file would have this file size */		n_file_size = offset + bytes - 1;	}	/*	 * are we doing a full truncate or delete, if so	 * kick in the reada code	 */	if (n_new_file_size == 0)		s_search_path.reada = PATH_READA | PATH_READA_BACK;	if (n_file_size == 0 || n_file_size < n_new_file_size) {		goto update_and_out;	}	/* Update key to search for the last file item. */	set_cpu_key_k_offset(&s_item_key, n_file_size);	do {		/* Cut or delete file item. */		n_deleted =		    reiserfs_cut_from_item(th, &s_search_path, &s_item_key,					   p_s_inode, page, n_new_file_size);		if (n_deleted < 0) {			reiserfs_warning(p_s_inode->i_sb,					 "vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed");			reiserfs_check_path(&s_search_path);			return 0;		}		RFALSE(n_deleted > n_file_size,		       "PAP-5670: reiserfs_cut_from_item: too many bytes deleted: deleted %d, file_size %lu, item_key %K",		       n_deleted, n_file_size, &s_item_key);		/* Change key to search the last file item. */		n_file_size -= n_deleted;		set_cpu_key_k_offset(&s_item_key, n_file_size);		/* While there are bytes to truncate and previous file item is presented in the tree. */		/*		 ** This loop could take a really long time, and could log 		 ** many more blocks than a transaction can hold.  So, we do a polite		 ** journal end here, and if the transaction needs ending, we make		 ** sure the file is consistent before ending the current trans		 ** and starting a new one		 */		if (journal_transaction_should_end(th, 0) ||		    reiserfs_transaction_free_space(th) <= JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {			int orig_len_alloc = th->t_blocks_allocated;			decrement_counters_in_path(&s_search_path);			if (update_timestamps) {				p_s_inode->i_mtime = p_s_inode->i_ctime =				    CURRENT_TIME_SEC;			}			reiserfs_update_sd(th, p_s_inode);			err = journal_end(th, p_s_inode->i_sb, orig_len_alloc);			if (err)				goto out;			err = journal_begin(th, p_s_inode->i_sb,					    JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD + JOURNAL_PER_BALANCE_CNT * 4) ;			if (err)				goto out;			reiserfs_update_inode_transaction(p_s_inode);		}	} while (n_file_size > ROUND_UP(n_new_file_size) &&		 search_for_position_by_key(p_s_inode->i_sb, &s_item_key,					    &s_search_path) == POSITION_FOUND);	RFALSE(n_file_size > ROUND_UP(n_new_file_size),	       "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d",	       n_new_file_size, n_file_size, s_item_key.on_disk_key.k_objectid);      update_and_out:	if (update_timestamps) {		// this is truncate, not file closing		p_s_inode->i_mtime = p_s_inode->i_ctime = CURRENT_TIME_SEC;	}	reiserfs_update_sd(th, p_s_inode);      out:	pathrelse(&s_search_path);	return err;}#ifdef CONFIG_REISERFS_CHECK// this makes sure, that we __append__, not overwrite or add holesstatic void check_research_for_paste(struct treepath *path,				     const struct cpu_key *p_s_key){	struct item_head *found_ih = get_ih(path);	if (is_direct_le_ih(found_ih)) {		if (le_ih_k_offset(found_ih) +		    op_bytes_number(found_ih,				    get_last_bh(path)->b_size) !=		    cpu_key_k_offset(p_s_key)		    || op_bytes_number(found_ih,				       get_last_bh(path)->b_size) !=		    pos_in_item(path))			reiserfs_panic(NULL,				       "PAP-5720: check_research_for_paste: "				       "found direct item %h or position (%d) does not match to key %K",				       found_ih, pos_in_item(path), p_s_key);	}	if (is_indirect_le_ih(found_ih)) {		if (le_ih_k_offset(found_ih) +		    op_bytes_number(found_ih,				    get_last_bh(path)->b_size) !=		    cpu_key_k_offset(p_s_key)		    || I_UNFM_NUM(found_ih) != pos_in_item(path)		    || get_ih_free_space(found_ih) != 0)			reiserfs_panic(NULL,				       "PAP-5730: check_research_for_paste: "				       "found indirect item (%h) or position (%d) does not match to key (%K)",				       found_ih, pos_in_item(path), p_s_key);	}}#endif				/* config reiserfs check *//* Paste bytes to the existing item. Returns bytes number pasted into the item. */int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_search_path,	/* Path to the pasted item.          */			     const struct cpu_key *p_s_key,	/* Key to search for the needed item. */			     struct inode *inode,	/* Inode item belongs to */			     const char *p_c_body,	/* Pointer to the bytes to paste.    */			     int n_pasted_size){				/* Size of pasted bytes.             */	struct tree_balance s_paste_balance;	int retval;	int fs_gen;	BUG_ON(!th->t_trans_id);	fs_gen = get_generation(inode->i_sb);#ifdef REISERQUOTA_DEBUG	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,		       "reiserquota paste_into_item(): allocating %u id=%u type=%c",		       n_pasted_size, inode->i_uid,		       key2type(&(p_s_key->on_disk_key)));#endif	if (DQUOT_ALLOC_SPACE_NODIRTY(inode, n_pasted_size)) {		pathrelse(p_s_search_path);		return -EDQUOT;	}	init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path,		       n_pasted_size);#ifdef DISPLACE_NEW_PACKING_LOCALITIES	s_paste_balance.key = p_s_key->on_disk_key;#endif	/* DQUOT_* can schedule, must check before the fix_nodes */	if (fs_changed(fs_gen, inode->i_sb)) {		goto search_again;	}	while ((retval =		fix_nodes(M_PASTE, &s_paste_balance, NULL,			  p_c_body)) == REPEAT_SEARCH) {	      search_again:		/* file system changed while we were in the fix_nodes */		PROC_INFO_INC(th->t_super, paste_into_item_restarted);		retval =		    search_for_position_by_key(th->t_super, p_s_key,					       p_s_search_path);		if (retval == IO_ERROR) {			retval = -EIO;			goto error_out;		}		if (retval == POSITION_FOUND) {			reiserfs_warning(inode->i_sb,					 "PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists",					 p_s_key);			retval = -EEXIST;			goto error_out;		}#ifdef CONFIG_REISERFS_CHECK		check_research_for_paste(p_s_search_path, p_s_key);#endif	}	/* Perform balancing after all resources are collected by fix_nodes, and	   accessing them will not risk triggering schedule. */	if (retval == CARRY_ON) {		do_balance(&s_paste_balance, NULL /*ih */ , p_c_body, M_PASTE);		return 0;	}	retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;      error_out:	/* this also releases the path */	unfix_nodes(&s_paste_balance);#ifdef REISERQUOTA_DEBUG	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,		       "reiserquota paste_into_item(): freeing %u id=%u type=%c",		       n_pasted_size, inode->i_uid,		       key2type(&(p_s_key->on_disk_key)));#endif	DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size);	return retval;}/* Insert new item into the buffer at the path. */int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,	/* Path to the inserteded item.         */			 const struct cpu_key *key,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -