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

📄 suballoc.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	status = ocfs2_journal_access(handle, alloc_inode, bg_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto out_rollback;	}	bg->bg_next_group = fe->id2.i_chain.cl_recs[chain].c_blkno;	status = ocfs2_journal_dirty(handle, bg_bh);	if (status < 0) {		mlog_errno(status);		goto out_rollback;	}	status = ocfs2_journal_access(handle, alloc_inode, fe_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto out_rollback;	}	fe->id2.i_chain.cl_recs[chain].c_blkno = bg->bg_blkno;	status = ocfs2_journal_dirty(handle, fe_bh);	if (status < 0) {		mlog_errno(status);		goto out_rollback;	}	status = 0;out_rollback:	if (status < 0) {		fe->id2.i_chain.cl_recs[chain].c_blkno = cpu_to_le64(fe_ptr);		bg->bg_next_group = cpu_to_le64(bg_ptr);		prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr);	}out:	mlog_exit(status);	return status;}static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,						     u32 wanted){	return le16_to_cpu(bg->bg_free_bits_count) > wanted;}/* return 0 on success, -ENOSPC to keep searching and any other < 0 * value on error. */static int ocfs2_cluster_group_search(struct inode *inode,				      struct buffer_head *group_bh,				      u32 bits_wanted, u32 min_bits,				      u16 *bit_off, u16 *bits_found){	int search = -ENOSPC;	int ret;	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;	u16 tmp_off, tmp_found;	unsigned int max_bits, gd_cluster_off;	BUG_ON(!ocfs2_is_cluster_bitmap(inode));	if (gd->bg_free_bits_count) {		max_bits = le16_to_cpu(gd->bg_bits);		/* Tail groups in cluster bitmaps which aren't cpg		 * aligned are prone to partial extention by a failed		 * fs resize. If the file system resize never got to		 * update the dinode cluster count, then we don't want		 * to trust any clusters past it, regardless of what		 * the group descriptor says. */		gd_cluster_off = ocfs2_blocks_to_clusters(inode->i_sb,							  le64_to_cpu(gd->bg_blkno));		if ((gd_cluster_off + max_bits) >		    OCFS2_I(inode)->ip_clusters) {			max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off;			mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n",			     (unsigned long long)le64_to_cpu(gd->bg_blkno),			     le16_to_cpu(gd->bg_bits),			     OCFS2_I(inode)->ip_clusters, max_bits);		}		ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),							group_bh, bits_wanted,							max_bits,							&tmp_off, &tmp_found);		if (ret)			return ret;		/* ocfs2_block_group_find_clear_bits() might		 * return success, but we still want to return		 * -ENOSPC unless it found the minimum number		 * of bits. */		if (min_bits <= tmp_found) {			*bit_off = tmp_off;			*bits_found = tmp_found;			search = 0; /* success */		}	}	return search;}static int ocfs2_block_group_search(struct inode *inode,				    struct buffer_head *group_bh,				    u32 bits_wanted, u32 min_bits,				    u16 *bit_off, u16 *bits_found){	int ret = -ENOSPC;	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;	BUG_ON(min_bits != 1);	BUG_ON(ocfs2_is_cluster_bitmap(inode));	if (bg->bg_free_bits_count)		ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),							group_bh, bits_wanted,							le16_to_cpu(bg->bg_bits),							bit_off, bits_found);	return ret;}static int ocfs2_alloc_dinode_update_counts(struct inode *inode,				       handle_t *handle,				       struct buffer_head *di_bh,				       u32 num_bits,				       u16 chain){	int ret;	u32 tmp_used;	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;	struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;	ret = ocfs2_journal_access(handle, inode, di_bh,				   OCFS2_JOURNAL_ACCESS_WRITE);	if (ret < 0) {		mlog_errno(ret);		goto out;	}	tmp_used = le32_to_cpu(di->id1.bitmap1.i_used);	di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used);	le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits);	ret = ocfs2_journal_dirty(handle, di_bh);	if (ret < 0)		mlog_errno(ret);out:	return ret;}static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,				  handle_t *handle,				  u32 bits_wanted,				  u32 min_bits,				  u16 *bit_off,				  unsigned int *num_bits,				  u64 gd_blkno,				  u16 *bits_left){	int ret;	u16 found;	struct buffer_head *group_bh = NULL;	struct ocfs2_group_desc *gd;	struct inode *alloc_inode = ac->ac_inode;	ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,			       &group_bh, OCFS2_BH_CACHED, alloc_inode);	if (ret < 0) {		mlog_errno(ret);		return ret;	}	gd = (struct ocfs2_group_desc *) group_bh->b_data;	if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);		ret = -EIO;		goto out;	}	ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,				  bit_off, &found);	if (ret < 0) {		if (ret != -ENOSPC)			mlog_errno(ret);		goto out;	}	*num_bits = found;	ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,					       *num_bits,					       le16_to_cpu(gd->bg_chain));	if (ret < 0) {		mlog_errno(ret);		goto out;	}	ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,					 *bit_off, *num_bits);	if (ret < 0)		mlog_errno(ret);	*bits_left = le16_to_cpu(gd->bg_free_bits_count);out:	brelse(group_bh);	return ret;}static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,			      handle_t *handle,			      u32 bits_wanted,			      u32 min_bits,			      u16 *bit_off,			      unsigned int *num_bits,			      u64 *bg_blkno,			      u16 *bits_left){	int status;	u16 chain, tmp_bits;	u32 tmp_used;	u64 next_group;	struct inode *alloc_inode = ac->ac_inode;	struct buffer_head *group_bh = NULL;	struct buffer_head *prev_group_bh = NULL;	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) ac->ac_bh->b_data;	struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;	struct ocfs2_group_desc *bg;	chain = ac->ac_chain;	mlog(0, "trying to alloc %u bits from chain %u, inode %llu\n",	     bits_wanted, chain,	     (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno);	status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),				  le64_to_cpu(cl->cl_recs[chain].c_blkno),				  &group_bh, OCFS2_BH_CACHED, alloc_inode);	if (status < 0) {		mlog_errno(status);		goto bail;	}	bg = (struct ocfs2_group_desc *) group_bh->b_data;	status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);	if (status) {		mlog_errno(status);		goto bail;	}	status = -ENOSPC;	/* for now, the chain search is a bit simplistic. We just use	 * the 1st group with any empty bits. */	while ((status = ac->ac_group_search(alloc_inode, group_bh,					     bits_wanted, min_bits, bit_off,					     &tmp_bits)) == -ENOSPC) {		if (!bg->bg_next_group)			break;		if (prev_group_bh) {			brelse(prev_group_bh);			prev_group_bh = NULL;		}		next_group = le64_to_cpu(bg->bg_next_group);		prev_group_bh = group_bh;		group_bh = NULL;		status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),					  next_group, &group_bh,					  OCFS2_BH_CACHED, alloc_inode);		if (status < 0) {			mlog_errno(status);			goto bail;		}		bg = (struct ocfs2_group_desc *) group_bh->b_data;		status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);		if (status) {			mlog_errno(status);			goto bail;		}	}	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",	     tmp_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));	*num_bits = tmp_bits;	BUG_ON(*num_bits == 0);	/*	 * Keep track of previous block descriptor read. When	 * we find a target, if we have read more than X	 * number of descriptors, and the target is reasonably	 * empty, relink him to top of his chain.	 *	 * We've read 0 extra blocks and only send one more to	 * the transaction, yet the next guy to search has a	 * much easier time.	 *	 * Do this *after* figuring out how many bits we're taking out	 * of our target group.	 */	if (ac->ac_allow_chain_relink &&	    (prev_group_bh) &&	    (ocfs2_block_group_reasonably_empty(bg, *num_bits))) {		status = ocfs2_relink_block_group(handle, alloc_inode,						  ac->ac_bh, group_bh,						  prev_group_bh, chain);		if (status < 0) {			mlog_errno(status);			goto bail;		}	}	/* Ok, claim our bits now: set the info on dinode, chainlist	 * and then the group */	status = ocfs2_journal_access(handle,				      alloc_inode,				      ac->ac_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);	fe->id1.bitmap1.i_used = cpu_to_le32(*num_bits + tmp_used);	le32_add_cpu(&cl->cl_recs[chain].c_free, -(*num_bits));	status = ocfs2_journal_dirty(handle,				     ac->ac_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = ocfs2_block_group_set_bits(handle,					    alloc_inode,					    bg,					    group_bh,					    *bit_off,					    *num_bits);	if (status < 0) {		mlog_errno(status);		goto bail;	}	mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits,	     (unsigned long long)le64_to_cpu(fe->i_blkno));	*bg_blkno = le64_to_cpu(bg->bg_blkno);	*bits_left = le16_to_cpu(bg->bg_free_bits_count);bail:	if (group_bh)		brelse(group_bh);	if (prev_group_bh)		brelse(prev_group_bh);	mlog_exit(status);	return status;}/* will give out up to bits_wanted contiguous bits. */static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,				     struct ocfs2_alloc_context *ac,				     handle_t *handle,				     u32 bits_wanted,				     u32 min_bits,				     u16 *bit_off,				     unsigned int *num_bits,				     u64 *bg_blkno){	int status;	u16 victim, i;	u16 bits_left = 0;	u64 hint_blkno = ac->ac_last_group;	struct ocfs2_chain_list *cl;	struct ocfs2_dinode *fe;	mlog_entry_void();	BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);	BUG_ON(bits_wanted > (ac->ac_bits_wanted - ac->ac_bits_given));	BUG_ON(!ac->ac_bh);	fe = (struct ocfs2_dinode *) ac->ac_bh->b_data;	if (!OCFS2_IS_VALID_DINODE(fe)) {		OCFS2_RO_ON_INVALID_DINODE(osb->sb, fe);		status = -EIO;		goto bail;	}	if (le32_to_cpu(fe->id1.bitmap1.i_used) >=	    le32_to_cpu(fe->id1.bitmap1.i_total)) {		ocfs2_error(osb->sb, "Chain allocator dinode %llu has %u used "			    "bits but only %u total.",			    (unsigned long long)le64_to_cpu(fe->i_blkno),			    le32_to_cpu(fe->id1.bitmap1.i_used),			    le32_to_cpu(fe->id1.bitmap1.i_total));		status = -EIO;		goto bail;	}	if (hint_blkno) {		/* Attempt to short-circuit the usual search mechanism		 * by jumping straight to the most recently used		 * allocation group. This helps us mantain some		 * contiguousness across allocations. */		status = ocfs2_search_one_group(ac, handle, bits_wanted,						min_bits, bit_off, num_bits,						hint_blkno, &bits_left);		if (!status) {			/* Be careful to update *bg_blkno here as the			 * caller is expecting it to be filled in, and			 * ocfs2_search_one_group() won't do that for			 * us. */			*bg_blkno = hint_blkno;			goto set_hint;		}		if (status < 0 && status != -ENOSPC) {			mlog_errno(status);			goto bail;		}	}	cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;	victim = ocfs2_find_victim_chain(cl);	ac->ac_chain = victim;	ac->ac_allow_chain_relink = 1;	status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off,				    num_bits, bg_blkno, &bits_left);	if (!status)		goto set_hint;	if (status < 0 && status != -ENOSPC) {		mlog_errno(status);		goto bail;	}	mlog(0, "Search of victim chain %u came up with nothing, "	     "trying all chains now.\n", victim);	/* If we didn't pick a good victim, then just default to	 * searching each chain in order. Don't allow chain relinking	 * because we only calculate enough journal credits for one	 * relink per alloc. */	ac->ac_allow_chain_relink = 0;	for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i ++) {		if (i == victim)			continue;		if (!cl->cl_recs[i].c_free)			continue;		ac->ac_chain = i;		status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,					    bit_off, num_bits, bg_blkno,					    &bits_left);		if (!status)			break;		if (status < 0 && status != -ENOSPC) {			mlog_errno(status);			goto bail;		}	}set_hint:

⌨️ 快捷键说明

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