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

📄 suballoc.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
				mlog_errno(status);			goto bail;		}		atomic_inc(&osb->alloc_stats.bg_extends);		/* You should never ask for this much metadata */		BUG_ON(bits_wanted >		       (le32_to_cpu(fe->id1.bitmap1.i_total)			- le32_to_cpu(fe->id1.bitmap1.i_used)));	}	get_bh(bh);	ac->ac_bh = bh;bail:	if (bh)		brelse(bh);	mlog_exit(status);	return status;}int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,			       struct ocfs2_dinode *fe,			       struct ocfs2_alloc_context **ac){	int status;	u32 slot;	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);	if (!(*ac)) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	(*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);	(*ac)->ac_which = OCFS2_AC_USE_META;	slot = osb->slot_num;	(*ac)->ac_group_search = ocfs2_block_group_search;	status = ocfs2_reserve_suballoc_bits(osb, (*ac),					     EXTENT_ALLOC_SYSTEM_INODE,					     slot, ALLOC_NEW_GROUP);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	status = 0;bail:	if ((status < 0) && *ac) {		ocfs2_free_alloc_context(*ac);		*ac = NULL;	}	mlog_exit(status);	return status;}static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,					      struct ocfs2_alloc_context *ac){	int i, status = -ENOSPC;	s16 slot = ocfs2_get_inode_steal_slot(osb);	/* Start to steal inodes from the first slot after ours. */	if (slot == OCFS2_INVALID_SLOT)		slot = osb->slot_num + 1;	for (i = 0; i < osb->max_slots; i++, slot++) {		if (slot == osb->max_slots)			slot = 0;		if (slot == osb->slot_num)			continue;		status = ocfs2_reserve_suballoc_bits(osb, ac,						     INODE_ALLOC_SYSTEM_INODE,						     slot, NOT_ALLOC_NEW_GROUP);		if (status >= 0) {			ocfs2_set_inode_steal_slot(osb, slot);			break;		}		ocfs2_free_ac_resource(ac);	}	return status;}int ocfs2_reserve_new_inode(struct ocfs2_super *osb,			    struct ocfs2_alloc_context **ac){	int status;	s16 slot = ocfs2_get_inode_steal_slot(osb);	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);	if (!(*ac)) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	(*ac)->ac_bits_wanted = 1;	(*ac)->ac_which = OCFS2_AC_USE_INODE;	(*ac)->ac_group_search = ocfs2_block_group_search;	/*	 * slot is set when we successfully steal inode from other nodes.	 * It is reset in 3 places:	 * 1. when we flush the truncate log	 * 2. when we complete local alloc recovery.	 * 3. when we successfully allocate from our own slot.	 * After it is set, we will go on stealing inodes until we find the	 * need to check our slots to see whether there is some space for us.	 */	if (slot != OCFS2_INVALID_SLOT &&	    atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL)		goto inode_steal;	atomic_set(&osb->s_num_inodes_stolen, 0);	status = ocfs2_reserve_suballoc_bits(osb, *ac,					     INODE_ALLOC_SYSTEM_INODE,					     osb->slot_num, ALLOC_NEW_GROUP);	if (status >= 0) {		status = 0;		/*		 * Some inodes must be freed by us, so try to allocate		 * from our own next time.		 */		if (slot != OCFS2_INVALID_SLOT)			ocfs2_init_inode_steal_slot(osb);		goto bail;	} else if (status < 0 && status != -ENOSPC) {		mlog_errno(status);		goto bail;	}	ocfs2_free_ac_resource(*ac);inode_steal:	status = ocfs2_steal_inode_from_other_nodes(osb, *ac);	atomic_inc(&osb->s_num_inodes_stolen);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	status = 0;bail:	if ((status < 0) && *ac) {		ocfs2_free_alloc_context(*ac);		*ac = NULL;	}	mlog_exit(status);	return status;}/* local alloc code has to do the same thing, so rather than do this * twice.. */int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,				      struct ocfs2_alloc_context *ac){	int status;	ac->ac_which = OCFS2_AC_USE_MAIN;	ac->ac_group_search = ocfs2_cluster_group_search;	status = ocfs2_reserve_suballoc_bits(osb, ac,					     GLOBAL_BITMAP_SYSTEM_INODE,					     OCFS2_INVALID_SLOT,					     ALLOC_NEW_GROUP);	if (status < 0 && status != -ENOSPC) {		mlog_errno(status);		goto bail;	}bail:	return status;}/* Callers don't need to care which bitmap (local alloc or main) to * use so we figure it out for them, but unfortunately this clutters * things a bit. */int ocfs2_reserve_clusters(struct ocfs2_super *osb,			   u32 bits_wanted,			   struct ocfs2_alloc_context **ac){	int status;	mlog_entry_void();	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);	if (!(*ac)) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	(*ac)->ac_bits_wanted = bits_wanted;	status = -ENOSPC;	if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {		status = ocfs2_reserve_local_alloc_bits(osb,							bits_wanted,							*ac);		if ((status < 0) && (status != -ENOSPC)) {			mlog_errno(status);			goto bail;		} else if (status == -ENOSPC) {			/* reserve_local_bits will return enospc with			 * the local alloc inode still locked, so we			 * can change this safely here. */			mlog(0, "Disabling local alloc\n");			/* We set to OCFS2_LA_DISABLED so that umount			 * can clean up what's left of the local			 * allocation */			osb->local_alloc_state = OCFS2_LA_DISABLED;		}	}	if (status == -ENOSPC) {		status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);		if (status < 0) {			if (status != -ENOSPC)				mlog_errno(status);			goto bail;		}	}	status = 0;bail:	if ((status < 0) && *ac) {		ocfs2_free_alloc_context(*ac);		*ac = NULL;	}	mlog_exit(status);	return status;}/* * More or less lifted from ext3. I'll leave their description below: * * "For ext3 allocations, we must not reuse any blocks which are * allocated in the bitmap buffer's "last committed data" copy.  This * prevents deletes from freeing up the page for reuse until we have * committed the delete transaction. * * If we didn't do this, then deleting something and reallocating it as * data would allow the old block to be overwritten before the * transaction committed (because we force data to disk before commit). * This would lead to corruption if we crashed between overwriting the * data and committing the delete. * * @@@ We may want to make this allocation behaviour conditional on * data-writes at some point, and disable it for metadata allocations or * sync-data inodes." * * Note: OCFS2 already does this differently for metadata vs data * allocations, as those bitmaps are separate and undo access is never * called on a metadata group descriptor. */static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,					 int nr){	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;	if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap))		return 0;	if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data)		return 1;	bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data;	return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);}static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,					     struct buffer_head *bg_bh,					     unsigned int bits_wanted,					     unsigned int total_bits,					     u16 *bit_off,					     u16 *bits_found){	void *bitmap;	u16 best_offset, best_size;	int offset, start, found, status = 0;	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {		OCFS2_RO_ON_INVALID_GROUP_DESC(osb->sb, bg);		return -EIO;	}	found = start = best_offset = best_size = 0;	bitmap = bg->bg_bitmap;	while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) {		if (offset == total_bits)			break;		if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) {			/* We found a zero, but we can't use it as it			 * hasn't been put to disk yet! */			found = 0;			start = offset + 1;		} else if (offset == start) {			/* we found a zero */			found++;			/* move start to the next bit to test */			start++;		} else {			/* got a zero after some ones */			found = 1;			start = offset + 1;		}		if (found > best_size) {			best_size = found;			best_offset = start - found;		}		/* we got everything we needed */		if (found == bits_wanted) {			/* mlog(0, "Found it all!\n"); */			break;		}	}	/* XXX: I think the first clause is equivalent to the second	 * 	- jlbec */	if (found == bits_wanted) {		*bit_off = start - found;		*bits_found = found;	} else if (best_size) {		*bit_off = best_offset;		*bits_found = best_size;	} else {		status = -ENOSPC;		/* No error log here -- see the comment above		 * ocfs2_test_bg_bit_allocatable */	}	return status;}static inline int ocfs2_block_group_set_bits(handle_t *handle,					     struct inode *alloc_inode,					     struct ocfs2_group_desc *bg,					     struct buffer_head *group_bh,					     unsigned int bit_off,					     unsigned int num_bits){	int status;	void *bitmap = bg->bg_bitmap;	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;	mlog_entry_void();	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);		status = -EIO;		goto bail;	}	BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);	mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,	     num_bits);	if (ocfs2_is_cluster_bitmap(alloc_inode))		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;	status = ocfs2_journal_access(handle,				      alloc_inode,				      group_bh,				      journal_type);	if (status < 0) {		mlog_errno(status);		goto bail;	}	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);	while(num_bits--)		ocfs2_set_bit(bit_off++, bitmap);	status = ocfs2_journal_dirty(handle,				     group_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}bail:	mlog_exit(status);	return status;}/* find the one with the most empty bits */static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl){	u16 curr, best;	BUG_ON(!cl->cl_next_free_rec);	best = curr = 0;	while (curr < le16_to_cpu(cl->cl_next_free_rec)) {		if (le32_to_cpu(cl->cl_recs[curr].c_free) >		    le32_to_cpu(cl->cl_recs[best].c_free))			best = curr;		curr++;	}	BUG_ON(best >= le16_to_cpu(cl->cl_next_free_rec));	return best;}static int ocfs2_relink_block_group(handle_t *handle,				    struct inode *alloc_inode,				    struct buffer_head *fe_bh,				    struct buffer_head *bg_bh,				    struct buffer_head *prev_bg_bh,				    u16 chain){	int status;	/* there is a really tiny chance the journal calls could fail,	 * but we wouldn't want inconsistent blocks in *any* case. */	u64 fe_ptr, bg_ptr, prev_bg_ptr;	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;	struct ocfs2_group_desc *prev_bg = (struct ocfs2_group_desc *) prev_bg_bh->b_data;	if (!OCFS2_IS_VALID_DINODE(fe)) {		OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);		status = -EIO;		goto out;	}	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);		status = -EIO;		goto out;	}	if (!OCFS2_IS_VALID_GROUP_DESC(prev_bg)) {		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, prev_bg);		status = -EIO;		goto out;	}	mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",	     (unsigned long long)le64_to_cpu(fe->i_blkno), chain,	     (unsigned long long)le64_to_cpu(bg->bg_blkno),	     (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));	fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);	bg_ptr = le64_to_cpu(bg->bg_next_group);	prev_bg_ptr = le64_to_cpu(prev_bg->bg_next_group);	status = ocfs2_journal_access(handle, alloc_inode, prev_bg_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto out_rollback;	}	prev_bg->bg_next_group = bg->bg_next_group;	status = ocfs2_journal_dirty(handle, prev_bg_bh);	if (status < 0) {		mlog_errno(status);		goto out_rollback;	}

⌨️ 快捷键说明

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