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

📄 localalloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		ocfs2_error(osb->sb, "local alloc inode %llu says it has "			    "%u free bits, but a count shows %u",			    (unsigned long long)le64_to_cpu(alloc->i_blkno),			    le32_to_cpu(alloc->id1.bitmap1.i_used),			    ocfs2_local_alloc_count_bits(alloc));		status = -EIO;		goto bail;	}#endif	free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -		le32_to_cpu(alloc->id1.bitmap1.i_used);	if (bits_wanted > free_bits) {		/* uhoh, window change time. */		status =			ocfs2_local_alloc_slide_window(osb, local_alloc_inode);		if (status < 0) {			if (status != -ENOSPC)				mlog_errno(status);			goto bail;		}	}	ac->ac_inode = local_alloc_inode;	ac->ac_which = OCFS2_AC_USE_LOCAL;	get_bh(osb->local_alloc_bh);	ac->ac_bh = osb->local_alloc_bh;	status = 0;bail:	if (status < 0 && local_alloc_inode) {		mutex_unlock(&local_alloc_inode->i_mutex);		iput(local_alloc_inode);	}	mlog_exit(status);	return status;}int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,				 handle_t *handle,				 struct ocfs2_alloc_context *ac,				 u32 bits_wanted,				 u32 *bit_off,				 u32 *num_bits){	int status, start;	struct inode *local_alloc_inode;	void *bitmap;	struct ocfs2_dinode *alloc;	struct ocfs2_local_alloc *la;	mlog_entry_void();	BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);	local_alloc_inode = ac->ac_inode;	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;	la = OCFS2_LOCAL_ALLOC(alloc);	start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted);	if (start == -1) {		/* TODO: Shouldn't we just BUG here? */		status = -ENOSPC;		mlog_errno(status);		goto bail;	}	bitmap = la->la_bitmap;	*bit_off = le32_to_cpu(la->la_bm_off) + start;	/* local alloc is always contiguous by nature -- we never	 * delete bits from it! */	*num_bits = bits_wanted;	status = ocfs2_journal_access(handle, local_alloc_inode,				      osb->local_alloc_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	while(bits_wanted--)		ocfs2_set_bit(start++, bitmap);	alloc->id1.bitmap1.i_used = cpu_to_le32(*num_bits +				le32_to_cpu(alloc->id1.bitmap1.i_used));	status = ocfs2_journal_dirty(handle, osb->local_alloc_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = 0;bail:	mlog_exit(status);	return status;}static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc){	int i;	u8 *buffer;	u32 count = 0;	struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);	mlog_entry_void();	buffer = la->la_bitmap;	for (i = 0; i < le16_to_cpu(la->la_size); i++)		count += hweight8(buffer[i]);	mlog_exit(count);	return count;}static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,					     struct ocfs2_dinode *alloc,					     u32 numbits){	int numfound, bitoff, left, startoff, lastzero;	void *bitmap = NULL;	mlog_entry("(numbits wanted = %u)\n", numbits);	if (!alloc->id1.bitmap1.i_total) {		mlog(0, "No bits in my window!\n");		bitoff = -1;		goto bail;	}	bitmap = OCFS2_LOCAL_ALLOC(alloc)->la_bitmap;	numfound = bitoff = startoff = 0;	lastzero = -1;	left = le32_to_cpu(alloc->id1.bitmap1.i_total);	while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) != -1) {		if (bitoff == left) {			/* mlog(0, "bitoff (%d) == left", bitoff); */			break;		}		/* mlog(0, "Found a zero: bitoff = %d, startoff = %d, "		   "numfound = %d\n", bitoff, startoff, numfound);*/		/* Ok, we found a zero bit... is it contig. or do we		 * start over?*/		if (bitoff == startoff) {			/* we found a zero */			numfound++;			startoff++;		} else {			/* got a zero after some ones */			numfound = 1;			startoff = bitoff+1;		}		/* we got everything we needed */		if (numfound == numbits) {			/* mlog(0, "Found it all!\n"); */			break;		}	}	mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff,	     numfound);	if (numfound == numbits)		bitoff = startoff - numfound;	else		bitoff = -1;bail:	mlog_exit(bitoff);	return bitoff;}static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc){	struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);	int i;	mlog_entry_void();	alloc->id1.bitmap1.i_total = 0;	alloc->id1.bitmap1.i_used = 0;	la->la_bm_off = 0;	for(i = 0; i < le16_to_cpu(la->la_size); i++)		la->la_bitmap[i] = 0;	mlog_exit_void();}#if 0/* turn this on and uncomment below to aid debugging window shifts. */static void ocfs2_verify_zero_bits(unsigned long *bitmap,				   unsigned int start,				   unsigned int count){	unsigned int tmp = count;	while(tmp--) {		if (ocfs2_test_bit(start + tmp, bitmap)) {			printk("ocfs2_verify_zero_bits: start = %u, count = "			       "%u\n", start, count);			printk("ocfs2_verify_zero_bits: bit %u is set!",			       start + tmp);			BUG();		}	}}#endif/* * sync the local alloc to main bitmap. * * assumes you've already locked the main bitmap -- the bitmap inode * passed is used for caching. */static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,				    handle_t *handle,				    struct ocfs2_dinode *alloc,				    struct inode *main_bm_inode,				    struct buffer_head *main_bm_bh){	int status = 0;	int bit_off, left, count, start;	u64 la_start_blk;	u64 blkno;	void *bitmap;	struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);	mlog_entry("total = %u, used = %u\n",		   le32_to_cpu(alloc->id1.bitmap1.i_total),		   le32_to_cpu(alloc->id1.bitmap1.i_used));	if (!alloc->id1.bitmap1.i_total) {		mlog(0, "nothing to sync!\n");		goto bail;	}	if (le32_to_cpu(alloc->id1.bitmap1.i_used) ==	    le32_to_cpu(alloc->id1.bitmap1.i_total)) {		mlog(0, "all bits were taken!\n");		goto bail;	}	la_start_blk = ocfs2_clusters_to_blocks(osb->sb,						le32_to_cpu(la->la_bm_off));	bitmap = la->la_bitmap;	start = count = bit_off = 0;	left = le32_to_cpu(alloc->id1.bitmap1.i_total);	while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start))	       != -1) {		if ((bit_off < left) && (bit_off == start)) {			count++;			start++;			continue;		}		if (count) {			blkno = la_start_blk +				ocfs2_clusters_to_blocks(osb->sb,							 start - count);			mlog(0, "freeing %u bits starting at local alloc bit "			     "%u (la_start_blk = %llu, blkno = %llu)\n",			     count, start - count,			     (unsigned long long)la_start_blk,			     (unsigned long long)blkno);			status = ocfs2_free_clusters(handle, main_bm_inode,						     main_bm_bh, blkno, count);			if (status < 0) {				mlog_errno(status);				goto bail;			}		}		if (bit_off >= left)			break;		count = 1;		start = bit_off + 1;	}bail:	mlog_exit(status);	return status;}static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,						struct ocfs2_alloc_context **ac,						struct inode **bitmap_inode,						struct buffer_head **bitmap_bh){	int status;	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);	if (!(*ac)) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	(*ac)->ac_bits_wanted = ocfs2_local_alloc_window_bits(osb);	status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	*bitmap_inode = (*ac)->ac_inode;	igrab(*bitmap_inode);	*bitmap_bh = (*ac)->ac_bh;	get_bh(*bitmap_bh);	status = 0;bail:	if ((status < 0) && *ac) {		ocfs2_free_alloc_context(*ac);		*ac = NULL;	}	mlog_exit(status);	return status;}/* * pass it the bitmap lock in lock_bh if you have it. */static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,					handle_t *handle,					struct ocfs2_alloc_context *ac){	int status = 0;	u32 cluster_off, cluster_count;	struct ocfs2_dinode *alloc = NULL;	struct ocfs2_local_alloc *la;	mlog_entry_void();	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;	la = OCFS2_LOCAL_ALLOC(alloc);	if (alloc->id1.bitmap1.i_total)		mlog(0, "asking me to alloc a new window over a non-empty "		     "one\n");	mlog(0, "Allocating %u clusters for a new window.\n",	     ocfs2_local_alloc_window_bits(osb));	/* Instruct the allocation code to try the most recently used	 * cluster group. We'll re-record the group used this pass	 * below. */	ac->ac_last_group = osb->la_last_gd;	/* we used the generic suballoc reserve function, but we set	 * everything up nicely, so there's no reason why we can't use	 * the more specific cluster api to claim bits. */	status = ocfs2_claim_clusters(osb, handle, ac,				      ocfs2_local_alloc_window_bits(osb),				      &cluster_off, &cluster_count);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	osb->la_last_gd = ac->ac_last_group;	la->la_bm_off = cpu_to_le32(cluster_off);	alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count);	/* just in case... In the future when we find space ourselves,	 * we don't have to get all contiguous -- but we'll have to	 * set all previously used bits in bitmap and update	 * la_bits_set before setting the bits in the main bitmap. */	alloc->id1.bitmap1.i_used = 0;	memset(OCFS2_LOCAL_ALLOC(alloc)->la_bitmap, 0,	       le16_to_cpu(la->la_size));	mlog(0, "New window allocated:\n");	mlog(0, "window la_bm_off = %u\n",	     OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);	mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total));bail:	mlog_exit(status);	return status;}/* Note that we do *NOT* lock the local alloc inode here as * it's been locked already for us. */static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,					  struct inode *local_alloc_inode){	int status = 0;	struct buffer_head *main_bm_bh = NULL;	struct inode *main_bm_inode = NULL;	handle_t *handle = NULL;	struct ocfs2_dinode *alloc;	struct ocfs2_dinode *alloc_copy = NULL;	struct ocfs2_alloc_context *ac = NULL;	mlog_entry_void();	/* This will lock the main bitmap for us. */	status = ocfs2_local_alloc_reserve_for_window(osb,						      &ac,						      &main_bm_inode,						      &main_bm_bh);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		handle = NULL;		mlog_errno(status);		goto bail;	}	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;	/* We want to clear the local alloc before doing anything	 * else, so that if we error later during this operation,	 * local alloc shutdown won't try to double free main bitmap	 * bits. Make a copy so the sync function knows which bits to	 * free. */	alloc_copy = kmalloc(osb->local_alloc_bh->b_size, GFP_KERNEL);	if (!alloc_copy) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);	status = ocfs2_journal_access(handle, local_alloc_inode,				      osb->local_alloc_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	ocfs2_clear_local_alloc(alloc);	status = ocfs2_journal_dirty(handle, osb->local_alloc_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = ocfs2_sync_local_to_main(osb, handle, alloc_copy,					  main_bm_inode, main_bm_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = ocfs2_local_alloc_new_window(osb, handle, ac);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto bail;	}	atomic_inc(&osb->alloc_stats.moves);	status = 0;bail:	if (handle)		ocfs2_commit_trans(osb, handle);	if (main_bm_bh)		brelse(main_bm_bh);	if (main_bm_inode)		iput(main_bm_inode);	if (alloc_copy)		kfree(alloc_copy);	if (ac)		ocfs2_free_alloc_context(ac);	mlog_exit(status);	return status;}

⌨️ 快捷键说明

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