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

📄 alloc.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
bail:	if (bh)		brelse(bh);	return status;}static int ocfs2_do_truncate(struct ocfs2_super *osb,			     unsigned int clusters_to_del,			     struct inode *inode,			     struct buffer_head *fe_bh,			     struct buffer_head *old_last_eb_bh,			     struct ocfs2_journal_handle *handle,			     struct ocfs2_truncate_context *tc){	int status, i, depth;	struct ocfs2_dinode *fe;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_block *last_eb = NULL;	struct ocfs2_extent_list *el;	struct buffer_head *eb_bh = NULL;	struct buffer_head *last_eb_bh = NULL;	u64 next_eb = 0;	u64 delete_blk = 0;	fe = (struct ocfs2_dinode *) fe_bh->b_data;	status = ocfs2_find_new_last_ext_blk(osb,					     inode,					     fe,					     le32_to_cpu(fe->i_clusters) -					     		clusters_to_del,					     old_last_eb_bh,					     &last_eb_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	if (last_eb_bh)		last_eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;	status = ocfs2_journal_access(handle, inode, fe_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	el = &(fe->id2.i_list);	spin_lock(&OCFS2_I(inode)->ip_lock);	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -				      clusters_to_del;	spin_unlock(&OCFS2_I(inode)->ip_lock);	le32_add_cpu(&fe->i_clusters, -clusters_to_del);	fe->i_mtime = cpu_to_le64(CURRENT_TIME.tv_sec);	fe->i_mtime_nsec = cpu_to_le32(CURRENT_TIME.tv_nsec);	i = le16_to_cpu(el->l_next_free_rec) - 1;	BUG_ON(le32_to_cpu(el->l_recs[i].e_clusters) < clusters_to_del);	le32_add_cpu(&el->l_recs[i].e_clusters, -clusters_to_del);	/* tree depth zero, we can just delete the clusters, otherwise	 * we need to record the offset of the next level extent block	 * as we may overwrite it. */	if (!el->l_tree_depth)		delete_blk = le64_to_cpu(el->l_recs[i].e_blkno)			+ ocfs2_clusters_to_blocks(osb->sb,					le32_to_cpu(el->l_recs[i].e_clusters));	else		next_eb = le64_to_cpu(el->l_recs[i].e_blkno);	if (!el->l_recs[i].e_clusters) {		/* if we deleted the whole extent record, then clear		 * out the other fields and update the extent		 * list. For depth > 0 trees, we've already recorded		 * the extent block in 'next_eb' */		el->l_recs[i].e_cpos = 0;		el->l_recs[i].e_blkno = 0;		BUG_ON(!el->l_next_free_rec);		le16_add_cpu(&el->l_next_free_rec, -1);	}	depth = le16_to_cpu(el->l_tree_depth);	if (!fe->i_clusters) {		/* trunc to zero is a special case. */		el->l_tree_depth = 0;		fe->i_last_eb_blk = 0;	} else if (last_eb)		fe->i_last_eb_blk = last_eb->h_blkno;	status = ocfs2_journal_dirty(handle, fe_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	if (last_eb) {		/* If there will be a new last extent block, then by		 * definition, there cannot be any leaves to the right of		 * him. */		status = ocfs2_journal_access(handle, inode, last_eb_bh,					      OCFS2_JOURNAL_ACCESS_WRITE);		if (status < 0) {			mlog_errno(status);			goto bail;		}		last_eb->h_next_leaf_blk = 0;		status = ocfs2_journal_dirty(handle, last_eb_bh);		if (status < 0) {			mlog_errno(status);			goto bail;		}	}	/* if our tree depth > 0, update all the tree blocks below us. */	while (depth) {		mlog(0, "traveling tree (depth = %d, next_eb = %"MLFu64")\n",		     depth,  next_eb);		status = ocfs2_read_block(osb, next_eb, &eb_bh,					  OCFS2_BH_CACHED, inode);		if (status < 0) {			mlog_errno(status);			goto bail;		}		eb = (struct ocfs2_extent_block *)eb_bh->b_data;		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);			status = -EIO;			goto bail;		}		el = &(eb->h_list);		status = ocfs2_journal_access(handle, inode, eb_bh,					      OCFS2_JOURNAL_ACCESS_WRITE);		if (status < 0) {			mlog_errno(status);			goto bail;		}		BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);		BUG_ON(depth != (le16_to_cpu(el->l_tree_depth) + 1));		i = le16_to_cpu(el->l_next_free_rec) - 1;		mlog(0, "extent block %"MLFu64", before: record %d: "		     "(%u, %u, %"MLFu64"), next = %u\n",		     le64_to_cpu(eb->h_blkno), i,		     le32_to_cpu(el->l_recs[i].e_cpos),		     le32_to_cpu(el->l_recs[i].e_clusters),		     le64_to_cpu(el->l_recs[i].e_blkno),		     le16_to_cpu(el->l_next_free_rec));		BUG_ON(le32_to_cpu(el->l_recs[i].e_clusters) < clusters_to_del);		le32_add_cpu(&el->l_recs[i].e_clusters, -clusters_to_del);		next_eb = le64_to_cpu(el->l_recs[i].e_blkno);		/* bottom-most block requires us to delete data.*/		if (!el->l_tree_depth)			delete_blk = le64_to_cpu(el->l_recs[i].e_blkno)				+ ocfs2_clusters_to_blocks(osb->sb,					le32_to_cpu(el->l_recs[i].e_clusters));		if (!el->l_recs[i].e_clusters) {			el->l_recs[i].e_cpos = 0;			el->l_recs[i].e_blkno = 0;			BUG_ON(!el->l_next_free_rec);			le16_add_cpu(&el->l_next_free_rec, -1);		}		mlog(0, "extent block %"MLFu64", after: record %d: "		     "(%u, %u, %"MLFu64"), next = %u\n",		     le64_to_cpu(eb->h_blkno), i,		     le32_to_cpu(el->l_recs[i].e_cpos),		     le32_to_cpu(el->l_recs[i].e_clusters),		     le64_to_cpu(el->l_recs[i].e_blkno),		     le16_to_cpu(el->l_next_free_rec));		status = ocfs2_journal_dirty(handle, eb_bh);		if (status < 0) {			mlog_errno(status);			goto bail;		}		if (!el->l_next_free_rec) {			mlog(0, "deleting this extent block.\n");			ocfs2_remove_from_cache(inode, eb_bh);			BUG_ON(eb->h_suballoc_slot);			BUG_ON(el->l_recs[0].e_clusters);			BUG_ON(el->l_recs[0].e_cpos);			BUG_ON(el->l_recs[0].e_blkno);			status = ocfs2_free_extent_block(handle,							 tc->tc_ext_alloc_inode,							 tc->tc_ext_alloc_bh,							 eb);			if (status < 0) {				mlog_errno(status);				goto bail;			}		}		brelse(eb_bh);		eb_bh = NULL;		depth--;	}	BUG_ON(!delete_blk);	status = ocfs2_truncate_log_append(osb, handle, delete_blk,					   clusters_to_del);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = 0;bail:	if (!status)		ocfs2_extent_map_trunc(inode, le32_to_cpu(fe->i_clusters));	else		ocfs2_extent_map_drop(inode, 0);	mlog_exit(status);	return status;}/* * It is expected, that by the time you call this function, * inode->i_size and fe->i_size have been adjusted. * * WARNING: This will kfree the truncate context */int ocfs2_commit_truncate(struct ocfs2_super *osb,			  struct inode *inode,			  struct buffer_head *fe_bh,			  struct ocfs2_truncate_context *tc){	int status, i, credits, tl_sem = 0;	u32 clusters_to_del, target_i_clusters;	u64 last_eb = 0;	struct ocfs2_dinode *fe;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_list *el;	struct buffer_head *last_eb_bh;	struct ocfs2_journal_handle *handle = NULL;	struct inode *tl_inode = osb->osb_tl_inode;	mlog_entry_void();	down_write(&OCFS2_I(inode)->ip_alloc_sem);	target_i_clusters = ocfs2_clusters_for_bytes(osb->sb,						     i_size_read(inode));	last_eb_bh = tc->tc_last_eb_bh;	tc->tc_last_eb_bh = NULL;	fe = (struct ocfs2_dinode *) fe_bh->b_data;	if (fe->id2.i_list.l_tree_depth) {		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;		el = &eb->h_list;	} else		el = &fe->id2.i_list;	last_eb = le64_to_cpu(fe->i_last_eb_blk);start:	mlog(0, "ocfs2_commit_truncate: fe->i_clusters = %u, "	     "last_eb = %"MLFu64", fe->i_last_eb_blk = %"MLFu64", "	     "fe->id2.i_list.l_tree_depth = %u last_eb_bh = %p\n",	     le32_to_cpu(fe->i_clusters), last_eb,	     le64_to_cpu(fe->i_last_eb_blk),	     le16_to_cpu(fe->id2.i_list.l_tree_depth), last_eb_bh);	if (last_eb != le64_to_cpu(fe->i_last_eb_blk)) {		mlog(0, "last_eb changed!\n");		BUG_ON(!fe->id2.i_list.l_tree_depth);		last_eb = le64_to_cpu(fe->i_last_eb_blk);		/* i_last_eb_blk may have changed, read it if		 * necessary. We don't have to worry about the		 * truncate to zero case here (where there becomes no		 * last_eb) because we never loop back after our work		 * is done. */		if (last_eb_bh) {			brelse(last_eb_bh);			last_eb_bh = NULL;		}		status = ocfs2_read_block(osb, last_eb,					  &last_eb_bh, OCFS2_BH_CACHED,					  inode);		if (status < 0) {			mlog_errno(status);			goto bail;		}		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);			status = -EIO;			goto bail;		}		el = &(eb->h_list);	}	/* by now, el will point to the extent list on the bottom most	 * portion of this tree. */	i = le16_to_cpu(el->l_next_free_rec) - 1;	if (le32_to_cpu(el->l_recs[i].e_cpos) >= target_i_clusters)		clusters_to_del = le32_to_cpu(el->l_recs[i].e_clusters);	else		clusters_to_del = (le32_to_cpu(el->l_recs[i].e_clusters) +				   le32_to_cpu(el->l_recs[i].e_cpos)) -				  target_i_clusters;	mlog(0, "clusters_to_del = %u in this pass\n", clusters_to_del);	mutex_lock(&tl_inode->i_mutex);	tl_sem = 1;	/* ocfs2_truncate_log_needs_flush guarantees us at least one	 * record is free for use. If there isn't any, we flush to get	 * an empty truncate log.  */	if (ocfs2_truncate_log_needs_flush(osb)) {		status = __ocfs2_flush_truncate_log(osb);		if (status < 0) {			mlog_errno(status);			goto bail;		}	}	credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,						fe, el);	handle = ocfs2_start_trans(osb, NULL, credits);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		handle = NULL;		mlog_errno(status);		goto bail;	}	inode->i_ctime = inode->i_mtime = CURRENT_TIME;	status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);	if (status < 0)		mlog_errno(status);	status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh,				   last_eb_bh, handle, tc);	if (status < 0) {		mlog_errno(status);		goto bail;	}	mutex_unlock(&tl_inode->i_mutex);	tl_sem = 0;	ocfs2_commit_trans(handle);	handle = NULL;	BUG_ON(le32_to_cpu(fe->i_clusters) < target_i_clusters);	if (le32_to_cpu(fe->i_clusters) > target_i_clusters)		goto start;bail:	up_write(&OCFS2_I(inode)->ip_alloc_sem);	ocfs2_schedule_truncate_log_flush(osb, 1);	if (tl_sem)		mutex_unlock(&tl_inode->i_mutex);	if (handle)		ocfs2_commit_trans(handle);	if (last_eb_bh)		brelse(last_eb_bh);	/* This will drop the ext_alloc cluster lock for us */	ocfs2_free_truncate_context(tc);	mlog_exit(status);	return status;}/* * Expects the inode to already be locked. This will figure out which * inodes need to be locked and will put them on the returned truncate * context. */int ocfs2_prepare_truncate(struct ocfs2_super *osb,			   struct inode *inode,			   struct buffer_head *fe_bh,			   struct ocfs2_truncate_context **tc){	int status, metadata_delete;	unsigned int new_i_clusters;	struct ocfs2_dinode *fe;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_list *el;	struct buffer_head *last_eb_bh = NULL;	struct inode *ext_alloc_inode = NULL;	struct buffer_head *ext_alloc_bh = NULL;	mlog_entry_void();	*tc = NULL;	new_i_clusters = ocfs2_clusters_for_bytes(osb->sb,						  i_size_read(inode));	fe = (struct ocfs2_dinode *) fe_bh->b_data;	mlog(0, "fe->i_clusters = %u, new_i_clusters = %u, fe->i_size ="	     "%"MLFu64"\n", fe->i_clusters, new_i_clusters, fe->i_size);	if (le32_to_cpu(fe->i_clusters) <= new_i_clusters) {		ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has cluster count "			    "%u and size %"MLFu64" whereas struct inode has "			    "cluster count %u and size %llu which caused an "			    "invalid truncate to %u clusters.",			    le64_to_cpu(fe->i_blkno),			    le32_to_cpu(fe->i_clusters),			    le64_to_cpu(fe->i_size),			    OCFS2_I(inode)->ip_clusters, i_size_read(inode),			    new_i_clusters);		mlog_meta_lvb(ML_ERROR, &OCFS2_I(inode)->ip_meta_lockres);		status = -EIO;		goto bail;	}	*tc = kcalloc(1, sizeof(struct ocfs2_truncate_context), GFP_KERNEL);	if (!(*tc)) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	metadata_delete = 0;	if (fe->id2.i_list.l_tree_depth) {		/* If we have a tree, then the truncate may result in		 * metadata deletes. Figure this out from the		 * rightmost leaf block.*/		status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),					  &last_eb_bh, OCFS2_BH_CACHED, inode);		if (status < 0) {			mlog_errno(status);			goto bail;		}		eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);			brelse(last_eb_bh);			status = -EIO;			goto bail;		}		el = &(eb->h_list);		if (le32_to_cpu(el->l_recs[0].e_cpos) >= new_i_clusters)			metadata_delete = 1;	}	(*tc)->tc_last_eb_bh = last_eb_bh;	if (metadata_delete) {		mlog(0, "Will have to delete metadata for this trunc. "		     "locking allocator.\n");		ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);		if (!ext_alloc_inode) {			status = -ENOMEM;			mlog_errno(status);			goto bail;		}		mutex_lock(&ext_alloc_inode->i_mutex);		(*tc)->tc_ext_alloc_inode = ext_alloc_inode;		status = ocfs2_meta_lock(ext_alloc_inode,					 NULL,					 &ext_alloc_bh,					 1);		if (status < 0) {			mlog_errno(status);			goto bail;		}		(*tc)->tc_ext_alloc_bh = ext_alloc_bh;		(*tc)->tc_ext_alloc_locked = 1;	}	status = 0;bail:	if (status < 0) {		if (*tc)			ocfs2_free_truncate_context(*tc);		*tc = NULL;	}	mlog_exit_void();	return status;}void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc){	if (tc->tc_ext_alloc_inode) {		if (tc->tc_ext_alloc_locked)			ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);		mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);		iput(tc->tc_ext_alloc_inode);	}	if (tc->tc_ext_alloc_bh)		brelse(tc->tc_ext_alloc_bh);	if (tc->tc_last_eb_bh)		brelse(tc->tc_last_eb_bh);	kfree(tc);}

⌨️ 快捷键说明

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