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

📄 extent_map.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	rb_erase(&old_ent->e_node, &em->em_extents);	/* Now that he's erased, set him up for deletion */	ctxt->old_ent = old_ent;	if (ctxt->need_left) {		ret = ocfs2_extent_map_insert_entry(em,						    ctxt->left_ent);		if (ret)			goto out_unlock;		ctxt->left_ent = NULL;	}	if (ctxt->need_right) {		ret = ocfs2_extent_map_insert_entry(em,						    ctxt->right_ent);		if (ret)			goto out_unlock;		ctxt->right_ent = NULL;	}	ret = ocfs2_extent_map_insert_entry(em, ctxt->new_ent);	if (!ret)		ctxt->new_ent = NULL;out_unlock:	spin_unlock(&OCFS2_I(inode)->ip_lock);	return ret;}int ocfs2_extent_map_insert(struct inode *inode, struct ocfs2_extent_rec *rec,			    int tree_depth){	int ret;	struct ocfs2_em_insert_context ctxt = {0, };	if ((le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters)) >	    OCFS2_I(inode)->ip_map.em_clusters) {		ret = -EBADR;		mlog_errno(ret);		return ret;	}	/* Zero e_clusters means a truncated tail record.  It better be EOF */	if (!rec->e_clusters) {		if ((le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters)) !=		    OCFS2_I(inode)->ip_map.em_clusters) {			ret = -EBADR;			mlog_errno(ret);			ocfs2_error(inode->i_sb,				    "Zero e_clusters on non-tail extent record at e_blkno %"MLFu64" on inode %"MLFu64"\n",				    le64_to_cpu(rec->e_blkno),				    OCFS2_I(inode)->ip_blkno);			return ret;		}		/* Ignore the truncated tail */		return 0;	}	ret = -ENOMEM;	ctxt.new_ent = kmem_cache_alloc(ocfs2_em_ent_cachep,					GFP_NOFS);	if (!ctxt.new_ent) {		mlog_errno(ret);		return ret;	}	ctxt.new_ent->e_rec = *rec;	ctxt.new_ent->e_tree_depth = tree_depth;	do {		ret = -ENOMEM;		if (ctxt.need_left && !ctxt.left_ent) {			ctxt.left_ent =				kmem_cache_alloc(ocfs2_em_ent_cachep,						 GFP_NOFS);			if (!ctxt.left_ent)				break;		}		if (ctxt.need_right && !ctxt.right_ent) {			ctxt.right_ent =				kmem_cache_alloc(ocfs2_em_ent_cachep,						 GFP_NOFS);			if (!ctxt.right_ent)				break;		}		ret = ocfs2_extent_map_try_insert(inode, rec,						  tree_depth, &ctxt);	} while (ret == -EAGAIN);	if ((ret < 0) && (ret != -EEXIST))		mlog_errno(ret);	if (ctxt.left_ent)		kmem_cache_free(ocfs2_em_ent_cachep, ctxt.left_ent);	if (ctxt.right_ent)		kmem_cache_free(ocfs2_em_ent_cachep, ctxt.right_ent);	if (ctxt.old_ent)		kmem_cache_free(ocfs2_em_ent_cachep, ctxt.old_ent);	if (ctxt.new_ent)		kmem_cache_free(ocfs2_em_ent_cachep, ctxt.new_ent);	return ret;}/* * Append this record to the tail of the extent map.  It must be * tree_depth 0.  The record might be an extension of an existing * record, and as such that needs to be handled.  eg: * * Existing record in the extent map: * *	cpos = 10, len = 10 *	|---------| * * New Record: * *	cpos = 10, len = 20 *	|------------------| * * The passed record is the new on-disk record.  The new_clusters value * is how many clusters were added to the file.  If the append is a * contiguous append, the new_clusters has been added to * rec->e_clusters.  If the append is an entirely new extent, then * rec->e_clusters is == new_clusters. */int ocfs2_extent_map_append(struct inode *inode,			    struct ocfs2_extent_rec *rec,			    u32 new_clusters){	int ret;	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	struct ocfs2_extent_map_entry *ent;	struct ocfs2_extent_rec *old;	BUG_ON(!new_clusters);	BUG_ON(le32_to_cpu(rec->e_clusters) < new_clusters);	if (em->em_clusters < OCFS2_I(inode)->ip_clusters) {		/*		 * Size changed underneath us on disk.  Drop any		 * straddling records and update our idea of		 * i_clusters		 */		ocfs2_extent_map_drop(inode, em->em_clusters - 1);		em->em_clusters = OCFS2_I(inode)->ip_clusters;	}	mlog_bug_on_msg((le32_to_cpu(rec->e_cpos) +			 le32_to_cpu(rec->e_clusters)) !=			(em->em_clusters + new_clusters),			"Inode %"MLFu64":\n"			"rec->e_cpos = %u + rec->e_clusters = %u = %u\n"			"em->em_clusters = %u + new_clusters = %u = %u\n",			OCFS2_I(inode)->ip_blkno,			le32_to_cpu(rec->e_cpos), le32_to_cpu(rec->e_clusters),			le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters),			em->em_clusters, new_clusters,			em->em_clusters + new_clusters);	em->em_clusters += new_clusters;	ret = -ENOENT;	if (le32_to_cpu(rec->e_clusters) > new_clusters) {		/* This is a contiguous append */		ent = ocfs2_extent_map_lookup(em, le32_to_cpu(rec->e_cpos), 1,					      NULL, NULL);		if (ent) {			old = &ent->e_rec;			BUG_ON((le32_to_cpu(rec->e_cpos) +				le32_to_cpu(rec->e_clusters)) !=				 (le32_to_cpu(old->e_cpos) +				  le32_to_cpu(old->e_clusters) +				  new_clusters));			if (ent->e_tree_depth == 0) {				BUG_ON(le32_to_cpu(old->e_cpos) !=				       le32_to_cpu(rec->e_cpos));				BUG_ON(le64_to_cpu(old->e_blkno) !=				       le64_to_cpu(rec->e_blkno));				ret = 0;			}			/*			 * Let non-leafs fall through as -ENOENT to			 * force insertion of the new leaf.			 */			le32_add_cpu(&old->e_clusters, new_clusters);		}	}	if (ret == -ENOENT)		ret = ocfs2_extent_map_insert(inode, rec, 0);	if (ret < 0)		mlog_errno(ret);	return ret;}/* * Look up the record containing this cluster offset.  This record is * part of the extent map.  Do not free it.  Any changes you make to * it will reflect in the extent map.  So, if your last extent * is (cpos = 10, clusters = 10) and you truncate the file by 5 * clusters, you can do: * * ret = ocfs2_extent_map_get_rec(em, orig_size - 5, &rec); * rec->e_clusters -= 5; * * The lookup does not read from disk.  If the map isn't filled in for * an entry, you won't find it. * * Also note that the returned record is valid until alloc_sem is * dropped.  After that, truncate and extend can happen.  Caveat Emptor. */int ocfs2_extent_map_get_rec(struct inode *inode, u32 cpos,			     struct ocfs2_extent_rec **rec,			     int *tree_depth){	int ret = -ENOENT;	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	struct ocfs2_extent_map_entry *ent;	*rec = NULL;	if (cpos >= OCFS2_I(inode)->ip_clusters)		return -EINVAL;	if (cpos >= em->em_clusters) {		/*		 * Size changed underneath us on disk.  Drop any		 * straddling records and update our idea of		 * i_clusters		 */		ocfs2_extent_map_drop(inode, em->em_clusters - 1);		em->em_clusters = OCFS2_I(inode)->ip_clusters ;	}	ent = ocfs2_extent_map_lookup(&OCFS2_I(inode)->ip_map, cpos, 1,				      NULL, NULL);	if (ent) {		*rec = &ent->e_rec;		if (tree_depth)			*tree_depth = ent->e_tree_depth;		ret = 0;	}	return ret;}int ocfs2_extent_map_get_clusters(struct inode *inode,				  u32 v_cpos, int count,				  u32 *p_cpos, int *ret_count){	int ret;	u32 coff, ccount;	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	struct ocfs2_extent_map_entry *ent = NULL;	*p_cpos = ccount = 0;	if ((v_cpos + count) > OCFS2_I(inode)->ip_clusters)		return -EINVAL;	if ((v_cpos + count) > em->em_clusters) {		/*		 * Size changed underneath us on disk.  Drop any		 * straddling records and update our idea of		 * i_clusters		 */		ocfs2_extent_map_drop(inode, em->em_clusters - 1);		em->em_clusters = OCFS2_I(inode)->ip_clusters;	}	ret = ocfs2_extent_map_lookup_read(inode, v_cpos, count, &ent);	if (ret)		return ret;	if (ent) {		/* We should never find ourselves straddling an interval */		if (!ocfs2_extent_rec_contains_clusters(&ent->e_rec,							v_cpos,							count))			return -ESRCH;		coff = v_cpos - le32_to_cpu(ent->e_rec.e_cpos);		*p_cpos = ocfs2_blocks_to_clusters(inode->i_sb,				le64_to_cpu(ent->e_rec.e_blkno)) +			  coff;		if (ret_count)			*ret_count = le32_to_cpu(ent->e_rec.e_clusters) - coff;		return 0;	}	return -ENOENT;}int ocfs2_extent_map_get_blocks(struct inode *inode,				u64 v_blkno, int count,				u64 *p_blkno, int *ret_count){	int ret;	u64 boff;	u32 cpos, clusters;	int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);	struct ocfs2_extent_map_entry *ent = NULL;	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	struct ocfs2_extent_rec *rec;	*p_blkno = 0;	cpos = ocfs2_blocks_to_clusters(inode->i_sb, v_blkno);	clusters = ocfs2_blocks_to_clusters(inode->i_sb,					    (u64)count + bpc - 1);	if ((cpos + clusters) > OCFS2_I(inode)->ip_clusters) {		ret = -EINVAL;		mlog_errno(ret);		return ret;	}	if ((cpos + clusters) > em->em_clusters) {		/*		 * Size changed underneath us on disk.  Drop any		 * straddling records and update our idea of		 * i_clusters		 */		ocfs2_extent_map_drop(inode, em->em_clusters - 1);		em->em_clusters = OCFS2_I(inode)->ip_clusters;	}	ret = ocfs2_extent_map_lookup_read(inode, cpos, clusters, &ent);	if (ret) {		mlog_errno(ret);		return ret;	}	if (ent)	{		rec = &ent->e_rec;		/* We should never find ourselves straddling an interval */		if (!ocfs2_extent_rec_contains_clusters(rec, cpos, clusters)) {			ret = -ESRCH;			mlog_errno(ret);			return ret;		}		boff = ocfs2_clusters_to_blocks(inode->i_sb, cpos -						le32_to_cpu(rec->e_cpos));		boff += (v_blkno & (u64)(bpc - 1));		*p_blkno = le64_to_cpu(rec->e_blkno) + boff;		if (ret_count) {			*ret_count = ocfs2_clusters_to_blocks(inode->i_sb,					le32_to_cpu(rec->e_clusters)) - boff;		}		return 0;	}	return -ENOENT;}int ocfs2_extent_map_init(struct inode *inode){	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	em->em_extents = RB_ROOT;	em->em_clusters = 0;	return 0;}/* Needs the lock */static void __ocfs2_extent_map_drop(struct inode *inode,				    u32 new_clusters,				    struct rb_node **free_head,				    struct ocfs2_extent_map_entry **tail_ent){	struct rb_node *node, *next;	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	struct ocfs2_extent_map_entry *ent;	*free_head = NULL;	ent = NULL;	node = rb_last(&em->em_extents);	while (node)	{		next = rb_prev(node);		ent = rb_entry(node, struct ocfs2_extent_map_entry,			       e_node);		if (le32_to_cpu(ent->e_rec.e_cpos) < new_clusters)			break;		rb_erase(&ent->e_node, &em->em_extents);		node->rb_right = *free_head;		*free_head = node;		ent = NULL;		node = next;	}	/* Do we have an entry straddling new_clusters? */	if (tail_ent) {		if (ent &&		    ((le32_to_cpu(ent->e_rec.e_cpos) +		      le32_to_cpu(ent->e_rec.e_clusters)) > new_clusters))			*tail_ent = ent;		else			*tail_ent = NULL;	}}static void __ocfs2_extent_map_drop_cleanup(struct rb_node *free_head){	struct rb_node *node;	struct ocfs2_extent_map_entry *ent;	while (free_head) {		node = free_head;		free_head = node->rb_right;		ent = rb_entry(node, struct ocfs2_extent_map_entry,			       e_node);		kmem_cache_free(ocfs2_em_ent_cachep, ent);	}}/* * Remove all entries past new_clusters, inclusive of an entry that * contains new_clusters.  This is effectively a cache forget. * * If you want to also clip the last extent by some number of clusters, * you need to call ocfs2_extent_map_trunc(). * This code does not check or modify ip_clusters. */int ocfs2_extent_map_drop(struct inode *inode, u32 new_clusters){	struct rb_node *free_head = NULL;	struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;	struct ocfs2_extent_map_entry *ent;	spin_lock(&OCFS2_I(inode)->ip_lock);	__ocfs2_extent_map_drop(inode, new_clusters, &free_head, &ent);	if (ent) {		rb_erase(&ent->e_node, &em->em_extents);		ent->e_node.rb_right = free_head;		free_head = &ent->e_node;	}	spin_unlock(&OCFS2_I(inode)->ip_lock);	if (free_head)		__ocfs2_extent_map_drop_cleanup(free_head);	return 0;}/* * Remove all entries past new_clusters and also clip any extent * straddling new_clusters, if there is one.  This does not check * or modify ip_clusters */int ocfs2_extent_map_trunc(struct inode *inode, u32 new_clusters){	struct rb_node *free_head = NULL;	struct ocfs2_extent_map_entry *ent = NULL;	spin_lock(&OCFS2_I(inode)->ip_lock);	__ocfs2_extent_map_drop(inode, new_clusters, &free_head, &ent);	if (ent)		ent->e_rec.e_clusters = cpu_to_le32(new_clusters -					       le32_to_cpu(ent->e_rec.e_cpos));	OCFS2_I(inode)->ip_map.em_clusters = new_clusters;	spin_unlock(&OCFS2_I(inode)->ip_lock);	if (free_head)		__ocfs2_extent_map_drop_cleanup(free_head);	return 0;}int __init init_ocfs2_extent_maps(void){	ocfs2_em_ent_cachep =		kmem_cache_create("ocfs2_em_ent",				  sizeof(struct ocfs2_extent_map_entry),				  0, SLAB_HWCACHE_ALIGN, NULL, NULL);	if (!ocfs2_em_ent_cachep)		return -ENOMEM;	return 0;}void __exit exit_ocfs2_extent_maps(void){	kmem_cache_destroy(ocfs2_em_ent_cachep);}

⌨️ 快捷键说明

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