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

📄 uptodate.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	rb_link_node(&new->c_node, parent, p);	rb_insert_color(&new->c_node, &ci->ci_cache.ci_tree);	ci->ci_num_cached++;}static inline int ocfs2_insert_can_use_array(struct ocfs2_inode_info *oi,					     struct ocfs2_caching_info *ci){	assert_spin_locked(&oi->ip_lock);	return (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) &&		(ci->ci_num_cached < OCFS2_INODE_MAX_CACHE_ARRAY);}/* tree should be exactly OCFS2_INODE_MAX_CACHE_ARRAY wide. NULL the * pointers in tree after we use them - this allows caller to detect * when to free in case of error. */static void ocfs2_expand_cache(struct ocfs2_inode_info *oi,			       struct ocfs2_meta_cache_item **tree){	int i;	struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;	mlog_bug_on_msg(ci->ci_num_cached != OCFS2_INODE_MAX_CACHE_ARRAY,			"Inode %llu, num cached = %u, should be %u\n",			(unsigned long long)oi->ip_blkno, ci->ci_num_cached,			OCFS2_INODE_MAX_CACHE_ARRAY);	mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),			"Inode %llu not marked as inline anymore!\n",			(unsigned long long)oi->ip_blkno);	assert_spin_locked(&oi->ip_lock);	/* Be careful to initialize the tree members *first* because	 * once the ci_tree is used, the array is junk... */	for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++)		tree[i]->c_block = ci->ci_cache.ci_array[i];	oi->ip_flags &= ~OCFS2_INODE_CACHE_INLINE;	ci->ci_cache.ci_tree = RB_ROOT;	/* this will be set again by __ocfs2_insert_cache_tree */	ci->ci_num_cached = 0;	for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) {		__ocfs2_insert_cache_tree(ci, tree[i]);		tree[i] = NULL;	}	mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n",	     (unsigned long long)oi->ip_blkno, oi->ip_flags, ci->ci_num_cached);}/* Slow path function - memory allocation is necessary. See the * comment above ocfs2_set_buffer_uptodate for more information. */static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,					sector_t block,					int expand_tree){	int i;	struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;	struct ocfs2_meta_cache_item *new = NULL;	struct ocfs2_meta_cache_item *tree[OCFS2_INODE_MAX_CACHE_ARRAY] =		{ NULL, };	mlog(0, "Inode %llu, block %llu, expand = %d\n",	     (unsigned long long)oi->ip_blkno,	     (unsigned long long)block, expand_tree);	new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS);	if (!new) {		mlog_errno(-ENOMEM);		return;	}	new->c_block = block;	if (expand_tree) {		/* Do *not* allocate an array here - the removal code		 * has no way of tracking that. */		for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) {			tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep,						   GFP_NOFS);			if (!tree[i]) {				mlog_errno(-ENOMEM);				goto out_free;			}			/* These are initialized in ocfs2_expand_cache! */		}	}	spin_lock(&oi->ip_lock);	if (ocfs2_insert_can_use_array(oi, ci)) {		mlog(0, "Someone cleared the tree underneath us\n");		/* Ok, items were removed from the cache in between		 * locks. Detect this and revert back to the fast path */		ocfs2_append_cache_array(ci, block);		spin_unlock(&oi->ip_lock);		goto out_free;	}	if (expand_tree)		ocfs2_expand_cache(oi, tree);	__ocfs2_insert_cache_tree(ci, new);	spin_unlock(&oi->ip_lock);	new = NULL;out_free:	if (new)		kmem_cache_free(ocfs2_uptodate_cachep, new);	/* If these were used, then ocfs2_expand_cache re-set them to	 * NULL for us. */	if (tree[0]) {		for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++)			if (tree[i])				kmem_cache_free(ocfs2_uptodate_cachep,						tree[i]);	}}/* Item insertion is guarded by ip_io_mutex, so the insertion path takes * advantage of this by not rechecking for a duplicate insert during * the slow case. Additionally, if the cache needs to be bumped up to * a tree, the code will not recheck after acquiring the lock -- * multiple paths cannot be expanding to a tree at the same time. * * The slow path takes into account that items can be removed * (including the whole tree wiped and reset) when this process it out * allocating memory. In those cases, it reverts back to the fast * path. * * Note that this function may actually fail to insert the block if * memory cannot be allocated. This is not fatal however (but may * result in a performance penalty) * * Readahead buffers can be passed in here before the I/O request is * completed. */void ocfs2_set_buffer_uptodate(struct inode *inode,			       struct buffer_head *bh){	int expand;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;	/* The block may very well exist in our cache already, so avoid	 * doing any more work in that case. */	if (ocfs2_buffer_cached(oi, bh))		return;	mlog(0, "Inode %llu, inserting block %llu\n",	     (unsigned long long)oi->ip_blkno,	     (unsigned long long)bh->b_blocknr);	/* No need to recheck under spinlock - insertion is guarded by	 * ip_io_mutex */	spin_lock(&oi->ip_lock);	if (ocfs2_insert_can_use_array(oi, ci)) {		/* Fast case - it's an array and there's a free		 * spot. */		ocfs2_append_cache_array(ci, bh->b_blocknr);		spin_unlock(&oi->ip_lock);		return;	}	expand = 0;	if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) {		/* We need to bump things up to a tree. */		expand = 1;	}	spin_unlock(&oi->ip_lock);	__ocfs2_set_buffer_uptodate(oi, bh->b_blocknr, expand);}/* Called against a newly allocated buffer. Most likely nobody should * be able to read this sort of metadata while it's still being * allocated, but this is careful to take ip_io_mutex anyway. */void ocfs2_set_new_buffer_uptodate(struct inode *inode,				   struct buffer_head *bh){	struct ocfs2_inode_info *oi = OCFS2_I(inode);	/* This should definitely *not* exist in our cache */	BUG_ON(ocfs2_buffer_cached(oi, bh));	set_buffer_uptodate(bh);	mutex_lock(&oi->ip_io_mutex);	ocfs2_set_buffer_uptodate(inode, bh);	mutex_unlock(&oi->ip_io_mutex);}/* Requires ip_lock. */static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci,					int index){	sector_t *array = ci->ci_cache.ci_array;	int bytes;	BUG_ON(index < 0 || index >= OCFS2_INODE_MAX_CACHE_ARRAY);	BUG_ON(index >= ci->ci_num_cached);	BUG_ON(!ci->ci_num_cached);	mlog(0, "remove index %d (num_cached = %u\n", index,	     ci->ci_num_cached);	ci->ci_num_cached--;	/* don't need to copy if the array is now empty, or if we	 * removed at the tail */	if (ci->ci_num_cached && index < ci->ci_num_cached) {		bytes = sizeof(sector_t) * (ci->ci_num_cached - index);		memmove(&array[index], &array[index + 1], bytes);	}}/* Requires ip_lock. */static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci,				       struct ocfs2_meta_cache_item *item){	mlog(0, "remove block %llu from tree\n",	     (unsigned long long) item->c_block);	rb_erase(&item->c_node, &ci->ci_cache.ci_tree);	ci->ci_num_cached--;}/* Called when we remove a chunk of metadata from an inode. We don't * bother reverting things to an inlined array in the case of a remove * which moves us back under the limit. */void ocfs2_remove_from_cache(struct inode *inode,			     struct buffer_head *bh){	int index;	sector_t block = bh->b_blocknr;	struct ocfs2_meta_cache_item *item = NULL;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;	spin_lock(&oi->ip_lock);	mlog(0, "Inode %llu, remove %llu, items = %u, array = %u\n",	     (unsigned long long)oi->ip_blkno,	     (unsigned long long) block, ci->ci_num_cached,	     oi->ip_flags & OCFS2_INODE_CACHE_INLINE);	if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) {		index = ocfs2_search_cache_array(ci, block);		if (index != -1)			ocfs2_remove_metadata_array(ci, index);	} else {		item = ocfs2_search_cache_tree(ci, block);		if (item)			ocfs2_remove_metadata_tree(ci, item);	}	spin_unlock(&oi->ip_lock);	if (item)		kmem_cache_free(ocfs2_uptodate_cachep, item);}int __init init_ocfs2_uptodate_cache(void){	ocfs2_uptodate_cachep = kmem_cache_create("ocfs2_uptodate",				  sizeof(struct ocfs2_meta_cache_item),				  0, SLAB_HWCACHE_ALIGN, NULL);	if (!ocfs2_uptodate_cachep)		return -ENOMEM;	mlog(0, "%u inlined cache items per inode.\n",	     OCFS2_INODE_MAX_CACHE_ARRAY);	return 0;}void exit_ocfs2_uptodate_cache(void){	if (ocfs2_uptodate_cachep)		kmem_cache_destroy(ocfs2_uptodate_cachep);}

⌨️ 快捷键说明

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